【android bluetooth 协议分析 02】【bluetooth hal 层详解 8】【高通蓝牙hal-进程被杀之前日志收集流程】
1. 背景
【android bluetooth 协议分析 02】【bluetooth hal 层详解 7】【高通蓝牙hal-读流程介绍】
上一节我在介绍 hal 读流程时,我们先从一个报错开始梳理。 本节还是看这个报错的例子。
hal 进程 出现错误,在被干掉之前。会触发 SSR 日志收集。目的是方便 让开发人员定位问题。
如果你已经很清楚上面的日志代表什么含义,请忽略本篇。
在阅读本篇开始时请思考如下几个问题:
- SSR 是什么? 高通的 SSR 机制是如何触发收集日志的?收集日志的流程是什么? 除了收集日志还之外还需要处理那些事情?
- 我们从 打印的这些log 里面,能获取那些有用的信息,来辅助我们定位问题?
- 我们怎么利用高通原有的日志收集系统,增加调试信息? 当出现 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 中会涉及到两个 重要的 错误原因:
- PrimaryReasonCode : 用于标识蓝牙系统崩溃或异常的 一级原因分类,通常是宏观层面上的崩溃来源。
- 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 |
---|---|---|---|---|
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 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)
错误码 | 名称 | 出错场景 | 可能原因 |
---|---|---|---|
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 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()
主要用于:
-
打印和记录蓝牙栈关键事件的时间戳(如 HCI cmd、ACL、ISO、select 调用)。
-
将这些信息保存在
BtState
中供崩溃分析。 -
打印出详细的日志用于日志系统抓取。
-
最后调用
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_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,创建或覆盖写入。