蓝牙知识库 2.0 · 建设大纲与调研规划

目的:让刚接手蓝牙模块的新人从「协议概念 → Android 框架 → 本仓代码 → 排障实战」四层递进上手。 现状诊断:已有 01/02/03 三篇偏「代码地图」(写得不错,保留),但缺第 0 层基础知识第 4 层排障实战——新人没有概念地基,直接看代码地图仍然懵。 使用方式:本文件每个章节 = 一个独立调研任务,含【待回答问题清单 + 代码取证锚点 + 对抗审查点】。拿去 GLM 时每章 spawn 2 个 agent(1 调研 + 1 对抗审查),对抗通过后才落库。 日期:2026-07-23 | 模块根:settingsPage/micarConnectionSettings/src/main/java/com/android/car/settings/miauto/bluetooth/


总体结构(目标目录树)

docs/连接/蓝牙/
├── 00-蓝牙-README.md                 (已存在,改造为总索引 + 学习路径)
├── 10-基础概念篇(新)
│   ├── 10-蓝牙协议速成.md             ★新人第一课
│   ├── 11-配对与SSP安全机制.md        ★MANNPROB-2956 直接相关
│   └── 12-Profile体系与车机角色.md
├── 20-Android框架篇(新)
│   ├── 20-Android蓝牙框架全景.md      ★新人第二课
│   ├── 21-settingslib架构与事件流.md  ★理解本仓的前提
│   └── 22-双flavor差异-dcddif-xcddif.md
├── 30-模块流程篇(已有,补强)
│   ├── 01-蓝牙-发现流程.md            (已存在)
│   ├── 02-蓝牙-配对流程.md            (已存在,待补 2956 案例修正)
│   ├── 03-蓝牙-设备详情与状态控制.md  (已存在)
│   ├── 31-连接与自动连接策略.md       (新)
│   ├── 32-双蓝牙上限与Picker.md       (新)
│   └── 33-CarPlay特殊链路.md          (新)
├── 40-排障实战篇(新)
│   ├── 40-日志取证速查.md             ★logcat tag / bugreport 定向 grep
│   ├── 41-经典案例-MANNPROB-2956.md   ★配对取消仍成功(已完成根因分析,素材现成)
│   └── 42-踩坑与反直觉设计.md         (死代码/过滤设计/UI先行 汇总)
└── 50-速查卡(新)
    ├── 50-术语与类职责速查.md
    └── 51-广播与事件清单.md

学习路径建议(写进 README):新人按 10→11→12→20→21→01→02→03→31~33→40 顺序读;排障时直接查 40/50。


任务卡 · 10 基础概念篇

任务 10:《蓝牙协议速成》★新人第一课

目标:不依赖本仓代码,建立协议层心智模型。读完能听懂「BR/EDR、BLE、ACL、SDP、UUID、配对码」这些词。 待回答问题清单

  1. BR/EDR(经典蓝牙)与 BLE 的区别?车机连手机走哪个?(MANNPROB-2956 日志里 Transport: 1 和 LE 侧 45.088 各是什么)
  2. 蓝牙设备怎么被「发现」?Inquiry / Scan / Advertise 的过程;设备 class of device(CoD)里的 major class(PHONE/AUDIO…)——为什么本仓扫描列表只显示手机(MiBluetoothUtils.isDeviceClassTypeSupport:131-160 的过滤依据)?
  3. SDP 是什么?UUID 怎么标识服务?ACTION_UUID 广播什么时候来?
  4. ACL 连接是什么?ACTION_ACL_CONNECTED/DISCONNECTED 和 profile 连接(HFP connect)是什么关系?
  5. 蓝牙地址、名称、别名(ALIAS)的区别。 对抗审查点:把「配对=连接」「发现=可连接」这类常见混淆逐个证伪;明确「bond(配对/绑钥)≠ ACL 连接 ≠ profile 连接」三层独立状态。 产出10-蓝牙协议速成.md,含一张「三层状态」图。

任务 11:《配对与 SSP 安全机制》★MANNPROB-2956 直接相关

目标:彻底搞懂配对流程与 4 种配对变体,能看懂 variant=2is_auto_accept_ssp=false 这类日志。 待回答问题清单

  1. 配对的本质是什么?(交换并持久化 Link Key/LTK;bond 状态机 BOND_NONE→BOND_BONDING→BOND_BONDED)
  2. SSP(Secure Simple Pairing)四种模式:Just Works / Numeric Comparison / Passkey Entry / Out of Band——各自的用户交互与安全级别(MITM 防护)。
  3. Android 侧配对变体常量:PAIRING_VARIANT_PASSKEY_CONFIRMATION(2)、CONSENTDISPLAY_PASSKEYPIN 各对应什么 UI?(对照 MiBluetoothPairingController.kt 各分支 + AOSP BluetoothPairingController.java
  4. createBondACTION_PAIRING_REQUESTsetPairingConfirmationBOND_BONDED 的完整时序;cancelBondProcessremoveBond 的语义差异(前者只对进行中的配对有效,IDLE 态空转;后者是唯一能撤销已完成配对的动作——2956 的血泪教训)。
  5. 为什么 BOND_BONDED 广播会被「wait for service discovery UUIDs」延迟?(BondStateMachine 等 SDP 完成再广播,44.862→46.534 延迟 1.67s 的实例)
  6. 跨传输密钥分发:BR/EDR 配完后 LE 侧怎么也 BONDED 了(SMP over BR,45.087 Save LTK)? 对抗审查点:「Numeric Comparison 必须用户点确认」是否绝对?(本仓车机主动发起时自动 accept,属设计降级为 Just Works 语义——代码 MiBluetoothPairingDialogFragment.kt:179-182);「自动 accept 是协议要求」这一说法要证伪(is_auto_accept_ssp=false 证明栈把决定权上抛应用层)。 产出11-配对与SSP安全机制.md,含配对时序图 + 变体对照表 + 「取消语义」专题框。

任务 12:《Profile 体系与车机角色》

目标:搞清车机在每个 profile 里的角色(谁是 Source 谁是 Sink、谁是 AG 谁是 HF),以及「配对成功后哪些 profile 会自动连」。 待回答问题清单

  1. HFP(车机=HF 免提端,手机=AG):通话链路;HfpClientProfile 在 settingslib 的位置。
  2. A2DP(车机=Sink 放音乐,手机=Source);A2dpSinkProfile vs A2dpProfile 并存的原因。
  3. PBAP(电话本同步):为什么详情页只有 PBAP 有独立开关MiCarBluetoothDeviceDetailFragment),其他 profile 没有?
  4. MAP(短信)、HID(手柄/键鼠)、PAN、SAP、OPP:本仓各自用不用?
  5. CarPlay 为什么靠一个私有蓝牙 UUID 2d8d2466-e14d-451c-88bc-7301abea291a 识别(ConnectionUtils.kt:30-31)?蓝牙在 CarPlay 里只承担「握手跳板」,真正的数据走 WiFi——这个「跳板」机制要讲清。
  6. BLE Audio / LeAudioProfile / HearingAid 在 xcddif flavor 出现、dcddif 没有——车机用不用? 对抗审查点:「profile 连接由系统自动完成」的说法要细化——本仓是 App 侧 settingslib CachedBluetoothDevice.onBondingStateChanged→connect()(xcddif:1090)触发,不是纯系统行为;disableAutoConnect 黑名单(xcddif:1079)何时生效、为何 2956 里没拦住 HFP/PBAP(待验证项)。 产出12-Profile体系与车机角色.md,含 profile-角色-开关-自动连接 四列表格。

任务卡 · 20 Android 框架篇

任务 20:《Android 蓝牙框架全景》★新人第二课

目标:建立「App → BluetoothAdapter API → BluetoothAdapterService(packages/apps/Bluetooth)→ BTIF/协议栈 → HCI」的分层模型,知道每层出问题看什么日志。 待回答问题清单

  1. BluetoothAdapter / BluetoothDevice 公开 API 概览;binder 到哪个进程(com.android.bluetooth)?
  2. BondStateMachine 是什么?它为什么要在 BONDED 前等 SDP UUID?(2956 关键:handleBondStateChanged: is bonded, wait for service discovery UUIDs)——需要读 packages/apps/Bluetooth 仓源码确认挂起/超时机制,这是当前知识空白
  3. 日志 tag 速查:BluetoothAdapterService / BluetoothBondStateMachine / bt_btif_dm / bt_btm_sec / smp 各代表哪一层?(示例:btm_confirm_req_reply() State: IDLE Res: 11 怎么读)
  4. 广播体系:ACTION_STATE_CHANGED / ACTION_BOND_STATE_CHANGED / ACTION_ACL_* / ACTION_UUID / ACTION_PAIRING_REQUEST 的产生源与时序保证(重点:广播不是实时信号,应用层不能假设它即时到达)。
  5. HCI snoop log 是什么、在哪、什么场景才需要它。 对抗审查点:「BOND_BONDED 广播到达 = 配对刚完成」证伪(可能延迟数秒);「getBondState() 和广播哪个可信」——getBondState 读服务侧实时状态,广播有延迟(2956 修复方案的依据)。 产出20-Android蓝牙框架全景.md,含分层图 + tag→层映射表。

任务 21:《settingslib 架构与事件流》★理解本仓的前提

目标:搞懂本仓复用的 base/settingsLibAndroid 蓝牙部分:LocalBluetoothManager / BluetoothEventManager / CachedBluetoothDevice(Manager) / LocalBluetoothProfile(Manager) 四件套的职责与数据流。 待回答问题清单

  1. LocalBluetoothManager 单例怎么拿(MiBluetoothUtils.getLocalBtManager())?它聚合了什么?
  2. BluetoothEventManager 注册的 ~25 个广播清单(xcddif 版 :108-181)→ 每个广播分发给谁?(这就是「系统事件 → UI 刷新」的总线)
  3. CachedBluetoothDevice 是什么?(设备的状态聚合体:bond 状态 + profile 连接状态 + 名称)onBondingStateChanged(xcddif:1090)里 isBondingInitiatedLocally→connect() 的自动连接链。
  4. LocalBluetoothProfileManager 如何管理各 profile?connect()/connectEnabledProfiles 的顺序(2956 日志:先 HFP 后 PBAP 排队)。
  5. UI 层怎么监听:BluetoothCallback 接口(BluetoothMainEntrySettingsFragment 注册)的回调集合。
  6. 双蓝牙上限DOUBLE_BLUETOOTH_DEVICE_LIMIT=2ConnectionConstants.kt:19)三处拦截点分别在哪、各拦什么场景。 对抗审查点:dcddif 与 xcddif 两套源码并存——同一符号两份实现,引用时必须标注 flavor(2956 分析里 xcddif:1090 与 dcddif:851 同逻辑但行号不同);「settingslib 是 AOSP 原样拷贝」证伪(有小米定制,如自动连接、黑名单)。 产出21-settingslib架构与事件流.md,含四件套类图 + 事件流图(广播→EventManager→Callback→UI)。

任务 22:《双 flavor 差异 dcddif vs xcddif》

目标:说清为什么会有两套 settingslib(DCD=骁龙 8295 / XCD=自研玄戒),差异点清单,以及「改蓝牙逻辑要不要两边都改」。 待回答问题清单

  1. flavor 怎么选(build variant);编译时哪套生效(对照 micarsettings-build skill 的变体规则)。
  2. diff 两套 settingsLibAndroid/src/{dcddif,xcddif}/java/com/android/settingslib/bluetooth/:xcddif 多出 LeAudio/DeviceGroup/广播音频等——是平台能力差异还是版本差异?
  3. 2956 修复(onCancel 降级 removeBond)是否需要双 flavor 同步改?本仓(非 settingslib)代码有没有 flavor 分支? 对抗审查点:「改一处即可」的说法危险——确认 MiBluetoothPairingController.kt 等本仓文件是单份还是按 flavor 分;settingslib 内改逻辑必须双 flavor 对照。 产出22-双flavor差异.md,含差异点表格 + 「改代码时的 flavor 检查清单」。

任务卡 · 30 模块流程篇(补强 + 新增)

任务 31:《连接与自动连接策略》(新)

待回答问题清单

  1. 配对成功后谁触发 profile 连接(settingslib connect 链,见任务 12);「连接/断开」按钮路径(BluetoothBondedDevicesPrefController.handlePreferClick + 断开确认弹窗 :220-243)。
  2. 回连策略:进蓝牙页/开机后自动回连哪台设备?ConnectionUtils.recordLastConnectedDevice + BluetoothDeviceService(断连时更新 last device 给蓝牙音乐用)的机制。
  3. CarPlay 设备 disableAutoConnectMiBluetoothPairingRequest.kt:104-106)与黑名单 isCloseAutoConnectDevice(xcddif:1079):2956 里为何没拦住自动连接?这是开放问题,需要代码+日志验证
  4. 双蓝牙场景:已连 2 台手机时的互斥/抢占规则。 产出31-连接与自动连接策略.md

任务 32:《双蓝牙上限与 Picker》(新)

待回答问题清单

  1. DOUBLE_BLUETOOTH_DEVICE_LIMIT=2 三处拦截点(配对请求 :85 / 列表 UI / Picker)逐一核。
  2. MiBluetoothPickerDialogActivity/Fragment 是什么场景拉起(副驾/互联选设备?)与主配对流程的关系。
  3. DevicePairStageEvent(isBusy/isConnected/mBondState)在谁和谁之间传递、解决什么并发问题。 产出32-双蓝牙上限与Picker.md

任务 33:《CarPlay 特殊链路》(新)

待回答问题清单

  1. CarPlay 设备识别(私有 UUID)→ 配对 → 二次弹窗 MiCarplayConnectTypeChooseDialogActivity(蓝牙连接 vs CarPlay)的完整链路;150ms 延迟拉起的设计意图。
  2. MisComplexSdk(车机互联 SDK,外部 aar)在详情页/配对页的监听(MiCarBluetoothDeviceDetailFragment:73-79)。
  3. CarPlay 与双蓝牙上限的交互;CarPlay 断开后的蓝牙残留行为。
  4. 关联文档:docs/连接/车机互联/01-车机互联-CarPlay-CarLink-AndroidAuto.md 交叉引用。 产出33-CarPlay特殊链路.md

任务 30-fix:《02-配对流程.md 修正补强》(已有文档修订)

待办

  1. 补 MANNPROB-2956 实证修正:①onCancel(:283)仅 cancelBondProcess 无降级;②BONDED 广播可被 service discovery 延迟,「配对完成立刻 dismiss」不可依赖;③receiver 取消后未解注册导致迟到广播拉起 CarPlay 弹窗(:190-215 在 isFinishing 检查 :218 之前)。
  2. 状态机章节补「广播延迟窗口」时序图。 产出:修订 02-蓝牙-配对流程.md

任务卡 · 40 排障实战篇

任务 40:《日志取证速查》

待回答问题清单(以 MANNPROB-2956 bugreport 为教材,素材在 /home/zbc/下载/test/车机JIRA/jira-data/MANNPROB-2956/):

  1. logcat 定向 grep 清单:配对问题 grep 什么(createBond|BOND_|Pairing|btm_|smp)、连接问题 grep 什么(connectEnabledProfile|HeadsetClient|A2dpSink|ACL)。
  2. bugreport 里蓝牙章节在哪;如何按时间窗过滤(问题时间 16:24 → awk '/^07-22 16:24:4/')。
  3. 时间线重建方法:App 层日志(CarSettings-)↔ 服务层(BluetoothAdapterService/BondStateMachine)↔ 协议栈(bt_)三层对齐,找「谁先谁后」。
  4. 视频/录屏逐帧与日志时间戳对齐技巧(ffmpeg 抽帧)。 产出40-日志取证速查.md,grep 命令可直接复制。

任务 41:《经典案例 MANNPROB-2956》

素材现成jira-data/MANNPROB-2956/analysis/root-cause.md(15 条 bugreport 证据 + 8 处 file:line + 视频 11 帧)。 待办:改写成教学案例——问题现象 → 三层时间线重建 → 四个假设 → 对抗审查推翻过程(H1 被源码证伪、H4 自灭)→ 最终根因(onCancel 无降级 + receiver 未解注册)→ 修复方案。重点呈现「想当然的根因如何被证据推翻」的方法论,不只是结论。 产出41-经典案例-MANNPROB-2956.md

任务 42:《踩坑与反直觉设计汇总》

待办(素材在现有 00-README 已确认事实 + 本次分析):

  1. 死代码清单:BluetoothDisconnectConfirmDialogFragment(仅自引用)、设备过滤 condition2 耳机分支。
  2. 反直觉设计:扫描列表只显示手机(预期设计非 bug);UI 先行+防抖的开关;详情页只有 PBAP 开关;AOSP 布局遗产不加载。
  3. 双 flavor 同名类行号不同,引用必须带 flavor 前缀。 产出42-踩坑与反直觉设计.md(持续追加,仿 jira-analyze/LESSONS.md 格式:现象+原因+怎么办+实例锚点)。

任务卡 · 50 速查卡

任务 50:《术语与类职责速查》

待办:两页纸——①术语表(bond/ACL/SDP/SSP/CoD/UUID/profile/flavor…)②本仓 30 个源文件 + settingslib 四件套的一句话职责表(类名 | 职责 | 关键行号)。 产出50-术语与类职责速查.md

任务 51:《广播与事件清单》

待办:BluetoothEventManager 全部注册广播表格(action | 含义 | 分发到哪 | 相关代码行),从 xcddif:108-181 逐条整理 + dcddif 差异标注。 产出51-广播与事件清单.md


GLM 多 agent 调研编排建议

节奏(3 轮,每轮并行 ≤4 个任务,避免互相踩踏)

  • 第 1 轮(概念地基):任务 10、11、12、20 —— 纯知识型,GLM 可直接产出,代码引用用本文锚点。
  • 第 2 轮(框架与本仓):任务 21、22、31、32 —— 需要读代码,给 agent 开源码只读权限(仓:/home/zbc/car/MiCarSettings)。
  • 第 3 轮(实战与速查):任务 33、40、41、42、50、51 + 30-fix —— 41 素材现成可直接写。

每个任务的对抗环节(不可省):调研 agent 产出后,spawn 对抗 agent 专挑:

  • 无 file:line / 日志行号支撑的「想当然」论断;
  • 协议层面的绝对化表述(「必须/一定/从不」);
  • 把 AOSP 行为当本仓行为(或反之);
  • flavor 混淆(dcddif/xcddif 行号张冠李戴)。

落库规范

  • 每篇头部写 > 核心文件: 和适用范围,与现有 01/02/03 风格对齐;
  • 事实性论断必须带锚点(file:line 或日志时间戳);推测性内容标「待验证」;
  • 核实过的事实同步追加到 docs/连接/_已核实事实基准.md,对抗过程记录追加 _对抗审查记录.md(沿用连接模块既有惯例)。

优先级(如果时间有限,先做这 5 个):任务 11(SSP 配对机制)、20(框架全景)、21(settingslib)、41(2956 案例)、40(日志取证)——这五个读完就能独立排查大部分蓝牙 bug。


2026-09-06 增补:80 系列 + 23 章 + 基础事实修正

  • 新增 80-Auracast广播QR篇(80 总览 / 81 QR 协议与编解码 / 篇内 _对抗核验记录-80篇.md):LE Audio 广播扫码链路,此前知识库空白段。
  • 新增 23-BluetoothCallback契约与接入指南(20 系列第 4 篇):51 §4 的操作手册延伸——6 个实现者、扩展三步、flavor 成对增删矩阵。
  • 基础事实修正(README/22/基准同步):f3dif 已合入 dev(262 文件,与 dev_a17_0610 同 blob);sourceSets 4→5 变体(新增 xcd_global_a14);BluetoothCallback 实现者 1→6。
  • 对抗:第四轮(12 声明 11 PASS 1 FAIL),见 ../_对抗审查记录.md
  • 留待任务:82+ LocalBluetoothLeBroadcast 源管理与 BroadcastAssistant 链路;f3dif Auracast 事件新机制(EventManager 删分发后走什么);f3dif 版 Ext 的 SIG 格式逐字段对照;BluetoothEventManagerExt/LocalBluetoothManagerExt 两个 f3dif 专属扩展的职责。