40 · 日志取证速查
核心文件:bugreport 主 txt / logcat 实时流 / dumpstate_board / btsnoop / 录屏 mp4 适用范围:蓝牙排障日志取证——拿到一份 bugreport 后从哪 grep、按哪条时间线重建、视频如何对齐 实证:MANNPROB-2956 bugreport(
/home/zbc/下载/test/车机JIRA/jira-data/MANNPROB-2956/),151 MB / 1,425,934 行 + 11 帧录屏,所有命令实跑通过
0. 这份文档解决什么
20-框架全景 给了”哪层叫什么 tag”的地图,11-配对与SSP 给了配对理论。本文是第三件武器:拿到 100+ MB bugreport,10 分钟挖出证据链。所有命令在 2956 bugreport 跑过、可直接复制。
export BUG="/home/zbc/下载/test/车机JIRA/jira-data/MANNPROB-2956/attachments/bugreport/bugreport-fermi-CP2A.260605.016-2026-07-22-16-24-55.txt"
export VID="/home/zbc/下载/test/车机JIRA/jira-data/MANNPROB-2956/attachments/小米办公Pro20260722-162834.mp4"1. bugreport 蓝牙章节在哪:主 txt + dumpstate_board + btsnoop
| 来源 | 路径/定位 | 内容 | 适用 |
|---|---|---|---|
| 主 txt | bugreport-*.txt(2956: 151MB/1,425,934 行) | 全程 logcat + dumpsys 快照 | 配对/连接/广播/profile,绝大多数 bug |
| dumpstate_board | /data/user_de/0/com.android.shell/files/bugreports/dumpstate_board.{txt,bin}(2956 行121686/198630) | 厂商 HAL 私有 dump(芯片日志) | 协议级疑难 |
| btsnoop | /data/misc/bluetooth/logs/*.btsnoop(主 txt 不含,需单独抓) | HCI 帧(L2CAP/SMP/RFCOMM) | SSP 包级、ACL 断因 |
主 txt 章节定位(2956 实证行号):
grep -n "DUMP OF SERVICE bluetooth_manager" "$BUG" # 2956: 953857
grep -n "bluetooth_close_autoconnect" "$BUG" # 2956: 1193483(value空→黑名单未生效)
grep -n "hci1_bt_config.conf\|Config created with path" "$BUG" # 密钥落盘位置主 txt 里
btsnoop_hci没有是正常的(2956 grep 0 命中)——snoop 不进 logcat,要单独开。不要因主 txt 没 snoop 就结论”没抓到”。
2. 时间窗过滤三板斧
2956 故障窗 16:24:40 ~ 16:24:47:
# ① 分钟级窗口(最常用)
awk '/^07-22 16:24:4[0-9]/' "$BUG" > w_16_24_4x.log
# ② 秒级(事件密集缩到秒)
awk '/^07-22 16:24:44./' "$BUG"
# ③ 窗内再按 tag 并集
awk '/^07-22 16:24:4[0-9]/' "$BUG" | grep -E "BluetoothBondStateMachine|bt_btm_sec|smp_|bt_btif_dm" | grep -E "createBond|BOND_|variant|Storing link key|wait for service|State: IDLE"3. 配对问题 grep 字典
grep -nE "createBond|cancelBondProcess|removeBond|BOND_NONE|BOND_BONDING|BOND_BONDED" "$BUG"
grep -nE "ACTION_PAIRING_REQUEST|sendPairingRequestIntent|pairingVariant|variant=|pairingAlgo" "$BUG"
grep -nE "is_auto_accept_ssp|sspRequestCallback|Storing link key|key_type|link_key_notification" "$BUG"
grep -nE "btm_confirm_req_reply|Unexpected pairing|smp_save_secure_connections|smp_calculate_long_term" "$BUG"
grep -nE "setPairingConfirmation|onPair|onCancel|onClick negative|MiBluetoothPairing" "$BUG"配对排查决策树
flowchart TD Start([配对异常 bugreport]) --> W1[切时间窗 awk] W1 --> G1{grep createBond 命中?} G1 -- 否 --> A1[App没发起 查扫描闸门/点击] G1 -- 是 --> G2{grep BOND_BONDING 3ms内即时?} G2 -- 否 --> A2[栈层拒配 查btm_sec鉴权] G2 -- 是 --> G3{grep variant=/PAIRING_REQUEST?} G3 -- 否 --> A3[SSP未触发 对端没响应] G3 -- 是 --> G4{grep Storing link key/key_type?} G4 -- 否 --> A4[SSP半途失败 查smp_/Res码] G4 -- 是 --> G5{grep wait for service discovery UUIDs?} G5 -- 是 --> B1[广播被SDP延迟0.05~3s 2956落点44.862] G5 -- 否 --> A5[直接BONDED无延迟] B1 --> G6{用户操作落在窗口内? grep onCancel} G6 -- 是 --> C1[🚨2956路径 cancelBondProcess vs已BONDED<br/>查State:IDLE Res:11 → onCancel加removeBond降级] G6 -- 否 --> Done([正常配对 证毕])
4. 连接问题 grep 字典
grep -nE "connectEnabledProfile|connectDevice|connectAllEnabledProfiles|mDevice\.connect" "$BUG"
grep -nE "HeadsetClient|A2dpSink|A2dpSinkService|PbapClient|MapClient" "$BUG"
grep -nE "ACTION_ACL_CONNECTED|ACTION_ACL_DISCONNECTED|onAclStateChanged" "$BUG"
grep -nE "onBondingStateChanged|isBondingInitiatedLocally" "$BUG"
grep -nE "isCloseAutoConnectDevice|close auto connect|cancel connect as device|disableAutoConnect" "$BUG"
grep -nE "bluetooth_close_autoconnect|BLUETOOTH_CLOSE_AUTO_CONNECT" "$BUG"A17(f3dif) 黑名单失效信号:2956 grep
close auto connect | cancel connect as device0 命中,bluetooth_close_autoconnect在 dumpsys settings value 空(行1193483)——f3dif 无isCloseAutoConnectDevice读逻辑(H6 实证)。A17 排查 CarPlay 抢占正门不存在,别在旁路浪费时间。
连接排查决策树
flowchart TD Start([连接异常 bugreport]) --> W1[切窗 以BONDED广播为锚向后5s] W1 --> G1{grep connectEnabledProfile/HeadsetClient?} G1 -- 否 --> A1[框架没发起 查onBondingStateChanged] G1 -- 是 --> G2{flavor?} G2 -- dcddif/xcddif --> G3{grep isCloseAutoConnectDevice?} G2 -- f3dif A17 --> R1[🚨黑名单100%失效 H6无读逻辑<br/>正门不存在 排查别的] G3 -- 命中黑名单 --> A2[符合预期被拦] G3 -- 未命中/value空 --> A3[黑名单未写或被覆盖 H1/H2/H3] R1 --> G4{grep onUuidChanged triggering connectDevice?} G4 -- 是 --> A4[onUuidChanged旁路 仅dcddif/xcddif] G4 -- 否 --> Done([正常自动连接 证毕])
5. 三层时间线重建:找”谁先谁后”
同一个事实在三层日志有三个时间戳,对齐后才能看出竞态:
| 层 | uid/pid(2956) | 代表 tag | 职责 |
|---|---|---|---|
| ① App(CarSettings) | uid1001000/pid5684 | CarSettings-*/MiBluetooth* | 点击、弹窗、onPair/onCancel |
| ② 服务(Bluetooth App) | uid1001002/pid27203 | BluetoothAdapterService/BluetoothBondStateMachine/RemoteDevices | binder入口、状态机、广播源 |
| ④ 协议栈(bluedroid) | uid1001002/tid27268 | bt_btif_dm/bt_btm_sec/smp_* | JNI桥、安全、密钥协商 |
2956 三层对齐(行号全实证)
sequenceDiagram participant App as ①App uid1001000/pid5684 participant Svc as ②服务 BondStateMachine participant Stack as ④栈 btm_sec/smp App->>Svc: createBond (40.698 行195848) Svc-->>Svc: BOND_NONE⇒BONDING (40.701 行195914, 3ms即时) Stack->>Svc: is_auto_accept_ssp=false (43.084 行205431) Svc-->>App: PAIRING_REQUEST variant=2 passkey=196742 (43.086 行205453) App->>Svc: 自动onPair setPairingConfirmation(true) (43.184 行205973, 2ms) Stack->>Stack: Storing link key key_type=0x8 (44.855 行213311) Stack->>Svc: 底层BONDED 广播未发 (44.860 行213396) Svc->>Svc: wait for SDP UUIDs 推迟广播 (44.862 行213446) Stack->>Stack: CTKD 存LTK/IRK (45.087 行214289+) App->>Svc: 用户取消 onCancel (46.336 行221952) App->>Svc: cancelBondProcess (46.339 行221988) Stack-->>Stack: State:IDLE Res:11 空转 (46.339 行221988) Note over Svc: 1.674s后 Svc-->>App: BONDING⇒BONDED广播 迟到 (46.534 行224044) App->>App: dismiss拉起CarPlay弹窗 (46.552 行224281) Svc->>Svc: connectEnabledProfile HeadsetClient (46.583 行224598)
对齐命令(以 BondStateMachine 为枢纽):
awk '/^07-22 16:24:4[0-9]/' "$BUG" \
| awk '$5 ~ /BluetoothBondStateMachine|BluetoothAdapterService$/ {print "②服务 " $0}
$5 ~ /bt_btif_dm|bt_btm_sec|^smp/ {print "④栈 " $0}
$5 ~ /CarSettings|MiBluetooth/ {print "①App " $0}' \
| grep -E "createBond|BOND_|variant|Storing link|wait for SDP|onPair|onCancel|State: IDLE|connectEnabledProfile"“谁先谁后”看三点:① BOND_BONDING 广播是否 createBond 后 3ms 内;② 底层 Storing link key/BONDED 是否早于用户取消;③ connectEnabledProfile 是否在 BONDED 广播后。2956 三点全中:底层 44.860 已 BONDED → 用户 46.336 取消 → 广播 46.534 迟到 1.674s → 46.583 自动连接。
6. 视频逐帧对齐(ffmpeg)
mkdir -p /tmp/2956_frames && cd /tmp/2956_frames
ffmpeg -i "$VID" -vf "fps=1,start_number=0" f_%ds.png # f_0s.png 起
# 锚点反推偏移量(录屏秒数 ≠ bugreport时间):
# f_4s 弹确认框 ≈ 日志43.086 PAIRING_REQUEST
# f_6s 手机已配对 ≈ 日志44.860 底层BONDED
# f_10s CarPlay框 ≈ 日志46.552 dismiss录屏帧时间 ≠ bugreport 时间,必须用”弹窗出现/按钮点击/连接成功”这类双方都有的事件做锚点反推偏移量,不能直接套。
7. disableAutoConnect / 黑名单排查(A17 H6)
adb shell settings get secure bluetooth_close_autoconnect # 实时读
adb shell settings put secure bluetooth_close_autoconnect "AA:BB:CC:DD:EE:FF" # 写
adb shell settings delete secure bluetooth_close_autoconnect # 清
adb logcat -s BluetoothCachedDevice | grep -E "get close auto connect|cancel connect as device" # dcddif/xcddif才有
grep -nE "bluetooth_close_autoconnect|update bluetooth_close_autoconnect" "$BUG" # 离线查轨迹(2956:1193483)| flavor | 写入 | 读取 | 结论 |
|---|---|---|---|
| dcddif/xcddif | 有(MiBluetoothPairingRequest:106) | 有(CachedBluetoothDevice) | 黑名单生效,排查走 H4 旁路 |
| f3dif(A17主线) | 有 | 无(grep 0) | 黑名单100%失效(H6),正门不存在 |
8. 关键 tag → 层 → 典型行映射(2956 实证)
| tag | 层 | 出什么问题看它 | 2956 行号 |
|---|---|---|---|
BluetoothManagerService | ②system_server | 开关打不开 | — |
BluetoothAdapterService | ③Bluetooth App | binder入口、profile启停 | 195848 createBond / 224598 connectEnabledProfile |
BluetoothBondStateMachine | ③Bluetooth App | BOND_xxx广播源、SDP延迟 | 195914 BONDING / 213446 wait for SDP / 224044 BONDED |
RemoteDevices | ③Bluetooth App | ACTION_UUID/ACL_*广播源 | — |
bt_btif_dm | ④BTIF(JNI) | Java↔Native配对/发现桥 | 205431 is_auto_accept_ssp=false |
bt_btm_sec | ④BTM(安全) | 密钥、配对状态机、鉴权 | 213311 Storing link key / 221988 State:IDLE Res:11 |
smp_* | ④SMP | 密钥协商 | 214289+ CTKD Save LTK/IRK |
CarSettings-*/MiBluetooth* | ①App | 交互、弹窗、自动accept | 205973 onPair / 221952 onClick negative |
速读
btm_confirm_req_reply() State: IDLE Res: 11:State: IDLE=协议栈配对状态机空闲(没开始或已BONDED),不是”待确认”——新人90%误读。看到这行=你的 cancelBondProcess/setPairingConfirmation 在底层 no-op。
9. 对抗自查清单
- logcat 实时 vs bugreport 离线:实时看”现在”,bugreport 是”过去快照”。复现型用实时;偶发只能啃 bugreport(必先 awk 切窗)。
- f3dif 黑名单失效不是”配置错”:A17 读逻辑源码层不存在(H6),
settings put写多少次都没用——转查 onBondingStateChanged 是否该为 CarPlay 跳过 connect()。 - BONDED 广播到达 ≠ 配对刚完成:被 SDP 延迟 0.05~3s(2956 实测1.674s)。判断”配对完成时刻”grep
Storing link key/底层BONDED,勿拿广播时间戳当锚点。 - getBondState() 才权威:广播是延迟副本。决策用 getBondState(),刷新UI才用广播。
10. 一页速查
export BUG="<bugreport-*.txt>"
awk '/^MM-DD HH:MM:SS/' "$BUG" > w.log # 1.切窗
grep -nE "createBond|BOND_|variant=|is_auto_accept_ssp|Storing link key|wait for service|State: IDLE|smp_" w.log # 2.配对
grep -nE "connectEnabledProfile|HeadsetClient|A2dpSink|onBondingStateChanged|ACL" w.log # 3.连接
grep -nE "bluetooth_close_autoconnect|close auto connect|cancel connect as device" "$BUG" # 4.黑名单(A17跳过)
awk '$5~/BluetoothBondStateMachine/{print "② "$0} $5~/bt_btm_sec|bt_btif_dm|^smp/{print "④ "$0} $5~/CarSettings|MiBluetooth/{print "① "$0}' w.log # 5.三层对齐
grep -n "DUMP OF SERVICE bluetooth_manager\|bluetooth_close_autoconnect\|hci1_bt_config.conf" "$BUG" # 6.章节
ffmpeg -i "<video>.mp4" -vf "fps=1,start_number=0" f_%ds.png # 7.抽帧