当前位置: 首页 > news >正文

【android bluetooth 协议分析 02】【bluetooth hal 层详解 8】【高通蓝牙hal-进程被杀之前日志收集流程】

1. 背景

【android bluetooth 协议分析 02】【bluetooth hal 层详解 7】【高通蓝牙hal-读流程介绍】
上一节我在介绍 hal 读流程时,我们先从一个报错开始梳理。 本节还是看这个报错的例子。

在这里插入图片描述

在这里插入图片描述

hal 进程 出现错误,在被干掉之前。会触发 SSR 日志收集。目的是方便 让开发人员定位问题。
如果你已经很清楚上面的日志代表什么含义,请忽略本篇。

在阅读本篇开始时请思考如下几个问题:

  1. SSR 是什么? 高通的 SSR 机制是如何触发收集日志的?收集日志的流程是什么? 除了收集日志还之外还需要处理那些事情?
  2. 我们从 打印的这些log 里面,能获取那些有用的信息,来辅助我们定位问题?
  3. 我们怎么利用高通原有的日志收集系统,增加调试信息? 当出现 crash 时,一同收集?

我将这部分 日志贴了出来。方便 在查问题时 cp 关键字。

05-29 15:01:47.825621  1220  2976 E vendor.randroid.bluetooth@1.0-uart_controller: RxThreadTimeOut:Rx thread stuck detected and callback scheduled in TS:3000.00 ms
05-29 15:01:47.825674  1220  2976 E vendor.randroid.bluetooth@1.0-uart_controller: RxThreadTimeOut:reporting SSR.
05-29 15:01:47.825683  1220  2976 D vendor.randroid.bluetooth@1.0-logger: SetRecoveryStartTime: recovery start time set
05-29 15:01:47.825717  1220  2976 E vendor.randroid.bluetooth@1.0-uart_transport: CheckForUartFailureCode: MSM_GENI_SERIAL_TIOCFAULT IOCTL not supported
05-29 15:01:47.825725  1220  2976 D vendor.randroid.bluetooth@1.0-uart_controller: SsrCleanup: IsSoCCrashNotNeeded 1
05-29 15:01:47.825745  1220  2976 D vendor.randroid.bluetooth@1.0-uart_controller: ReportSocFailure: reason 7
05-29 15:01:47.825756  1220  2976 I vendor.randroid.bluetooth@1.0-logger: BtPrimaryCrashReason:Rx Thread Stuck
05-29 15:01:47.825760  1220  2976 I vendor.randroid.bluetooth@1.0-logger: BtSecondaryCrashReason:Default
05-29 15:01:47.825763  1220  2976 I vendor.randroid.bluetooth@1.0-logger: TS for SoC Crash:Thu May 29 15:01:44 2025
05-29 15:01:47.825766  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: AddDelayListInfo: Adding Init phase delay list info to state file
05-29 15:01:47.825801  1220  2976 D vendor.randroid.bluetooth@1.0-uart_controller: ReportSocFailure calling CleanupSocCrashWaitTimer
05-29 15:01:47.825805  1220  2976 D vendor.randroid.bluetooth@1.0-uart_controller: HciTransportCleanup: deleting hci_transport
05-29 15:01:47.825815  1220  2976 D vendor.randroid.bluetooth@1.0-uart_transport: Disconnect: discard unsent data
05-29 15:01:47.825837  1220  2976 D vendor.randroid.bluetooth@1.0-uart_transport: CleanUp:> soc_type: 4, need_reload: 1
05-29 15:01:47.825844  1220  2976 D vendor.randroid.bluetooth@1.0-uart_transport: userial clock off
05-29 15:01:47.830651  1220  2976 I vendor.randroid.bluetooth@1.0-uart_transport: DeInitTransport: Transport is being closed!
05-29 15:01:47.831067  1220  2976 D vendor.randroid.bluetooth@1.0-wake_lock: CleanUp wakelock is destroyed 
05-29 15:01:47.839362  2325  3011 I bt_btif : packages/modules/Bluetooth/system/main/bte_logmsg.cc:115 LogMsg: btif_a2dp_sink_avk_handle_timer: empty queue
05-29 15:01:47.843294  1220  2976 D vendor.randroid.bluetooth@1.0-uart_ipc: DumpUartLogs: -->
05-29 15:01:47.843403  1220  2976 E vendor.randroid.bluetooth@1.0-uart_ipc: DumpUartLogs: Unable to open the Dir /sys/kernel/debug/ipc_logging/ err: No such file or directory (2)
05-29 15:01:47.843412  1220  2976 D vendor.randroid.bluetooth@1.0-uart_logs: DumpLogs: -->
05-29 15:01:47.843440  1220  2976 E vendor.randroid.bluetooth@1.0-uart_logs: DumpLogs: Unable to open the Dir /sys/kernel/tracing/instances/hsuart err: Permission denied (13)
05-29 15:01:47.843445  1220  2976 D vendor.randroid.bluetooth@1.0-ring_buffer: DumpData
05-29 15:01:47.843448  1220  2976 E vendor.randroid.bluetooth@1.0-ring_buffer: TS and last HCI cmd from stack = 07:01:45:135-0x040
05-29 15:01:47.843452  1220  2976 E vendor.randroid.bluetooth@1.0-ring_buffer: TS of posting event to stack 07:01:43:336
05-29 15:01:47.843455  1220  2976 E vendor.randroid.bluetooth@1.0-ring_buffer: TS of event posted to stack 07:01:43:336
05-29 15:01:47.843457  1220  2976 E vendor.randroid.bluetooth@1.0-ring_buffer: TS of posting ACL packet to stack 07:01:44:825
05-29 15:01:47.843459  1220  2976 E vendor.randroid.bluetooth@1.0-ring_buffer: TS of ACL packet posted to stack 07:01:44:812
05-29 15:01:47.843461  1220  2976 E vendor.randroid.bluetooth@1.0-ring_buffer: TS of posting ISO packet to stack 00:00:00:000
05-29 15:01:47.843465  1220  2976 E vendor.randroid.bluetooth@1.0-ring_buffer: TS of ISO packet posted to stack 00:00:00:000
05-29 15:01:47.843468  1220  2976 E vendor.randroid.bluetooth@1.0-ring_buffer: TS of pre select 07:01:44:825
05-29 15:01:47.843470  1220  2976 E vendor.randroid.bluetooth@1.0-ring_buffer: TS of post select 07:01:44:825
05-29 15:01:47.843473  1220  2976 E vendor.randroid.bluetooth@1.0-ring_buffer: DumpData: TS System 07:01:47:843 TS kernel 3476:543322422
05-29 15:01:47.848469  1220  2976 I vendor.randroid.bluetooth@1.0-ring_buffer: DumpData: writing dump into a file: /data/vendor/ssrdump/ramdump_bt_snoop_2025-05-29_15-01-47.cfa
05-29 15:01:47.859568  2325  3011 I bt_btif : packages/modules/Bluetooth/system/main/bte_logmsg.cc:115 LogMsg: btif_a2dp_sink_avk_handle_timer: empty queue
05-29 15:01:47.863259  1220  2976 I vendor.randroid.bluetooth@1.0-logger: ReadSsrLevel: ssr_level set to 3
05-29 15:01:47.863369  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: DumpBtState: Dumping stats into /data/vendor/ssrdump/ramdump_bt_state_2025-05-29_15-01-47.log
05-29 15:01:47.863373  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: BtPrimaryCrashReason:Rx Thread Stuck
05-29 15:01:47.863403  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: BtSecondaryCrashReason:Default
05-29 15:01:47.863409  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: BQR RIE Crash Code : 0x07 
05-29 15:01:47.863409  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: BQR RIE Crash String : Rx Thread Stuck
05-29 15:01:47.863413  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: TS for SoC Crash:Thu May 29 15:01:44 2025
05-29 15:01:47.863417  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: TS System 07:01:47:843 TS kernel 3476:543322422 
05-29 15:01:47.863430  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: SOC AlwaysOn disabled 
05-29 15:01:47.863435  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: SSR LVL = 3
05-29 15:01:47.863440  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:545-HCI initialize rcvd from client type = 0
05-29 15:01:47.863444  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:711-Reading sibs property
05-29 15:01:47.863448  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:711-Done reading sibs property
05-29 15:01:47.863453  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000-HCI close not rcvd from client
05-29 15:01:47.863458  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:711-Getting Local BD Address
05-29 15:01:47.863462  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:711-Done getting Local BD Address
05-29 15:01:47.863466  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:711-Fetching vendor BD Address
05-29 15:01:47.863471  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:711-Done fetching vendor BD Address
05-29 15:01:47.863475  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:711-Sending Get Version CMD to SOC
05-29 15:01:47.863480  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:711-Reading Get Version CMD RSP from SOC
05-29 15:01:47.863484  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: Pre Version info. write TS: Unknown
05-29 15:01:47.863488  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: Post Version info. write TS: Unknown
05-29 15:01:47.863492  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:716-Get Version rsp rcvd, num bytes in last rsp = 5
05-29 15:01:47.863496  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:724-Setting proper Rampatch and NVM path
05-29 15:01:47.863500  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:726-Done setting proper rampatch and NVM path
05-29 15:01:47.863504  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:751-Opening and reading patch file
05-29 15:01:47.863508  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:752-Done opening and reading patch file
05-29 15:01:47.863512  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:21:453-Opening and reading NVM file
05-29 15:01:47.863516  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:21:454-Done opening and reading NVM file
05-29 15:01:47.863520  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:21:453-iPA supported, configure TCS now
05-29 15:01:47.863525  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:21:454-Done configuring TCS as iPA is supported
05-29 15:01:47.863530  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: Pre SU build info. write TS: Unknown
05-29 15:01:47.863534  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: Post SU build info. write TS: Unknown
05-29 15:01:47.863538  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:21:643-SoC initialization successful
05-29 15:01:47.863543  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:21:634 BT SoC FW SU Build info: BTFW.HSP.2.1.2-00034-PATCHZ-1
05-29 15:01:47.863548  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: OTP info. length: 64
05-29 15:01:47.863548  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: OTP bytes are as follows:
05-29 15:01:47.863548  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 13 2F 1F 58 41 32 4B 4E 53 00 CB 06 00 00 03 03 C5 1D 39 17 85 1C 14 1C 67 20 F2 24 A0 20 AC 2C D4 00 D8 00 DF 00 D1 00 D1 00 D7 00 7E 00 00 00 FD 01 00 00 00 00 00 00 61 00 48 00 00 00 00 00 
05-29 15:01:47.863554  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: unified Current SOC Version : 0x400c0210
05-29 15:01:47.863558  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: BT Power Resources State: Unknown
05-29 15:01:47.863562  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: BT UART CTS: Unknown
05-29 15:01:47.863566  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:21:643-Starting Read thread
05-29 15:01:47.863570  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:21:643-Read thread was started: SUCCESS
05-29 15:01:47.863574  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000:Pre Diag init not started 
05-29 15:01:47.865955  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000:Post Diag init not started 
05-29 15:01:47.865970  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000:Diag not initialized
05-29 15:01:47.865975  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:21:643-Controller Init status = 1
05-29 15:01:47.865979  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:21:644-Init callback status = 1
05-29 15:01:47.865984  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:751-UART Flow On
05-29 15:01:47.865988  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:726-UART Flow Off
05-29 15:01:47.865993  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000:Pre Diag deinit not started 
05-29 15:01:47.865997  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000:Post Diag deinit not started 
05-29 15:01:47.866001  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: HealthStatisticsTimerStart started: SUCCESS
05-29 15:01:47.866018  1220  2976 D vendor.randroid.bluetooth@1.0-health-info: ReportHealthInfo:statistics:
05-29 15:01:47.866018  1220  2976 D vendor.randroid.bluetooth@1.0-health-info: ts <07:01:47:866006> rx_vote:0, tx_vote:0, wake_lock holding:0, maximum rx sleep-wake-interval:0sec, maximum tx packet-interval:0secWake_Req sent out:0, Wake_Req received:0Sleep_Ind sent out:0, Sleep_Ind received:0
05-29 15:01:47.866022  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: ts <07:01:47:866006> rx_vote:0, tx_vote:0, wake_lock holding:0, maximum rx sleep-wake-interval:0sec, maximum tx packet-interval:0secWake_Req sent out:0, Wake_Req received:0Sleep_Ind sent out:0, Sleep_Ind received:0
05-29 15:01:47.866027  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: No internal commands sent to SoC 
05-29 15:01:47.866031  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: Not rcvd RSP for any internal commands 
05-29 15:01:47.866035  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: TS and last HCI cmd from stack = 07:01:45:135-0x040
05-29 15:01:47.866039  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000-Last sequence num
05-29 15:01:47.866045  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000-Writing FD to SOC
05-29 15:01:47.866049  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000-Received FC from SOC
05-29 15:01:47.866052  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000-Received FD from SOC
05-29 15:01:47.866056  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000-Writing FC to SOC
05-29 15:01:47.866061  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000-Writing FE to SoC
05-29 15:01:47.866065  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000-Received FE from SOC
05-29 15:01:47.866068  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: TS of posting event to stack 07:01:43:336
05-29 15:01:47.866074  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: TS of event posted to stack 07:01:43:336
05-29 15:01:47.866078  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: TS of posting ACL packet to stack 07:01:44:825
05-29 15:01:47.866081  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: TS of ACL packet posted to stack 07:01:44:812
05-29 15:01:47.866086  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: TS of posting ISO packet to stack 00:00:00:000
05-29 15:01:47.866090  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: TS of ISO packet posted to stack 00:00:00:000
05-29 15:01:47.866094  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: TS of pre select 07:01:44:825
05-29 15:01:47.866098  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: TS of post select 07:01:44:825
05-29 15:01:47.866101  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:711-UART Clock On
05-29 15:01:47.866105  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 07:01:47:825-UART Clock Off
05-29 15:01:47.866109  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 07:01:45:135-Last TX packet and timestamp 
05-29 15:01:47.866117  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 02 04 00 11 00 0D 00 0C E2 40 11 0E 01 48 00 00 19 58 30 00 00 
05-29 15:01:47.866122  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: Actual last TX pkt len: 22
05-29 15:01:47.866126  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 00:00:00:000-last rx before ssr
05-29 15:01:47.866131  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 
05-29 15:01:47.866136  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: Actual RX pkt len before SSR: 0
05-29 15:01:47.866138  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 07:01:44:825-Last RX packet and timestamp
05-29 15:01:47.866147  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 02 04 20 8A 01 86 01 47 00 80 60 11 4A 03 82 37 DF 00 00 00 00 
05-29 15:01:47.866151  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: Actual last RX pkt len: 399
05-29 15:01:47.866155  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: Health timer Abort TS: Unkown
05-29 15:01:47.866159  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:20:684-Wakelock Acquired by UartController Init
05-29 15:01:47.866163  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: 06:04:21:643-Wakelock::ReleaseDelay 500ms during UART init
05-29 15:01:47.866167  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: PC address of FW crash: 0x00
05-29 15:01:47.866171  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: SOC build ver: 0x00
05-29 15:01:47.866176  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo: Delay list elements:
05-29 15:01:47.866176  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo:   Activity: UART INIT
05-29 15:01:47.866176  1220  2976 D vendor.randroid.bluetooth@1.0-btstateinfo:     Start time: 06:04:20:685    End time: 06:04:20:710    Extra Delay(ms): 5    Total Time(ms): 25
05-29 15:01:47.873854  1220  2976 D vendor.randroid.bluetooth@1.0-health-info: ReportHealthInfo:statistics:
05-29 15:01:47.873854  1220  2976 D vendor.randroid.bluetooth@1.0-health-info: ts <07:01:47:873832> rx_vote:0, tx_vote:0, wake_lock holding:0, maximum rx sleep-wake-interval:0sec, maximum tx packet-interval:0secWake_Req sent out:0, Wake_Req received:0Sleep_Ind sent out:0, Sleep_Ind received:0
05-29 15:01:47.873891  1220  2976 D vendor.randroid.bluetooth@1.0-power_manager: SetPower: enable: 0
05-29 15:01:47.874114  1220  2976 D vendor.randroid.bluetooth@1.0-power_manager: GetRfkillFd: rfkill_fd: 6
05-29 15:01:47.874118  1220  2976 D vendor.randroid.bluetooth@1.0-power_manager: ControlRfkill: rfkill_fd: 6, enable: 0// kill -9 杀死 hal 进程
01-01 08:57:56.827305     1     1 I libprocessgroup: Successfully killed process cgroup uid 1002 pid 1220 in 0ms
05-29 15:01:48.065919  1220  2976 E vendor.randroid.bluetooth@1.0-uart_controller: Killing daemon as SSR is completed!

void UartController::RxThreadTimeOut(union sigval sig)
{{...ALOGE("%s:Rx thread stuck detected and callback scheduled in TS:%0.2lf ms",__func__, uart_controller->GetRxThreadSchedTSDiff());}{...ALOGE("%s:reporting SSR.", __func__);uart_controller->SsrCleanup(BT_HOST_REASON_RX_THREAD_STUCK);}
}

在 UartController::RxThreadTimeOut 超时函数中,主要就是 为了触发 SSR 机制。

2. 何为 SSR

在 Qualcomm 平台和 Android 蓝牙/通信子系统中,SSR(Subsystem Restart) 指的是某个硬件子系统(如 Bluetooth、Wi-Fi、Modem 等)由于异常或者重启请求而重新启动的过程。这是一种容错机制,允许系统在不完全重启整个设备的情况下恢复某个出错的子模块。

1. 错误原因介绍

在 qcom SSR 中会涉及到两个 重要的 错误原因:

  1. PrimaryReasonCode : 用于标识蓝牙系统崩溃或异常的 一级原因分类,通常是宏观层面上的崩溃来源。
  2. SecondaryReasonCode : 在 PrimaryReasonCode 给出的主分类基础上,进一步细化崩溃或失败的 具体原因(子原因),用于辅助诊断与日志追踪。
05-29 15:01:47.825756  1220  2976 I vendor.randroid.bluetooth@1.0-logger: BtPrimaryCrashReason:Rx Thread Stuck
05-29 15:01:47.825760  1220  2976 I vendor.randroid.bluetooth@1.0-logger: BtSecondaryCrashReason:Default
  • 可以重点关注上述两个日志, 大概能够清楚 是哪里出现了问题。

1. PrimaryReasonCode 介绍

在调用 uart_controller->SsrCleanup(BT_HOST_REASON_RX_THREAD_STUCK); 会将出错的原因传递进来

如下是所有 出错的原因:

enum PrimaryReasonCode  {BT_HOST_REASON_DEFAULT_NONE  = 0x00,                         //INVALID REASONBT_HOST_REASON_SOC_CRASHED = 0x01,                           //SOC WAS CRASHEDBT_HOST_REASON_SOC_CRASHED_DIAG_SSR = 0x02,                  //SOC CRASHED DIAG INITIATED SSRBT_HOST_REASON_INIT_FAILED = 0x03,                           //HOST INITIALIZATION FAILEDBT_HOST_REASON_CLOSE_RCVD_DURING_INIT = 0x04,                //CLOSE RECEIVED FROM STACK DURING SOC INITBT_HOST_REASON_ERROR_READING_DATA_FROM_UART = 0x05,          //ERROR READING DATA FROM UARTBT_HOST_REASON_WRITE_FAIL_SPCL_BUFF_CRASH_SOC = 0x06,        //FAILED TO WRITE SPECIAL BYTES TO CRASH SOCBT_HOST_REASON_RX_THREAD_STUCK = 0x07,                       //RX THREAD STUCKBT_HOST_REASON_SSR_CMD_TIMEDOUT = 0x08,                      //SSR DUE TO CMD TIMED OUTBT_HOST_REASON_SSR_SPURIOUS_WAKEUP = 0x09,                   //SSR DUE TO SPURIOUS WAKE UPBT_HOST_REASON_SSR_INVALID_BYTES_RCVD = 0x0A,                //INVALID HCI CMD TYPE RECEIVEDBT_HOST_REASON_SSR_RCVD_LARGE_PKT_FROM_SOC = 0x0B,           //SSR DUE TO LARGE PKT RECVIVED FROM SOCBT_HOST_REASON_SSR_UNABLE_TO_WAKEUP_SOC = 0x0C,              //UNABLE TO WAKE UP SOCBT_HOST_REASON_CMD_TIMEDOUT_SOC_WAIT_TIMEOUT = 0x0D,         //COMMAND TIMEOUT AND SOC CRASH WAIT TIMEOUTBT_HOST_REASON_SPURIOUS_WAKEUP_SOC_WAIT_TIMEOUT = 0x0E,      //SPURIOUS WAKE AND SOC CRASH WAIT TIMEOUTBT_HOST_REASON_INV_BYTES_SOC_WAIT_TIMEOUT = 0x0F,            //INVALID BYTES AND SOC CRASH WAIT TIMEOUTBT_HOST_REASON_SOC_WAKEUP_FAILED_SOC_WAIT_TIMEOUT = 0x10,    //SOC WAKEUP FAILURE AND SOC CRASH WAIT TIMEOUTBT_HOST_REASON_SOC_CRASHED_DIAG_SSR_SOC_WAIT_TIMEOUT = 0x11, //SOC CRASHED DIAG INITIATED SSR CRASH WAIT TIMEOUTBT_HOST_REASON_NONE_SOC_WAIT_TIMEOUT = 0x12,                 //INVALID FAILURE AND SOC CRASH WAIT TIMEOUTBT_HOST_REASON_SOC_DEINIT_STUCK = 0x13,                      //SOC DEINIT STUCKBT_HOST_REASON_SSR_INTERNAL_CMD_TIMEDOUT = 0x14,             //SSR DUE TO CMD INTERNAL TIMED OUTBT_HOST_REASON_FAILED_TO_SEND_INTERNAL_CMD = 0x15,           //FAILED TO SEND INTERNAL CMDBT_HOST_REASON_SSR_SLEEP_IND_NOT_RCVD = 0x16,                //SOC DID NOT RCVD SLEEP IND DURING CLOSEBT_HOST_REASON_DIAG_LOG_API_STUCK = 0x39,                    //DIAG log API stuck.
};
错误码枚举名出错场景可能原因是否触发 SSR
0x00BT_HOST_REASON_DEFAULT_NONE无具体错误信息默认值或无效原因
0x01BT_HOST_REASON_SOC_CRASHEDSoC 异常重启蓝牙 SoC Crash,未具体说明由谁触发
0x02BT_HOST_REASON_SOC_CRASHED_DIAG_SSRDiag 模块触发 SSRModem/Diag 检测到异常,触发 SSR
0x03BT_HOST_REASON_INIT_FAILED初始化失败蓝牙驱动或 HAL 初始化失败
0x04BT_HOST_REASON_CLOSE_RCVD_DURING_INIT初始化过程中收到上层 close 命令状态未就绪,框架强行终止蓝牙流程否(视情况)
0x05BT_HOST_REASON_ERROR_READING_DATA_FROM_UARTUART 接收数据异常UART 接收错误、SoC 掉电、通讯中断
0x06BT_HOST_REASON_WRITE_FAIL_SPCL_BUFF_CRASH_SOC向 SoC 写入特殊 crash buffer 失败HAL 试图崩溃 SoC 但失败
0x07BT_HOST_REASON_RX_THREAD_STUCKRX 接收线程卡死蓝牙接收线程无响应或死锁
0x08BT_HOST_REASON_SSR_CMD_TIMEDOUTHAL 发送命令超时无响应SoC 不响应 HCI 命令
0x09BT_HOST_REASON_SSR_SPURIOUS_WAKEUP非预期唤醒事件Wake Lock 或中断异常
0x0ABT_HOST_REASON_SSR_INVALID_BYTES_RCVD收到非法数据非法 HCI 包类型或 SoC 异常输出
0x0BBT_HOST_REASON_SSR_RCVD_LARGE_PKT_FROM_SOC收到异常大包SoC 发出超过协议长度限制的数据包
0x0CBT_HOST_REASON_SSR_UNABLE_TO_WAKEUP_SOC无法唤醒 SoCSoC 进入 sleep 状态无法恢复
0x0DBT_HOST_REASON_CMD_TIMEDOUT_SOC_WAIT_TIMEOUT命令超时 + 等待 crash 超时等待 SoC crash 文件超时
0x0EBT_HOST_REASON_SPURIOUS_WAKEUP_SOC_WAIT_TIMEOUT非法唤醒 + Crash 等待超时双重异常情况
0x0FBT_HOST_REASON_INV_BYTES_SOC_WAIT_TIMEOUT非法字节 + Crash 等待超时收到非法数据且 crash log 等待超时
0x10BT_HOST_REASON_SOC_WAKEUP_FAILED_SOC_WAIT_TIMEOUTSoC 唤醒失败 + 等待 crash 超时睡眠失败后尝试恢复失败
0x11BT_HOST_REASON_SOC_CRASHED_DIAG_SSR_SOC_WAIT_TIMEOUTDIAG SSR 后 crash log 超时DIAG 已触发 SSR,但 log 没回
0x12BT_HOST_REASON_NONE_SOC_WAIT_TIMEOUT无效原因 + Crash log 等待超时异常未捕获但等待超时
0x13BT_HOST_REASON_SOC_DEINIT_STUCKDeinit 过程卡住SoC 去初始化失败(关闭失败)
0x14BT_HOST_REASON_SSR_INTERNAL_CMD_TIMEDOUT内部命令超时控制命令发送后未响应
0x15BT_HOST_REASON_FAILED_TO_SEND_INTERNAL_CMD无法发送内部命令HAL 内部机制故障
0x16BT_HOST_REASON_SSR_SLEEP_IND_NOT_RCVDSoC 在关闭前未收到 sleep 指令关闭流程异常,未同步 sleep 状态
0x39BT_HOST_REASON_DIAG_LOG_API_STUCKDIAG API 卡住DIAG log 模块内部死锁或卡死
特别说明:
  • 是否触发 SSR:表示该错误通常是否会触发 Bluetooth HAL 层的 SSR 清理逻辑(如 UartController::SsrCleanup())。

  • Crash wait timeout 类原因意味着:HAL 等待 soc_crash_logs 返回超时后强制执行 SSR。

  • 一些 非致命错误(如 BT_HOST_REASON_CLOSE_RCVD_DURING_INIT)则不一定触发 SSR,而是流程终止。

  • 上面提到的 Soc 指蓝牙芯片。并不是车机的 Soc.

2.SecondaryReasonCode

typedef enum {BT_SOC_REASON_DEFAULT                 =  0x00,// SoC Crash ReasonsBT_SOC_REASON_UNKNOWN        =  0x81,BT_SOC_REASON_SW_REQUESTED   =  0x82,BT_SOC_REASON_STACK_OVERFLOW =  0x83,BT_SOC_REASON_EXCEPTION      =  0x84,BT_SOC_REASON_ASSERT         =  0x85,BT_SOC_REASON_TRAP           =  0x86,BT_SOC_REASON_OS_FATAL       =  0x87,BT_SOC_REASON_HCI_RESET      =  0x88,BT_SOC_REASON_PATCH_RESET    =  0x89,BT_SOC_REASON_ABT            =  0x8A,BT_SOC_REASON_RAMMASK        =  0x8B,BT_SOC_REASON_PREBARK        =  0x8C,BT_SOC_REASON_BUSERROR       =  0x8D,BT_SOC_REASON_IO_FATAL       =  0x8E,BT_SOC_REASON_SSR_CMD        =  0x8F,BT_SOC_REASON_POWERON        =  0x90,BT_SOC_REASON_WATCHDOG       =  0x91,BT_SOC_REASON_RAMMASK_RGN1   =  0x92,BT_SOC_REASON_RAMMASK_RGN0   =  0x93,BT_SOC_REASON_Q6_WATCHDOG    =  0x94,BT_SOC_REASON_ZEALIS_RAM_MASK_RGN0 =  0x95,BT_SOC_REASON_ZEALIS_RAM_MASK_RGN1 =  0x96,BT_SOC_REASON_APSS_RESET           =  0x97,BT_SOC_REASON_TIME_RESET           =  0x98,BT_SOC_REASON_AUDIOSS_RESET        =  0x99,BT_SOC_REASON_HOST_WARMRESET       =  0x9A,BT_SOC_REASON_HOST_NMI_INIT        =  0x9B,BT_SOC_REASON_TX_RX_INVALID_PKT_FATAL = 0xC0,BT_SOC_REASON_TX_RX_INVALID_LEN_FATAL = 0xC1,BT_SOC_REASON_INVALID_STACK  =  0xF0,// Transport Driver Crash ReasonsBT_HOST_REASON_UARTINIT_STUCK        =  0x17,BT_HOST_REASON_GETVER_SEND_STUCK     =  0x18,BT_HOST_REASON_GETVER_NO_RSP_RCVD    =  0x19,BT_HOST_REASON_SETBAUDRATE_CMD_STUCK =  0x1A,BT_HOST_REASON_PATCH_DNLD_STUCK      =  0x1B,BT_HOST_REASON_GETBOARDID_CMD_STUCK  =  0x1C,BT_HOST_REASON_NVM_DNLD_STUCK        =  0x1D,BT_HOST_REASON_HCI_RESET_STUCK       =  0x1E,BT_HOST_REASON_GETBLDINFO_CMD_STUCK  =  0x1F,BT_HOST_REASON_ADDONFEAT_CMD_STUCK   =  0x20,BT_HOST_REASON_ENHLOG_CMD_STUCK      =  0x21,BT_HOST_REASON_DIAGINIT_STUCK        =  0x22,BT_HOST_REASON_DIAGDEINIT_STUCK      =  0x23,BT_HOST_REASON_XMEM_NVM_DNLD_STUCK   =  0x24,BT_HOST_REASON_XMEM_PATCH_DNLD_STUCK =  0x25,BT_HOST_REASON_SECURE_BRIDGE_CMD_STUCK = 0x26,BT_HOST_REASON_FAILED_TO_SEND_CMD              =  0x27,BT_HOST_REASON_HCI_RESET_CC_NOT_RCVD           =  0x28,BT_HOST_REASON_HCI_PRE_SHUTDOWN_CC_NOT_RCVD    =  0x29,BT_HOST_REASON_HCI_SET_BD_ADDRESS_CC_NOT_RCVD  =  0x2A,BT_HOST_REASON_FAILED_TO_RECEIVE_SLEEP_IND     =  0x2B,BT_HOST_REASON_POWER_ON_REGS_STUCK             =  0x2C,BT_HOST_REASON_RX_THREAD_START_STUCK           =  0x2D,BT_HOST_REASON_GET_LOCALADDR_STUCK             =  0x2E,BT_HOST_REASON_OTP_INFO_GET_CMD_STUCK          =  0x2F,BT_HOST_REASON_FILE_SYSTEM_CALL_STUCK          =  0x30,BT_HOST_REASON_PROPERTY_GET_STUCK              =  0x31,BT_HOST_REASON_PROPERTY_SET_STUCK              =  0x32,BT_HOST_REASON_RAM_PATCH_READ_STUCK            =  0x33,BT_HOST_REASON_NVM_PATCH_READ_STUCK            =  0x34,BT_HOST_REASON_UART_IOCTL_STUCK                =  0x35,BT_HOST_REASON_POWER_IOCTL_STUCK               =  0x36,BT_HOST_REASON_PATCH_CONFIG_CMD_STUCK          =  0x37,BT_HOST_REASON_GET_APP_VER_CMD_STUCK           =  0x38,BT_HOST_REASON_SOC_NAME_UNKOWN                 =  0x3A,// Exception in HOST reason, below is actually related to SoC.SOC_REASON_START_TX_IOS_SOC_RFR_HIGH_DURING_INIT =  0x3B,BT_HOST_REASON_GETVER_CMD_FAILED               = 0x3C,BT_HOST_REASON_BAUDRATE_CHANGE_FAILED          = 0x3D,BT_HOST_REASON_TLV_DOWNLOAD_FAILED             = 0x3E,BT_HOST_REASON_FW_BUILD_INFO_CMD_FAILED        = 0x3F,BT_HOST_REASON_HCI_RESET_CMD_FAILED            = 0x40,BT_HOST_REASON_UART_INIT_FAILED                = 0x41,BT_HOST_REASON_MEMORY_ALLOCATION_FAILED        = 0x42,BT_HOST_REASON_READ_THREAD_START_FAILED        = 0x43,BT_HOST_REASON_HW_FLOW_ON_FAILED               = 0x44,BT_HOST_REASON_NVM_FILE_NOT_FOUND              = 0x45,BT_HOST_REASON_UART_BAUDRATE_CHANGE_FAILED     = 0x46,BT_HOST_REASON_PATCH_CONFIG_FAILED             = 0x47,// UART driver crash reasonsUART_REASON_DEFAULT                            =  0x51,UART_REASON_INVALID_FW_LOADED                  =  0x52,UART_REASON_CLK_GET_FAIL                       =  0x53,UART_REASON_SE_CLK_RATE_FIND_FAIL              =  0x54,UART_REASON_SE_RESOURCES_INIT_FAIL             =  0x55,UART_REASON_SE_RESOURCES_ON_FAIL               =  0x56,UART_REASON_SE_RESOURCES_OFF_FAIL              =  0x57,UART_REASON_TX_DMA_MAP_FAIL                    =  0x58,UART_REASON_TX_CANCEL_FAIL                     =  0x59,UART_REASON_TX_ABORT_FAIL                      =  0x5A,UART_REASON_TX_FSM_RESET_FAIL                  =  0x5B,UART_REASON_RX_CANCEL_FAIL                     =  0x5C,UART_REASON_RX_ABORT_FAIL                      =  0x5D,UART_REASON_RX_FSM_RESET_FAIL                  =  0x5E,UART_REASON_RX_TTY_INSET_FAIL                  =  0x5F,UART_REASON_ILLEGAL_INTERRUPT                  =  0x60,UART_REASON_BUFFER_OVERRUN                     =  0x61,UART_REASON_RX_PARITY_REASON                   =  0x62,UART_REASON_RX_BREAK_REASON                    =  0x63,UART_REASON_RX_SBE_REASON                      =  0x64,SOC_REASON_START_TX_IOS_SOC_RFR_HIGH           =  0x65,UART_REASON_FLOW_OFF                           =  0x66,
} SecondaryReasonCode;
1. SoC Crash 原因(0x81 ~ 0x9B, 0xC0 ~ 0xC1, 0xF0)
错误码名称出错场景可能原因
0x81BT_SOC_REASON_UNKNOWN未知 SoC 崩溃未记录具体原因,可能为底层未捕获异常
0x82BT_SOC_REASON_SW_REQUESTED主动触发崩溃软件请求 SSR,例如测试或错误恢复机制
0x83BT_SOC_REASON_STACK_OVERFLOWSoC 崩溃SoC 内部任务栈溢出
0x84BT_SOC_REASON_EXCEPTIONSoC 崩溃SoC 捕获未处理异常
0x85BT_SOC_REASON_ASSERTSoC 崩溃SoC 中断言失败(assert hit)
0x86BT_SOC_REASON_TRAPSoC 崩溃陷阱异常(如非法指令)
0x87BT_SOC_REASON_OS_FATALSoC 崩溃RTOS 致命错误,如调度器出错
0x88BT_SOC_REASON_HCI_RESET主动或异常复位HCI Reset 导致 SSR
0x89BT_SOC_REASON_PATCH_RESET打补丁后复位下载 patch 后要求 SoC 重启
0x8ABT_SOC_REASON_ABT异常终止异常 abort 终止指令执行
0x8BBT_SOC_REASON_RAMMASK崩溃检测RAM MASK 检测到内存非法访问
0x8CBT_SOC_REASON_PREBARK错误中断触发所谓 “bark” 是 watchdog 报警触发
0x8DBT_SOC_REASON_BUSERROR总线异常SoC 访问异常或非法地址
0x8EBT_SOC_REASON_IO_FATALI/O 错误外设或通信口故障
0x8FBT_SOC_REASON_SSR_CMDSSR 命令触发接收到 SSR 特定命令
0x90BT_SOC_REASON_POWERON上电重启SoC 刚上电初始化
0x91BT_SOC_REASON_WATCHDOG看门狗复位Watchdog 超时未喂
0x92BT_SOC_REASON_RAMMASK_RGN1RAM 崩溃检测指定区域1检测到非法内存
0x93BT_SOC_REASON_RAMMASK_RGN0RAM 崩溃检测指定区域0检测到非法内存
0x94BT_SOC_REASON_Q6_WATCHDOGQDSP 崩溃Q6 DSP 触发 Watchdog
0x95BT_SOC_REASON_ZEALIS_RAM_MASK_RGN0内存保护RAM mask 检测 ZEALIS 区域
0x96BT_SOC_REASON_ZEALIS_RAM_MASK_RGN1内存保护RAM mask 检测 ZEALIS 区域
0x97BT_SOC_REASON_APSS_RESETAP 复位AP 发起 warm/cold reset
0x98BT_SOC_REASON_TIME_RESET时钟复位时钟配置异常或复位触发
0x99BT_SOC_REASON_AUDIOSS_RESETAudio 子系统异常AudioSS 出现错误导致全局重启
0x9ABT_SOC_REASON_HOST_WARMRESET主机发起复位Host 请求 warm reset
0x9BBT_SOC_REASON_HOST_NMI_INIT主机发起 NMI 初始化Host 发出非屏蔽中断
0xC0BT_SOC_REASON_TX_RX_INVALID_PKT_FATAL接收到异常数据包数据包格式非法导致崩溃
0xC1BT_SOC_REASON_TX_RX_INVALID_LEN_FATAL接收到长度错误的数据包长度超限或错位
0xF0BT_SOC_REASON_INVALID_STACK内部栈错误SoC 栈初始化失败或破坏

2. Host 层异常(0x17 ~ 0x3F, 0x41 ~ 0x47)
错误码名称出错场景可能原因
0x17 ~ 0x21*_STUCK 类错误Host 初始化命令卡死通常是发送命令后未收到回应或接口阻塞
0x22 ~ 0x26DIAG/XMEM 命令卡死DIAG、XMEM 初始化或补丁卡住
0x27FAILED_TO_SEND_CMDHost 无法发送命令发送失败或内部缓冲异常
0x28 ~ 0x2A*_CC_NOT_RCVD未收到命令完成事件SoC 没有回应 HCI 命令
0x2BFAILED_TO_RECEIVE_SLEEP_IND未收到 Sleep 指示关机流程不完整,SoC 未响应
0x2CPOWER_ON_REGS_STUCK电源寄存器初始化异常上电失败或寄存器配置卡住
0x2DRX_THREAD_START_STUCK接收线程启动失败pthread 或资源申请异常
0x2E ~ 0x31GET/SET STUCK属性获取失败HAL 或系统属性异常
0x32 ~ 0x34补丁/文件读异常读取失败或路径错误
0x35 ~ 0x37IOCTL 调用失败驱动接口调用异常或无权限
0x38 ~ 0x3F初始化相关命令失败版本查询、Patch配置失败等
0x41 ~ 0x47初始化失败类包含内存不足、串口失败、补丁失败等

3. Transport/UART 驱动崩溃(0x51 ~ 0x66)
错误码名称出错场景可能原因
0x51UART_REASON_DEFAULT默认 UART 错误一般作为兜底错误码
0x52INVALID_FW_LOADED加载错误固件固件不匹配或损坏
0x53 ~ 0x57CLK/资源类错误获取时钟失败,资源初始化失败等
0x58 ~ 0x5BTX 方向失败DMA 映射、TX 取消、TX FSM 初始化失败
0x5C ~ 0x5ERX 方向失败RX 取消、FSM 异常
0x5FRX_TTY_INSET_FAILTTY 配置失败串口 TTY 接口未就绪
0x60 ~ 0x64中断/接收异常接收到非法中断或奇偶校验错误
0x65SOC_REASON_START_TX_IOS_SOC_RFR_HIGH初始化时 TX IOS 高电平未降SoC 初始化握手失败
0x66UART_REASON_FLOW_OFF流控未开启SoC 未成功建立通信通道

2. UartController::SsrCleanup

作用:

  • 在检测到蓝牙 SoC 或 Host 层异常(例如崩溃、失去响应、唤醒失败等)后进行清理和异常处理,包括日志记录、触发 crashdump、必要时触发 kernel panic 等。

// 接收一个 PrimaryReasonCode 类型的参数(主崩溃原因),用于标识引发 SSR(Subsystem Restart)清理的主因。
void UartController::SsrCleanup(PrimaryReasonCode reason)
{/*1. SSR 是否已触发判断- 尝试设置一个“SSR 已触发”标志。- 如果已经在清理中或 SSR 已处理过,打印日志后直接返回。   - 如果此前没有设置主原因码(prv_reason),就用当前 reason 赋值。说明:防止重复清理;避免多线程下重复触发导致的问题*/if (!Logger::Get()->SetSsrTriggeredFlag()) {ALOGE("%s: Returning as SSR or cleanup in progress", __func__);if (prv_reason == BT_HOST_REASON_DEFAULT_NONE) {prv_reason = reason;}return;}// 2. 检查 UART 是否失败,并设置二级崩溃原因if (CheckForUartFailureStatus()) {// 2.1 如果 UART 层检测到失败(如流控失败、无法获取时钟等),则记录对应的二级错误码。logger_->SetSecondaryCrashReason(logger_->GetUartErrCode());}// 3. 设置主崩溃原因logger_->SetPrimaryCrashReason(reason);/*4. 判断 reason 是否是“特殊字节触发型崩溃”- 这些属于 必须通过发送特殊字节触发 crashdump 的场景,比如唤醒失败、接收非法数据包等。*//*Indicate it by sending special byte */if (reason == BT_HOST_REASON_SSR_CMD_TIMEDOUT ||reason == BT_HOST_REASON_SSR_SPURIOUS_WAKEUP ||reason == BT_HOST_REASON_SSR_INVALID_BYTES_RCVD ||reason == BT_HOST_REASON_SSR_UNABLE_TO_WAKEUP_SOC ||reason == BT_HOST_REASON_SSR_RCVD_LARGE_PKT_FROM_SOC ||reason == BT_HOST_REASON_SSR_INTERNAL_CMD_TIMEDOUT ||reason == BT_HOST_REASON_SSR_SLEEP_IND_NOT_RCVD ||reason == BT_HOST_REASON_INIT_FAILED ||reason == BT_HOST_REASON_RX_THREAD_STUCK ||reason == BT_HOST_REASON_FAILED_TO_SEND_INTERNAL_CMD) {/*4.1: 是否启用发送特殊字节- force_special_byte_enabled_ 控制是否启用“发送特殊字节”触发方式。- 如果已经在 dump,就不再触发。*/if (force_special_byte_enabled_ && !logger_->IsCrashDumpStarted()) {// 设置 flags(供之后流程使用), 描述当前属于哪种异常情况(如超时、非法数据包、唤醒失败等)。if (reason == BT_HOST_REASON_SSR_CMD_TIMEDOUT ||reason == BT_HOST_REASON_SSR_INTERNAL_CMD_TIMEDOUT) {if (!logger_->isThisFpissue())is_cmd_timeout = true;} else if (reason == BT_HOST_REASON_SSR_SPURIOUS_WAKEUP) {is_spurious_wake = true;} else if (reason == BT_HOST_REASON_SSR_INVALID_BYTES_RCVD ||reason == BT_HOST_REASON_SSR_RCVD_LARGE_PKT_FROM_SOC) {is_invalid_pkt_from_soc = true;} else if (reason == BT_HOST_REASON_SSR_UNABLE_TO_WAKEUP_SOC) {if (!logger_->isThisFpissue())is_soc_wakeup_failure = true;// 如果是 INIT 失败,执行专属处理逻辑, 初始化失败场景做了特别处理:} else if (reason == BT_HOST_REASON_INIT_FAILED) {// 标记“初始化期间崩溃”;logger_->host_crash_during_init = true;if (logger_->GetUartErrCode() == SOC_REASON_START_TX_IOS_SOC_RFR_HIGH) {ALOGD("%s: Converting SOC_REASON_START_TX_IOS_SOC_RFR_HIGH"" to SOC_REASON_START_TX_IOS_SOC_RFR_HIGH_DURING_INIT", __func__);logger_->SetUartErrCode(SOC_REASON_START_TX_IOS_SOC_RFR_HIGH_DURING_INIT);}// Checking delay list and set appropriate crash reason.// 检查 delay list(用于初始化 hang 检查);logger_->CheckDelayListAndSetCrashReason();// Send BQR RIE early as crash reason dont depend on FW dump for init stuck case.// 提前发送 RIE 报文(即 BQR - Root Inference Event)。SendBqrRiePacket();}// 设置 SSR trigger 状态, 设置全局状态,标志 SSR 已触发。BtState::Get()->SetSSRtrigger(true);/*若严重问题或可配置强制 crash,则触发 kernel panic.*/if (is_soc_wakeup_failure ||reason == BT_HOST_REASON_INIT_FAILED ||reason == BT_HOST_REASON_SSR_INVALID_BYTES_RCVD) { // 条件满足(如唤醒失败 + 系统配置允许)时:if(DataHandler::CheckSignalCaughtStatus() == false) {char value[PROPERTY_VALUE_MAX] = {'\0'};property_get("persist.vendor.service.bdroid.trigger_crash", value, "0");// call kernel panic so that all dumps are collectedif (strcmp(value, "1") == 0) {ALOGE("%s: Do kernel panic immediately as property \"trigger_crash\" set to %s",__func__, value);// Log all power srcs and UART flow ctrl statusLogPwrSrcsUartFlowCtrl();logger_->StoreCrashReason();logger_->PrepareDumpProcess();// Send BQR RIE before kernel panicSendBqrRiePacket();logger_->CollectDumps(true, true); // 触发后续 日志 dump// 执行 kernel panic(重启系统),确保 crash dump 被保存。// 通过 ioctl(/dev/btpower, 0xbfc1)if (bt_kernel_panic() == 0)return;elseALOGE("%s: Failed to do kernel panic", __func__);}}}ALOGD("%s: IsSoCCrashNotNeeded %d", __func__, IsSoCCrashNotNeeded(reason));// 判断是否无需 crash 控制器 SoC(或者是 FP issue)if (IsSoCCrashNotNeeded(reason) || logger_->isThisFpissue()) {// 如果这类问题不需要强制触发 SoC dump(或者厂商自定义某些 FP - false positive 情况),就只上报。ReportSocFailure(false, reason, true, false); // 本文 开头的 问题就会触发这里} else {// 否则真正触发 crash dump(根据芯片版本)// 根据芯片型号选择是否通过 NMI 触发 crash dump,或者使用传统方式发送特殊 buffer(唤醒控制器进入 dump 状态)。// Log all power srcs and UART flow ctrl statusLogPwrSrcsUartFlowCtrl();ALOGD("%s: SSR triggered due to %d sending special buffer", __func__, reason);if ((chipset_ver_ == HAMILTON_VER_2_0) ||(chipset_ver_ == 0 && soc_type_  == BT_SOC_HAMILTON)) {TriggerSocCrashdump(NMI_INTERRUPT_BYTE, reason);} else {SendSpecialBuffer(reason);}}} else if (!force_special_byte_enabled_) {// 如果未启用特殊字节发送,则直接走 fallback/*  Kill HIDL daemon for graceful recovery after SSR conditions are*  triggerred in USER builds, where vendor.wc_transport.force_special_byte* flag is set to false.*/ALOGD("%s: SSR triggered due to %d skip sending special buffer",__func__, reason);ReportSocFailure(false, reason, true, false);}} else {// 最后 fallback:没有在“特殊字节场景”内的普通 reason,直接清理Cleanup(); // 处理不是 SSR 类 reason,直接调用 Cleanup() 执行清理操作。}
}
功能点说明
SSR 防重入通过 SetSsrTriggeredFlag 防止重复处理
主/次原因记录使用 PrimaryReasonCode 和 UART 错误码标记崩溃
条件判断触发 crash dump根据崩溃类型选择是否发送特殊字节或触发 SoC crashdump
kernel panic 支持在必要条件下强制系统 panic 以收集完整日志
chip/版本差异支持根据芯片版本选择不同触发 dump 机制
默认清理流程其他普通 reason 直接清理不触发 dump

接下来我们着重,分析一下:

ReportSocFailure(false, reason, true, false);

3. UartController::ReportSocFailure

ReportSocFailure 用于当 BT SoC(蓝牙芯片)出现故障时,统一处理崩溃上报、资源清理、异常记录、进程终止等流程。它防止重复清理,处理特殊情况如 Rx 线程卡死、系统初始化时 crash、LMKD 影响调度等,并视情触发 kernel panic 或 bugreport。


void UartController::ReportSocFailure(bool dumped_uart_log, PrimaryReasonCode reason,bool cleanupSocCrashWaitTimer, bool cleanupIbs)
{// 三个 buffer 是 BT / FM / ANT 对应的 HCI H/W Error Event 报文。unsigned char bt_eve_buf[LENGTH_HW_ERROR_EVT] = { 0x10, 0x01, 0x0f };unsigned char fm_eve_buf[LENGTH_HW_ERROR_EVT] = { 0x1A, 0x01, 0x0f };unsigned char ant_eve_buf[LENGTH_HW_ERROR_EVT] = { 0x1C, 0x01, 0x0f };char count[PROPERTY_VALUE_MAX];static bool execution_count = false; // 防止重复处理,确保只清理一次。bool IsRxSchedDelay = false; // 表示是否因系统调度异常导致 Rx 卡住。bool kill_needed = false; // 用于标记是否要强制终止进程。// 防止多线程情况下重复执行崩溃流程。多见于 SoC Crash Timer 与主线程竞争触发的情况。   if (execution_count) {ALOGW("returing as other thread is in process of execution of %s", __func__);return;}actual_reason = reason;/* If Rx thread might have unblocked, stop closing BT. */if (reason == BT_HOST_REASON_RX_THREAD_STUCK) { // 判断是否为 Rx 卡死导致if (GetRxThreadTimerState() != TIMER_OVERFLOW andResetForceSsrTriggeredIfNoCleanup()) {// 如果 Rx 卡死问题已恢复(未超时 + 未触发强制 SSR),就不执行清理。ALOGI("%s: Rx thread unblocked returning back from cleanup", __func__);return;}long TsDiff = GetRxThreadSchedTSDiff();if (TsDiff > (RX_THREAD_USAGE_TIMEOUT + RX_THREAD_SCHEDULING_DELAY)) {// 如果线程调度被系统进程(如 LMKD)影响,设置 IsRxSchedDelay = trueIsRxSchedDelay = true;ALOGE("%s: Might be LMKD is running in background resulting RxThread Scheduling delay",__func__);}BtState ::Get()->UpdateBqrRieErrCodeAndErrString(reason,std::string(logger_->GetPrimaryReasonString(reason)));}execution_count = true;ALOGD("%s: reason %d", __func__, reason);/* Dont save crash reason here for host crashes during init.* Crash reason is stored at beggining when init timeout is detected.*/// 记录 crash 原因和系统延迟处理if (logger_->host_crash_during_init == false) { // 区分初始化期间 crash 和正常运行时 crash。logger_->StoreCrashReason();// Add Delay list info. in state file object.logger_->AddDelayListInfo();} else {// 系统初始化时 crash,检查是否系统运行缓慢导致property_get("persist.vendor.service.bdroid.system_delay_crash_count", count, "0");int trials = atoi(count);/* Incase of system delay issue, kill only upto certain max continuous count.* Check if init stuck happened because of system running slow, if yes then set kill flag.*/if (trials < MAX_CONTINUOUS_SYSTEM_DELAY_CRASH_COUNT &&!logger_->CheckActivityCodeForCrashCmd(logger_->GetSecondaryCrashReasonCode())) {kill_needed = true;trials++;// 初始化时若是系统延迟造成,统计 crash 次数,property_set("persist.vendor.service.bdroid.system_delay_crash_count", std::to_string(trials).c_str());} else {// 超过阈值就不上报。ALOGE("%s: System delay crash count %d", __func__, trials);property_set("persist.vendor.service.bdroid.system_delay_crash_count", "0");}}// 判断是否是 fingerprint (FP) issueif (logger_->isThisFpissue())kill_needed = true; // 特定条件下系统判定为 FP 问题(可能是硬件),设置为需要 kill。/* No point in sending the HW error event to stack if crash* is due to Rx thread stuck.*/// 向 BT/FM/ANT 层发送错误事件if (read_cb_ && reason != BT_HOST_REASON_RX_THREAD_STUCK) {hidl_vec<uint8_t> *bt_packet_ = new hidl_vec<uint8_t>;hidl_vec<uint8_t> *fm_packet_ = new hidl_vec<uint8_t>;hidl_vec<uint8_t> *ant_packet_ = new hidl_vec<uint8_t>;fm_packet_->resize(LENGTH_HW_ERROR_EVT);ant_packet_->resize(LENGTH_HW_ERROR_EVT);bt_packet_->resize(LENGTH_HW_ERROR_EVT);/* For BT Client only */SendCrashPacket(); // BT 客户端 crash 包// Dont send BQR RIE here as we already sent it before for init stuck cases.if (logger_->host_crash_during_init == false)SendBqrRiePacket(); // 附加错误报告(非 init)ALOGD("%s send H/W error event to FM/ANT/BT client", __func__);memcpy(fm_packet_->data(), fm_eve_buf, LENGTH_HW_ERROR_EVT);// BT/FM/ANT 三个通道都会发送 H/W 错误事件。如果是 Rx 卡死就不发送,避免误报。read_cb_(GetProtocol(HCI_PACKET_TYPE_FM_EVENT), HCI_PACKET_TYPE_FM_EVENT, fm_packet_);memcpy(ant_packet_->data(), ant_eve_buf, LENGTH_HW_ERROR_EVT);read_cb_(GetProtocol(HCI_PACKET_TYPE_ANT_CTRL), HCI_PACKET_TYPE_ANT_CTRL, ant_packet_);memcpy(bt_packet_->data(), bt_eve_buf, LENGTH_HW_ERROR_EVT);read_cb_(GetProtocol(HCI_PACKET_TYPE_EVENT), HCI_PACKET_TYPE_EVENT, bt_packet_);}// 停止接收线程, 停止读取数据线程,防止后续访问失效资源。fd_watcher_.StopThreadRoutine();/* Don't perform Cleanup of SocCrashTimeout if ReportSoC Failure is* triggerred from SocCrashWaitTimeout, which would stall* cleanup progress. Subsequent abort/kill will take* care of freeing IBS resources.*/// 清理 SoC Crash 超时计时器, 防止 SoC Crash Timer 在清理中重复触发。if (cleanupSocCrashWaitTimer) {ALOGD("%s calling CleanupSocCrashWaitTimer", __func__);CleanupSocCrashWaitTimer();}// Get current thread id.std::thread::id current_thread_id = std::this_thread::get_id();/* Killing init thread if it is not current thread inorder* to prevent ASAN issues that might occur if init thread get unstuck* and try to access freed resources.*/// 避免 Init 线程与当前线程并发执行清理if (current_thread_id != DataHandler::Get()->GetInitThreadId()) {DataHandler::Get()->KillInitThread(); // 如果当前线程不是 init 线程,则主动 kill init 线程,防止其恢复执行访问已释放资源(防 ASAN 报错)。}// 清理 HCI 传输资源, 释放 HCI 通道传输资源。HciTransportCleanup();/* stack_timeout_triggered stands true during cleanup* timeouts in stack. These timeouts may block HIDL* Rx thread. No point in logging the dumps in those* cases. Also if force reboot happened then also no need* to dump logs as issue might be false positive & caused* by force reboot.*/// 判断是否需要 dump, if ((reason == BT_HOST_REASON_RX_THREAD_STUCK &&(logger_->stack_timeout_triggered || IsRxSchedDelay)) ||DataHandler::CheckSignalCaughtStatus() || kill_needed) {// 某些情况下不会 dump(如 Rx 卡死或已捕捉信号)。ALOGW("%s: not logging dumps as timeout triggered in stack or force reboot happened or System running slow",__func__);  // 不 dump(堆栈 timeout、强制中断等情况)} else if (!dumped_uart_log) {// 触发 dump 收集。logger_->PrepareDumpProcess();logger_->CollectDumps(true, true);
#ifdef ENABLE_HEALTH_TIMERhealth_info->ReportHealthInfo();
#endif} else {// 触发 dump 收集。logger_->CollectDumps(false, true);}// 等待 bugreport 收集日志完成if (Logger::is_bugreport_triggered_during_crash_dump) {pthread_mutex_lock(&Logger::crash_dump_lock);ALOGE("%s: now signal and wait for max. 1 sec for bugreport debug method to collect logs",__func__);pthread_cond_signal(&Logger::crash_dump_cond);pthread_mutex_unlock(&Logger::crash_dump_lock);std::unique_lock<std::mutex> guard(Logger::bugreport_wait_mutex);// 协调 bugreport 机制等待 crash dump 收集完成,最多等待 1 秒。Logger::bugreport_wait_cv.wait_for(guard, std::chrono::milliseconds(BUGREPORT_WAIT_TIME),[]{return !(Logger::is_bugreport_triggered);});} else if (Logger::is_bugreport_triggered) {ALOGE("%s:  waiting for max. 1 sec for bugreport to collect logs", __func__);std::unique_lock<std::mutex> guard(Logger::bugreport_wait_mutex);Logger::bugreport_wait_cv.wait_for(guard, std::chrono::milliseconds(BUGREPORT_WAIT_TIME),[]{return !(Logger::is_bugreport_triggered);});}if(DataHandler::CheckSignalCaughtStatus() == false) {char value[PROPERTY_VALUE_MAX] = {'\0'};property_get("persist.vendor.service.bdroid.trigger_crash", value, "0");/* 满足以下条件时触发 kernel panic:- property "persist.vendor.service.bdroid.trigger_crash" == "2"- 且 reason 是超时/唤醒失败等严重错误- 且 SSR 等级允许*/if (strcmp(value, "2") == 0) {ALOGE("%s: \"trigger_crash\" property set to %s",__func__, value);/* Do kernel panic in case of cmd timeout/unable to wake up SoC* along with unable collect SoC crash dump partially or* completely when ssr level set to 1 or 2.*/if (reason == BT_HOST_REASON_SOC_WAKEUP_FAILED_SOC_WAIT_TIMEOUT|| reason == BT_HOST_REASON_CMD_TIMEDOUT_SOC_WAIT_TIMEOUT ||(force_special_byte_enabled_ &&(reason == BT_HOST_REASON_SSR_CMD_TIMEDOUT ||((reason == BT_HOST_REASON_SSR_UNABLE_TO_WAKEUP_SOC) &&!logger_->isThisFpissue())))) {int ssr_level = logger_->ReadSsrLevel();// call kernel panic so that all dumps are collectedif (ssr_level == 1 || ssr_level == 2) {ALOGE("%s: Do kernel panic", __func__);if (bt_kernel_panic() < 0) {ALOGE("%s: Failed to do kernel panic", __func__);}}}}}/* If SSR is triggered due close sequence failure.* There could be a chance of power leakage if any of the* clients are not starting immediately.*/// 关闭 SoC 电源并清理电源管理器, 确保 SoC 电源被关闭,并清理可能的资源泄露。power_manager_.SetPower(false);power_manager_.Cleanup();ALOGE("Killing daemon as SSR is completed!");kill(getpid(), SIGKILL); // 强制终止当前 daemon 进程,防止异常遗留。}
模块作用
多线程保护防止多次执行 SSR
Rx 卡死判断系统调度异常分析与处理
dump 控制视情况收集日志与触发 kernel panic
属性机制控制是否 kill、是否 panic
清理资源包括 HCI、线程、power manager 等
bugreport 协同等待 debug 工具收集 dump
最终 SIGKILL强制退出,触发外层 watchdog 重启

4. Logger::CollectDumps

该函数用于在蓝牙崩溃或异常时,按需收集不同类型的调试信息,包括:

  • UART 日志

  • IPC 通信日志(仅非 SMD SoC 且开启)

  • RingBuffer 日志(按属性判断)

  • 蓝牙状态日志

收集行为受两个布尔参数控制,也可通过 persist.vendor.service.bdroid.* 属性控制启用项。


void Logger::CollectDumps(bool is_uart_ipc_enabled, bool is_state_log_enabled) {// 使用递归互斥锁保护 bugreport 日志收集过程,防止并发冲突或多线程重复 dump。std::unique_lock<std::recursive_mutex> guard(bugreport_mutex);int dump_uart_logs = DUMP_FTRACE_AND_IPC_LOGS; // 设置默认收集类型为全部(FTRACE + IPC)/*获取属性配置 dump_uartlogs- "0" → 不收集- "1" → 仅 FTRACE- "2" → 仅 IPC- "3" → 全部(默认)*/char value[PROPERTY_VALUE_MAX] = "false";property_get("persist.vendor.service.bdroid.dump_uartlogs", value, "3");dump_uart_logs = atoi(value); // 字符串转整数后存入 dump_uart_logs{DataHandler *data_handler = DataHandler::Get();if (is_uart_ipc_enabled && data_handler&& data_handler->GetSocType() != BT_SOC_SMD) {
#ifdef DUMP_IPC_LOGif (dump_uart_logs == DUMP_IPC_LOGS || dump_uart_logs == DUMP_FTRACE_AND_IPC_LOGS)DumpUartIpcLogs(); // 若属性值为 `2` 或 `3`,执行 IPC 日志收集。
#endifif (dump_uart_logs == DUMP_FTRACE_LOGS || dump_uart_logs == DUMP_FTRACE_AND_IPC_LOGS)DumpUartLogs(); // 如果配置值为 `1`(仅 FTRACE)或 `3`(全部),执行 UART log 收集。 是关键 UART 调试信息收集接口。}}#ifdef DUMP_RINGBUF_LOG{//Dumping the ring buffer logs based on property for debugging purposechar value[PROPERTY_VALUE_MAX] = "false";if (!is_uart_ipc_enabled)PropertyGet("persist.vendor.service.bdroid.dump_ringbuff", value, "false");if (is_uart_ipc_enabled || (strcmp(value, "true") == 0))DumpRingBuffers(); // 通常用于低层通信 trace。}
#endifif (is_state_log_enabled)//Dump last BT states of transport driverBtState :: Get()->DumpBtState(); // 主要用于记录最近的蓝牙状态机事件(如上电、断电、crash 状态等),可帮助分析系统行为。
}

接下来我们重点介绍:


DumpRingBuffers();BtState :: Get()->DumpBtState();

1. DumpRingBuffers

RingBuffer snoop_buff_;void DumpRingBuffers(void) {snoop_buff_.DumpData();};

RingBuffer::DumpData() 主要用于:

  1. 打印和记录蓝牙栈关键事件的时间戳(如 HCI cmd、ACL、ISO、select 调用)。

  2. 将这些信息保存在 BtState 中供崩溃分析。

  3. 打印出详细的日志用于日志系统抓取。

  4. 最后调用 snoop_.DumpData() 输出缓冲区中的通信内容。

前置知识:

  • BtState::Get()->SetXXX(...):设置最后的状态信息。
  • AddRxTagEvent():将给定的 time_t 时间转为人类可读字符串并保存到 tag 中。
  • snoop_RingBuffer 内部的 ring buffer 日志对象,负责保存历史通信日志。

void RingBuffer::DumpData()
{char dst_buff[MAX_BUFF_SIZE] = {'\0'}; // 通用字符串缓冲区,用于格式化所有日志信息。char tag_event_call_back[RX_TAG_STR_LEN]; // 用于存储转换后的时间戳字符串。ALOGD("%s", __func__);std::unique_lock<std::mutex> guard(snoop_ring_buffer_mutex_);// 记录“最后一条发送到 Controller 的 HCI 命令”。snprintf(dst_buff, MAX_BUFF_SIZE, "TS and last HCI cmd from stack = %s", last_hci_cmd);BtState :: Get()->SetLastHciCmdStack(dst_buff); // 保存到 BtState 状态系统中(供上层 bugreport 抓取)。ALOGE("%s", dst_buff); // 打印到 logcat。// 记录事件:事件准备推送至 Stack 之前的时间AddRxTagEvent(tag_event_call_back, time_pre_stack_event_call_back);snprintf(dst_buff, MAX_BUFF_SIZE, "TS of posting event to stack %s", tag_event_call_back);BtState::Get()->SetPreStackEvent(dst_buff);ALOGE("%s", dst_buff);// 事件推送到 stack 后的时间, 比对 pre/post 可分析 event dispatch 延迟。AddRxTagEvent(tag_event_call_back, time_post_stack_event_call_back);snprintf(dst_buff, MAX_BUFF_SIZE, "TS of event posted to stack %s", tag_event_call_back);BtState::Get()->SetPostStackEvent(dst_buff);ALOGE("%s", dst_buff);// 准备发送 ACL 到 stack 前的时间戳AddRxTagEvent(tag_event_call_back,time_pre_stack_acl_call_back);snprintf(dst_buff, MAX_BUFF_SIZE, "TS of posting ACL packet to stack %s", tag_event_call_back);BtState::Get()->SetPreStackAcl(dst_buff);ALOGE("%s", dst_buff);// ACL 包已发送后的时间戳, 可帮助定位 ACL 通信延迟或堵塞点。AddRxTagEvent(tag_event_call_back, time_post_stack_acl_call_back);snprintf(dst_buff, MAX_BUFF_SIZE, "TS of ACL packet posted to stack %s", tag_event_call_back);BtState::Get()->SetPostStackAcl(dst_buff);ALOGE("%s", dst_buff);// ISO 包准备发送前AddRxTagEvent(tag_event_call_back,time_pre_stack_iso_call_back);snprintf(dst_buff, MAX_BUFF_SIZE, "TS of posting ISO packet to stack %s", tag_event_call_back);BtState::Get()->SetPreStackIso(dst_buff);ALOGE("%s", dst_buff);// ISO 包发送后AddRxTagEvent(tag_event_call_back, time_post_stack_iso_call_back);snprintf(dst_buff, MAX_BUFF_SIZE, "TS of ISO packet posted to stack %s", tag_event_call_back);BtState::Get()->SetPostStackIso(dst_buff);ALOGE("%s", dst_buff);// select() 调用前(监听 socket IO): 表示即将调用 select 等待蓝牙 socket。AddRxTagEvent(tag_event_call_back, time_pre_select_call_back);snprintf(dst_buff, MAX_BUFF_SIZE, "TS of pre select %s", tag_event_call_back);BtState::Get()->SetPreSelect(dst_buff);ALOGE("%s", dst_buff);// select() 返回后: 可结合前一条日志分析线程等待耗时,判断是否卡在 IO。AddRxTagEvent(tag_event_call_back, time_post_select_call_back);snprintf(dst_buff, MAX_BUFF_SIZE, "TS of post select %s", tag_event_call_back);BtState::Get()->SetPostSelect(dst_buff);ALOGE("%s", dst_buff);// 最后:dump ring buffer 的原始数据// 调用内部 snoop_ 环形缓冲区的 DumpData(),通常会把 Controller 通信记录导出供分析。// 数据格式为十六进制串或协议日志(如 HCI 包头等)。snoop_.DumpData();
}

这些日志在调试蓝牙异常如“配对失败”、“音频卡顿”、“蓝牙通信丢包”时非常关键,可以:

  • 定位发送指令栈响应延迟
  • 排查socket select 卡顿时间点
  • 对比 pre/post 时间判断执行耗时瓶颈
  • 利用 snoop_ 提取底层通信轨迹

2. BtState::DumpBtState

它的主要职责是将当前 Bluetooth 状态记录(尤其是崩溃相关信息)写入文件中,供后续分析使用

这个函数的主要作用是:

  • 收集 Bluetooth 崩溃与行为记录
  • 写入标准格式的状态 dump 文件(供 QA 或开发人员分析)
  • 记录时间戳、patch 加载路径、线程状态、BQR 信息等

void BtState::DumpBtState() {int fd;char file_name[BT_FILE_NAME_LEN];char hex_buff[3] = "";char dst_buff[MAX_BUFF_SIZE] = {'\0'};int j =0;int ssrlvl;#ifndef DONT_DELETE_DUMPS_SETDeleteDumpsIfRequired();
#endif/* Get the exact time stamp of close */Logger* logger = Logger::Get();logger->GetStateFileName(file_name);ssrlvl = logger->ReadSsrLevel();fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH);if (fd < 0) {ALOGE("%s: File open (%s) failed: errno: %d", __func__, file_name, errno);return;}ALOGD("%s: Dumping stats into %s", __func__, file_name);ALOGD("%s", stat_info_obj.pri_crash_reason);write(fd, stat_info_obj.pri_crash_reason, strlen(stat_info_obj.pri_crash_reason));write(fd, " \n", 2);ALOGD("%s",stat_info_obj.sec_crash_reason);write(fd, stat_info_obj.sec_crash_reason, strlen(stat_info_obj.sec_crash_reason));write(fd, " \n", 2);ALOGD("%s",stat_info_obj.bqr_rie_info);write(fd, stat_info_obj.bqr_rie_info, strlen(stat_info_obj.bqr_rie_info));if (stat_info_obj.bqr_rie_vs_params.length()) {write(fd, " \n", 2);ALOGD("%s",stat_info_obj.bqr_rie_vs_params.c_str());write(fd, stat_info_obj.bqr_rie_vs_params.c_str(), stat_info_obj.bqr_rie_vs_params.length());}write(fd, " \n", 2);ALOGD("%s",stat_info_obj.crash_ts);write(fd, stat_info_obj.crash_ts, strlen(stat_info_obj.crash_ts));ALOGD("%s ", stat_info_obj.kernel_time);write(fd, stat_info_obj.kernel_time, strlen(stat_info_obj.kernel_time));SetAlwaysOnEnabled();write(fd, " \n", 2);ALOGD("%s ", stat_info_obj.alwayson_status);write(fd, stat_info_obj.alwayson_status, strlen(stat_info_obj.alwayson_status));snprintf(dst_buff, sizeof(dst_buff), "SSR LVL = %d", ssrlvl);write(fd, " \n", 2);ALOGD("SSR LVL = %d", ssrlvl);write(fd, dst_buff, strlen(dst_buff));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_hci_initialize);write(fd, stat_info_obj.ts_hci_initialize, strlen(stat_info_obj.ts_hci_initialize));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_sibs_property_read);write(fd, stat_info_obj.pre_sibs_property_read, strlen(stat_info_obj.pre_sibs_property_read));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_sibs_property_read);write(fd, stat_info_obj.post_sibs_property_read, strlen(stat_info_obj.post_sibs_property_read));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_hci_close);write(fd, stat_info_obj.ts_hci_close, strlen(stat_info_obj.ts_hci_close));if (soc_need_reload_patch) {write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_local_addr);write(fd, stat_info_obj.pre_local_addr,strlen(stat_info_obj.pre_local_addr));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_local_addr);write(fd, stat_info_obj.post_local_addr, strlen(stat_info_obj.post_local_addr));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_fetch_vendor_addr);write(fd, stat_info_obj.pre_fetch_vendor_addr,strlen(stat_info_obj.pre_fetch_vendor_addr));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_fetch_vendor_addr);write(fd, stat_info_obj.post_fetch_vendor_addr,strlen(stat_info_obj.post_fetch_vendor_addr));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_getver_start_send_cmd);write(fd, stat_info_obj.ts_getver_start_send_cmd,strlen(stat_info_obj.ts_getver_start_send_cmd));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_getver_start_read_rsp);write(fd, stat_info_obj.ts_getver_start_read_rsp,strlen(stat_info_obj.ts_getver_start_read_rsp));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_version_info);write(fd, stat_info_obj.pre_version_info,strlen(stat_info_obj.pre_version_info));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_version_info);write(fd, stat_info_obj.post_version_info, strlen(stat_info_obj.post_version_info));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_getver_rcvd);write(fd, stat_info_obj.ts_getver_rcvd, strlen(stat_info_obj.ts_getver_rcvd));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_chk_patch_path);write(fd, stat_info_obj.pre_chk_patch_path,strlen(stat_info_obj.pre_chk_patch_path));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_chk_patch_path);write(fd, stat_info_obj.post_chk_patch_path, strlen(stat_info_obj.post_chk_patch_path));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_patch_open);write(fd, stat_info_obj.pre_patch_open,strlen(stat_info_obj.pre_patch_open));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_patch_open);write(fd, stat_info_obj.post_patch_open, strlen(stat_info_obj.post_patch_open));if (stat_info_obj.is_xmem_enabled) {write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_xmem_patch_open);write(fd, stat_info_obj.pre_xmem_patch_open,strlen(stat_info_obj.pre_xmem_patch_open));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_xmem_patch_open);write(fd, stat_info_obj.post_xmem_patch_open, strlen(stat_info_obj.post_xmem_patch_open));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_xmem_nvm_open);write(fd, stat_info_obj.pre_xmem_nvm_open,strlen(stat_info_obj.pre_xmem_nvm_open));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_xmem_nvm_open);write(fd, stat_info_obj.post_xmem_nvm_open, strlen(stat_info_obj.post_xmem_nvm_open));}write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_nvm_open);write(fd, stat_info_obj.pre_nvm_open,strlen(stat_info_obj.pre_nvm_open));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_nvm_open);write(fd, stat_info_obj.post_nvm_open, strlen(stat_info_obj.post_nvm_open));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_tcs_config);write(fd, stat_info_obj.pre_tcs_config, strlen(stat_info_obj.pre_tcs_config));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_tcs_config);write(fd, stat_info_obj.post_tcs_config, strlen(stat_info_obj.post_tcs_config));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_su_build_info);write(fd, stat_info_obj.pre_su_build_info,strlen(stat_info_obj.pre_su_build_info));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_su_build_info);write(fd, stat_info_obj.post_su_build_info, strlen(stat_info_obj.post_su_build_info));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.fw_dwnld_success);write(fd, stat_info_obj.fw_dwnld_success, strlen(stat_info_obj.fw_dwnld_success));write(fd, " \n", 2);char tmp_buf[128];add_time_str(tmp_buf, &stat_info_obj.fw_su_build_info_set_time);snprintf(tmp_buf + strlen(tmp_buf), sizeof(tmp_buf), " %s", stat_info_obj.fw_su_build_info);ALOGD("%s", tmp_buf);write(fd, tmp_buf, strlen(tmp_buf));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.otp_info_bytes);write(fd, stat_info_obj.otp_info_bytes, strlen(stat_info_obj.otp_info_bytes));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.bt_soc_id);write(fd, stat_info_obj.bt_soc_id, strlen(stat_info_obj.bt_soc_id));}write(fd, " \n", 2);ALOGD("%s", stat_info_obj.power_resources_state);write(fd, stat_info_obj.power_resources_state,strlen(stat_info_obj.power_resources_state));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.bt_uart_cts);write(fd, stat_info_obj.bt_uart_cts,strlen(stat_info_obj.bt_uart_cts));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.read_thread_start);write(fd, stat_info_obj.read_thread_start, strlen(stat_info_obj.read_thread_start));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.status_read_thread);write(fd, stat_info_obj.status_read_thread, strlen(stat_info_obj.status_read_thread));write(fd, " \n", 2);ALOGD("%s ", stat_info_obj.pre_diag_init_ts);write(fd, stat_info_obj.pre_diag_init_ts, strlen(stat_info_obj.pre_diag_init_ts));write(fd, " \n", 2);ALOGD("%s ", stat_info_obj.post_diag_init_ts);write(fd, stat_info_obj.post_diag_init_ts, strlen(stat_info_obj.post_diag_init_ts));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_status_diag_init);write(fd, stat_info_obj.ts_status_diag_init, strlen(stat_info_obj.ts_status_diag_init));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_status_ctrlr_init);write(fd, stat_info_obj.ts_status_ctrlr_init, strlen(stat_info_obj.ts_status_ctrlr_init));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_status_init_cb_sent);write(fd, stat_info_obj.ts_status_init_cb_sent, strlen(stat_info_obj.ts_status_init_cb_sent));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_uart_flow_on);write(fd, stat_info_obj.ts_uart_flow_on, strlen(stat_info_obj.ts_uart_flow_on));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_uart_flow_off);write(fd, stat_info_obj.ts_uart_flow_off, strlen(stat_info_obj.ts_uart_flow_off));write(fd, " \n", 2);ALOGD("%s ", stat_info_obj.pre_diag_deinit_ts);write(fd, stat_info_obj.pre_diag_deinit_ts, strlen(stat_info_obj.pre_diag_deinit_ts));write(fd, " \n", 2);ALOGD("%s ", stat_info_obj.post_diag_deinit_ts);write(fd, stat_info_obj.post_diag_deinit_ts, strlen(stat_info_obj.post_diag_deinit_ts));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.health_timer_status);write(fd, stat_info_obj.health_timer_status, strlen(stat_info_obj.health_timer_status));write(fd, " \n", 2);HealthInfoLog::Get()->ReportHealthInfo();ALOGD("%s", stat_info_obj.last_health_stat_info);write(fd, stat_info_obj.last_health_stat_info, strlen(stat_info_obj.last_health_stat_info));write(fd, " \n", 2);ALOGD("%s ", stat_info_obj.ts_hci_internal_cmd);write(fd, stat_info_obj.ts_hci_internal_cmd, strlen(stat_info_obj.ts_hci_internal_cmd));write(fd, " \n", 2);ALOGD("%s ", stat_info_obj.ts_hci_internal_rsp);write(fd, stat_info_obj.ts_hci_internal_rsp, strlen(stat_info_obj.ts_hci_internal_rsp));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.last_hci_cmd_stack);write(fd, stat_info_obj.last_hci_cmd_stack, strlen(stat_info_obj.last_hci_cmd_stack));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_last_seq_number);write(fd, stat_info_obj.ts_last_seq_number, strlen(stat_info_obj.ts_last_seq_number));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.last_wk_ind_from_host);write(fd, stat_info_obj.last_wk_ind_from_host, strlen(stat_info_obj.last_wk_ind_from_host));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.last_wk_ack_from_soc);write(fd, stat_info_obj.last_wk_ack_from_soc, strlen(stat_info_obj.last_wk_ack_from_soc));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.last_wk_ind_from_soc);write(fd, stat_info_obj.last_wk_ind_from_soc, strlen(stat_info_obj.last_wk_ind_from_soc));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.last_wk_ack_from_host);write(fd, stat_info_obj.last_wk_ack_from_host, strlen(stat_info_obj.last_wk_ack_from_host));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.last_sleep_ind_from_host);write(fd, stat_info_obj.last_sleep_ind_from_host, strlen(stat_info_obj.last_sleep_ind_from_host));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.last_sleep_ind_from_soc);write(fd, stat_info_obj.last_sleep_ind_from_soc, strlen(stat_info_obj.last_sleep_ind_from_soc));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_stack_event);write(fd, stat_info_obj.pre_stack_event, strlen(stat_info_obj.pre_stack_event));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_stack_event);write(fd, stat_info_obj.post_stack_event, strlen(stat_info_obj.post_stack_event));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_stack_acl);write(fd, stat_info_obj.pre_stack_acl, strlen(stat_info_obj.pre_stack_acl));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_stack_acl);write(fd, stat_info_obj.post_stack_acl, strlen(stat_info_obj.post_stack_acl));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_stack_iso);write(fd, stat_info_obj.pre_stack_iso, strlen(stat_info_obj.pre_stack_iso));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_stack_iso);write(fd, stat_info_obj.post_stack_iso, strlen(stat_info_obj.post_stack_iso));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_select);write(fd, stat_info_obj.pre_select, strlen(stat_info_obj.pre_select));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_select);write(fd, stat_info_obj.post_select, strlen(stat_info_obj.post_select));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_uart_clock_on);write(fd, stat_info_obj.ts_uart_clock_on, strlen(stat_info_obj.ts_uart_clock_on));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.ts_uart_clock_off);write(fd, stat_info_obj.ts_uart_clock_off, strlen(stat_info_obj.ts_uart_clock_off));//last Tx packetwrite(fd, " \n", 2);ALOGD("%s", stat_info_obj.last_tx_pkt_ts);write(fd, stat_info_obj.last_tx_pkt_ts, strlen(stat_info_obj.last_tx_pkt_ts));{j =0;memset(hex_buff, '\0', 3);for (int i = 0; i < stat_info_obj.last_tx_pkt_len; i++) {snprintf(hex_buff, 3, "%.2X ", stat_info_obj.last_tx_pkt_asc[i]);stat_info_obj.last_tx_pkt_hex[j++] = hex_buff[0];stat_info_obj.last_tx_pkt_hex[j++] = hex_buff[1];stat_info_obj.last_tx_pkt_hex[j++] = 32;}stat_info_obj.last_tx_pkt_hex [j] = '\0';write(fd, " \n", 2);write(fd, stat_info_obj.last_tx_pkt_hex, strlen(stat_info_obj.last_tx_pkt_hex));ALOGD("%s", stat_info_obj.last_tx_pkt_hex);snprintf(dst_buff, sizeof(dst_buff), "Actual last TX pkt len = %d",stat_info_obj.actual_tx_pkt_len);write(fd, " \n", 2);write(fd, dst_buff, strlen(dst_buff));ALOGD("Actual last TX pkt len: %d", stat_info_obj.actual_tx_pkt_len);}//last Rx packet before SSRwrite(fd, " \n", 2);ALOGD("%s", stat_info_obj.ssr_rx_pkt_ts);write(fd, stat_info_obj.ssr_rx_pkt_ts, strlen(stat_info_obj.ssr_rx_pkt_ts));{j =0;memset(hex_buff, '\0', 3);for (int i = 0; i < stat_info_obj.ssr_rx_pkt_len; i++) {snprintf(hex_buff, 3, "%.2X ", stat_info_obj.ssr_rx_pkt_asc[i]);stat_info_obj.ssr_rx_pkt_hex[j++] = hex_buff[0];stat_info_obj.ssr_rx_pkt_hex[j++] = hex_buff[1];stat_info_obj.ssr_rx_pkt_hex[j++] = 32;}stat_info_obj.ssr_rx_pkt_hex [j] = '\0';write(fd, " \n", 2);write(fd, stat_info_obj.ssr_rx_pkt_hex, strlen(stat_info_obj.ssr_rx_pkt_hex));ALOGD("%s", stat_info_obj.ssr_rx_pkt_hex);memset(dst_buff, '\0', MAX_BUFF_SIZE);snprintf(dst_buff, sizeof(dst_buff), "Actual RX pkt len before SSR = %d",stat_info_obj.actual_ssr_rx_pkt_len);write(fd, " \n", 2);write(fd, dst_buff, strlen(dst_buff));ALOGD("Actual RX pkt len before SSR: %d", stat_info_obj.actual_ssr_rx_pkt_len);}//last Rx packetwrite(fd, " \n", 2);ALOGD("%s", stat_info_obj.last_rx_pkt_ts);write(fd, stat_info_obj.last_rx_pkt_ts, strlen(stat_info_obj.last_rx_pkt_ts));{j =0;memset(hex_buff, '\0', 3);for (int i = 0; i < stat_info_obj.last_rx_pkt_len && i < TX_RX_PKT_ASC_SIZE; i++) {snprintf(hex_buff, 3, "%.2X ", stat_info_obj.last_rx_pkt_asc[i]);stat_info_obj.last_rx_pkt_hex[j++] = hex_buff[0];stat_info_obj.last_rx_pkt_hex[j++] = hex_buff[1];stat_info_obj.last_rx_pkt_hex[j++] = 32;}stat_info_obj.last_rx_pkt_hex [j] = '\0';write(fd, " \n", 2);write(fd, stat_info_obj.last_rx_pkt_hex, strlen(stat_info_obj.last_rx_pkt_hex));ALOGD("%s", stat_info_obj.last_rx_pkt_hex);memset(dst_buff, '\0', MAX_BUFF_SIZE);snprintf(dst_buff, sizeof(dst_buff), "Actual last RX pkt len = %d",stat_info_obj.actual_rx_pkt_len);write(fd, " \n", 2);write(fd, dst_buff, strlen(dst_buff));ALOGD("Actual last RX pkt len: %d", stat_info_obj.actual_rx_pkt_len);}// Invalid packetif (stat_info_obj.inv_bytes_len) {write(fd, " \n", 2);ALOGD("%s", stat_info_obj.inv_bytes_ts);write(fd, stat_info_obj.inv_bytes_ts, strlen(stat_info_obj.inv_bytes_ts));{j = 0;memset(hex_buff, '\0', 3);for (int i = 0; i < stat_info_obj.inv_bytes_len && i < TX_RX_PKT_ASC_SIZE; i++) {snprintf(hex_buff, 3, "%.2X ", stat_info_obj.inv_bytes_asc[i]);stat_info_obj.inv_bytes_hex[j++] = hex_buff[0];stat_info_obj.inv_bytes_hex[j++] = hex_buff[1];stat_info_obj.inv_bytes_hex[j++] = 32;}stat_info_obj.inv_bytes_hex[j] = '\0';write(fd, " \n", 2);write(fd, stat_info_obj.inv_bytes_hex, strlen(stat_info_obj.inv_bytes_hex));ALOGD("%s", stat_info_obj.inv_bytes_hex);snprintf(dst_buff, sizeof(dst_buff), "Num Invalid Bytes = %d",stat_info_obj.inv_bytes_len);write(fd, " \n", 2);write(fd, dst_buff, strlen(dst_buff));ALOGD("Num Invalid Bytes: %d", stat_info_obj.inv_bytes_len);}}#ifdef DIAG_ENABLEDif (logger->GetDiagInitStatus() && logger->IsSnoopLogEnabled()) {write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_diag_rx_acl);write(fd, stat_info_obj.pre_diag_rx_acl, strlen(stat_info_obj.pre_diag_rx_acl));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_diag_rx_acl);write(fd, stat_info_obj.post_diag_rx_acl, strlen(stat_info_obj.post_diag_rx_acl));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_diag_rx_hci);write(fd, stat_info_obj.pre_diag_rx_hci, strlen(stat_info_obj.pre_diag_rx_hci));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_diag_rx_hci);write(fd, stat_info_obj.post_diag_rx_hci, strlen(stat_info_obj.post_diag_rx_hci));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_diag_tx_acl);write(fd, stat_info_obj.pre_diag_tx_acl, strlen(stat_info_obj.pre_diag_tx_acl));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_diag_tx_acl);write(fd, stat_info_obj.post_diag_tx_acl, strlen(stat_info_obj.post_diag_tx_acl));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pre_diag_tx_hci);write(fd, stat_info_obj.pre_diag_tx_hci, strlen(stat_info_obj.pre_diag_tx_hci));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.post_diag_tx_hci);write(fd, stat_info_obj.post_diag_tx_hci, strlen(stat_info_obj.post_diag_tx_hci));snprintf(dst_buff, sizeof(dst_buff), "Max diag ACL RX logging delay = %d",stat_info_obj.max_diag_rx_acl_delay);write(fd, " \n", 2);ALOGD("Max diag ACL RX delay = %d", stat_info_obj.max_diag_rx_acl_delay);write(fd, dst_buff, strlen(dst_buff));snprintf(dst_buff, sizeof(dst_buff), "Max diag HCI RX logging delay = %d",stat_info_obj.max_diag_rx_hci_delay);write(fd, " \n", 2);ALOGD("Max diag HCI RX delay = %d", stat_info_obj.max_diag_rx_hci_delay);write(fd, dst_buff, strlen(dst_buff));snprintf(dst_buff, sizeof(dst_buff), "Max diag ACL TX logging delay = %d",stat_info_obj.max_diag_tx_acl_delay);write(fd, " \n", 2);ALOGD("Max diag ACL TX delay = %d", stat_info_obj.max_diag_tx_acl_delay);write(fd, dst_buff, strlen(dst_buff));snprintf(dst_buff, sizeof(dst_buff), "Max diag HCI TX logging delay = %d",stat_info_obj.max_diag_tx_hci_delay);write(fd, " \n", 2);ALOGD("Max diag HCI TX delay = %d", stat_info_obj.max_diag_tx_hci_delay);write(fd, dst_buff, strlen(dst_buff));}
#endifwrite(fd, " \n", 2);ALOGD("%s", stat_info_obj.stuck_issue);write(fd, stat_info_obj.stuck_issue, strlen(stat_info_obj.stuck_issue));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.last_wk_lck_acq_info);write(fd, stat_info_obj.last_wk_lck_acq_info, strlen(stat_info_obj.last_wk_lck_acq_info));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.last_wk_lck_rel_info);write(fd, stat_info_obj.last_wk_lck_rel_info, strlen(stat_info_obj.last_wk_lck_rel_info));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.pc_addr);write(fd, stat_info_obj.pc_addr, strlen(stat_info_obj.pc_addr));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.build_ver);write(fd, stat_info_obj.build_ver, strlen(stat_info_obj.build_ver));write(fd, " \n", 2);ALOGD("%s", stat_info_obj.delay_list_info.c_str());write(fd, stat_info_obj.delay_list_info.c_str(), stat_info_obj.delay_list_info.length());if (fsync(fd) == -1) {ALOGE("%s: Error while synchronization of logs in :%s error code:%s",__func__, file_name, strerror(errno));}close(fd);
}

1.BtState 状态日志字段说明表
字段名 / 内容来源含义说明
pri_crash_reason主异常原因(Primary crash reason),可能是导致 BT 崩溃的最初原因
sec_crash_reason次要异常原因(Secondary crash reason),辅助说明故障背景
bqr_rie_infoBQR(Bluetooth Quality Report)相关的 RIE 信息(Reason/Indicator/Event)
bqr_rie_vs_paramsBQR RIE 相关的厂商扩展参数(Vendor Specific Params)
crash_ts崩溃发生的时间戳(格式可能为字符串)
kernel_time从内核记录获得的时间,通常用于定位与内核交互的时序问题
alwayson_status蓝牙 Always-On 功能是否启用(如 BT 为 Always-On 模式)
ssrlvlSSR(Sub-System Restart)等级,表示故障严重程度(通常从属性中读取)
ts_hci_initialize初始化 HCI(Host Controller Interface)的时间戳
pre_sibs_property_read读取 SIBS(Shared Info Between Subsystems)属性前的状态
post_sibs_property_read读取 SIBS 属性后的状态
ts_hci_closeHCI 关闭的时间戳(系统准备关闭 BT)

2.Patch Reload 流程记录

(仅在 soc_need_reload_patch == true 时记录)

字段名含义说明
pre_local_addr获取本地地址前的状态
post_local_addr获取本地地址后的状态
pre_fetch_vendor_addr获取厂商地址前的状态
post_fetch_vendor_addr获取厂商地址后的状态
ts_getver_start_send_cmd发送 get version 命令的时间戳
ts_getver_start_read_rsp接收 get version 响应的时间戳
pre_version_info获取版本号信息前的状态
post_version_info获取版本号信息后的状态
ts_getver_rcvd成功接收到版本信息的时间戳
pre_chk_patch_path检查 patch 路径前的状态
post_chk_patch_path检查 patch 路径后的状态
pre_patch_open打开 patch 文件前的状态
post_patch_open打开 patch 文件后的状态
pre_xmem_patch_open / post_xmem_patch_open打开 xmem patch 文件前/后的状态(仅在 XMEM 模式下)
pre_xmem_nvm_open / post_xmem_nvm_open打开 xmem NVM 文件前/后的状态
pre_nvm_open / post_nvm_open打开 NVM 文件前/后的状态
pre_tcs_config / post_tcs_config配置 TCS 参数前/后的状态
pre_su_build_info / post_su_build_info设置 build info 前/后的状态
fw_dwnld_success固件下载是否成功的状态描述
fw_su_build_info_set_time + fw_su_build_info设置 SU build info 的时间戳和内容
otp_info_bytesOTP(One Time Programmable)信息(字节字符串)
bt_soc_idBT SoC 芯片标识

3. 电源与线程状态类字段
字段名含义说明
power_resources_state电源资源状态(是否开启、配置状态等)
bt_uart_ctsUART CTS(Clear To Send)引脚状态
read_thread_start读线程启动状态
status_read_thread读线程运行状态汇总
pre_diag_init_ts初始化 diagnostic 模块前的时间戳
post_diag_init_ts初始化 diagnostic 模块后的时间戳
ts_status_diag_initdiagnostic 初始化整体状态

4.DumpBtState
  DumpBtState stat_info_obj;typedef struct {char last_health_stat_info[MAX_STATE_INFO_SIZE];char last_wk_lck_acq_info[MAX_BUFF_SIZE];char last_wk_lck_rel_info[MAX_BUFF_SIZE];char last_hci_cmd_stack[MAX_BUFF_SIZE];char last_wk_ind_from_host[MAX_BUFF_SIZE];char last_wk_ack_from_soc[MAX_BUFF_SIZE];char last_wk_ind_from_soc[MAX_BUFF_SIZE];char last_wk_ack_from_host[MAX_BUFF_SIZE];char last_sleep_ind_from_host[MAX_BUFF_SIZE];char last_sleep_ind_from_soc[MAX_BUFF_SIZE];char pc_addr[MAX_BUFF_SIZE];char build_ver[MAX_BUFF_SIZE];char pre_stack_event[MAX_BUFF_SIZE];char post_stack_event[MAX_BUFF_SIZE];char pre_stack_acl[MAX_BUFF_SIZE];char post_stack_acl[MAX_BUFF_SIZE];char pre_select[MAX_BUFF_SIZE];char post_select[MAX_BUFF_SIZE];uint16_t last_tx_pkt_len;uint16_t actual_tx_pkt_len;char last_tx_pkt_ts[MAX_BUFF_SIZE];HciPacketType last_tx_pkt_type;char last_rx_pkt_ts[MAX_BUFF_SIZE];char ssr_rx_pkt_ts[MAX_BUFF_SIZE];uint16_t last_rx_pkt_len;uint16_t actual_rx_pkt_len;uint16_t ssr_rx_pkt_len;uint16_t actual_ssr_rx_pkt_len;HciPacketType last_rx_pkt_type;HciPacketType ssr_rx_pkt_type;uint16_t inv_bytes_len;int max_diag_rx_hci_delay;int max_diag_rx_acl_delay;int max_diag_tx_hci_delay;int max_diag_tx_acl_delay;struct timeval diag_rx_acl_start;struct timeval diag_tx_acl_start;struct timeval diag_rx_hci_start;struct timeval diag_tx_hci_start;int diag_pending_pkt;char inv_bytes_ts[MAX_BUFF_SIZE];char ts_getver_start_send_cmd[MAX_BUFF_SIZE];char ts_getver_start_read_rsp[MAX_BUFF_SIZE];char ts_getver_rcvd[MAX_BUFF_SIZE];char ts_hci_initialize[MAX_BUFF_SIZE];char ts_hci_close[MAX_BUFF_SIZE];char ts_last_seq_number[MAX_BUFF_SIZE];char ts_uart_flow_on[MAX_BUFF_SIZE];char ts_uart_flow_off[MAX_BUFF_SIZE];char ts_uart_clock_on[MAX_BUFF_SIZE];char ts_uart_clock_off[MAX_BUFF_SIZE];char ts_status_init_cb_sent[MAX_BUFF_SIZE];char ts_status_diag_init[MAX_BUFF_SIZE];char ts_status_ctrlr_init[MAX_BUFF_SIZE];char ts_hci_internal_cmd[MAX_BUFF_SIZE];char ts_hci_internal_rsp[MAX_BUFF_SIZE];char health_timer_status[MAX_BUFF_SIZE];char status_read_thread[MAX_BUFF_SIZE];char pri_crash_reason[MAX_CRASH_BUFF_SIZE];char sec_crash_reason[MAX_CRASH_BUFF_SIZE];char crash_ts[MAX_CRASH_BUFF_SIZE];char kernel_time[MAX_BUFF_SIZE];char last_tx_pkt_asc[TX_RX_PKT_ASC_SIZE];char last_tx_pkt_hex[TX_RX_PKT_HEX_SIZE];char last_rx_pkt_asc[TX_RX_PKT_ASC_SIZE];char last_rx_pkt_hex[TX_RX_PKT_HEX_SIZE];char ssr_rx_pkt_asc[TX_RX_PKT_ASC_SIZE];char ssr_rx_pkt_hex[TX_RX_PKT_HEX_SIZE];char inv_bytes_asc[TX_RX_PKT_ASC_SIZE];char inv_bytes_hex[TX_RX_PKT_HEX_SIZE];bool ssr_trigger;bool is_xmem_enabled;char alwayson_status[MAX_BUFF_SIZE];char post_diag_deinit_ts[MAX_BUFF_SIZE];char pre_diag_deinit_ts[MAX_BUFF_SIZE];char post_diag_init_ts[MAX_BUFF_SIZE];char pre_diag_init_ts[MAX_BUFF_SIZE];char fw_dwnld_success[MAX_BUFF_SIZE];char fw_su_build_info[MAX_BUFF_SIZE];char bt_soc_id[MAX_BUFF_SIZE];char power_resources_state[MAX_PWR_RSRC_INFO_SIZE];char bt_uart_cts[MAX_BUFF_SIZE];char pre_patch_open[MAX_BUFF_SIZE];char post_patch_open[MAX_BUFF_SIZE];char pre_nvm_open[MAX_BUFF_SIZE];char post_nvm_open[MAX_BUFF_SIZE];char pre_xmem_patch_open[MAX_BUFF_SIZE];char post_xmem_patch_open[MAX_BUFF_SIZE];char pre_xmem_nvm_open[MAX_BUFF_SIZE];char post_xmem_nvm_open[MAX_BUFF_SIZE];char pre_chk_patch_path[MAX_BUFF_SIZE];char post_chk_patch_path[MAX_BUFF_SIZE];char pre_version_info[MAX_BUFF_SIZE];char post_version_info[MAX_BUFF_SIZE];char pre_su_build_info[MAX_BUFF_SIZE];char post_su_build_info[MAX_BUFF_SIZE];char pre_local_addr[MAX_BUFF_SIZE];char post_local_addr[MAX_BUFF_SIZE];char pre_fetch_vendor_addr[MAX_BUFF_SIZE];char post_fetch_vendor_addr[MAX_BUFF_SIZE];char read_thread_start[MAX_BUFF_SIZE];char pre_tcs_config[MAX_BUFF_SIZE];char post_tcs_config[MAX_BUFF_SIZE];char pre_sibs_property_read[MAX_BUFF_SIZE];char post_sibs_property_read[MAX_BUFF_SIZE];char otp_info_bytes[OTP_INFO_BYTES_MAX_SIZE];char stuck_issue[MAX_BUFF_SIZE];char pre_diag_rx_acl[MAX_BUFF_SIZE];char post_diag_rx_acl[MAX_BUFF_SIZE];char pre_diag_rx_hci[MAX_BUFF_SIZE];char post_diag_rx_hci[MAX_BUFF_SIZE];char pre_diag_tx_acl[MAX_BUFF_SIZE];char post_diag_tx_acl[MAX_BUFF_SIZE];char pre_diag_tx_hci[MAX_BUFF_SIZE];char post_diag_tx_hci[MAX_BUFF_SIZE];char bqr_rie_info[MAX_CRASH_BUFF_SIZE];char uart_ipc_err[MAX_BUFF_SIZE];std::string delay_list_info;std::string bqr_rie_vs_params;struct timeval fw_su_build_info_set_time;char pre_stack_iso[MAX_BUFF_SIZE];char post_stack_iso[MAX_BUFF_SIZE];
} DumpBtState;
字段名类型说明(推测)
last_health_stat_infochar[MAX_STATE_INFO_SIZE]最近一次健康状态信息
last_wk_lck_acq_infochar[MAX_BUFF_SIZE]最近一次 wake lock 获取信息
last_wk_lck_rel_infochar[MAX_BUFF_SIZE]最近一次 wake lock 释放信息
last_hci_cmd_stackchar[MAX_BUFF_SIZE]最近一次 HCI 命令堆栈
last_wk_ind_from_hostchar[MAX_BUFF_SIZE]Host 发出的 wake indication
last_wk_ack_from_socchar[MAX_BUFF_SIZE]SoC 发出的 wake ack
last_wk_ind_from_socchar[MAX_BUFF_SIZE]SoC 发出的 wake indication
last_wk_ack_from_hostchar[MAX_BUFF_SIZE]Host 发出的 wake ack
last_sleep_ind_from_hostchar[MAX_BUFF_SIZE]Host 发出的 sleep indication
last_sleep_ind_from_socchar[MAX_BUFF_SIZE]SoC 发出的 sleep indication
pc_addrchar[MAX_BUFF_SIZE]程序计数器地址
build_verchar[MAX_BUFF_SIZE]构建版本信息
pre_stack_eventchar[MAX_BUFF_SIZE]堆栈事件前状态
post_stack_eventchar[MAX_BUFF_SIZE]堆栈事件后状态
pre_stack_aclchar[MAX_BUFF_SIZE]ACL 事件前状态
post_stack_aclchar[MAX_BUFF_SIZE]ACL 事件后状态
pre_selectchar[MAX_BUFF_SIZE]select() 前状态
post_selectchar[MAX_BUFF_SIZE]select() 后状态
last_tx_pkt_lenuint16_t最后一次发送包长度(理论)
actual_tx_pkt_lenuint16_t最后一次发送包长度(实际)
last_tx_pkt_tschar[MAX_BUFF_SIZE]最后发送时间戳
last_tx_pkt_typeHciPacketType最后发送包类型
last_rx_pkt_tschar[MAX_BUFF_SIZE]最后接收时间戳
ssr_rx_pkt_tschar[MAX_BUFF_SIZE]SSR 接收时间戳
last_rx_pkt_lenuint16_t最后接收包长度(理论)
actual_rx_pkt_lenuint16_t最后接收包长度(实际)
ssr_rx_pkt_lenuint16_tSSR 接收包长度(理论)
actual_ssr_rx_pkt_lenuint16_tSSR 接收包长度(实际)
last_rx_pkt_typeHciPacketType最后接收包类型
ssr_rx_pkt_typeHciPacketTypeSSR 接收包类型
inv_bytes_lenuint16_t非法字节数长度
max_diag_rx_hci_delayintHCI 接收最大延迟(诊断)
max_diag_rx_acl_delayintACL 接收最大延迟(诊断)
max_diag_tx_hci_delayintHCI 发送最大延迟(诊断)
max_diag_tx_acl_delayintACL 发送最大延迟(诊断)
diag_rx_acl_startstruct timevalACL 接收开始时间(诊断)
diag_tx_acl_startstruct timevalACL 发送开始时间(诊断)
diag_rx_hci_startstruct timevalHCI 接收开始时间(诊断)
diag_tx_hci_startstruct timevalHCI 发送开始时间(诊断)
diag_pending_pktint待诊断处理的包数
inv_bytes_tschar[MAX_BUFF_SIZE]非法字节时间戳
ts_getver_start_send_cmdchar[MAX_BUFF_SIZE]发送 GetVer 命令开始时间
ts_getver_start_read_rspchar[MAX_BUFF_SIZE]开始读取 GetVer 响应时间
ts_getver_rcvdchar[MAX_BUFF_SIZE]收到 GetVer 响应时间
ts_hci_initializechar[MAX_BUFF_SIZE]HCI 初始化时间
ts_hci_closechar[MAX_BUFF_SIZE]HCI 关闭时间
ts_last_seq_numberchar[MAX_BUFF_SIZE]最近的序列号时间戳
ts_uart_flow_onchar[MAX_BUFF_SIZE]UART 流控开启时间
ts_uart_flow_offchar[MAX_BUFF_SIZE]UART 流控关闭时间
ts_uart_clock_onchar[MAX_BUFF_SIZE]UART 时钟开启时间
ts_uart_clock_offchar[MAX_BUFF_SIZE]UART 时钟关闭时间
ts_status_init_cb_sentchar[MAX_BUFF_SIZE]init callback 发送时间
ts_status_diag_initchar[MAX_BUFF_SIZE]诊断初始化时间
ts_status_ctrlr_initchar[MAX_BUFF_SIZE]控制器初始化时间
ts_hci_internal_cmdchar[MAX_BUFF_SIZE]内部 HCI 命令时间
ts_hci_internal_rspchar[MAX_BUFF_SIZE]内部 HCI 响应时间
health_timer_statuschar[MAX_BUFF_SIZE]健康定时器状态
status_read_threadchar[MAX_BUFF_SIZE]读取线程状态
pri_crash_reasonchar[MAX_CRASH_BUFF_SIZE]主崩溃原因
sec_crash_reasonchar[MAX_CRASH_BUFF_SIZE]次崩溃原因
crash_tschar[MAX_CRASH_BUFF_SIZE]崩溃时间戳
kernel_timechar[MAX_BUFF_SIZE]内核时间
last_tx_pkt_ascchar[TX_RX_PKT_ASC_SIZE]发送包(ASCII)
last_tx_pkt_hexchar[TX_RX_PKT_HEX_SIZE]发送包(HEX)
last_rx_pkt_ascchar[TX_RX_PKT_ASC_SIZE]接收包(ASCII)
last_rx_pkt_hexchar[TX_RX_PKT_HEX_SIZE]接收包(HEX)
ssr_rx_pkt_ascchar[TX_RX_PKT_ASC_SIZE]SSR 接收包(ASCII)
ssr_rx_pkt_hexchar[TX_RX_PKT_HEX_SIZE]SSR 接收包(HEX)
inv_bytes_ascchar[TX_RX_PKT_ASC_SIZE]非法字节(ASCII)
inv_bytes_hexchar[TX_RX_PKT_HEX_SIZE]非法字节(HEX)
ssr_triggerbool是否触发 SSR
is_xmem_enabledbool是否启用 xmem 模式
alwayson_statuschar[MAX_BUFF_SIZE]Always-On 状态信息
post_diag_deinit_tschar[MAX_BUFF_SIZE]诊断 deinit 后时间戳
pre_diag_deinit_tschar[MAX_BUFF_SIZE]诊断 deinit 前时间戳
post_diag_init_tschar[MAX_BUFF_SIZE]诊断 init 后时间戳
pre_diag_init_tschar[MAX_BUFF_SIZE]诊断 init 前时间戳
fw_dwnld_successchar[MAX_BUFF_SIZE]固件下载是否成功
fw_su_build_infochar[MAX_BUFF_SIZE]固件 SU 构建信息
bt_soc_idchar[MAX_BUFF_SIZE]BT SoC ID
power_resources_statechar[MAX_PWR_RSRC_INFO_SIZE]电源资源状态
bt_uart_ctschar[MAX_BUFF_SIZE]UART CTS 状态
pre_patch_openchar[MAX_BUFF_SIZE]Patch 打开前
post_patch_openchar[MAX_BUFF_SIZE]Patch 打开后
pre_nvm_openchar[MAX_BUFF_SIZE]NVM 打开前
post_nvm_openchar[MAX_BUFF_SIZE]NVM 打开后
pre_xmem_patch_openchar[MAX_BUFF_SIZE]xmem patch 打开前
post_xmem_patch_openchar[MAX_BUFF_SIZE]xmem patch 打开后
pre_xmem_nvm_openchar[MAX_BUFF_SIZE]xmem NVM 打开前
post_xmem_nvm_openchar[MAX_BUFF_SIZE]xmem NVM 打开后
pre_chk_patch_pathchar[MAX_BUFF_SIZE]检查 patch 路径前
post_chk_patch_pathchar[MAX_BUFF_SIZE]检查 patch 路径后
pre_version_infochar[MAX_BUFF_SIZE]获取版本信息前
post_version_infochar[MAX_BUFF_SIZE]获取版本信息后
pre_su_build_infochar[MAX_BUFF_SIZE]获取构建信息前
post_su_build_infochar[MAX_BUFF_SIZE]获取构建信息后
pre_local_addrchar[MAX_BUFF_SIZE]获取本地地址前
post_local_addrchar[MAX_BUFF_SIZE]获取本地地址后
pre_fetch_vendor_addrchar[MAX_BUFF_SIZE]获取厂商地址前
post_fetch_vendor_addrchar[MAX_BUFF_SIZE]获取厂商地址后
read_thread_startchar[MAX_BUFF_SIZE]读取线程启动时间
pre_tcs_configchar[MAX_BUFF_SIZE]TCS 配置前状态
post_tcs_configchar[MAX_BUFF_SIZE]TCS 配置后状态
pre_sibs_property_readchar[MAX_BUFF_SIZE]读取 SIBS 属性前
post_sibs_property_readchar[MAX_BUFF_SIZE]读取 SIBS 属性后
otp_info_byteschar[OTP_INFO_BYTES_MAX_SIZE]OTP 字节信息
stuck_issuechar[MAX_BUFF_SIZE]卡死问题描述
pre_diag_rx_aclchar[MAX_BUFF_SIZE]诊断 ACL 接收前
post_diag_rx_aclchar[MAX_BUFF_SIZE]诊断 ACL 接收后
pre_diag_rx_hcichar[MAX_BUFF_SIZE]诊断 HCI 接收前
post_diag_rx_hcichar[MAX_BUFF_SIZE]诊断 HCI 接收后
pre_diag_tx_aclchar[MAX_BUFF_SIZE]诊断 ACL 发送前
post_diag_tx_aclchar[MAX_BUFF_SIZE]诊断 ACL 发送后
pre_diag_tx_hcichar[MAX_BUFF_SIZE]诊断 HCI 发送前
post_diag_tx_hcichar[MAX_BUFF_SIZE]诊断 HCI 发送后
bqr_rie_infochar[MAX_CRASH_BUFF_SIZE]BQR RIE 信息
uart_ipc_errchar[MAX_BUFF_SIZE]UART IPC 错误描述
delay_list_infostd::string延迟列表信息
bqr_rie_vs_paramsstd::stringBQR RIE VS 参数信息
fw_su_build_info_set_timestruct timeval设置固件构建信息的时间
pre_stack_isochar[MAX_BUFF_SIZE]ISO 堆栈前状态
post_stack_isochar[MAX_BUFF_SIZE]ISO 堆栈后状态
5. 附加说明
  • 每条数据前后通常有 write(fd, " \n", 2) 添加换行;
  • 日志中同时用 ALOGD 打印同样内容到 logcat;
  • 字段依赖全局对象 stat_info_obj 的内容(结构体 StatInfo 类似);
  • soc_need_reload_patch 控制是否需要记录 Patch 相关详细信息;
  • 使用 Logger::Get()->GetStateFileName() 获取目标 dump 文件路径;
  • 最终文件权限为 0664,创建或覆盖写入。
http://www.xdnf.cn/news/911107.html

相关文章:

  • jmeter之导出接口
  • 立定跳远-二分
  • 20250606-C#知识:委托和事件
  • 企业引入数字孪生,优化决策,提升市场竞争力的秘诀
  • 缓存一致性的形式化定义
  • UVM环境打印如何显示时间单位
  • 仿射变换、根据特征点进行仿射变换
  • HarmonyOS运动开发:如何用mpchart绘制运动配速图表
  • 计算与分析2-深度学习
  • F5 – TCP 连接管理:会话、池级和节点级操作
  • 嵌入式Linux下如何启动和使用Docker
  • 【数据结构】图
  • FPGA 动态重构配置流程
  • CVAT标注服务
  • 中国移动6周年!
  • C++.OpenGL (10/64)基础光照(Basic Lighting)
  • 2025年6月6日15:48:23
  • [蓝桥杯]防御力
  • Source insight 4自用技巧整理
  • webstorm 配置 Prettier
  • 每次clone都会有:Enter passphrase for key ‘/Users/xxx/.ssh/id_rsa‘:
  • JavaScript操作数组、字符串、对象的一些方法
  • vcs仿真产生fsdb波形的两种方式
  • YOLO训练保持原有识别能力
  • maven私服
  • JAVA元编程
  • QPS、TPS、RT、IOQS、并发数等性能名词介绍
  • AI系统提示词:V0
  • C++.OpenGL (9/64)摄像机(Camera)
  • UChart图标 y轴取整