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

来源路径/定位内容适用
主 txtbugreport-*.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 device 0 命中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/pid5684CarSettings-*/MiBluetooth*点击、弹窗、onPair/onCancel
② 服务(Bluetooth App)uid1001002/pid27203BluetoothAdapterService/BluetoothBondStateMachine/RemoteDevicesbinder入口、状态机、广播源
④ 协议栈(bluedroid)uid1001002/tid27268bt_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 Appbinder入口、profile启停195848 createBond / 224598 connectEnabledProfile
BluetoothBondStateMachine③Bluetooth AppBOND_xxx广播源、SDP延迟195914 BONDING / 213446 wait for SDP / 224044 BONDED
RemoteDevices③Bluetooth AppACTION_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交互、弹窗、自动accept205973 onPair / 221952 onClick negative

速读 btm_confirm_req_reply() State: IDLE Res: 11State: IDLE=协议栈配对状态机空闲(没开始或已BONDED),不是”待确认”——新人90%误读。看到这行=你的 cancelBondProcess/setPairingConfirmation 在底层 no-op。

9. 对抗自查清单

  1. logcat 实时 vs bugreport 离线:实时看”现在”,bugreport 是”过去快照”。复现型用实时;偶发只能啃 bugreport(必先 awk 切窗)。
  2. f3dif 黑名单失效不是”配置错”:A17 读逻辑源码层不存在(H6),settings put 写多少次都没用——转查 onBondingStateChanged 是否该为 CarPlay 跳过 connect()。
  3. BONDED 广播到达 ≠ 配对刚完成:被 SDP 延迟 0.05~3s(2956 实测1.674s)。判断”配对完成时刻”grep Storing link key/底层BONDED,勿拿广播时间戳当锚点
  4. 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.抽帧