# 同力老项目蓝牙模块完整代码分析 > 项目路径:`F:\zdCode\tongli_old` > 核心模块:`YX_BlueTooth` > 分析日期:2026-07-13 > 分析方式:静态代码分析,未修改项目源码,未执行真机蓝牙测试 ## 1. 总体结论 `YX_BlueTooth` 是一个拥有系统 UID 的独立车机蓝牙 APK,核心能力包括设备管理、HFP 蓝牙电话、A2DP/AVRCP 蓝牙音乐、PBAP 通讯录和通话记录同步,以及语音、仪表、音频通道、GPIO MIC、系统休眠唤醒等整车联动。 当前实际底层链路是: ```text 业务 UI / 广播 / AIDL ↓ UseCase / Presenter / Repository ↓ BtAdapterManager(约 4200 行的核心总控) ↓ GocJar(外部 GOC 蓝牙服务客户端) ↓ 外部蓝牙系统服务 / 蓝牙芯片 ↓ HFP / SCO / A2DP / AVRCP / PBAP 回调 ``` 旧的 `BtAdapter_NF2311` JNI 适配层仍保留大量 native API 和旧回调代码,但加载 native 库、初始化及主要调用均已注释。当前不能把旧 NF2311 回调中的功能等同于现行 GOC 链路已支持。 ### 1.1 功能成熟度判断 | 功能 | 代码状态 | 结论 | |---|---|---| | 蓝牙开关、扫描、配对、连接 | 主链路存在 | 可用,但存在回调过早、配对时序和状态一致性风险 | | 单方 HFP 电话 | 主链路较完整 | 拨号、来电、接听、挂断、拒接、DTMF、MIC、音频切换基本具备 | | 三方通话 | 有 UI、状态和旧回调残留 | **不能认定为完整支持**,新 GOC 回调链未形成可靠闭环 | | 蓝牙音乐 | 主链路完整 | A2DP 出声、AVRCP 控制、ID3、进度、音频焦点均具备 | | 通讯录/通话记录 | 主链路完整 | PBAP 下载、本地缓存、搜索和 Provider 查询均具备 | | 语音与整车联动 | 多条链路存在 | 功能丰富,但广播、全局状态和服务绑定耦合较重 | ## 2. 工程定位与依赖 - 包名:`com.yaxon.bluetooth` - 系统身份:`android:sharedUserId="android.uid.system"` - 最低 Android:API 19(Android 4.4) - 编译/目标 SDK:27 - 代码规模:约 160 个 Java 文件、23,911 行 - 自动化测试:未发现 `src/test` 或 `src/androidTest` 主要依赖: - `goc.jar`:当前蓝牙协议栈和外部服务接口 - `EventBus 2.4.0`:模块内事件分发 - `LitePal 1.3.1`:配对设备、通讯录、通话记录持久化 - `classes_44new.jar`:Android framework 隐藏 API - `yx_skin`:项目 UI/皮肤依赖 主要源码入口: - `YX_BlueTooth/src/main/java/com/yaxon/bluetooth/YXApplication.java` - `YX_BlueTooth/src/main/java/com/yaxon/bluetooth/nf2311/BtAdapterManager.java` - `YX_BlueTooth/src/main/java/com/yaxon/bluetooth/main/MainActivity.java` - `YX_BlueTooth/src/main/AndroidManifest.xml` ## 3. 启动和初始化 ```text YXApplication.onCreate() ├─ 初始化 SharedPreferences / LitePal ├─ 绑定语音切换服务 ├─ 绑定音频通道服务 ├─ 绑定 GPIO 服务 ├─ 绑定仪表音乐状态服务 ├─ BtAdapterManager.moduleInit() │ ├─ GocJar.init(context) │ ├─ 注册 Adapter/设置回调 │ ├─ 注册 HFP/SCO 电话回调 │ └─ 注册 A2DP/AVRCP/ID3 回调 └─ 启动 OpenBlueToothService ``` `OpenBlueToothService` 根据持久化的用户期望状态决定是否开蓝牙。这里存在冷启动竞态:如果 GOC AIDL 服务尚未连接,代码重新调用 `GocJar.init()` 后没有可靠的排队与重试,服务很快结束,可能出现“配置为开,实际未开”。 ## 4. 模块划分 | 模块 | 主要职责 | 关键类 | |---|---|---| | 应用总控 | 初始化、服务绑定、全局状态 | `YXApplication`、`ServiceBindManage` | | 底层适配 | GOC 命令、Profile 回调、状态汇聚 | `BtAdapterManager`、`GocJar` | | 蓝牙设置 | 开关、扫描、配对、连接、名称、PIN | `BluetoothSettingPresenter`、Setting Fragments | | 电话 | 拨号、来电、通话控制和通话 UI | `KeyBoardFragment`、`PhoningActivity`、`PhoningPresenter` | | 音乐 | AVRCP 控制、ID3、进度和页面 | `MusicFragment`、`AudioFocusManager` | | 通讯录 | PBAP、搜索、本地缓存、Provider | `PhoneBookRepository`、`BluetoothPhonebookProvider` | | 通话记录 | PBAP 通话记录、本地缓存、列表 | `CallRecordRepository`、`PhoneRecordFragment` | | 外部联动 | 语音、ITS、仪表、本地音乐、休眠 | 多个 Receiver、AIDL Service、`music_sdk` | ## 5. 设备管理功能 ### 5.1 蓝牙开关 ```text Setting UI → BluetoothSettingPresenter.openBluetooth()/closeBluetooth() → SwitchBluetooth UseCase → BtAdapterManager.setBluetoothPower(on, callback) → GocJar.setBtEnable(boolean) → onEnableChanged(boolean) → handleBluetoothOpened()/handleBluetoothClosed() → 设置图标、广播、扫描和 UI 回调 ``` 问题在于 `setBluetoothPower()` 将 `GocJar.setBtEnable()` 的命令受理结果当作最终状态,立即回调成功并执行 opened/closed 处理,没有等待 `onEnableChanged()`。真实回调到达时还可能再次执行,形成成功回调重复、语音回复成功但底层状态未完成等问题。 ### 5.2 扫描 ```text Presenter.inquiryDevice() → InquiryDevice → BtAdapterManager.inquiry() → GocJar.startBtDiscovery()/cancelBtDiscovery() → onAdapterDiscoveryStarted/Finished → onDeviceFound → LinkedInfoRepository → EventBus 刷新附近设备列表 ``` 扫描状态保存在 `YXApplication.mBlueToothInquiryStatus`。设备数据同时存在于 GOC 实际列表、Repository 内存和 LitePal 数据库中。 ### 5.3 配对和取消配对 附近设备点击后,Presenter 当前代码倾向于先发起 HFP 连接,再根据状态决定是否显式配对。由于连接结果异步,检查时 `mBlueToothConnect` 通常尚未变化,显式 `requestBtPair()` 可能不会执行。该时序依赖底层“连接自动触发配对”的容错能力。 取消配对先删除本地数据,再异步下发远端 unpair,失败时没有回滚,会造成车机列表与底层配对列表不一致。 ### 5.4 连接和断开 ```text ConnectMacDevice → 设置 mConnectingMac / mLinkingMac → requestHfpConnect(mac) → onHfpStateChanged(CONNECT_SUCCESSED) → 更新 mLinkedMac、Repository、广播、回调 ``` 总连接状态主要由 HFP 成功置位,因此 A2DP-only 情况不能可靠代表“已连接”。断开操作依赖 `mLinkedMac`,但该值主要在 HFP 成功后写入;进程恢复、状态丢失或仅媒体连接时可能为空或过期。 ### 5.5 名称和 PIN 代码支持读取/设置本机蓝牙名称和 PIN。当前实现中: - 已有名称偏好时,部分 `getBluetoothName()` 路径返回空串而不是偏好值。 - `setBluetoothPassWord()` 未可靠透传远端执行结果,调用侧可能收到伪成功。 ## 6. HFP 蓝牙电话 ### 6.1 页面与功能 - `KeyBoardFragment`:号码输入、删除、拨号、通话记录回拨。 - `PhoningActivity`:来电、去电、通话中 UI,计时、接听、拒接、挂断、MIC、手机/车机音频切换、DTMF、小键盘、三方提示。 - `PhoningPresenter`:通过 UseCase 把 UI 命令放入后台执行。 - `RingManager`:铃声音频焦点和系统来电标记;但 `startRing()` 未发现业务调用,本地铃声并未真正启动。 ### 6.2 电话调用链 拨号: ```text KeyBoardFragment → Dial UseCase → BtAdapterManager.dial(number) → GocJar.requestHfpDialCall(mac, number) ``` 来电/去电状态: ```text GOC onHfpCallChanged(mac, call) → 保存 Settings.System.BT_CALL_STATE → 映射为项目旧 phoneStatus → processCallStatus() → actionStart() → 启动/刷新 PhoningActivity → EventBus、广播、仪表状态上报 ``` 控制操作: | 功能 | 底层命令 | |---|---| | 接听 | HFP accept/pick up | | 挂断 | HFP hang up | | 拒接 | HFP reject | | DTMF | `requestHfpSendDtmf(mac, value)` | | MIC 静音 | `GocJar.muteHfpMic()` | | 转手机 | `requestHfpAudioTransferToPhone()` | | 转车机 | `requestHfpAudioTransferToCarkit()` | SCO(通话音频链路)状态通过回调更新 `scoState`。通话激活和结束还会调用 GPIO 服务切换物理 MIC 通道。 ### 6.3 电话状态模型 新 GOC 回调大致映射为: ```text IDLE / TERMINATED ├─ DIALING → phoneStatus=4 → 去电 └─ INCOMING → phoneStatus=5 → 来电 DIALING / INCOMING → ACTIVE → phoneStatus=6 → 通话中 ACTIVE → TERMINATED → phoneStatus=3 → 挂断 ``` 通话 UI 同时使用另一套 `CurrentCalls` 语义: | 值 | 含义 | |---|---| | 0 | ACTIVE | | 1 | HELD | | 2 | DIALING | | 3 | ALERTING | | 4 | INCOMING | | 5 | WAITING | 此外还有 `isPhoneActive`、`isMultiCallBuild`、`hfpState`、`scoState`、系统 Settings、EventBus 消息和外部广播,多套状态并存,没有统一状态机。 ## 7. 三方通话专项结论 ### 7.1 是否有三方通话功能 **代码中有三方通话意图、UI 和部分控制,但现行 GOC 链路不完整,不能确认产品具备可靠可用的三方通话功能。** 代码证据包括: - `isMultiCallBuild` 三方状态标志。 - `SECOND_PHONE_IN` 第二路来电事件。 - `CurrentCalls` 中 ACTIVE、HELD、WAITING 等状态。 - `PhoningActivity` 的第二路号码、等待提示、三方计时和处理 UI。 - `enhancedCallCtrl(int action)` 增强通话控制入口。 - `GocJar.setThreePartyCallEnable(true)` 三方开关命令。 ### 7.2 为什么不能认定完整支持 1. `enhancedCallCtrl(int action)` 完全忽略 `action`,无论调用方请求释放当前、保持当前、接听等待或合并,最终都只执行 `setThreePartyCallEnable(true)`。 2. `isMultiCallBuild=true` 和 `SECOND_PHONE_IN` 的明确设置点位于旧 `CallWaitingCallback()`;旧 NF2311 适配器初始化已被注释,现行 GOC 回调没有对应闭环。 3. 新 `onHfpCallChanged()` 使用 `prePreStatus == status` 直接去重。第二路电话如果状态值与第一路相同,但号码或 `isMultiParty` 变化,回调可能被丢弃。 4. 三方 ACTIVE 的映射存在被当成旧状态“普通来电”处理的可能,可能重复拉起或错误刷新通话页面。 5. 未找到针对不同增强通话 action 的底层命令映射,也没有三方通话自动化或真机验证证据。 ### 7.3 三方通话验收前置条件 必须在支持呼叫等待的手机和 SIM 卡上完成以下真机矩阵: - 通话 A 中收到 B 来电,显示第二路号码。 - 保持 A 并接听 B。 - 挂断 A 并接听 B。 - 在 A/B 间切换。 - 合并会议。 - 单独挂断其中一路。 - 手机端主动保持、切换、合并后,车机 UI 同步。 - 每一步验证 SCO、MIC、通话计时、仪表、本地音乐暂停恢复。 ## 8. 蓝牙音乐 ### 8.1 职责边界 应用自身不解码音乐: - A2DP:手机音乐音频流传输到车机。 - AVRCP:播放、暂停、停止、上一首、下一首、播放状态、进度和 ID3 元数据。 - GOC:提供 A2DP/AVRCP 命令和回调。 - `MusicFragment`:展示和控制 UI。 - `AudioFocusManager`:车机音频焦点、音量和其他音源协调。 ### 8.2 控制链 ```text MusicFragment / 语音 / MODE 按键 → PlayControls / ModePlayControls → BtAdapterManager.playControl(command) → GocJar AVRCP Play/Pause/Stop/Next/Prev → 手机端播放器 → AVRCP 播放状态回调 → mPlaying / UI / 仪表 / 音频通道 ``` MODE 场景会在首次 Play 后约 1.5 秒重试一次,以适配手机或协议栈尚未就绪的情况。 ### 8.3 播放状态 1. A2DP 连接后设置 `a2dpState=CONNECTED`;未取得播放条件时先将 A2DP 本地音量置 0。 2. AVRCP 连接后设置 `avrcpState=CONNECTED`。 3. 蓝牙主 Activity 进入前台时注册 `BTMusic/MusicBluetooth` 音频资源并申请媒体焦点。 4. UI/语音发送 AVRCP 命令。 5. 实际播放状态以 AVRCP 回调确认:`1=播放、2=暂停、0=停止`。 6. 播放且持有焦点时恢复 A2DP 音量、更新 UI 和仪表。 7. 未持有焦点却收到播放时,代码静音并连续发送 Pause。 8. 暂停、停止或 A2DP 断开时,更新 UI 并注销/释放相关音频资源。 ### 8.4 ID3 和进度 AVRCP 1.3 元数据写入静态 `ID3Repository`: - 标题 - 歌手 - 专辑 - 总时长 - 当前进度 更新后通过 EventBus 刷新 `MusicFragment`。SeekBar 只展示进度,不允许用户拖动定位。 ### 8.5 音频焦点和本地音乐联动 蓝牙音乐与 `music_sdk` 没有直接 Gradle 依赖,主要通过以下方式协调: - Android `AudioFocus` - VoiceSwitcher AIDL 音频资源 - `com.yaxon.ACTION_MEDIA_STATUS_CHANGE` 广播 - `media.type` / `yaxon_media` 等系统状态 - `IMusicStateService` 仪表音乐状态 媒体类型约定: - 本地音乐:`request_value=1`、`local` - 蓝牙音乐:`request_value=2`、`blue` `music_sdk` 还监听蓝牙来电、拨号、挂断和拒接广播,在电话期间暂停本地音乐,通话结束后恢复。 ### 8.6 蓝牙音乐主要风险 - `VoiceSwitchReceiver` 中 Pause/Stop 处理被注释,Resume 也不直接下发 AVRCP Play,音源抢占后不保证手机端真正暂停/恢复。 - 旧 ID3 长度解析高字节掩码错误,长度超过 255 时可能解析错误;部分边界检查发生在读取之后,存在越界风险。 - 首次只收到时长/进度回调时,新建的 `ID3Info` 没有放回 Repository,页面可能继续显示 `00:00`。 - 播放状态同时存在于 GOC、`mPlaying`、Fragment、SharedPreferences、AudioFocus 和系统媒体类型,乱序回调可能造成“图标播放但无声”。 - 永久丢失焦点路径可能重复发送 Pause。 - 方向盘音乐广播注释声称支持播放/暂停/快进快退,但实际只处理上一首、下一首。 - 蓝牙音乐语音资源注册标志未正确置为 true,重复注册依赖远端服务容错。 ## 9. PBAP 通讯录与通话记录 ### 9.1 数据模型 LitePal 数据库名为 `bluetooth`,版本 2,主要表: - `Linkedinfo`:配对/连接设备 - `PhoneBook`:通讯录 - `CallRecord`:通话记录 数据层采用 Repository 组合: ```text UI / Presenter → Repository ├─ 内存缓存 ├─ LitePal 本地数据源 └─ GOC/PBAP 远端数据源 ``` ### 9.2 通讯录功能 - 手机通讯录下载 - SIM 通讯录下载 - 本地缓存和数据库持久化 - 中文姓名、拼音首字母、全拼和电话号码搜索 - 下载完成后刷新缓存、落库 - 广播 `ACTION_BLUETOOTH_CONTACT` 给语音模块 - 通过 `BluetoothPhonebookProvider` 给外部模块查询联系人 ### 9.3 Provider 风险 `BluetoothPhonebookProvider` 在 Manifest 中导出,但未配置访问权限,外部应用可查询完整通讯录。其 `insert/delete/update` 直接抛出 `UnsupportedOperationException`,因此它实际上是未显式声明契约的只读 Provider。 建议后续明确: - 配置 signature/system 权限。 - 或设置 `exported=false`,由受控 AIDL 提供查询。 - 对所有 query 参数、投影和返回字段做白名单限制。 ## 10. 外部系统联动 ### 10.1 语音 `VoiceRecognizeReceiver` 支持: - 打开/关闭蓝牙 - 打开蓝牙音乐 - 上一首、下一首 - 暂停、继续 - 联系人查询与拨号相关命令 语音执行前会检查连接状态和当前媒体类型。蓝牙开关当前存在“命令受理即回复成功”的问题,可能导致语音说成功但实际状态未变化。 ### 10.2 ITS AIDL `ItsAutoBtService` 对外提供蓝牙与电话控制,但存在明显测试/逻辑残留: - `type == 2` 关闭蓝牙时,把 `BOOLEAN_SETTING_BLUETOOTH_STATE` 写成了 `true`,应为 `false`。 - `type == 5` 不是单纯打开通话界面,而是硬编码拨打 `10000`。 ### 10.3 状态栏和仪表 - 主界面 `StatusBarIconReceiver` 监听 `com.yaxon.bluetooth.BLUETOOTH` 更新蓝牙图标。 - `IMusicStateService` 接收蓝牙音乐类型、播放状态和电话状态,用于仪表显示。 - 多条系统 Settings 和广播同时承担状态同步,缺少统一协议版本和来源优先级。 ### 10.4 音频和 GPIO - 音频服务提供 Bluetooth 输入通道和蓝牙音量控制。 - HFP 通话激活/结束时通过 GPIO `SwitchMicChannel()` 切换 MIC。 - 蓝牙音乐使用 `STREAM_MUSIC` 和永久 AudioFocus。 - 电话铃声使用 `STREAM_RING` 焦点,但本地铃声启动链不完整。 ### 10.5 EasyConn 和休眠唤醒 外部广播和服务负责系统休眠/唤醒时关闭、恢复蓝牙,也与 EasyConn 等车机互联场景协调。关闭服务会先清理电话、音乐和全局状态,再调用底层关闭,因此异常中断时可能出现“状态已清理、底层未关闭”的短暂不一致。 ## 11. 全局状态与并发模型 `YXApplication` 保存大量全局静态状态: - 蓝牙总开关和扫描状态 - `mBlueToothConnect` - `hfpState/a2dpState/avrcpState/scoState` - `mLinkedMac/mConnectingMac/mLinkingMac` - `mPlaying` - `isPhoneActive/isMultiCallBuild` - 通讯录下载状态 同时还有: - SharedPreferences - Settings.System - LitePal/Repository 缓存 - EventBus - Android 广播 - AIDL 服务状态 - GOC 实际状态 这些状态会被 AIDL 回调线程、HandlerThread、UseCase 线程池、IntentService 和主线程共同读写,大多没有 `volatile`、锁或统一 reducer/state machine。`BtAdapterManager` 又只保存单个 open/connect/disconnect 等结果回调,并发请求时后一个请求可能覆盖前一个请求。 `UseCaseScheduler` 的线程池队列容量只有 2,拒绝策略为 `DiscardPolicy`。高频扫描、连接或控制命令可能无日志静默丢弃。 ## 12. 重点风险清单 ### 12.1 高风险 | 编号 | 风险 | 影响 | |---|---|---| | H1 | 蓝牙开关未等待最终回调,成功回调可能重复 | UI/语音与实际状态不一致 | | H2 | GOC 冷启动绑定无可靠排队重试 | 开机自动开蓝牙偶发失败 | | H3 | 未配对设备连接/配对时序反向 | 配对失败或依赖底层隐式行为 | | H4 | 连接失败不清理旧回调 | 后续请求可能误完成旧操作 | | H5 | 三方电话主要依赖已停用旧回调 | 第二路来电和增强控制可能失效 | | H6 | `enhancedCallCtrl()` 忽略 action | 保持、释放、切换、合并语义不成立 | | H7 | Provider 导出且无访问权限 | 通讯录隐私泄露 | | H8 | ITS 关闭状态写反、硬编码拨号 10000 | 外部控制状态错误或误拨号 | | H9 | ID3 长度/边界解析错误 | 元数据错乱、潜在数组越界 | ### 12.2 中风险 | 编号 | 风险 | 影响 | |---|---|---| | M1 | 多套全局状态、无统一状态机 | UI、仪表、语音与底层乱序 | | M2 | UseCase 队列满时静默丢任务 | 用户操作无响应且无日志 | | M3 | 断开依赖可能为空的 `mLinkedMac` | 断开失败、状态残留 | | M4 | MAC 有冒号/无冒号混用 | 部分底层命令兼容性不确定 | | M5 | `Linkedinfo.equals()` 契约错误且无 `hashCode()` | 设备误去重、集合行为异常 | | M6 | 音源抢占 Pause/Resume 不完整 | 蓝牙音乐与本地音乐互抢或不恢复 | | M7 | `PhoningActivity singleTask` 无 `onNewIntent()` | 第二次来电号码/方向不刷新 | | M8 | 挂断/拒接忽略底层结果,6 秒强关 UI | 手机仍通话但车机页面消失 | | M9 | 外部 Receiver 广播普遍缺权限保护 | 非受信应用可注入控制命令 | | M10 | `music_sdk` 中蓝牙 Activity 类名错误 | 前台页面判断失败 | `music_sdk/src/futian/.../ProjectConstant.java` 中写的是: ```text com.yaxon.bluetooth.activity.PhoningActivity com.yaxon.bluetooth.activity.MainActivity ``` 实际类名是: ```text com.yaxon.bluetooth.keyboard.PhoningActivity com.yaxon.bluetooth.main.MainActivity ``` ## 13. 建议整改顺序 ### P0:先保证真实状态闭环 1. 蓝牙开关只在 `onEnableChanged()` 确认后完成请求;增加超时、幂等和单次回调保护。 2. GOC 服务绑定期间建立命令队列或明确重试状态。 3. 重做连接/配对流程:先判断 bond,未配对先 pair,bonded 后 connect。 4. 连接、断开和开关请求使用 request token,超时后清除回调,拒绝陈旧回调。 5. 修复 ITS 关闭状态与硬编码 `10000`。 ### P1:补齐三方电话和隐私安全 1. 根据 GOC 当前 SDK 能力明确 `CHLD=0/1/2/3` 或对应 API 映射。 2. 新 GOC 回调按“号码 + 状态 + multiparty + index”去重,不能只看状态值。 3. 在新链路中明确生成第二路来电、保持、激活、会议状态事件。 4. 为 Provider 和控制广播添加系统签名权限。 5. 修复 `PhoningActivity.onNewIntent()` 和挂断结果确认。 ### P2:统一音乐与全局状态 1. 建立单一蓝牙状态模型,区分 Desired、Command、Confirmed、Error。 2. 音乐状态以 AVRCP confirmed state 为准,AudioFocus 只控制是否允许出声。 3. 修复 ID3 解析、首次进度对象未落 Repository、重复 Pause。 4. 完善 VoiceSwitcher Pause/Resume 的真实 AVRCP 操作。 5. 将线程池拒绝策略改为可观测策略,至少记录任务名、队列和调用来源。 ## 14. 测试与验收建议 ### 14.1 设备管理 - GOC 服务未绑定、延迟绑定、绑定断开、服务重启。 - 连续快速开关蓝牙,验证回调只完成一次。 - 扫描中关蓝牙、休眠、切换页面。 - 新手机首次配对、PIN 错误、用户取消、超时。 - 已配对连接、连接另一设备、HFP-only、A2DP-only。 - 进程被杀后恢复连接并断开。 ### 14.2 电话 - 去电、来电、接听、拒接、挂断。 - 手机端与车机端分别操作,验证双向同步。 - SCO 手机/车机切换,MIC 静音,DTMF。 - 空号码、隐藏号码、超长号码和特殊字符。 - 来电时本地音乐、蓝牙音乐、收音机的暂停与恢复。 - 三方通话按第 7.3 节完整矩阵测试。 ### 14.3 蓝牙音乐 - Play/Pause/Stop/Prev/Next。 - Android 与 iPhone,多种播放器。 - 无 ID3、长标题、中文、emoji、元数据超过 255 字节。 - 只先到进度回调、回调乱序、A2DP/AVRCP 分别断开。 - 导航播报、语音、电话、收音机抢占与恢复。 - 方向盘、MODE、语音和页面按键连续快速操作。 ### 14.4 通讯录 - 0、1、1000、5000 条联系人。 - 同名、多号码、中文、英文、特殊字符。 - PBAP 拒绝授权、中途断开、重复同步、换手机。 - Provider 未授权应用访问验证。 ## 15. 可追踪的关键代码位置 | 主题 | 文件/位置 | |---|---| | 总初始化 | `YXApplication.java:115` | | Manager 初始化与回调注册 | `BtAdapterManager.java:174` | | 蓝牙开关 | `BtAdapterManager.java:1923` | | 扫描 | `BtAdapterManager.java:1983` | | 连接 | `BtAdapterManager.java:2023`、`:3479` | | 三方控制 | `BtAdapterManager.java:619` | | 旧等待电话回调 | `BtAdapterManager.java:1903` | | 新 GOC 电话回调 | `BtAdapterManager.java:3801` | | AVRCP 播放状态 | `BtAdapterManager.java:4090` | | 音乐页面 | `music/MusicFragment.java:42` | | 电话页面 | `keyboard/PhoningActivity.java:266` | | Provider | `phonebook/model/BluetoothPhonebookProvider.java:39` | | ITS 服务 | `aidl/its/ItsAutoBtService.java:95` | | 线程池 | `UseCaseScheduler.java:23` | ## 16. 分析边界 本结论来自应用层 Java、Manifest、Gradle 配置及跨模块静态调用分析。以下内容未获得运行时证据: - `goc.jar` 内部实现和外部 GOC 蓝牙服务源码。 - 蓝牙芯片固件及其协议兼容性。 - 实车音频路由、GPIO MIC 和仪表服务行为。 - Android/iPhone 真机连接、PBAP、SCO、A2DP 和三方通话结果。 因此,“代码入口存在”不等于“硬件环境已验证可用”。三方通话尤其需要按真机矩阵重新确认。