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

发布于:2025-06-08 ⋅ 阅读:(16) ⋅ 点赞:(0)

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 REASON
  BT_HOST_REASON_SOC_CRASHED = 0x01,                           //SOC WAS CRASHED
  BT_HOST_REASON_SOC_CRASHED_DIAG_SSR = 0x02,                  //SOC CRASHED DIAG INITIATED SSR
  BT_HOST_REASON_INIT_FAILED = 0x03,                           //HOST INITIALIZATION FAILED
  BT_HOST_REASON_CLOSE_RCVD_DURING_INIT = 0x04,                //CLOSE RECEIVED FROM STACK DURING SOC INIT
  BT_HOST_REASON_ERROR_READING_DATA_FROM_UART = 0x05,          //ERROR READING DATA FROM UART
  BT_HOST_REASON_WRITE_FAIL_SPCL_BUFF_CRASH_SOC = 0x06,        //FAILED TO WRITE SPECIAL BYTES TO CRASH SOC
  BT_HOST_REASON_RX_THREAD_STUCK = 0x07,                       //RX THREAD STUCK
  BT_HOST_REASON_SSR_CMD_TIMEDOUT = 0x08,                      //SSR DUE TO CMD TIMED OUT
  BT_HOST_REASON_SSR_SPURIOUS_WAKEUP = 0x09,                   //SSR DUE TO SPURIOUS WAKE UP
  BT_HOST_REASON_SSR_INVALID_BYTES_RCVD = 0x0A,                //INVALID HCI CMD TYPE RECEIVED
  BT_HOST_REASON_SSR_RCVD_LARGE_PKT_FROM_SOC = 0x0B,           //SSR DUE TO LARGE PKT RECVIVED FROM SOC
  BT_HOST_REASON_SSR_UNABLE_TO_WAKEUP_SOC = 0x0C,              //UNABLE TO WAKE UP SOC
  BT_HOST_REASON_CMD_TIMEDOUT_SOC_WAIT_TIMEOUT = 0x0D,         //COMMAND TIMEOUT AND SOC CRASH WAIT TIMEOUT
  BT_HOST_REASON_SPURIOUS_WAKEUP_SOC_WAIT_TIMEOUT = 0x0E,      //SPURIOUS WAKE AND SOC CRASH WAIT TIMEOUT
  BT_HOST_REASON_INV_BYTES_SOC_WAIT_TIMEOUT = 0x0F,            //INVALID BYTES AND SOC CRASH WAIT TIMEOUT
  BT_HOST_REASON_SOC_WAKEUP_FAILED_SOC_WAIT_TIMEOUT = 0x10,    //SOC WAKEUP FAILURE AND SOC CRASH WAIT TIMEOUT
  BT_HOST_REASON_SOC_CRASHED_DIAG_SSR_SOC_WAIT_TIMEOUT = 0x11, //SOC CRASHED DIAG INITIATED SSR CRASH WAIT TIMEOUT
  BT_HOST_REASON_NONE_SOC_WAIT_TIMEOUT = 0x12,                 //INVALID FAILURE AND SOC CRASH WAIT TIMEOUT
  BT_HOST_REASON_SOC_DEINIT_STUCK = 0x13,                      //SOC DEINIT STUCK
  BT_HOST_REASON_SSR_INTERNAL_CMD_TIMEDOUT = 0x14,             //SSR DUE TO CMD INTERNAL TIMED OUT
  BT_HOST_REASON_FAILED_TO_SEND_INTERNAL_CMD = 0x15,           //FAILED TO SEND INTERNAL CMD
  BT_HOST_REASON_SSR_SLEEP_IND_NOT_RCVD = 0x16,                //SOC DID NOT RCVD SLEEP IND DURING CLOSE
  BT_HOST_REASON_DIAG_LOG_API_STUCK = 0x39,                    //DIAG log API stuck.
};
错误码 枚举名 出错场景 可能原因 是否触发 SSR
0x00 BT_HOST_REASON_DEFAULT_NONE 无具体错误信息 默认值或无效原因
0x01 BT_HOST_REASON_SOC_CRASHED SoC 异常重启 蓝牙 SoC Crash,未具体说明由谁触发
0x02 BT_HOST_REASON_SOC_CRASHED_DIAG_SSR Diag 模块触发 SSR Modem/Diag 检测到异常,触发 SSR
0x03 BT_HOST_REASON_INIT_FAILED 初始化失败 蓝牙驱动或 HAL 初始化失败
0x04 BT_HOST_REASON_CLOSE_RCVD_DURING_INIT 初始化过程中收到上层 close 命令 状态未就绪,框架强行终止蓝牙流程 否(视情况)
0x05 BT_HOST_REASON_ERROR_READING_DATA_FROM_UART UART 接收数据异常 UART 接收错误、SoC 掉电、通讯中断
0x06 BT_HOST_REASON_WRITE_FAIL_SPCL_BUFF_CRASH_SOC 向 SoC 写入特殊 crash buffer 失败 HAL 试图崩溃 SoC 但失败
0x07 BT_HOST_REASON_RX_THREAD_STUCK RX 接收线程卡死 蓝牙接收线程无响应或死锁
0x08 BT_HOST_REASON_SSR_CMD_TIMEDOUT HAL 发送命令超时无响应 SoC 不响应 HCI 命令
0x09 BT_HOST_REASON_SSR_SPURIOUS_WAKEUP 非预期唤醒事件 Wake Lock 或中断异常
0x0A BT_HOST_REASON_SSR_INVALID_BYTES_RCVD 收到非法数据 非法 HCI 包类型或 SoC 异常输出
0x0B BT_HOST_REASON_SSR_RCVD_LARGE_PKT_FROM_SOC 收到异常大包 SoC 发出超过协议长度限制的数据包
0x0C BT_HOST_REASON_SSR_UNABLE_TO_WAKEUP_SOC 无法唤醒 SoC SoC 进入 sleep 状态无法恢复
0x0D BT_HOST_REASON_CMD_TIMEDOUT_SOC_WAIT_TIMEOUT 命令超时 + 等待 crash 超时 等待 SoC crash 文件超时
0x0E BT_HOST_REASON_SPURIOUS_WAKEUP_SOC_WAIT_TIMEOUT 非法唤醒 + Crash 等待超时 双重异常情况
0x0F BT_HOST_REASON_INV_BYTES_SOC_WAIT_TIMEOUT 非法字节 + Crash 等待超时 收到非法数据且 crash log 等待超时
0x10 BT_HOST_REASON_SOC_WAKEUP_FAILED_SOC_WAIT_TIMEOUT SoC 唤醒失败 + 等待 crash 超时 睡眠失败后尝试恢复失败
0x11 BT_HOST_REASON_SOC_CRASHED_DIAG_SSR_SOC_WAIT_TIMEOUT DIAG SSR 后 crash log 超时 DIAG 已触发 SSR,但 log 没回
0x12 BT_HOST_REASON_NONE_SOC_WAIT_TIMEOUT 无效原因 + Crash log 等待超时 异常未捕获但等待超时
0x13 BT_HOST_REASON_SOC_DEINIT_STUCK Deinit 过程卡住 SoC 去初始化失败(关闭失败)
0x14 BT_HOST_REASON_SSR_INTERNAL_CMD_TIMEDOUT 内部命令超时 控制命令发送后未响应
0x15 BT_HOST_REASON_FAILED_TO_SEND_INTERNAL_CMD 无法发送内部命令 HAL 内部机制故障
0x16 BT_HOST_REASON_SSR_SLEEP_IND_NOT_RCVD SoC 在关闭前未收到 sleep 指令 关闭流程异常,未同步 sleep 状态
0x39 BT_HOST_REASON_DIAG_LOG_API_STUCK DIAG 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 Reasons
  BT_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 Reasons
  BT_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 reasons
  UART_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)
错误码 名称 出错场景 可能原因
0x81 BT_SOC_REASON_UNKNOWN 未知 SoC 崩溃 未记录具体原因,可能为底层未捕获异常
0x82 BT_SOC_REASON_SW_REQUESTED 主动触发崩溃 软件请求 SSR,例如测试或错误恢复机制
0x83 BT_SOC_REASON_STACK_OVERFLOW SoC 崩溃 SoC 内部任务栈溢出
0x84 BT_SOC_REASON_EXCEPTION SoC 崩溃 SoC 捕获未处理异常
0x85 BT_SOC_REASON_ASSERT SoC 崩溃 SoC 中断言失败(assert hit)
0x86 BT_SOC_REASON_TRAP SoC 崩溃 陷阱异常(如非法指令)
0x87 BT_SOC_REASON_OS_FATAL SoC 崩溃 RTOS 致命错误,如调度器出错
0x88 BT_SOC_REASON_HCI_RESET 主动或异常复位 HCI Reset 导致 SSR
0x89 BT_SOC_REASON_PATCH_RESET 打补丁后复位 下载 patch 后要求 SoC 重启
0x8A BT_SOC_REASON_ABT 异常终止 异常 abort 终止指令执行
0x8B BT_SOC_REASON_RAMMASK 崩溃检测 RAM MASK 检测到内存非法访问
0x8C BT_SOC_REASON_PREBARK 错误中断触发 所谓 “bark” 是 watchdog 报警触发
0x8D BT_SOC_REASON_BUSERROR 总线异常 SoC 访问异常或非法地址
0x8E BT_SOC_REASON_IO_FATAL I/O 错误 外设或通信口故障
0x8F BT_SOC_REASON_SSR_CMD SSR 命令触发 接收到 SSR 特定命令
0x90 BT_SOC_REASON_POWERON 上电重启 SoC 刚上电初始化
0x91 BT_SOC_REASON_WATCHDOG 看门狗复位 Watchdog 超时未喂
0x92 BT_SOC_REASON_RAMMASK_RGN1 RAM 崩溃检测 指定区域1检测到非法内存
0x93 BT_SOC_REASON_RAMMASK_RGN0 RAM 崩溃检测 指定区域0检测到非法内存
0x94 BT_SOC_REASON_Q6_WATCHDOG QDSP 崩溃 Q6 DSP 触发 Watchdog
0x95 BT_SOC_REASON_ZEALIS_RAM_MASK_RGN0 内存保护 RAM mask 检测 ZEALIS 区域
0x96 BT_SOC_REASON_ZEALIS_RAM_MASK_RGN1 内存保护 RAM mask 检测 ZEALIS 区域
0x97 BT_SOC_REASON_APSS_RESET AP 复位 AP 发起 warm/cold reset
0x98 BT_SOC_REASON_TIME_RESET 时钟复位 时钟配置异常或复位触发
0x99 BT_SOC_REASON_AUDIOSS_RESET Audio 子系统异常 AudioSS 出现错误导致全局重启
0x9A BT_SOC_REASON_HOST_WARMRESET 主机发起复位 Host 请求 warm reset
0x9B BT_SOC_REASON_HOST_NMI_INIT 主机发起 NMI 初始化 Host 发出非屏蔽中断
0xC0 BT_SOC_REASON_TX_RX_INVALID_PKT_FATAL 接收到异常数据包 数据包格式非法导致崩溃
0xC1 BT_SOC_REASON_TX_RX_INVALID_LEN_FATAL 接收到长度错误的数据包 长度超限或错位
0xF0 BT_SOC_REASON_INVALID_STACK 内部栈错误 SoC 栈初始化失败或破坏

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

3. Transport/UART 驱动崩溃(0x51 ~ 0x66)
错误码 名称 出错场景 可能原因
0x51 UART_REASON_DEFAULT 默认 UART 错误 一般作为兜底错误码
0x52 INVALID_FW_LOADED 加载错误固件 固件不匹配或损坏
0x53 ~ 0x57 CLK/资源类错误 获取时钟失败,资源初始化失败等
0x58 ~ 0x5B TX 方向失败 DMA 映射、TX 取消、TX FSM 初始化失败
0x5C ~ 0x5E RX 方向失败 RX 取消、FSM 异常
0x5F RX_TTY_INSET_FAIL TTY 配置失败 串口 TTY 接口未就绪
0x60 ~ 0x64 中断/接收异常 接收到非法中断或奇偶校验错误
0x65 SOC_REASON_START_TX_IOS_SOC_RFR_HIGH 初始化时 TX IOS 高电平未降 SoC 初始化握手失败
0x66 UART_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 collected
          if (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 status
            LogPwrSrcsUartFlowCtrl();
            logger_->StoreCrashReason();
            logger_->PrepareDumpProcess();
            // Send BQR RIE before kernel panic
            SendBqrRiePacket();
            logger_->CollectDumps(true, true); // 触发后续 日志 dump
            // 执行 kernel panic(重启系统),确保 crash dump 被保存。
            // 通过 ioctl(/dev/btpower, 0xbfc1)
            if (bt_kernel_panic() == 0)
              return;
            else
              ALOGE("%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 status
        LogPwrSrcsUartFlowCtrl();
        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 and
        ResetForceSsrTriggeredIfNoCleanup()) {
        // 如果 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 = true
      IsRxSchedDelay = 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) issue
  if (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_TIMER
    health_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 collected
        if (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_LOG
      if (dump_uart_logs == DUMP_IPC_LOGS || dump_uart_logs == DUMP_FTRACE_AND_IPC_LOGS)
        DumpUartIpcLogs(); // 若属性值为 `2` 或 `3`,执行 IPC 日志收集。
#endif
      if (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 purpose
    char 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。
  }
#endif
  if (is_state_log_enabled)
    //Dump last BT states of transport driver
    BtState :: 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_SET
  DeleteDumpsIfRequired();
#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 packet
  write(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 SSR
  write(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 packet
  write(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 packet
  if (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_ENABLED
  if (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));
  }
#endif

  write(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_info BQR(Bluetooth Quality Report)相关的 RIE 信息(Reason/Indicator/Event)
bqr_rie_vs_params BQR RIE 相关的厂商扩展参数(Vendor Specific Params)
crash_ts 崩溃发生的时间戳(格式可能为字符串)
kernel_time 从内核记录获得的时间,通常用于定位与内核交互的时序问题
alwayson_status 蓝牙 Always-On 功能是否启用(如 BT 为 Always-On 模式)
ssrlvl SSR(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_close HCI 关闭的时间戳(系统准备关闭 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_bytes OTP(One Time Programmable)信息(字节字符串)
bt_soc_id BT SoC 芯片标识

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

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_info char[MAX_STATE_INFO_SIZE] 最近一次健康状态信息
last_wk_lck_acq_info char[MAX_BUFF_SIZE] 最近一次 wake lock 获取信息
last_wk_lck_rel_info char[MAX_BUFF_SIZE] 最近一次 wake lock 释放信息
last_hci_cmd_stack char[MAX_BUFF_SIZE] 最近一次 HCI 命令堆栈
last_wk_ind_from_host char[MAX_BUFF_SIZE] Host 发出的 wake indication
last_wk_ack_from_soc char[MAX_BUFF_SIZE] SoC 发出的 wake ack
last_wk_ind_from_soc char[MAX_BUFF_SIZE] SoC 发出的 wake indication
last_wk_ack_from_host char[MAX_BUFF_SIZE] Host 发出的 wake ack
last_sleep_ind_from_host char[MAX_BUFF_SIZE] Host 发出的 sleep indication
last_sleep_ind_from_soc char[MAX_BUFF_SIZE] SoC 发出的 sleep indication
pc_addr char[MAX_BUFF_SIZE] 程序计数器地址
build_ver char[MAX_BUFF_SIZE] 构建版本信息
pre_stack_event char[MAX_BUFF_SIZE] 堆栈事件前状态
post_stack_event char[MAX_BUFF_SIZE] 堆栈事件后状态
pre_stack_acl char[MAX_BUFF_SIZE] ACL 事件前状态
post_stack_acl char[MAX_BUFF_SIZE] ACL 事件后状态
pre_select char[MAX_BUFF_SIZE] select() 前状态
post_select char[MAX_BUFF_SIZE] select() 后状态
last_tx_pkt_len uint16_t 最后一次发送包长度(理论)
actual_tx_pkt_len uint16_t 最后一次发送包长度(实际)
last_tx_pkt_ts char[MAX_BUFF_SIZE] 最后发送时间戳
last_tx_pkt_type HciPacketType 最后发送包类型
last_rx_pkt_ts char[MAX_BUFF_SIZE] 最后接收时间戳
ssr_rx_pkt_ts char[MAX_BUFF_SIZE] SSR 接收时间戳
last_rx_pkt_len uint16_t 最后接收包长度(理论)
actual_rx_pkt_len uint16_t 最后接收包长度(实际)
ssr_rx_pkt_len uint16_t SSR 接收包长度(理论)
actual_ssr_rx_pkt_len uint16_t SSR 接收包长度(实际)
last_rx_pkt_type HciPacketType 最后接收包类型
ssr_rx_pkt_type HciPacketType SSR 接收包类型
inv_bytes_len uint16_t 非法字节数长度
max_diag_rx_hci_delay int HCI 接收最大延迟(诊断)
max_diag_rx_acl_delay int ACL 接收最大延迟(诊断)
max_diag_tx_hci_delay int HCI 发送最大延迟(诊断)
max_diag_tx_acl_delay int ACL 发送最大延迟(诊断)
diag_rx_acl_start struct timeval ACL 接收开始时间(诊断)
diag_tx_acl_start struct timeval ACL 发送开始时间(诊断)
diag_rx_hci_start struct timeval HCI 接收开始时间(诊断)
diag_tx_hci_start struct timeval HCI 发送开始时间(诊断)
diag_pending_pkt int 待诊断处理的包数
inv_bytes_ts char[MAX_BUFF_SIZE] 非法字节时间戳
ts_getver_start_send_cmd char[MAX_BUFF_SIZE] 发送 GetVer 命令开始时间
ts_getver_start_read_rsp char[MAX_BUFF_SIZE] 开始读取 GetVer 响应时间
ts_getver_rcvd char[MAX_BUFF_SIZE] 收到 GetVer 响应时间
ts_hci_initialize char[MAX_BUFF_SIZE] HCI 初始化时间
ts_hci_close char[MAX_BUFF_SIZE] HCI 关闭时间
ts_last_seq_number char[MAX_BUFF_SIZE] 最近的序列号时间戳
ts_uart_flow_on char[MAX_BUFF_SIZE] UART 流控开启时间
ts_uart_flow_off char[MAX_BUFF_SIZE] UART 流控关闭时间
ts_uart_clock_on char[MAX_BUFF_SIZE] UART 时钟开启时间
ts_uart_clock_off char[MAX_BUFF_SIZE] UART 时钟关闭时间
ts_status_init_cb_sent char[MAX_BUFF_SIZE] init callback 发送时间
ts_status_diag_init char[MAX_BUFF_SIZE] 诊断初始化时间
ts_status_ctrlr_init char[MAX_BUFF_SIZE] 控制器初始化时间
ts_hci_internal_cmd char[MAX_BUFF_SIZE] 内部 HCI 命令时间
ts_hci_internal_rsp char[MAX_BUFF_SIZE] 内部 HCI 响应时间
health_timer_status char[MAX_BUFF_SIZE] 健康定时器状态
status_read_thread char[MAX_BUFF_SIZE] 读取线程状态
pri_crash_reason char[MAX_CRASH_BUFF_SIZE] 主崩溃原因
sec_crash_reason char[MAX_CRASH_BUFF_SIZE] 次崩溃原因
crash_ts char[MAX_CRASH_BUFF_SIZE] 崩溃时间戳
kernel_time char[MAX_BUFF_SIZE] 内核时间
last_tx_pkt_asc char[TX_RX_PKT_ASC_SIZE] 发送包(ASCII)
last_tx_pkt_hex char[TX_RX_PKT_HEX_SIZE] 发送包(HEX)
last_rx_pkt_asc char[TX_RX_PKT_ASC_SIZE] 接收包(ASCII)
last_rx_pkt_hex char[TX_RX_PKT_HEX_SIZE] 接收包(HEX)
ssr_rx_pkt_asc char[TX_RX_PKT_ASC_SIZE] SSR 接收包(ASCII)
ssr_rx_pkt_hex char[TX_RX_PKT_HEX_SIZE] SSR 接收包(HEX)
inv_bytes_asc char[TX_RX_PKT_ASC_SIZE] 非法字节(ASCII)
inv_bytes_hex char[TX_RX_PKT_HEX_SIZE] 非法字节(HEX)
ssr_trigger bool 是否触发 SSR
is_xmem_enabled bool 是否启用 xmem 模式
alwayson_status char[MAX_BUFF_SIZE] Always-On 状态信息
post_diag_deinit_ts char[MAX_BUFF_SIZE] 诊断 deinit 后时间戳
pre_diag_deinit_ts char[MAX_BUFF_SIZE] 诊断 deinit 前时间戳
post_diag_init_ts char[MAX_BUFF_SIZE] 诊断 init 后时间戳
pre_diag_init_ts char[MAX_BUFF_SIZE] 诊断 init 前时间戳
fw_dwnld_success char[MAX_BUFF_SIZE] 固件下载是否成功
fw_su_build_info char[MAX_BUFF_SIZE] 固件 SU 构建信息
bt_soc_id char[MAX_BUFF_SIZE] BT SoC ID
power_resources_state char[MAX_PWR_RSRC_INFO_SIZE] 电源资源状态
bt_uart_cts char[MAX_BUFF_SIZE] UART CTS 状态
pre_patch_open char[MAX_BUFF_SIZE] Patch 打开前
post_patch_open char[MAX_BUFF_SIZE] Patch 打开后
pre_nvm_open char[MAX_BUFF_SIZE] NVM 打开前
post_nvm_open char[MAX_BUFF_SIZE] NVM 打开后
pre_xmem_patch_open char[MAX_BUFF_SIZE] xmem patch 打开前
post_xmem_patch_open char[MAX_BUFF_SIZE] xmem patch 打开后
pre_xmem_nvm_open char[MAX_BUFF_SIZE] xmem NVM 打开前
post_xmem_nvm_open char[MAX_BUFF_SIZE] xmem NVM 打开后
pre_chk_patch_path char[MAX_BUFF_SIZE] 检查 patch 路径前
post_chk_patch_path char[MAX_BUFF_SIZE] 检查 patch 路径后
pre_version_info char[MAX_BUFF_SIZE] 获取版本信息前
post_version_info char[MAX_BUFF_SIZE] 获取版本信息后
pre_su_build_info char[MAX_BUFF_SIZE] 获取构建信息前
post_su_build_info char[MAX_BUFF_SIZE] 获取构建信息后
pre_local_addr char[MAX_BUFF_SIZE] 获取本地地址前
post_local_addr char[MAX_BUFF_SIZE] 获取本地地址后
pre_fetch_vendor_addr char[MAX_BUFF_SIZE] 获取厂商地址前
post_fetch_vendor_addr char[MAX_BUFF_SIZE] 获取厂商地址后
read_thread_start char[MAX_BUFF_SIZE] 读取线程启动时间
pre_tcs_config char[MAX_BUFF_SIZE] TCS 配置前状态
post_tcs_config char[MAX_BUFF_SIZE] TCS 配置后状态
pre_sibs_property_read char[MAX_BUFF_SIZE] 读取 SIBS 属性前
post_sibs_property_read char[MAX_BUFF_SIZE] 读取 SIBS 属性后
otp_info_bytes char[OTP_INFO_BYTES_MAX_SIZE] OTP 字节信息
stuck_issue char[MAX_BUFF_SIZE] 卡死问题描述
pre_diag_rx_acl char[MAX_BUFF_SIZE] 诊断 ACL 接收前
post_diag_rx_acl char[MAX_BUFF_SIZE] 诊断 ACL 接收后
pre_diag_rx_hci char[MAX_BUFF_SIZE] 诊断 HCI 接收前
post_diag_rx_hci char[MAX_BUFF_SIZE] 诊断 HCI 接收后
pre_diag_tx_acl char[MAX_BUFF_SIZE] 诊断 ACL 发送前
post_diag_tx_acl char[MAX_BUFF_SIZE] 诊断 ACL 发送后
pre_diag_tx_hci char[MAX_BUFF_SIZE] 诊断 HCI 发送前
post_diag_tx_hci char[MAX_BUFF_SIZE] 诊断 HCI 发送后
bqr_rie_info char[MAX_CRASH_BUFF_SIZE] BQR RIE 信息
uart_ipc_err char[MAX_BUFF_SIZE] UART IPC 错误描述
delay_list_info std::string 延迟列表信息
bqr_rie_vs_params std::string BQR RIE VS 参数信息
fw_su_build_info_set_time struct timeval 设置固件构建信息的时间
pre_stack_iso char[MAX_BUFF_SIZE] ISO 堆栈前状态
post_stack_iso char[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,创建或覆盖写入。