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 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()
主要用于:
打印和记录蓝牙栈关键事件的时间戳(如 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_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,创建或覆盖写入。