first commit
This commit is contained in:
commit
669f49b1d6
342 files changed
+320811
No files matched your search
@@ -0,0 +1,194 @@
|
||||
# HFP 通话音频切换无声问题分析与修复验证
|
||||
|
||||
## 1. 问题现象
|
||||
|
||||
蓝牙通话过程中,先将通话音频切换到手机端,等待车机扬声器输出进入 standby 后,再切回车机端,车机喇叭没有声音。
|
||||
|
||||
## 2. 分析资料
|
||||
|
||||
- 异常日志:`C:\Users\Administrator\Desktop\同力日志\tongli_2026_07_28_15_59_31.log`
|
||||
- 修复后日志:`C:\Users\Administrator\Desktop\同力日志\tongli_2026_07_28_19_50_02.log`
|
||||
- 蓝牙 SCO PCM:`cq_blink_soc_read.pcm`
|
||||
- AudioTrack 写入前 PCM:`cq_blink_play.pcm`
|
||||
- 系统源码:`Y:\tongli\android14.0_rk3562`
|
||||
|
||||
## 3. 蓝牙侧确认
|
||||
|
||||
蓝牙厂商提供的两份 PCM 数据均正常:
|
||||
|
||||
- `cq_blink_soc_read.pcm`:蓝牙 SCO 声卡读取到的下行通话数据正常。
|
||||
- `cq_blink_play.pcm`:经过蓝牙侧处理后,在调用 `AudioTrack.write()` 前的数据正常。
|
||||
|
||||
日志显示 AudioTrack 能正常创建、写入并累计 delivered frames。采样率和声道转换关系也符合当前实现:
|
||||
|
||||
```text
|
||||
蓝牙 SCO 8000 Hz / 单声道 / S16LE
|
||||
AudioTrack 16000 Hz / 双声道 / PCM 16-bit
|
||||
Audio HAL 48000 Hz / 双声道 / S16LE
|
||||
```
|
||||
|
||||
因此,蓝牙 PCM 输入和 AudioTrack 写入前的数据不是本次无声问题的主要原因,排查范围应落在 AudioTrack 后面的系统音频输出链路:
|
||||
|
||||
```text
|
||||
AudioTrack
|
||||
-> AudioFlinger
|
||||
-> AudioPolicy
|
||||
-> Rockchip Audio HAL
|
||||
-> Speaker PCM
|
||||
-> Codec / 功放 / 喇叭
|
||||
```
|
||||
|
||||
## 4. 异常日志时间线
|
||||
|
||||
```text
|
||||
16:00:15.147 HAL通过start_output_stream打开Speaker,device=0x2
|
||||
16:00:18.464 Telecom设置adev_set_mode=2,即AUDIO_MODE_IN_CALL
|
||||
16:00:27.886 音频切到手机端,蓝牙AudioTrack停止
|
||||
16:00:30.915 AudioFlinger空闲约3秒,HAL进入standby并关闭Speaker PCM
|
||||
16:00:36.907 音频切回车机,蓝牙重新创建AudioTrack
|
||||
16:00:38.054 AudioTrack音量恢复为1.0
|
||||
16:00:36.420
|
||||
至16:01:24 HAL持续高频执行do_out_standby/close device,喇叭无声
|
||||
```
|
||||
|
||||
异常期间,HAL每秒约90次执行以下流程:
|
||||
|
||||
```text
|
||||
get_presentation_position: Operation not permitted
|
||||
do_out_standby, device=0x2
|
||||
close device
|
||||
```
|
||||
|
||||
与此同时,蓝牙AudioTrack仍持续写入且帧数增长。这表明HAL虽然向上层返回了“数据已消费”,但数据没有真正送入Speaker PCM。
|
||||
|
||||
## 5. 系统源码根因
|
||||
|
||||
源码文件:
|
||||
|
||||
```text
|
||||
Y:\tongli\android14.0_rk3562\hardware\rockchip\audio\tinyalsa_hal\audio_hw.c
|
||||
```
|
||||
|
||||
目标函数:
|
||||
|
||||
```c
|
||||
static int start_output_stream(struct stream_out *out)
|
||||
```
|
||||
|
||||
原代码约位于第1374行:
|
||||
|
||||
```c
|
||||
if (adev->mode == AUDIO_MODE_IN_CALL) {
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
该代码只要发现系统处于 `AUDIO_MODE_IN_CALL`,就直接返回成功,但没有打开扬声器 PCM。
|
||||
|
||||
切换到手机端后,原有Speaker PCM会在空闲超时后关闭。再次切回车机时,`start_output_stream()` 因上述判断直接返回,导致 `out->pcm[]` 中没有有效的Speaker PCM。
|
||||
|
||||
后续 `out_write()` 的行为如下:
|
||||
|
||||
1. 没有找到有效的 `out->pcm[i]`,`ret` 保持为 `-1`。
|
||||
2. 错误恢复分支调用 `do_out_standby()`,再次关闭输出流。
|
||||
3. HAL最终仍向AudioTrack返回 `bytes`,所以上层认为写入成功。
|
||||
4. 下一次写入重复同样过程,形成高频 `standby/close` 循环。
|
||||
|
||||
当前HFP Client通话下行链路为:
|
||||
|
||||
```text
|
||||
蓝牙SCO PCM -> 蓝牙处理 -> AudioTrack -> Speaker PCM
|
||||
```
|
||||
|
||||
该链路不属于Rockchip基带Voice Session。`AUDIO_MODE_IN_CALL` 只表示Framework处于通话模式,不能单独证明基带Voice Session正在占用声卡。
|
||||
|
||||
同一文件中的 `out_write()` 和 `do_out_standby()` 已使用 `voice_is_in_call(adev)` 判断真实Voice Session,只有 `start_output_stream()` 的判断条件不一致。
|
||||
|
||||
## 6. 修复方案
|
||||
|
||||
修改前:
|
||||
|
||||
```c
|
||||
if (adev->mode == AUDIO_MODE_IN_CALL) {
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
修改后:
|
||||
|
||||
```c
|
||||
if ((adev->mode == AUDIO_MODE_IN_CALL) && voice_is_in_call(adev)) {
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
修改含义:
|
||||
|
||||
- 系统处于通话模式,且真实Rockchip Voice Session正在运行时,保持原逻辑,不重复打开声卡。
|
||||
- 系统处于通话模式,但HFP Client通过AudioTrack播放时,允许重新打开Speaker PCM。
|
||||
|
||||
## 7. 修复后验证
|
||||
|
||||
修复后已完成多轮“手机端/车机端”音频切换,实车确认切回车机后喇叭声音能够恢复。
|
||||
|
||||
关键验证时间线一:
|
||||
|
||||
```text
|
||||
19:51:19.207 切到手机端,AudioTrack停止
|
||||
19:51:22.237 Speaker输出进入standby
|
||||
19:51:22.263 通话模式下成功执行start_output_stream,device=0x2
|
||||
19:51:22.804 蓝牙重新创建AudioTrack
|
||||
19:51:23.946 AudioTrack音量恢复为1.0
|
||||
```
|
||||
|
||||
关键验证时间线二,Speaker关闭后等待约9秒再切回:
|
||||
|
||||
```text
|
||||
19:52:40.288 adev_set_mode=2,即AUDIO_MODE_IN_CALL
|
||||
19:52:44.501 切到手机端,AudioTrack停止
|
||||
19:52:47.501 Speaker输出进入standby
|
||||
19:52:56.608 成功重新执行start_output_stream,device=0x2
|
||||
19:52:57.115 蓝牙重新创建AudioTrack
|
||||
19:52:58.262 AudioTrack音量恢复为1.0
|
||||
```
|
||||
|
||||
修复前后日志统计对比:
|
||||
|
||||
| 日志 | `do_out_standby` | `get_presentation_position`告警 | 完整`start_output_stream` |
|
||||
| --- | ---------------: | ----------------------------: | ----------------------: |
|
||||
| 修复前 | 18648次 | 19645次 | 19次 |
|
||||
| 修复后 | 13次 | 13次 | 13次 |
|
||||
|
||||
修复后,高频约90次/秒的 `standby/close` 失败循环已经消失。剩余 `get_presentation_position` 告警只在输出流启动阶段出现一次,不再持续刷屏。
|
||||
|
||||
日志中的 `pcm_read error: File descriptor in bad state` 均出现在SCO关闭、蓝牙音频切到手机端之后,属于停止读取过程中的收尾现象,不影响本次修复结论。
|
||||
|
||||
## 8. 责任归属
|
||||
|
||||
本问题主责建议归属Android BSP/Rockchip Audio HAL层:
|
||||
|
||||
- Framework/Telecom设置 `AUDIO_MODE_IN_CALL` 符合通话流程。
|
||||
- AudioTrack能够正常创建和写入。
|
||||
- AudioPolicy输出设备为 `AUDIO_DEVICE_OUT_SPEAKER (0x2)`。
|
||||
- 实际故障发生在Audio HAL重新打开Speaker PCM的状态判断中。
|
||||
|
||||
蓝牙厂商需继续配合提供SCO PCM、AudioTrack写入数据及切换时序,但本次无需修改蓝牙PCM处理逻辑。
|
||||
|
||||
## 9. 回归测试建议
|
||||
|
||||
1. 通话中执行至少5轮“车机端 -> 手机端 -> 等待超过3秒 -> 车机端”。
|
||||
2. 确认每次切回车机后均出现 `start_output_stream device=0x2`。
|
||||
3. 确认不再出现高频 `do_out_standby/close device` 循环。
|
||||
4. 验证通话下行声音、上行麦克风和音量调节。
|
||||
5. 回归蓝牙音乐、系统提示音和其他媒体播放。
|
||||
6. 如果产品支持真实基带通话,回归基带Voice Session,确认 `voice_is_in_call(adev) == true` 时原有声卡独占逻辑不变。
|
||||
|
||||
## 10. 版本管理注意事项
|
||||
|
||||
当前可见的以下文件仍显示为修改前代码,Git状态也为干净:
|
||||
|
||||
```text
|
||||
Y:\tongli\android14.0_rk3562\hardware\rockchip\audio\tinyalsa_hal\audio_hw.c
|
||||
```
|
||||
|
||||
本次验证镜像可能来自另一份源码或构建目录,或者已验证修改尚未同步回正式仓库。正式提交和后续重新编译前,应确认实际构建源码路径,并将上述一行条件修改同步到目标仓库,避免修复丢失。
|
||||
@@ -0,0 +1,430 @@
|
||||
# 蓝牙业务迁移梳理
|
||||
|
||||
日期:2026-07-09
|
||||
|
||||
## 1. 背景
|
||||
|
||||
目标是让新项目 `F:\zdCode\tongli` 的蓝牙业务交互、需求和 UI,与旧项目 `F:\zdCode\tongli_old` 保持一致。
|
||||
|
||||
用户强调:
|
||||
|
||||
```text
|
||||
业务逻辑一样,代码可以不参考。
|
||||
```
|
||||
|
||||
因此本次迁移不能只看代码能不能跑,而要按旧项目和截图确认:
|
||||
|
||||
- 用户入口是否一致
|
||||
- 页面结构是否一致
|
||||
- 操作路径是否一致
|
||||
- 空状态/加载状态/错误状态是否一致
|
||||
- 通话状态机是否一致
|
||||
- 蓝牙音乐、设置、桌面卡片、状态栏是否联动一致
|
||||
|
||||
## 2. 已确认截图范围
|
||||
|
||||
截图里覆盖了以下 UI 和业务状态:
|
||||
|
||||
| 模块 | 页面/状态 |
|
||||
|---|---|
|
||||
| 蓝牙拨号 | 左侧菜单、数字键盘、拨号按钮、右侧通话记录列表 |
|
||||
| 通话记录 | 正常列表、暂无记录、未同步、一键同步、正在同步 |
|
||||
| 联系人 | 联系人列表、搜索、下载/同步、重新下载联系人弹窗 |
|
||||
| 通话态 | 来电中、正在拨号、通话中、通话中键盘 |
|
||||
| 三方通话 | 第二路来电、保持中、三方通话中 |
|
||||
| 蓝牙音乐 | 歌曲信息、封面、进度、上一首、播放/暂停、下一首 |
|
||||
| 蓝牙设置 | 自动接听、蓝牙开关、蓝牙名称、已配对设备、可用设备、修改名称 |
|
||||
| 桌面联动 | 蓝牙电话卡片、蓝牙音乐卡片、状态栏蓝牙状态 |
|
||||
|
||||
## 3. 旧项目业务基线
|
||||
|
||||
旧项目路径:
|
||||
|
||||
```text
|
||||
F:\zdCode\tongli_old
|
||||
```
|
||||
|
||||
旧蓝牙模块:
|
||||
|
||||
```text
|
||||
F:\zdCode\tongli_old\YX_BlueTooth
|
||||
```
|
||||
|
||||
旧项目主入口:
|
||||
|
||||
```text
|
||||
F:\zdCode\tongli_old\YX_BlueTooth\src\main\java\com\yaxon\bluetooth\main\MainActivity.java
|
||||
```
|
||||
|
||||
旧项目四个一级入口:
|
||||
|
||||
| Tab | 常量 | 业务 |
|
||||
|---|---|---|
|
||||
| 蓝牙拨号 | `TAB_KEYBOARD = 0` | 数字拨号、拨出电话 |
|
||||
| 联系人 | `TAB_PHONEBOOK = 1` | 联系人列表、搜索、同步 |
|
||||
| 蓝牙音乐 | `TAB_BLUETOOTHMUSIC = 2` | A2DP/AVRCP 音乐播放 |
|
||||
| 蓝牙设置 | `TAB_SETTING = 3` | 蓝牙开关、名称、配对、扫描 |
|
||||
| 通话记录 | `TAB_PHONERECORD = 4` | 通话记录列表和分类 |
|
||||
|
||||
旧项目 Manifest 关键入口:
|
||||
|
||||
| 类型 | 名称 |
|
||||
|---|---|
|
||||
| 主界面 | `MainActivity` |
|
||||
| 通话界面 | `PhoningActivity` |
|
||||
| 语音/外部控制 | `VoiceSwitchReceiver`、`VoiceRecognizeReceiver`、`ExternalControlReceiver` |
|
||||
| 蓝牙音乐控制 | `BluetoothMusicReceiver` |
|
||||
| 联系人数据 | `BluetoothPhonebookProvider` |
|
||||
|
||||
旧通话状态:
|
||||
|
||||
| 常量 | 值 | 含义 |
|
||||
|---|---:|---|
|
||||
| `STATUS_ACTIVE` | 0 | 通话中 |
|
||||
| `STATUS_HELD` | 1 | 保持中 |
|
||||
| `STATUS_DIALING` | 2 | 正在拨号 |
|
||||
| `STATUS_ALERTING` | 3 | 对方振铃 |
|
||||
| `STATUS_INCOMING` | 4 | 来电 |
|
||||
| `STATUS_WAITING` | 5 | 等待来电/三方来电 |
|
||||
|
||||
旧通话动作:
|
||||
|
||||
- 拨号
|
||||
- 挂断
|
||||
- 接听
|
||||
- 拒接
|
||||
- 麦克风静音
|
||||
- 车机/手机音频切换
|
||||
- DTMF 小键盘
|
||||
- 三方增强通话控制
|
||||
|
||||
旧联系人/通话记录能力:
|
||||
|
||||
- 联系人同步
|
||||
- 重新下载联系人确认弹窗
|
||||
- 联系人搜索
|
||||
- 通话记录同步
|
||||
- 通话记录分类:全部、拨出、已接、未接
|
||||
- 点击联系人/通话记录拨号
|
||||
|
||||
旧音乐能力:
|
||||
|
||||
- 标题
|
||||
- 歌手
|
||||
- 时长
|
||||
- 当前进度
|
||||
- 上一首
|
||||
- 播放/暂停
|
||||
- 下一首
|
||||
|
||||
旧设置能力:
|
||||
|
||||
- 自动接听
|
||||
- 蓝牙开关
|
||||
- 蓝牙名称
|
||||
- 已配对设备
|
||||
- 附近/可用设备
|
||||
- 搜索设备
|
||||
- 连接/断开/删除设备
|
||||
|
||||
## 4. 新项目承接点
|
||||
|
||||
新项目路径:
|
||||
|
||||
```text
|
||||
F:\zdCode\tongli
|
||||
```
|
||||
|
||||
### 4.1 蓝牙电话 App
|
||||
|
||||
模块:
|
||||
|
||||
```text
|
||||
F:\zdCode\tongli\YX_BlueTooth
|
||||
```
|
||||
|
||||
关键文件:
|
||||
|
||||
| 文件 | 作用 |
|
||||
|---|---|
|
||||
| `YX_BlueTooth\src\main\AndroidManifest.xml` | 蓝牙电话模块入口 |
|
||||
| `YX_BlueTooth\src\main\java\com\yaxon\bluetooth\main\MainActivity.java` | 主拨号/通话记录/联系人页面 |
|
||||
| `YX_BlueTooth\src\main\java\com\yaxon\bluetooth\main\BluetoothPhoneActivity.java` | 通话界面 |
|
||||
| `YX_BlueTooth\src\main\java\com\yaxon\bluetooth\fragment\CallLogsFragment.java` | 通话记录 |
|
||||
| `YX_BlueTooth\src\main\java\com\yaxon\bluetooth\fragment\ContactsFragment.java` | 联系人 |
|
||||
| `YX_BlueTooth\src\main\java\com\yaxon\bluetooth\dialog\BtSettingDialog.java` | 蓝牙设置弹窗 |
|
||||
| `YX_BlueTooth\src\main\java\com\yaxon\bluetooth\service\BluetoothService.java` | 后台服务和来电窗口联动 |
|
||||
|
||||
新项目主界面当前 Tab:
|
||||
|
||||
| Tab | 常量 | 当前业务 |
|
||||
|---|---|---|
|
||||
| 通话记录 | `TAB_CALL_LOGS = 0` | 右侧通话记录 |
|
||||
| 联系人 | `TAB_CONTACTS = 1` | 右侧通讯录 |
|
||||
| 拨号键盘 | `TAB_KEYBOARD = 2` | 左侧拨号键盘 |
|
||||
|
||||
说明:
|
||||
|
||||
新项目主界面已经不是旧项目四个一级 Tab 结构,而是左侧拨号键盘 + 右侧通话记录/联系人切换。后续要确认 UI 是否必须完全恢复旧截图里的左侧菜单结构:
|
||||
|
||||
```text
|
||||
蓝牙拨号 / 联系人 / 蓝牙音乐 / 蓝牙设置
|
||||
```
|
||||
|
||||
### 4.2 通话状态
|
||||
|
||||
新项目通话状态:
|
||||
|
||||
| 新常量 | 值 | 对应旧状态 |
|
||||
|---|---:|---|
|
||||
| `CALL_STATE_ACTIVE` | 0 | `STATUS_ACTIVE` |
|
||||
| `CALL_STATE_HELD` | 1 | `STATUS_HELD` |
|
||||
| `CALL_STATE_DIALING` | 2 | `STATUS_DIALING` |
|
||||
| `CALL_STATE_ALERTING` | 3 | `STATUS_ALERTING` |
|
||||
| `CALL_STATE_INCOMING` | 4 | `STATUS_INCOMING` |
|
||||
| `CALL_STATE_WAITING` | 5 | `STATUS_WAITING` |
|
||||
| `CALL_STATE_TERMINATED` | 7 | 旧项目无显式同名常量,表示结束 |
|
||||
|
||||
关键承接文件:
|
||||
|
||||
| 文件 | 作用 |
|
||||
|---|---|
|
||||
| `BluetoothPhoneActivity.java` | 全屏通话界面 |
|
||||
| `BluetoothPhoneViewModel.java` | 通话状态和动作控制 |
|
||||
| `TelephoneWindowControl.java` | 通话窗口控制 |
|
||||
| `ThirdCallingControl.java` | 三方通话/等待来电控制 |
|
||||
| `ThirdCallControlView.java` | 三方通话控制视图 |
|
||||
|
||||
### 4.3 蓝牙 SDK
|
||||
|
||||
模块:
|
||||
|
||||
```text
|
||||
F:\zdCode\tongli\YX_BluetoothSDK
|
||||
```
|
||||
|
||||
关键管理类:
|
||||
|
||||
| 类 | 作用 |
|
||||
|---|---|
|
||||
| `BtPhoneManager` | HFP 电话状态管理 |
|
||||
| `BtContactsManager` | 联系人/PBAP |
|
||||
| `BtCallRecordsManager` | 通话记录 |
|
||||
| `BtMusicManager` | 蓝牙音乐 |
|
||||
| `BtSettingManager` | 蓝牙开关、名称、设备状态 |
|
||||
| `BtInfoPushManager` | 状态推送 |
|
||||
| `BtVoiceManager` | 语音控制 |
|
||||
|
||||
关键控制类:
|
||||
|
||||
| 类 | 作用 |
|
||||
|---|---|
|
||||
| `BtPhoneControlManager` | 拨号、接听、挂断、拒接、DTMF 等 |
|
||||
| `BtContactsControlManager` | 联系人控制 |
|
||||
| `BtCallRecordsControlManager` | 通话记录控制 |
|
||||
| `BtMusicControlManager` | 播放、暂停、上一首、下一首 |
|
||||
| `BtSettingControlManager` | 蓝牙开关、连接、断开、配对 |
|
||||
| `BtPairedControlManager` | 已配对设备 |
|
||||
|
||||
结论:新平台应优先使用 SDK 的 manager/control manager,不建议搬旧项目底层实现。
|
||||
|
||||
### 4.4 蓝牙音乐
|
||||
|
||||
新项目有两个承接点:
|
||||
|
||||
| 模块 | 文件 | 说明 |
|
||||
|---|---|---|
|
||||
| `YX_BtMusic` | `YX_BtMusic\src\main\java\com\yaxon\btmusic\main\MainActivity.java` | 独立蓝牙音乐 App |
|
||||
| `YX_BlueTooth` | `YX_BlueTooth\src\main\java\com\yaxon\bluetooth\main\BluetoothMusicActivity.java` | 蓝牙电话模块内也存在音乐 Activity |
|
||||
|
||||
当前需要确认:
|
||||
|
||||
```text
|
||||
点击截图左侧“蓝牙音乐”时,是在蓝牙 App 内切换,还是跳转独立 YX_BtMusic?
|
||||
```
|
||||
|
||||
### 4.5 Launcher / SystemUI 联动
|
||||
|
||||
桌面卡片:
|
||||
|
||||
| 文件 | 作用 |
|
||||
|---|---|
|
||||
| `YX_Launcher\src\main\res\layout\card_bluetooth.xml` | 蓝牙电话卡片 |
|
||||
| `YX_Launcher\src\main\res\layout\card_bluetoothmusic.xml` | 蓝牙音乐卡片 |
|
||||
| `YX_Launcher\src\main\java\com\yaxon\launcher\card\BluetoothCardView.java` | 蓝牙电话状态卡片 |
|
||||
| `YX_Launcher\src\main\java\com\yaxon\launcher\card\BluetoothMusicCardView.java` | 蓝牙音乐卡片 |
|
||||
|
||||
状态栏/快捷设置:
|
||||
|
||||
| 文件/模块 | 作用 |
|
||||
|---|---|
|
||||
| `YX_SystemUI` | 状态栏蓝牙图标、快捷开关 |
|
||||
| `YX_SystemUISDK` | SystemUI 控制器 |
|
||||
|
||||
需要验收:
|
||||
|
||||
- 蓝牙开关状态是否同步到下拉快捷栏。
|
||||
- 已连接/未连接状态是否同步到桌面卡片。
|
||||
- 蓝牙音乐播放状态是否同步到桌面音乐卡片。
|
||||
|
||||
## 5. 业务交互基线表
|
||||
|
||||
| 模块 | 页面/状态 | 用户动作 | 期望结果 | 新项目承接 | 风险 |
|
||||
|---|---|---|---|---|---|
|
||||
| 蓝牙拨号 | 数字键盘 | 点击数字 | 输入框追加号码 | `MainActivity` + `KeyBoardView` | UI 结构需对齐截图 |
|
||||
| 蓝牙拨号 | 删除号码 | 点击删除 | 删除最后一位 | `KeyBoardView` | 长按清空是否支持待查 |
|
||||
| 蓝牙拨号 | 发起呼叫 | 点击绿色拨号 | 进入正在拨号页 | `BtPhoneControlManager` / `BluetoothPhoneActivity` | 未连接时提示需统一 |
|
||||
| 通话记录 | 正常列表 | 点击记录 | 使用该号码拨号 | `CallLogsFragment` | 记录合并/分类需验收 |
|
||||
| 通话记录 | 暂无记录 | 无记录 | 显示暂无记录 | `CallLogsFragment` | 空状态文案/图标需对齐 |
|
||||
| 通话记录 | 未同步 | 未下载记录 | 显示一键同步 | `CallHistoryViewModel` | 是否自动同步需确认 |
|
||||
| 通话记录 | 正在同步 | 点击同步 | 显示同步中 | `CallLogsFragment` | 超时/失败状态需补齐 |
|
||||
| 联系人 | 正常列表 | 点击联系人 | 拨打联系人号码 | `ContactsFragment` | 多号码联系人行为待确认 |
|
||||
| 联系人 | 搜索 | 输入关键字 | 按名称/号码/拼音搜索 | `ContactListViewModel` | 需验中文、拼音、数字 |
|
||||
| 联系人 | 重新下载 | 点击下载图标 | 弹出确认框 | `ContactsFragment` | 弹窗样式需对齐截图 |
|
||||
| 来电 | 来电中 | 接听 | 进入通话中 | `BluetoothPhoneActivity` | 倒车/AVM 场景窗口策略需验收 |
|
||||
| 来电 | 来电中 | 拒接 | 结束来电 | `BluetoothPhoneViewModel` | 单路/三方状态不同 |
|
||||
| 拨出 | 正在拨号 | 挂断 | 结束拨号 | `BluetoothPhoneActivity` | alerting/dialing 显示需统一 |
|
||||
| 通话中 | 静音 | 点击麦克风 | 麦克风静音/取消静音 | `BluetoothPhoneViewModel` | 状态图标需对齐 |
|
||||
| 通话中 | 音频切换 | 点击车机/手机 | SCO 在车机/手机间切换 | `BluetoothPhoneViewModel` | 需实车或蓝牙设备验证 |
|
||||
| 通话中 | DTMF | 打开小键盘 | 发送 DTMF 按键 | `BluetoothPhoneViewModel` | DTMF 兼容性需验收 |
|
||||
| 三方通话 | 第二路来电 | 接听/拒接/保持 | 状态正确切换 | `ThirdCallingControl` | 高风险,必须实测 |
|
||||
| 蓝牙音乐 | 播放页 | 播放/暂停 | AVRCP 控制手机音乐 | `BtMusicViewModel` | 有两个音乐 Activity,入口需确认 |
|
||||
| 蓝牙音乐 | 歌曲信息 | 手机切歌 | 标题/歌手/进度刷新 | `BtMusicControlManager` | 部分手机元数据为空 |
|
||||
| 蓝牙设置 | 蓝牙开关 | 打开/关闭 | 蓝牙状态变化 | `BtSettingDialog` | 截图是页面式,当前是弹窗式 |
|
||||
| 蓝牙设置 | 修改名称 | 输入新名称 | 本机蓝牙名更新 | `BtSettingViewModel` | 修改名称入口需对齐 |
|
||||
| 蓝牙设置 | 可用设备 | 搜索/点击设备 | 配对或连接 | `BtSettingViewModel` | 连接超时/失败提示需统一 |
|
||||
| 桌面卡片 | 蓝牙电话卡片 | 点击卡片 | 进入蓝牙电话 | `BluetoothCardView` | 状态同步需验收 |
|
||||
| 桌面卡片 | 蓝牙音乐卡片 | 点击卡片 | 进入蓝牙音乐 | `BluetoothMusicCardView` | 包名/入口需确认 |
|
||||
| 状态栏 | 快捷蓝牙 | 点击开关 | 打开/关闭蓝牙 | `YX_SystemUI` | 与蓝牙 App 状态需同步 |
|
||||
|
||||
## 6. 当前初步缺口
|
||||
|
||||
### 6.1 入口结构缺口
|
||||
|
||||
旧项目左侧一级入口是:
|
||||
|
||||
```text
|
||||
蓝牙拨号 / 联系人 / 蓝牙音乐 / 蓝牙设置
|
||||
```
|
||||
|
||||
新项目主界面当前更像:
|
||||
|
||||
```text
|
||||
拨号键盘 + 通话记录/通讯录二级切换
|
||||
```
|
||||
|
||||
要确认是否需要把新项目 UI 改回截图结构,至少视觉上应保持一致。
|
||||
|
||||
### 6.2 设置形态缺口
|
||||
|
||||
截图里的蓝牙设置是完整页面区域:
|
||||
|
||||
- 自动接听
|
||||
- 蓝牙开关
|
||||
- 蓝牙名称
|
||||
- 已配对设备
|
||||
- 可用设备
|
||||
|
||||
新项目目前主要是 `BtSettingDialog` 弹窗式承接。
|
||||
|
||||
需要确认:
|
||||
|
||||
```text
|
||||
设置必须做成截图里的完整页面,还是弹窗也可接受?
|
||||
```
|
||||
|
||||
### 6.3 蓝牙音乐入口缺口
|
||||
|
||||
新项目同时存在:
|
||||
|
||||
- `YX_BtMusic`
|
||||
- `YX_BlueTooth\BluetoothMusicActivity`
|
||||
|
||||
必须统一入口和状态来源,避免一个入口播放状态正常,另一个入口不同步。
|
||||
|
||||
### 6.4 三方通话高风险
|
||||
|
||||
三方通话是最容易出现状态错乱的地方:
|
||||
|
||||
- 单路来电
|
||||
- 通话中第二路来电
|
||||
- 一路保持一路激活
|
||||
- 接听第二路并挂断第一路
|
||||
- 挂断当前保留保持中通话
|
||||
|
||||
这一块必须实测,不能只靠 UI 静态对齐。
|
||||
|
||||
## 7. 建议开发顺序
|
||||
|
||||
### 第一阶段:冻结需求和页面资产
|
||||
|
||||
输出并确认:
|
||||
|
||||
- 页面清单
|
||||
- 弹窗清单
|
||||
- 图标清单
|
||||
- 状态清单
|
||||
- 入口跳转清单
|
||||
- Launcher/SystemUI 联动清单
|
||||
|
||||
### 第二阶段:主流程 UI 对齐
|
||||
|
||||
优先对齐:
|
||||
|
||||
1. 蓝牙拨号
|
||||
2. 通话记录
|
||||
3. 联系人
|
||||
4. 来电/拨号/通话中
|
||||
|
||||
### 第三阶段:高风险业务对齐
|
||||
|
||||
重点处理:
|
||||
|
||||
1. 三方通话
|
||||
2. 联系人/通话记录同步状态
|
||||
3. 蓝牙设置设备连接状态
|
||||
4. 蓝牙音乐播放状态同步
|
||||
|
||||
### 第四阶段:系统级联动
|
||||
|
||||
验证:
|
||||
|
||||
1. 桌面蓝牙电话卡片
|
||||
2. 桌面蓝牙音乐卡片
|
||||
3. 状态栏蓝牙图标
|
||||
4. 下拉快捷蓝牙开关
|
||||
5. 开机自启动服务
|
||||
|
||||
## 8. 明天继续时优先做什么
|
||||
|
||||
建议下一步直接做两件事:
|
||||
|
||||
1. 输出《蓝牙页面资产清单》
|
||||
- 页面
|
||||
- 弹窗
|
||||
- 空状态
|
||||
- 加载状态
|
||||
- 错误状态
|
||||
- 按钮状态
|
||||
- 图标状态
|
||||
|
||||
2. 输出《新旧项目功能缺口表》
|
||||
- 已具备,需验收
|
||||
- 已具备,但 UI 不一致
|
||||
- 业务可能缺失
|
||||
- 高风险必须实测
|
||||
- 可以延后处理
|
||||
|
||||
## 9. 后续开发前需要确认的问题
|
||||
|
||||
1. 新项目蓝牙主界面是否必须恢复旧截图的四个左侧入口?
|
||||
2. 蓝牙设置是做完整页面,还是保留当前弹窗式?
|
||||
3. 蓝牙音乐入口以 `YX_BtMusic` 为准,还是以 `YX_BlueTooth\BluetoothMusicActivity` 为准?
|
||||
4. 是否需要完全复刻截图背景、图标和尺寸,还是只对齐交互和业务?
|
||||
5. 是否需要兼容方向盘按键、语音控制、ITS/EasyConn 外部控制?
|
||||
|
||||
## 10. 重要提醒
|
||||
|
||||
进入开发阶段前,需要再次确认是否备份。
|
||||
|
||||
当前文档只是梳理,不代表已经完成代码修改。
|
||||
@@ -0,0 +1,203 @@
|
||||
# 蓝牙主界面开发进展_2026-07-09
|
||||
|
||||
## 范围
|
||||
|
||||
本次只专注新项目 `F:\zdCode\tongli` 的 `YX_BlueTooth` 蓝牙模块。
|
||||
|
||||
不处理:
|
||||
|
||||
- SystemUI
|
||||
- Launcher
|
||||
- MCU
|
||||
- 其他系统联动模块
|
||||
|
||||
## 用户要求
|
||||
|
||||
- UI 和需求要跟老项目 `F:\zdCode\tongli_old` 一致。
|
||||
- 业务逻辑一样。
|
||||
- 代码可以不参考老项目。
|
||||
- 不需要备份。
|
||||
- 资源优先直接拷贝老项目,不从截图切图。
|
||||
|
||||
## 本次完成
|
||||
|
||||
主界面已从新项目原来的:
|
||||
|
||||
```text
|
||||
键盘 + 通话记录/联系人横向页签
|
||||
```
|
||||
|
||||
调整为老项目式:
|
||||
|
||||
```text
|
||||
左侧四菜单 + 右侧页面容器
|
||||
```
|
||||
|
||||
四个菜单:
|
||||
|
||||
```text
|
||||
蓝牙拨号
|
||||
联系人
|
||||
蓝牙音乐
|
||||
蓝牙设置
|
||||
```
|
||||
|
||||
## 代码结构
|
||||
|
||||
主入口:
|
||||
|
||||
```text
|
||||
YX_BlueTooth/src/main/java/com/yaxon/bluetooth/main/MainActivity.java
|
||||
```
|
||||
|
||||
主界面现在只负责:
|
||||
|
||||
- 左侧菜单显示
|
||||
- 右侧 Fragment 切换
|
||||
- 联系人搜索/重新同步入口
|
||||
- 蓝牙连接状态同步给拨号页和联系人页
|
||||
|
||||
新增页面:
|
||||
|
||||
```text
|
||||
YX_BlueTooth/src/main/java/com/yaxon/bluetooth/fragment/DialHomeFragment.java
|
||||
YX_BlueTooth/src/main/java/com/yaxon/bluetooth/fragment/BtMusicFragment.java
|
||||
YX_BlueTooth/src/main/java/com/yaxon/bluetooth/fragment/BtSettingFragment.java
|
||||
```
|
||||
|
||||
复用页面:
|
||||
|
||||
```text
|
||||
YX_BlueTooth/src/main/java/com/yaxon/bluetooth/fragment/ContactsFragment.java
|
||||
YX_BlueTooth/src/main/java/com/yaxon/bluetooth/fragment/CallLogsFragment.java
|
||||
```
|
||||
|
||||
## 页面说明
|
||||
|
||||
### 蓝牙拨号
|
||||
|
||||
文件:
|
||||
|
||||
```text
|
||||
fragment_dial_home.xml
|
||||
DialHomeFragment.java
|
||||
```
|
||||
|
||||
结构:
|
||||
|
||||
```text
|
||||
左侧:KeyBoardView
|
||||
右侧:CallLogsFragment
|
||||
输入号码后:显示联系人匹配列表
|
||||
```
|
||||
|
||||
### 联系人
|
||||
|
||||
继续复用:
|
||||
|
||||
```text
|
||||
ContactsFragment
|
||||
fragment_contacts.xml
|
||||
```
|
||||
|
||||
主界面右上角保留:
|
||||
|
||||
- 搜索
|
||||
- 重新同步
|
||||
|
||||
### 蓝牙音乐
|
||||
|
||||
新增:
|
||||
|
||||
```text
|
||||
BtMusicFragment
|
||||
fragment_bt_music.xml
|
||||
```
|
||||
|
||||
复用:
|
||||
|
||||
```text
|
||||
BtMusicViewModel
|
||||
BtMusicControlManager
|
||||
```
|
||||
|
||||
### 蓝牙设置
|
||||
|
||||
新增:
|
||||
|
||||
```text
|
||||
BtSettingFragment
|
||||
fragment_bt_setting.xml
|
||||
```
|
||||
|
||||
复用:
|
||||
|
||||
```text
|
||||
BtSettingViewModel
|
||||
BtDevForumAdapter
|
||||
BtDevScanedAdapter
|
||||
```
|
||||
|
||||
它相当于把原来的 `BtSettingDialog` 弹窗式设置迁成主界面里的页面式设置。
|
||||
|
||||
## 资源复用
|
||||
|
||||
已从老项目拷贝到新项目:
|
||||
|
||||
```text
|
||||
activity_bg.png
|
||||
common_bg_line.png
|
||||
title_head_background.png
|
||||
bluetooth_tabvertical.xml
|
||||
text_click_selector.xml
|
||||
icon_tabvertical_selected.png
|
||||
```
|
||||
|
||||
新增/修改资源:
|
||||
|
||||
```text
|
||||
activity_main.xml
|
||||
listitem_main.xml
|
||||
fragment_dial_home.xml
|
||||
fragment_bt_music.xml
|
||||
fragment_bt_setting.xml
|
||||
colors.xml
|
||||
dimens.xml
|
||||
```
|
||||
|
||||
## 验证
|
||||
|
||||
默认 Java 11 会失败,原因是当前 Android Gradle Plugin 需要 Java 17。
|
||||
|
||||
使用 Android Studio JBR 临时编译:
|
||||
|
||||
```powershell
|
||||
$env:JAVA_HOME='C:\Program Files\Android\Android Studio\jbr'
|
||||
$env:Path="$env:JAVA_HOME\bin;$env:Path"
|
||||
.\gradlew.bat :YX_BlueTooth:assembleDebug --no-daemon --console=plain
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||
```text
|
||||
BUILD SUCCESSFUL
|
||||
```
|
||||
|
||||
## 已知风险
|
||||
|
||||
- 当前完成的是主界面四入口骨架,尚未做上车/模拟器视觉验收。
|
||||
- 蓝牙拨号页的号码显示、删除键、点击通话记录拨号等细节需要继续对齐老项目。
|
||||
- 蓝牙设置页目前复用现有设置逻辑,名称修改、自动接听等细节还需要继续核对老项目。
|
||||
- 蓝牙音乐页复用现有音乐逻辑,播放状态、歌曲信息、未连接页还需要实测。
|
||||
- 三方通话还未进入本轮实现,后续需要专项验收。
|
||||
|
||||
## 下一步
|
||||
|
||||
优先顺序:
|
||||
|
||||
1. 实测主界面四入口切换。
|
||||
2. 对齐蓝牙拨号页 UI 和交互。
|
||||
3. 对齐联系人页搜索/同步/空状态。
|
||||
4. 对齐蓝牙音乐页播放控制和未连接状态。
|
||||
5. 对齐蓝牙设置页扫描/连接/断开/删除/蓝牙名称。
|
||||
6. 再做通话页和三方通话专项。
|
||||
@@ -0,0 +1,504 @@
|
||||
# 蓝牙开发实施方案
|
||||
|
||||
日期:2026-07-09
|
||||
|
||||
## 1. 开发目标
|
||||
|
||||
在新项目 `F:\zdCode\tongli` 上开发蓝牙功能,使蓝牙业务交互、需求和 UI 与旧项目 `F:\zdCode\tongli_old` 保持一致。
|
||||
|
||||
用户要求:
|
||||
|
||||
```text
|
||||
业务逻辑一样,UI 和需求跟老项目一致,代码可以不参考。
|
||||
```
|
||||
|
||||
因此开发策略是:
|
||||
|
||||
```text
|
||||
旧项目 = 需求基线和验收标准
|
||||
新项目 = 实现架构和平台能力
|
||||
```
|
||||
|
||||
不建议搬旧代码,不建议重写底层蓝牙栈。应优先使用新项目已有 `YX_BluetoothSDK`、ViewModel、Activity、Service 架构补齐业务和 UI。
|
||||
|
||||
## 2. 总体开发原则
|
||||
|
||||
### 2.1 老项目只做业务参考
|
||||
|
||||
老项目重点参考:
|
||||
|
||||
- 页面入口
|
||||
- 操作路径
|
||||
- 通话状态机
|
||||
- 联系人/通话记录同步流程
|
||||
- 蓝牙音乐控制
|
||||
- 蓝牙设置和设备管理
|
||||
- 三方通话/第二路来电行为
|
||||
- 空状态、加载状态、弹窗和提示
|
||||
|
||||
不直接复制:
|
||||
|
||||
- 老项目 `BtAdapterManager` 底层实现
|
||||
- 老项目老式 Activity/Fragment 结构
|
||||
- 老项目 Android 4.4 平台兼容写法
|
||||
|
||||
### 2.2 新项目保持现有架构
|
||||
|
||||
新项目优先使用:
|
||||
|
||||
| 能力 | 新项目承接 |
|
||||
| -------- | ---------------------------------------------------- |
|
||||
| 蓝牙电话 | `YX_BlueTooth` |
|
||||
| 蓝牙 SDK | `YX_BluetoothSDK` |
|
||||
| 蓝牙音乐 | `YX_BtMusic` 或 `YX_BlueTooth\BluetoothMusicActivity` |
|
||||
| 桌面卡片 | `YX_Launcher` |
|
||||
| 状态栏/快捷开关 | `YX_SystemUI` |
|
||||
|
||||
核心调用应走:
|
||||
|
||||
| 功能 | 控制类 |
|
||||
| ---------------- | ----------------------------- |
|
||||
| 拨号/接听/挂断/拒接/DTMF | `BtPhoneControlManager` |
|
||||
| 联系人 | `BtContactsControlManager` |
|
||||
| 通话记录 | `BtCallRecordsControlManager` |
|
||||
| 蓝牙音乐 | `BtMusicControlManager` |
|
||||
| 蓝牙设置/设备连接 | `BtSettingControlManager` |
|
||||
| 已配对设备 | `BtPairedControlManager` |
|
||||
|
||||
### 2.3 先页面后底层
|
||||
|
||||
开发顺序不应从底层 SDK 开始大改,而应:
|
||||
|
||||
```text
|
||||
页面结构对齐
|
||||
-> 状态和交互对齐
|
||||
-> ViewModel 调用补齐
|
||||
-> SDK 缺口验证
|
||||
-> 系统联动验收
|
||||
```
|
||||
|
||||
## 3. 模块拆分
|
||||
|
||||
蓝牙功能按以下模块推进:
|
||||
|
||||
| 模块 | 目标 |
|
||||
|---|---|
|
||||
| 主界面导航 | 对齐旧项目/截图入口结构 |
|
||||
| 蓝牙拨号 | 数字输入、拨号、删除、未连接提示 |
|
||||
| 通话记录 | 记录列表、分类、同步、空状态、点击拨号 |
|
||||
| 联系人 | 同步、搜索、重新下载、点击拨号 |
|
||||
| 通话界面 | 来电、拨出、通话中、静音、音频切换、DTMF |
|
||||
| 三方通话 | 第二路来电、等待、保持、释放当前接听另一通 |
|
||||
| 蓝牙音乐 | 歌曲信息、进度、播放控制、未连接状态 |
|
||||
| 蓝牙设置 | 自动接听、开关、名称、配对、扫描、连接/断开 |
|
||||
| Launcher 联动 | 蓝牙电话卡片、蓝牙音乐卡片 |
|
||||
| SystemUI 联动 | 状态栏图标、快捷蓝牙开关 |
|
||||
|
||||
## 4. 推荐开发顺序
|
||||
|
||||
### 阶段 1:冻结页面资产和需求
|
||||
|
||||
先产出并确认以下清单:
|
||||
|
||||
- 页面清单
|
||||
- 弹窗清单
|
||||
- 图标清单
|
||||
- 按钮清单
|
||||
- 空状态清单
|
||||
- 加载状态清单
|
||||
- 错误状态清单
|
||||
- 路由/入口清单
|
||||
- Launcher/SystemUI 联动清单
|
||||
|
||||
阶段目标:
|
||||
|
||||
```text
|
||||
开发前知道每个页面长什么样、有哪些状态、点击后去哪里。
|
||||
```
|
||||
|
||||
### 阶段 2:主界面 UI 结构对齐
|
||||
|
||||
旧项目和截图里的主入口更接近:
|
||||
|
||||
```text
|
||||
蓝牙拨号
|
||||
联系人
|
||||
蓝牙音乐
|
||||
蓝牙设置
|
||||
```
|
||||
|
||||
新项目当前主界面更接近:
|
||||
|
||||
```text
|
||||
左侧拨号键盘 + 右侧通话记录/通讯录二级切换
|
||||
```
|
||||
|
||||
这里需要先做产品决策:
|
||||
|
||||
1. 如果要求 UI 完全跟老项目/截图一致,应把新项目 `MainActivity` 的入口视觉改成四项左侧菜单。
|
||||
2. 如果只要求业务一致,当前结构可以保留,但必须补齐蓝牙音乐和蓝牙设置入口。
|
||||
|
||||
建议:
|
||||
|
||||
```text
|
||||
优先按截图恢复四个左侧入口。
|
||||
通话记录可以作为蓝牙拨号页右侧区域或拨号页内二级状态。
|
||||
```
|
||||
|
||||
涉及文件:
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `YX_BlueTooth\src\main\java\com\yaxon\bluetooth\main\MainActivity.java` | 主界面控制 |
|
||||
| `YX_BlueTooth\src\main\res\layout\activity_main.xml` | 主界面布局 |
|
||||
| `YX_BlueTooth\src\main\res\layout\fragment_call_logs.xml` | 通话记录 |
|
||||
| `YX_BlueTooth\src\main\res\layout\fragment_contacts.xml` | 联系人 |
|
||||
|
||||
### 阶段 3:电话核心流程
|
||||
|
||||
先保证最基础电话链路可用:
|
||||
|
||||
```text
|
||||
输入号码
|
||||
-> 点击拨号
|
||||
-> 进入拨号中
|
||||
-> 对方接听
|
||||
-> 通话中
|
||||
-> 挂断
|
||||
-> 返回/关闭通话页
|
||||
```
|
||||
|
||||
再补:
|
||||
|
||||
- 来电接听
|
||||
- 来电拒接
|
||||
- 通话中静音
|
||||
- 车机/手机音频切换
|
||||
- DTMF 小键盘
|
||||
- 未连接时禁止拨号并提示
|
||||
|
||||
涉及文件:
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `BluetoothPhoneActivity.java` | 通话全屏页 |
|
||||
| `BluetoothPhoneViewModel.java` | 电话动作和状态 |
|
||||
| `TelephoneWindowControl.java` | 电话窗口 |
|
||||
| `view_keyboard_dial.xml` | 拨号键盘 |
|
||||
| `view_keyboard_dtmf.xml` | DTMF 键盘 |
|
||||
| `view_control_calling.xml` | 通话控制按钮 |
|
||||
|
||||
验收重点:
|
||||
|
||||
- 来电显示号码/联系人名称
|
||||
- 拨出显示号码/联系人名称
|
||||
- 通话计时正确
|
||||
- 静音图标状态正确
|
||||
- 车机/手机音频图标状态正确
|
||||
- DTMF 按键能发出
|
||||
- 断开蓝牙时通话页正确关闭或提示
|
||||
|
||||
### 阶段 4:联系人和通话记录
|
||||
|
||||
联系人:
|
||||
|
||||
- 未同步状态
|
||||
- 一键同步
|
||||
- 正在同步
|
||||
- 同步成功
|
||||
- 同步失败
|
||||
- 空联系人
|
||||
- 搜索联系人
|
||||
- 搜索无结果
|
||||
- 重新下载联系人确认弹窗
|
||||
- 点击联系人拨号
|
||||
|
||||
通话记录:
|
||||
|
||||
- 未同步状态
|
||||
- 一键同步
|
||||
- 正在同步
|
||||
- 同步成功
|
||||
- 暂无记录
|
||||
- 全部/拨出/已接/未接分类
|
||||
- 点击通话记录拨号
|
||||
|
||||
涉及文件:
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `ContactsFragment.java` | 联系人 UI |
|
||||
| `ContactListViewModel.java` | 联系人业务 |
|
||||
| `CallLogsFragment.java` | 通话记录 UI |
|
||||
| `CallHistoryViewModel.java` | 通话记录业务 |
|
||||
| `listitem_phonebook.xml` | 联系人条目 |
|
||||
| `listitem_phonerecord.xml` | 通话记录条目 |
|
||||
|
||||
验收重点:
|
||||
|
||||
- 蓝牙未连接时显示正确状态
|
||||
- 手机未授权 PBAP 时提示合理
|
||||
- 同步中不能重复触发多次
|
||||
- 搜索支持名称、号码、拼音/首字母
|
||||
- 点击条目拨号行为一致
|
||||
|
||||
### 阶段 5:三方通话专项
|
||||
|
||||
老项目明确支持第二路来电/三方通话相关行为:
|
||||
|
||||
- `SECOND_PHONE_IN`
|
||||
- `SECOND_PHONE_PICKUP_OR_REJECT`
|
||||
- `STATUS_WAITING`
|
||||
- `STATUS_HELD`
|
||||
- `EnhancedCallCtrl`
|
||||
- `RELEASE_ACTIVE_AND_ACCEPT_OTHER`
|
||||
|
||||
新项目已有承接:
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `ThirdCallingControl.java` | 三方通话/第二路来电控制 |
|
||||
| `ThirdCallControlView.java` | 三方通话控制视图 |
|
||||
| `BluetoothPhoneViewModel.java` | 多通话状态处理 |
|
||||
| `BluetoothPhoneActivity.java` | 通话状态显示 |
|
||||
|
||||
必须单独验收以下场景:
|
||||
|
||||
1. 无通话时来电。
|
||||
2. 通话中第二路来电。
|
||||
3. 拒接第二路来电。
|
||||
4. 接听第二路并挂断当前。
|
||||
5. 接听第二路并保持当前。
|
||||
6. 当前一路 active,另一路 held。
|
||||
7. 挂断 active 后 held 是否恢复。
|
||||
8. 第二路来电号码/名称显示是否正确。
|
||||
|
||||
风险:
|
||||
|
||||
```text
|
||||
三方通话最依赖手机、HFP 协议栈和平台蓝牙实现,不能只靠静态代码判断。
|
||||
必须用真实手机或稳定蓝牙测试设备验证。
|
||||
```
|
||||
|
||||
### 阶段 6:蓝牙音乐
|
||||
|
||||
需要先统一入口:
|
||||
|
||||
```text
|
||||
蓝牙音乐入口到底打开 YX_BtMusic,还是 YX_BlueTooth 内的 BluetoothMusicActivity?
|
||||
```
|
||||
|
||||
建议:
|
||||
|
||||
- 如果项目已有独立 `YX_BtMusic` 桌面入口,主入口可以跳转 `YX_BtMusic`。
|
||||
- 如果要求完全贴近老项目“蓝牙 App 内四项菜单”,可以在 `YX_BlueTooth` 内保留音乐页面或 Activity。
|
||||
- 不建议两个入口长期并存不同逻辑,应统一 ViewModel 和 SDK 状态来源。
|
||||
|
||||
功能验收:
|
||||
|
||||
- 未连接 A2DP 时显示未连接状态
|
||||
- 点击连接按钮进入设置或连接流程
|
||||
- 标题/歌手/封面刷新
|
||||
- 播放/暂停状态刷新
|
||||
- 上一首/下一首可用
|
||||
- 进度和总时长显示
|
||||
- 手机端切歌后车机 UI 同步
|
||||
|
||||
涉及文件:
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `YX_BtMusic\src\main\java\com\yaxon\btmusic\main\MainActivity.java` | 独立蓝牙音乐页 |
|
||||
| `YX_BtMusic\src\main\java\com\yaxon\btmusic\mvvm\BtMusicViewModel.java` | 独立音乐业务 |
|
||||
| `YX_BlueTooth\src\main\java\com\yaxon\bluetooth\main\BluetoothMusicActivity.java` | 蓝牙模块内音乐页 |
|
||||
| `BtMusicControlManager` | 蓝牙音乐控制 |
|
||||
|
||||
### 阶段 7:蓝牙设置和设备管理
|
||||
|
||||
截图里的蓝牙设置是页面式:
|
||||
|
||||
- 自动接听
|
||||
- 蓝牙开关
|
||||
- 蓝牙名称
|
||||
- 已配对设备
|
||||
- 可用设备
|
||||
- 修改名称
|
||||
|
||||
新项目当前主要承接是 `BtSettingDialog`。
|
||||
|
||||
建议:
|
||||
|
||||
```text
|
||||
如果 UI 必须跟截图一致,应做成完整设置页面或主界面右侧设置页。
|
||||
如果只要求功能一致,可以先保留 BtSettingDialog,再统一视觉。
|
||||
```
|
||||
|
||||
功能验收:
|
||||
|
||||
- 蓝牙开关可打开/关闭
|
||||
- 本机蓝牙名称显示正确
|
||||
- 本机蓝牙名称可修改
|
||||
- 已配对设备显示正确
|
||||
- 可用设备扫描和刷新
|
||||
- 点击设备可配对/连接
|
||||
- 已连接设备可断开
|
||||
- 连接中、连接失败、连接成功状态正确
|
||||
- 自动接听开关生效
|
||||
|
||||
涉及文件:
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `BtSettingDialog.java` | 设置 UI |
|
||||
| `BtSettingViewModel.java` | 设置业务 |
|
||||
| `dialog_bt_setting.xml` | 设置弹窗布局 |
|
||||
| `item_btdev_forum.xml` | 已配对设备条目 |
|
||||
| `item_btdev_scaned.xml` | 可用设备条目 |
|
||||
|
||||
### 阶段 8:Launcher/SystemUI 联动
|
||||
|
||||
需要纳入最终验收,而不是蓝牙 App 做完就结束。
|
||||
|
||||
Launcher:
|
||||
|
||||
- 蓝牙电话卡片显示连接/未连接
|
||||
- 蓝牙音乐卡片显示播放状态
|
||||
- 点击卡片打开正确 App
|
||||
|
||||
SystemUI:
|
||||
|
||||
- 状态栏蓝牙图标显示已连接/未连接
|
||||
- 下拉快捷蓝牙开关可打开/关闭
|
||||
- 快捷开关状态和蓝牙 App 状态一致
|
||||
|
||||
涉及文件:
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `YX_Launcher\src\main\res\layout\card_bluetooth.xml` | 蓝牙电话卡片 |
|
||||
| `YX_Launcher\src\main\res\layout\card_bluetoothmusic.xml` | 蓝牙音乐卡片 |
|
||||
| `YX_Launcher\src\main\java\com\yaxon\launcher\card\BluetoothCardView.java` | 蓝牙卡片 |
|
||||
| `YX_Launcher\src\main\java\com\yaxon\launcher\card\BluetoothMusicCardView.java` | 蓝牙音乐卡片 |
|
||||
| `YX_SystemUI` | 状态栏和快捷开关 |
|
||||
|
||||
## 5. 关键风险
|
||||
|
||||
| 风险 | 说明 | 建议 |
|
||||
|---|---|---|
|
||||
| UI 入口结构不一致 | 新项目入口结构和旧项目不同 | 先确认四项左侧菜单是否必须恢复 |
|
||||
| 蓝牙音乐双入口 | `YX_BtMusic` 和 `BluetoothMusicActivity` 并存 | 统一入口和状态来源 |
|
||||
| 设置形态不一致 | 截图是页面式,新项目是弹窗式 | 先确认产品要求 |
|
||||
| 三方通话复杂 | 依赖手机、协议栈、平台实现 | 单独实测 |
|
||||
| PBAP 授权 | 手机可能未授权联系人/通话记录 | 做未授权和同步失败提示 |
|
||||
| SystemUI 状态同步 | 蓝牙开关和连接状态可能不同步 | 最后做系统级联动验收 |
|
||||
| 旧项目编码/架构老 | 直接搬代码风险高 | 只抽业务行为 |
|
||||
|
||||
## 6. 开发验收清单
|
||||
|
||||
### 6.1 蓝牙拨号
|
||||
|
||||
- 输入号码显示正确
|
||||
- 删除号码正确
|
||||
- 点击拨号进入拨出页
|
||||
- 未连接时不拨号并提示
|
||||
- 联系人匹配显示正确
|
||||
|
||||
### 6.2 通话流程
|
||||
|
||||
- 来电可接听
|
||||
- 来电可拒接
|
||||
- 拨出可挂断
|
||||
- 通话中可挂断
|
||||
- 通话中计时正确
|
||||
- 静音可切换
|
||||
- 车机/手机音频可切换
|
||||
- DTMF 可发送
|
||||
|
||||
### 6.3 三方通话
|
||||
|
||||
- 第二路来电能显示
|
||||
- 第二路来电可拒接
|
||||
- 第二路来电可接听
|
||||
- 当前通话可保持
|
||||
- 当前通话可释放并接听另一通
|
||||
- held/active 状态显示正确
|
||||
|
||||
### 6.4 联系人
|
||||
|
||||
- 未同步状态正确
|
||||
- 同步中状态正确
|
||||
- 同步成功列表正确
|
||||
- 同步失败提示正确
|
||||
- 搜索正确
|
||||
- 重新下载弹窗正确
|
||||
- 点击联系人拨号正确
|
||||
|
||||
### 6.5 通话记录
|
||||
|
||||
- 未同步状态正确
|
||||
- 同步中状态正确
|
||||
- 暂无记录状态正确
|
||||
- 记录列表正确
|
||||
- 记录类型图标正确
|
||||
- 点击记录拨号正确
|
||||
|
||||
### 6.6 蓝牙音乐
|
||||
|
||||
- 未连接状态正确
|
||||
- 播放/暂停正确
|
||||
- 上一首/下一首正确
|
||||
- 标题/歌手/封面正确
|
||||
- 进度/总时长正确
|
||||
- 手机端状态变化能同步
|
||||
|
||||
### 6.7 蓝牙设置
|
||||
|
||||
- 蓝牙开关正确
|
||||
- 蓝牙名称显示正确
|
||||
- 蓝牙名称可修改
|
||||
- 已配对设备列表正确
|
||||
- 可用设备扫描正确
|
||||
- 连接/断开正确
|
||||
- 连接失败/超时提示正确
|
||||
- 自动接听生效
|
||||
|
||||
### 6.8 系统联动
|
||||
|
||||
- 桌面蓝牙卡片状态正确
|
||||
- 桌面蓝牙音乐卡片状态正确
|
||||
- 状态栏蓝牙图标正确
|
||||
- 下拉快捷蓝牙开关正确
|
||||
- 开机后蓝牙服务正常启动
|
||||
|
||||
## 7. 建议下一步
|
||||
|
||||
下一步不要直接改代码,建议先输出两份更细文档:
|
||||
|
||||
1. `蓝牙页面资产清单`
|
||||
- 页面
|
||||
- 弹窗
|
||||
- 图标
|
||||
- 按钮
|
||||
- 空状态
|
||||
- 加载状态
|
||||
- 错误状态
|
||||
|
||||
2. `蓝牙新旧功能缺口表`
|
||||
- 老项目能力
|
||||
- 新项目现状
|
||||
- 缺口
|
||||
- 影响文件
|
||||
- 优先级
|
||||
- 验收方式
|
||||
|
||||
确认后再进入代码开发。
|
||||
|
||||
## 8. 开发前必须确认
|
||||
|
||||
进入代码修改前,需要再次确认:
|
||||
|
||||
1. 是否备份。
|
||||
2. 是否要求 UI 像素级复刻截图。
|
||||
3. 蓝牙音乐入口以哪个模块为准。
|
||||
4. 蓝牙设置使用页面式还是弹窗式。
|
||||
5. 是否必须覆盖方向盘、语音、ITS/EasyConn 外部控制。
|
||||
@@ -0,0 +1,840 @@
|
||||
# 通力蓝牙模块整体流程与开发指南
|
||||
|
||||
> 代码仓库:`F:\zdCode\tongli`
|
||||
> 文档目的:帮助开发者理解“蓝牙模块”和“蓝牙音乐”的真实关系,熟悉整体功能链路,后续能独立开发、定位和修改问题。
|
||||
> 当前版本重点:先讲清楚蓝牙模块底座,再讲蓝牙音乐为什么依赖蓝牙模块。
|
||||
|
||||
---
|
||||
|
||||
## 0. 先给结论
|
||||
|
||||
### 0.1 蓝牙音乐和蓝牙模块是什么关系?
|
||||
|
||||
**蓝牙音乐是蓝牙模块里的一个媒体子功能。**
|
||||
|
||||
它看起来有独立 App 入口 `YX_BtMusic`,也在主蓝牙 App `YX_BlueTooth` 里有音乐页,但底层不是独立播放器,而是依赖蓝牙模块提供的连接能力。
|
||||
|
||||
```text
|
||||
蓝牙模块 = 蓝牙能力底座
|
||||
├─ 蓝牙开关
|
||||
├─ 设备扫描
|
||||
├─ 设备配对
|
||||
├─ 手机连接/断开
|
||||
├─ HFP 蓝牙电话
|
||||
├─ PBAP 联系人
|
||||
├─ MAP 消息
|
||||
└─ A2DP + AVRCP 蓝牙音乐
|
||||
```
|
||||
|
||||
蓝牙音乐必须依赖:
|
||||
|
||||
| 依赖 | 作用 |
|
||||
|---|---|
|
||||
| 蓝牙连接 | 手机必须先连上 |
|
||||
| A2DP Sink | 手机音乐声音通过 A2DP 进车机 |
|
||||
| AVRCP | 控制手机音乐播放/暂停/上一首/下一首,接收歌名 |
|
||||
| AudioFocus | 和收音机、导航、电话、语音等抢音频焦点 |
|
||||
| DataCenter | 把音乐状态同步给 Launcher/媒体卡片 |
|
||||
|
||||
所以开发时要这样定性:
|
||||
|
||||
```text
|
||||
蓝牙设置模块:负责“手机能不能连上”
|
||||
蓝牙电话模块:负责“HFP 电话能不能用”
|
||||
蓝牙音乐模块:负责“连上后手机音乐能不能播”
|
||||
音频焦点模块:负责“当前该谁出声”
|
||||
DataCenter:负责“状态给谁看、谁能反控”
|
||||
```
|
||||
|
||||
### 0.2 为什么容易误解为两个模块?
|
||||
|
||||
因为代码里有两个入口:
|
||||
|
||||
| 入口 | 说明 |
|
||||
|---|---|
|
||||
| `YX_BlueTooth\...\BluetoothMusicActivity.java` | 主蓝牙 App 内置蓝牙音乐页 |
|
||||
| `YX_BtMusic\...\MainActivity.java` | 独立蓝牙音乐 App |
|
||||
|
||||
但它们底层都走同一套 SDK:
|
||||
|
||||
```text
|
||||
BtMusicViewModel
|
||||
-> BtMusicControlManager
|
||||
-> BtMusicManager
|
||||
-> BluetoothAvrcpClient / BluetoothA2dpSinkClient
|
||||
```
|
||||
|
||||
所以是:
|
||||
|
||||
```text
|
||||
入口分开
|
||||
底层同源
|
||||
能力依赖蓝牙模块
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 整体架构
|
||||
|
||||
### 1.1 一张小图看全局
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
A["页面/服务层<br/>YX_BlueTooth / YX_BtMusic"]
|
||||
B["SDK 门面层<br/>ControlManager"]
|
||||
C["业务模块层<br/>Setting / Phone / Music"]
|
||||
D["平台封装层<br/>HFP / A2DP / AVRCP / PBAP / MAP"]
|
||||
E["Android 蓝牙栈"]
|
||||
F["DataCenter<br/>DataManager / DataUtils"]
|
||||
G["Launcher / 媒体卡片 / 其他模块"]
|
||||
|
||||
A --> B --> C --> D --> E
|
||||
C --> F --> G
|
||||
```
|
||||
|
||||
### 1.2 分层职责
|
||||
|
||||
| 层级 | 代码位置 | 作用 |
|
||||
|---|---|---|
|
||||
| 页面/服务层 | `YX_BlueTooth`、`YX_BtMusic` | Activity、Fragment、ViewModel、Service、Receiver |
|
||||
| SDK 门面层 | `YX_BluetoothSDK\...\manager` | 给 App 层提供统一 API |
|
||||
| 业务模块层 | `YX_BluetoothSDK\...\modules` | 组织蓝牙业务逻辑 |
|
||||
| 平台封装层 | `YX_BluetoothSDK\...\platform` | 封装 Android 蓝牙 Profile |
|
||||
| 音频焦点层 | `YX_BluetoothSDK\...\audio` | 蓝牙音乐音频焦点、静音、反控 |
|
||||
| 状态总线层 | `YX_Support` / `YX_DataCenterService` | 跨模块共享蓝牙状态 |
|
||||
|
||||
### 1.3 关键工程模块
|
||||
|
||||
| Module | 定位 |
|
||||
|---|---|
|
||||
| `YX_BlueTooth` | 主蓝牙应用,包含设置、电话、联系人、通话记录、蓝牙音乐页和后台服务 |
|
||||
| `YX_BtMusic` | 独立蓝牙音乐入口 |
|
||||
| `YX_BluetoothSDK` | 蓝牙核心 SDK |
|
||||
| `YX_Support` | `DataUtils`、`DataManager` 等共享工具 |
|
||||
| `YX_DataCenterService` | DataCenter 状态服务 |
|
||||
| `YX_Launcher` | 使用蓝牙状态、展示蓝牙卡片、可能反控音乐 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 蓝牙模块启动主线
|
||||
|
||||
### 2.1 启动流程
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
A["BluetoothApplication.onCreate"]
|
||||
B["BluetoothSdkApplication.onCreate"]
|
||||
C["初始化 ControlManager"]
|
||||
D["启动 BluetoothService"]
|
||||
E["BootReceiver 开机启动兜底"]
|
||||
|
||||
A --> B --> C
|
||||
A --> D
|
||||
E --> D
|
||||
```
|
||||
|
||||
### 2.2 步骤说明
|
||||
|
||||
| 步骤 | 文件/类 | 做什么 |
|
||||
|---|---|---|
|
||||
| 1 | `BluetoothApplication` | 主蓝牙 App 启动 |
|
||||
| 2 | `BluetoothSdkApplication` | 初始化 SDK 管理器 |
|
||||
| 3 | `BtContactsControlManager` | 初始化联系人门面 |
|
||||
| 4 | `BtSettingControlManager` | 初始化蓝牙设置门面 |
|
||||
| 5 | `BtPhoneControlManager` | 初始化蓝牙电话门面 |
|
||||
| 6 | `BtCallRecordsControlManager` | 初始化通话记录门面 |
|
||||
| 7 | `BtMusicControlManager` | 初始化蓝牙音乐门面 |
|
||||
| 8 | `BtVoiceControlManager` | 初始化语音蓝牙控制门面 |
|
||||
| 9 | `BluetoothService` | 处理电话、外部命令、悬浮窗 |
|
||||
| 10 | `BootReceiver` | 开机后兜底拉起蓝牙服务 |
|
||||
|
||||
### 2.3 `BluetoothService` 的角色
|
||||
|
||||
`BluetoothService` 不是普通空服务,它是蓝牙电话和外部命令的编排中心。
|
||||
|
||||
它负责:
|
||||
|
||||
- 注册电话模块监听。
|
||||
- 注册设置模块监听。
|
||||
- 注册联系人弹窗相关监听。
|
||||
- 接收外部拨号、挂断、接听命令。
|
||||
- 接收方向盘按键。
|
||||
- 处理来电时电话页/悬浮窗显示。
|
||||
- 处理自动接听。
|
||||
- 避让倒车、AVM 等特殊页面。
|
||||
|
||||
---
|
||||
|
||||
## 3. 蓝牙连接底座
|
||||
|
||||
### 3.1 为什么先看连接?
|
||||
|
||||
因为其他功能都依赖连接状态。
|
||||
|
||||
```text
|
||||
手机没连上
|
||||
-> HFP 电话不可用
|
||||
-> PBAP 联系人不可同步
|
||||
-> A2DP 音乐没声音
|
||||
-> AVRCP 控制拿不到歌名/播放状态
|
||||
```
|
||||
|
||||
### 3.2 设置连接模块职责
|
||||
|
||||
核心类:`BtSettingManager`
|
||||
|
||||
| 功能 | 说明 |
|
||||
|---|---|
|
||||
| 蓝牙开关 | 打开/关闭 BluetoothAdapter |
|
||||
| 设备扫描 | 搜索附近手机或蓝牙设备 |
|
||||
| 设备配对 | 处理绑定、配对请求、配对状态 |
|
||||
| 连接手机 | 建立 HFP、A2DP、PBAP、MAP 等 Profile |
|
||||
| 断开手机 | 断开 HFP、A2DP、PBAP、MAP |
|
||||
| 查询状态 | 当前是否打开、是否连接、是否连接中 |
|
||||
| 耳机 A2DP | 支持外部蓝牙耳机相关连接 |
|
||||
|
||||
### 3.3 连接手机小流程
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
A["用户点击设备"]
|
||||
B["SettingViewModel"]
|
||||
C["BtSettingControlManager"]
|
||||
D["BtSettingManager.connectPhoneDevice"]
|
||||
E["连接 A2DP + HFP"]
|
||||
F["连接状态广播/回调"]
|
||||
G["页面与 DataCenter 刷新"]
|
||||
|
||||
A --> B --> C --> D --> E --> F --> G
|
||||
```
|
||||
|
||||
### 3.4 连接手机详细链路
|
||||
|
||||
```text
|
||||
MainActivity / 设置弹窗
|
||||
-> SettingViewModel 或 BtSettingViewModel
|
||||
-> BtSettingControlManager.connectPhoneDevice(linkedInfo)
|
||||
-> BtSettingManager.connectPhoneDevice(linkedInfo)
|
||||
-> BluetoothA2dpSinkClient.connectA2dp(mac)
|
||||
-> BluetoothHfpClient.connectHfp(mac)
|
||||
-> PBAP/MAP 后续连接或同步
|
||||
-> BluetoothConnectListenerClient 收到状态
|
||||
-> IBtSettingModuleListener 回调
|
||||
-> ViewModel LiveData 刷新页面
|
||||
```
|
||||
|
||||
### 3.5 多 Profile 的含义
|
||||
|
||||
连接手机不是一个单点动作,而是多个蓝牙 Profile 共同组成。
|
||||
|
||||
| Profile | 作用 | 对应功能 |
|
||||
|---|---|---|
|
||||
| HFP | Hands-Free Profile | 蓝牙电话、通话音频 |
|
||||
| A2DP Sink | Advanced Audio Distribution Profile | 手机音乐音频流输入车机 |
|
||||
| AVRCP | Audio/Video Remote Control Profile | 控制手机音乐、读取歌曲信息 |
|
||||
| PBAP | Phone Book Access Profile | 联系人、电话本 |
|
||||
| MAP | Message Access Profile | 消息、短信相关能力 |
|
||||
|
||||
### 3.6 断开手机链路
|
||||
|
||||
```text
|
||||
BtSettingControlManager.disconnectPhoneDevice(mac)
|
||||
-> BtSettingManager.disconnectPhoneDevice(mac)
|
||||
-> BluetoothHfpClient.disconnectHfp(mac)
|
||||
-> BluetoothPbapClient.disconnectPbab(mac)
|
||||
-> BluetoothMapConnectClient.disconnectMap(mac)
|
||||
-> BluetoothA2dpSinkClient.disconnectA2dp(mac)
|
||||
-> 连接状态回调
|
||||
-> 页面刷新
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 蓝牙电话功能
|
||||
|
||||
### 4.1 电话依赖什么?
|
||||
|
||||
蓝牙电话依赖 HFP。
|
||||
|
||||
```text
|
||||
手机 HFP 连接成功
|
||||
-> 车机可以拨号/接听/挂断
|
||||
-> 可以拿到当前通话状态
|
||||
-> 可以处理通话音频
|
||||
```
|
||||
|
||||
核心链路:
|
||||
|
||||
```text
|
||||
BluetoothHfpClient
|
||||
-> BtPhoneManager
|
||||
-> BtPhoneControlManager
|
||||
-> BluetoothPhoneViewModel / BluetoothService
|
||||
-> BluetoothPhoneActivity / 电话悬浮窗
|
||||
```
|
||||
|
||||
### 4.2 拨号流程
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
A["电话页/联系人/通话记录/外部命令"]
|
||||
B["BluetoothPhoneViewModel 或 BluetoothService"]
|
||||
C["BtPhoneControlManager"]
|
||||
D["BtPhoneManager"]
|
||||
E["BluetoothHfpClient.dial"]
|
||||
F["HFP 通话状态回调"]
|
||||
G["电话界面刷新"]
|
||||
|
||||
A --> B --> C --> D --> E --> F --> G
|
||||
```
|
||||
|
||||
### 4.3 来电流程
|
||||
|
||||
```text
|
||||
手机来电
|
||||
-> BluetoothHfpClient 收到 HFP 状态
|
||||
-> BtPhoneManager 转换通话状态
|
||||
-> BluetoothService.onHfpCallChanged()
|
||||
-> 判断是否倒车/AVM/前台/自动接听
|
||||
-> 显示 BluetoothPhoneActivity 或电话悬浮窗
|
||||
-> BtInfoPushManager 推送 BT_INFO
|
||||
```
|
||||
|
||||
### 4.4 电话开发要重点看哪里?
|
||||
|
||||
| 场景 | 优先看 |
|
||||
|---|---|
|
||||
| 电话页面 UI | `BluetoothPhoneActivity` |
|
||||
| 电话页面状态 | `BluetoothPhoneViewModel` |
|
||||
| 来电弹窗/外部命令 | `BluetoothService` |
|
||||
| 拨号/接听/挂断 API | `BtPhoneControlManager` |
|
||||
| 电话业务核心 | `BtPhoneManager` |
|
||||
| HFP 底层状态 | `BluetoothHfpClient` |
|
||||
|
||||
---
|
||||
|
||||
## 5. 联系人与通话记录
|
||||
|
||||
### 5.1 联系人依赖什么?
|
||||
|
||||
联系人主要依赖 PBAP。
|
||||
|
||||
```text
|
||||
手机连接成功
|
||||
-> PBAP 可用
|
||||
-> 拉取手机电话本
|
||||
-> 本地整理
|
||||
-> 联系人页面展示
|
||||
```
|
||||
|
||||
核心链路:
|
||||
|
||||
```text
|
||||
BluetoothPbapClient
|
||||
-> BtContactsManager
|
||||
-> BtContactsControlManager
|
||||
-> ContactListViewModel
|
||||
-> ContactsFragment
|
||||
```
|
||||
|
||||
### 5.2 通话记录依赖什么?
|
||||
|
||||
通话记录依赖 PBAP/HFP 相关数据。
|
||||
|
||||
```text
|
||||
手机连接成功
|
||||
-> 通话记录数据可用
|
||||
-> BtCallRecordsManager 拉取/整理
|
||||
-> CallHistoryViewModel
|
||||
-> CallLogsFragment
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 蓝牙音乐功能
|
||||
|
||||
### 6.1 蓝牙音乐的本质
|
||||
|
||||
蓝牙音乐不是车机本地播放器,而是“车机控制手机音乐 + 接收手机音频流”。
|
||||
|
||||
```text
|
||||
手机负责播放音乐
|
||||
车机负责:
|
||||
1. 通过 A2DP 接收声音
|
||||
2. 通过 AVRCP 控制播放
|
||||
3. 通过 AVRCP 获取歌曲信息
|
||||
4. 通过 AudioFocus 决定是否出声
|
||||
```
|
||||
|
||||
### 6.2 蓝牙音乐必须满足的前置条件
|
||||
|
||||
| 前置条件 | 不满足时表现 |
|
||||
|---|---|
|
||||
| 手机已连接 | 蓝牙音乐不可用 |
|
||||
| A2DP Sink 已连接 | 没有手机音乐声音输入 |
|
||||
| AVRCP 可用 | 按钮可能无效,歌名可能不刷新 |
|
||||
| AudioFocus 成功 | 有状态但可能没声音 |
|
||||
| 未被电话/语音/导航抢占 | 可能暂停、静音或降低音量 |
|
||||
|
||||
### 6.3 蓝牙音乐两个入口
|
||||
|
||||
| 入口 | 文件 | 说明 |
|
||||
|---|---|---|
|
||||
| 主蓝牙 App 音乐页 | `YX_BlueTooth\...\BluetoothMusicActivity.java` | 集成在主蓝牙应用 |
|
||||
| 独立音乐 App | `YX_BtMusic\...\MainActivity.java` | 独立启动入口 |
|
||||
|
||||
底层调用一致:
|
||||
|
||||
```text
|
||||
BtMusicViewModel
|
||||
-> BtMusicControlManager
|
||||
-> BtMusicManager
|
||||
-> BluetoothAvrcpClient / BluetoothA2dpSinkClient / BtMusicAudioManager
|
||||
```
|
||||
|
||||
### 6.4 播放控制流程
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
A["用户点击播放/暂停/上一首/下一首"]
|
||||
B["BtMusicViewModel"]
|
||||
C["BtMusicControlManager"]
|
||||
D["BtMusicManager"]
|
||||
E["BtMusicAudioManager 请求焦点"]
|
||||
F["BluetoothAvrcpClient 控制手机"]
|
||||
G["手机音乐 App"]
|
||||
|
||||
A --> B --> C --> D --> E --> F --> G
|
||||
```
|
||||
|
||||
### 6.5 播放控制详细链路
|
||||
|
||||
```text
|
||||
BluetoothMusicActivity / YX_BtMusic MainActivity
|
||||
-> BtMusicViewModel.playBtMusic/pauseBtMusic/preBtMusic/nextBtMusic
|
||||
-> BtMusicControlManager
|
||||
-> BtMusicManager
|
||||
-> 播放前 requestAudioFocus()
|
||||
-> BluetoothAvrcpClient.play/pause/previous/next
|
||||
-> 手机音乐 App 执行
|
||||
```
|
||||
|
||||
### 6.6 歌曲信息流程
|
||||
|
||||
```text
|
||||
手机音乐元数据变化
|
||||
-> BluetoothAvrcpClient.onMetadataChanged()
|
||||
-> BtMusicManager.onMetadataChanged()
|
||||
-> MusicInfo(title/artist/album/albumUrl/duration)
|
||||
-> BtMusicViewModel.mLiveDataMusicInfo
|
||||
-> 蓝牙音乐页面刷新
|
||||
-> BtInfoPushManager.sendMusicInfoToLauncher()
|
||||
-> DataManager 写 BT_MUSIC_INFO
|
||||
-> Launcher 蓝牙音乐卡片刷新
|
||||
```
|
||||
|
||||
### 6.7 播放状态流程
|
||||
|
||||
```text
|
||||
手机播放/暂停状态变化
|
||||
-> BluetoothAvrcpClient.onPlaybackStateChanged()
|
||||
-> BtMusicManager.onPlaybackStateChanged()
|
||||
-> BtMusicViewModel.mLiveDataPlayState
|
||||
-> 播放按钮刷新
|
||||
-> BtInfoPushManager.sendMusicStateToLauncher()
|
||||
-> DataManager 写 BT_MUSIC_INFO
|
||||
```
|
||||
|
||||
### 6.8 A2DP 连接状态流程
|
||||
|
||||
```text
|
||||
BluetoothConnectListenerClient 收到 A2DP 连接
|
||||
-> BtMusicManager.onA2dpConnect()
|
||||
-> 如果未获得音频焦点,先 setA2dpMute()
|
||||
-> BtMusicViewModel.mLiveDataA2dpConnectStatus = true
|
||||
-> 页面显示已连接
|
||||
```
|
||||
|
||||
断开时:
|
||||
|
||||
```text
|
||||
A2DP 断开
|
||||
-> BtMusicManager.onA2dpDisconnect()
|
||||
-> 清理音乐状态
|
||||
-> BtMusicViewModel.mLiveDataA2dpConnectStatus = false
|
||||
-> 页面显示未连接
|
||||
```
|
||||
|
||||
### 6.9 音频焦点流程
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
A["准备播放蓝牙音乐"]
|
||||
B["BtMusicAudioManager.requestAudioFocus"]
|
||||
C{"是否拿到焦点"}
|
||||
D["A2DP unmute"]
|
||||
E["允许 AVRCP play"]
|
||||
F["A2DP mute / pause"]
|
||||
G["清理或更新 BT_MUSIC_INFO"]
|
||||
|
||||
A --> B --> C
|
||||
C -->|是| D --> E
|
||||
C -->|否| F --> G
|
||||
```
|
||||
|
||||
焦点事件:
|
||||
|
||||
| 事件 | 处理 |
|
||||
|---|---|
|
||||
| `AUDIOFOCUS_GAIN` | A2DP unmute,必要时恢复播放 |
|
||||
| `AUDIOFOCUS_LOSS` | 释放焦点、A2DP mute、暂停、清理音乐信息 |
|
||||
| `AUDIOFOCUS_LOSS_TRANSIENT` | 临时 mute、暂停 |
|
||||
| `AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK` | 降低 A2DP 音量 |
|
||||
|
||||
### 6.10 电话与蓝牙音乐的关系
|
||||
|
||||
电话和蓝牙音乐都属于蓝牙模块,但使用不同 Profile:
|
||||
|
||||
| 功能 | Profile |
|
||||
|---|---|
|
||||
| 蓝牙电话 | HFP |
|
||||
| 蓝牙音乐音频 | A2DP Sink |
|
||||
| 蓝牙音乐控制/歌名 | AVRCP |
|
||||
|
||||
来电或通话时,电话通常会影响蓝牙音乐:
|
||||
|
||||
```text
|
||||
来电/通话
|
||||
-> 电话或系统音频焦点抢占
|
||||
-> 蓝牙音乐 AUDIOFOCUS_LOSS 或 TRANSIENT
|
||||
-> A2DP mute / pause
|
||||
-> 通话结束后按策略恢复
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. DataCenter 状态同步
|
||||
|
||||
### 7.1 为什么要有 DataCenter?
|
||||
|
||||
蓝牙模块不只给自己页面用,还要给 Launcher、媒体卡片、语音、其他系统模块用。
|
||||
|
||||
所以蓝牙状态会写入 DataCenter。
|
||||
|
||||
### 7.2 关键状态
|
||||
|
||||
定义位置:`YX_Support\src\main\java\com\yaxon\support\utils\DataUtils.java`
|
||||
|
||||
| Key | 作用 |
|
||||
|---|---|
|
||||
| `BT_INFO` | 蓝牙开关、连接、电话等综合状态 |
|
||||
| `BT_MUSIC_INFO` | 蓝牙音乐歌名、歌手、播放状态、进度、时长 |
|
||||
| `MUSIC_BT_CONTROL_STATE` | Launcher 反控蓝牙音乐 |
|
||||
| `SOURCE_ID` | 当前音源标识 |
|
||||
|
||||
### 7.3 电话状态推送
|
||||
|
||||
```text
|
||||
BtPhoneManager / BtSettingManager
|
||||
-> BtInfoPushManager.sendBtInfo()
|
||||
-> DataManager.putObject(MEDIA_URI, BT_INFO, btInfo)
|
||||
-> Launcher / 其他模块读取
|
||||
```
|
||||
|
||||
### 7.4 音乐状态推送
|
||||
|
||||
```text
|
||||
BluetoothAvrcpClient 收到播放状态或歌曲信息
|
||||
-> BtInfoPushManager.sendMusicStateToLauncher()
|
||||
-> BtInfoPushManager.sendMusicInfoToLauncher()
|
||||
-> DataManager.putObject(MEDIA_URI, BT_MUSIC_INFO, btMusicInfo)
|
||||
-> Launcher 蓝牙音乐卡片刷新
|
||||
```
|
||||
|
||||
### 7.5 Launcher 反控蓝牙音乐
|
||||
|
||||
```text
|
||||
Launcher 写 MUSIC_BT_CONTROL_STATE
|
||||
-> BtMusicAudioManager.ContentObserver 触发
|
||||
-> 读取命令 PRE/NEXT/PLAY/PAUSE
|
||||
-> 调用 BtMusicManager
|
||||
-> BluetoothAvrcpClient 控制手机
|
||||
-> 重置 MUSIC_BT_CONTROL_STATE = -1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 开发入口速查
|
||||
|
||||
### 8.1 蓝牙设置/连接
|
||||
|
||||
| 目标 | 优先文件 |
|
||||
|---|---|
|
||||
| 页面入口 | `YX_BlueTooth\...\main\MainActivity.java` |
|
||||
| 设置状态 | `YX_BlueTooth\...\viewmodel\SettingViewModel.java` |
|
||||
| 设置弹窗状态 | `YX_BlueTooth\...\viewmodel\BtSettingViewModel.java` |
|
||||
| SDK 门面 | `YX_BluetoothSDK\...\manager\BtSettingControlManager.java` |
|
||||
| 连接核心 | `YX_BluetoothSDK\...\modules\BtSettingManager.java` |
|
||||
| 连接广播 | `YX_BluetoothSDK\...\platform\BluetoothConnectListenerClient.java` |
|
||||
| 扫描配对 | `YX_BluetoothSDK\...\platform\BluetoothDeviceClient.java` |
|
||||
|
||||
### 8.2 蓝牙电话
|
||||
|
||||
| 目标 | 优先文件 |
|
||||
|---|---|
|
||||
| 电话页面 | `YX_BlueTooth\...\main\BluetoothPhoneActivity.java` |
|
||||
| 电话状态 | `YX_BlueTooth\...\viewmodel\BluetoothPhoneViewModel.java` |
|
||||
| 来电/外部命令 | `YX_BlueTooth\...\service\BluetoothService.java` |
|
||||
| SDK 门面 | `YX_BluetoothSDK\...\manager\BtPhoneControlManager.java` |
|
||||
| 电话核心 | `YX_BluetoothSDK\...\modules\BtPhoneManager.java` |
|
||||
| HFP 底层 | `YX_BluetoothSDK\...\platform\BluetoothHfpClient.java` |
|
||||
|
||||
### 8.3 蓝牙音乐
|
||||
|
||||
| 目标 | 优先文件 |
|
||||
|---|---|
|
||||
| 主 App 音乐页 | `YX_BlueTooth\...\main\BluetoothMusicActivity.java` |
|
||||
| 主 App 音乐状态 | `YX_BlueTooth\...\viewmodel\BtMusicViewModel.java` |
|
||||
| 独立音乐页 | `YX_BtMusic\...\main\MainActivity.java` |
|
||||
| 独立音乐状态 | `YX_BtMusic\...\mvvm\BtMusicViewModel.java` |
|
||||
| SDK 门面 | `YX_BluetoothSDK\...\manager\BtMusicControlManager.java` |
|
||||
| 音乐核心 | `YX_BluetoothSDK\...\modules\BtMusicManager.java` |
|
||||
| 音频焦点 | `YX_BluetoothSDK\...\audio\BtMusicAudioManager.java` |
|
||||
| AVRCP | `YX_BluetoothSDK\...\platform\BluetoothAvrcpClient.java` |
|
||||
| A2DP Sink | `YX_BluetoothSDK\...\platform\BluetoothA2dpSinkClient.java` |
|
||||
|
||||
### 8.4 DataCenter / Launcher 卡片
|
||||
|
||||
| 目标 | 优先文件 |
|
||||
|---|---|
|
||||
| 蓝牙状态推送 | `YX_BluetoothSDK\...\modules\BtInfoPushManager.java` |
|
||||
| 状态 key | `YX_Support\...\utils\DataUtils.java` |
|
||||
| 状态读写 | `YX_Support\...\data\DataManager.java` |
|
||||
| 状态服务 | `YX_Support\...\data\DataManagerService.java` |
|
||||
| Launcher 展示 | 搜索 `BT_INFO`、`BT_MUSIC_INFO`、`MUSIC_BT_CONTROL_STATE` |
|
||||
|
||||
---
|
||||
|
||||
## 9. 常见问题定位路径
|
||||
|
||||
### 9.1 蓝牙打不开/关不上
|
||||
|
||||
```text
|
||||
BtSettingControlManager.openBluetooth/closeBluetooth
|
||||
-> BtSettingManager
|
||||
-> BluetoothAdapter.enable/disable
|
||||
-> BluetoothDeviceClient 广播
|
||||
-> IBtSettingModuleListener
|
||||
-> ViewModel LiveData
|
||||
-> BT_INFO
|
||||
```
|
||||
|
||||
### 9.2 手机连接失败
|
||||
|
||||
```text
|
||||
BtSettingManager.connectPhoneDevice()
|
||||
-> 当前是否已有设备
|
||||
-> connectA2dp(mac)
|
||||
-> connectHfp(mac)
|
||||
-> BluetoothConnectListenerClient 状态广播
|
||||
-> PBAP/MAP 后续状态
|
||||
-> 页面连接状态刷新
|
||||
```
|
||||
|
||||
### 9.3 来电不弹窗
|
||||
|
||||
```text
|
||||
BluetoothHfpClient
|
||||
-> BtPhoneManager.onHfpCallChanged
|
||||
-> BluetoothService.onHfpCallChanged
|
||||
-> 判断倒车/AVM/前台/自动接听
|
||||
-> BluetoothPhoneActivity 或悬浮窗
|
||||
```
|
||||
|
||||
### 9.4 蓝牙音乐按钮无效
|
||||
|
||||
```text
|
||||
Activity 点击
|
||||
-> BtMusicViewModel
|
||||
-> BtMusicControlManager
|
||||
-> BtMusicManager
|
||||
-> BluetoothAvrcpClient
|
||||
-> 手机音乐 App
|
||||
```
|
||||
|
||||
重点确认:
|
||||
|
||||
- AVRCP 是否连接。
|
||||
- 手机音乐 App 是否支持 AVRCP。
|
||||
- 当前是否有 AudioFocus。
|
||||
|
||||
### 9.5 蓝牙音乐无声音
|
||||
|
||||
```text
|
||||
A2DP Sink 是否连接
|
||||
-> AudioFocus 是否成功
|
||||
-> 是否被 setA2dpMute()
|
||||
-> 是否被电话/语音/导航抢焦点
|
||||
-> 当前音源 SOURCE_ID 是否正确
|
||||
```
|
||||
|
||||
### 9.6 歌名不刷新
|
||||
|
||||
```text
|
||||
BluetoothAvrcpClient.onMetadataChanged
|
||||
-> BtMusicManager.onMetadataChanged
|
||||
-> BtMusicViewModel.mLiveDataMusicInfo
|
||||
-> 蓝牙音乐页面
|
||||
-> BtInfoPushManager
|
||||
-> BT_MUSIC_INFO
|
||||
-> Launcher 卡片
|
||||
```
|
||||
|
||||
### 9.7 Launcher 反控无效
|
||||
|
||||
```text
|
||||
Launcher 写 MUSIC_BT_CONTROL_STATE
|
||||
-> BtMusicAudioManager.ContentObserver
|
||||
-> 命令值是否正确
|
||||
-> BtMusicManager 是否执行
|
||||
-> AVRCP 是否控制手机
|
||||
-> 是否重置为 -1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 当前代码风险点
|
||||
|
||||
### 10.1 `isA2dpSinkConnected()` 返回值疑似错误
|
||||
|
||||
现象:
|
||||
|
||||
```text
|
||||
BtMusicControlManager.isA2dpSinkConnected()
|
||||
调用了 mBtMusicManager.isA2dpSinkConnected()
|
||||
但没有 return 结果
|
||||
```
|
||||
|
||||
同类问题也出现在 `BtMusicViewModel.isA2dpSinkConnected()`。
|
||||
|
||||
可能影响:
|
||||
|
||||
- 页面一直认为 A2DP 未连接。
|
||||
- 蓝牙音乐连接状态显示异常。
|
||||
- 自动播放逻辑异常。
|
||||
|
||||
### 10.2 `removeIBtMusicModuleListener()` 参数类型疑似错误
|
||||
|
||||
现象:
|
||||
|
||||
```text
|
||||
BtMusicManager.removeIBtMusicModuleListener(IBtSettingModuleListener listener)
|
||||
```
|
||||
|
||||
但音乐监听列表维护的是 `IBtMusicModuleListener`。
|
||||
|
||||
可能影响:
|
||||
|
||||
- 音乐监听无法正确移除。
|
||||
- 页面销毁后仍收到回调。
|
||||
- 重复回调或内存泄漏。
|
||||
|
||||
### 10.3 `BtMusicAudioManager` 的 `ContentObserver` 生命周期需要核对
|
||||
|
||||
现象:
|
||||
|
||||
```text
|
||||
注册 Launcher 反控 ContentObserver
|
||||
但需要确认 destroy() 中是否完整 unregister
|
||||
```
|
||||
|
||||
可能影响:
|
||||
|
||||
- 内存泄漏。
|
||||
- 反控命令重复触发。
|
||||
- 销毁后仍收到状态变化。
|
||||
|
||||
### 10.4 `BluetoothService` 的 `ContentObserver` 注销路径需要核对
|
||||
|
||||
现象:
|
||||
|
||||
```text
|
||||
onDestroy() 中 unregisterContentObserver(mContentObserver)
|
||||
但注册路径需要确认是否一定执行
|
||||
```
|
||||
|
||||
可能影响:
|
||||
|
||||
- 未注册就注销导致异常。
|
||||
- 服务销毁异常。
|
||||
|
||||
---
|
||||
|
||||
## 11. 开发建议
|
||||
|
||||
### 11.1 保持调用层级
|
||||
|
||||
推荐:
|
||||
|
||||
```text
|
||||
Activity / Fragment
|
||||
-> ViewModel
|
||||
-> ControlManager
|
||||
-> Manager
|
||||
-> Platform Client
|
||||
```
|
||||
|
||||
不推荐:
|
||||
|
||||
```text
|
||||
Activity 直接调用 BluetoothHfpClient
|
||||
Activity 直接调用 BluetoothAvrcpClient
|
||||
```
|
||||
|
||||
### 11.2 修改蓝牙音乐时同时确认三件事
|
||||
|
||||
| 检查项 | 原因 |
|
||||
|---|---|
|
||||
| AVRCP 是否可控 | 决定按钮和歌名 |
|
||||
| A2DP 是否连接 | 决定有没有手机音频流 |
|
||||
| AudioFocus 是否成功 | 决定车机是否允许出声 |
|
||||
|
||||
### 11.3 修改电话时必须同时看 Service
|
||||
|
||||
电话页不是唯一入口,下面这些都会走 `BluetoothService`:
|
||||
|
||||
- 来电
|
||||
- 挂断
|
||||
- 自动接听
|
||||
- 方向盘按键
|
||||
- 外部拨号
|
||||
- 电话悬浮窗
|
||||
- 倒车/AVM 避让
|
||||
|
||||
### 11.4 修改状态展示时必须看 DataCenter
|
||||
|
||||
| 状态 | Key |
|
||||
|---|---|
|
||||
| 电话/连接状态 | `BT_INFO` |
|
||||
| 蓝牙音乐状态 | `BT_MUSIC_INFO` |
|
||||
| Launcher 反控命令 | `MUSIC_BT_CONTROL_STATE` |
|
||||
|
||||
---
|
||||
|
||||
## 12. 建议读代码顺序
|
||||
|
||||
| 顺序 | 文件/类 | 读它的目的 |
|
||||
|---|---|---|
|
||||
| 1 | `settings.gradle` | 确认蓝牙相关 module |
|
||||
| 2 | `BluetoothSdkApplication` | 理解 SDK 初始化 |
|
||||
| 3 | `BluetoothApplication` | 理解主蓝牙 App 启动 |
|
||||
| 4 | `BootReceiver` | 理解开机启动 |
|
||||
| 5 | `BluetoothService` | 理解电话和外部命令编排 |
|
||||
| 6 | `BtSettingManager` | 理解连接底座 |
|
||||
| 7 | `BluetoothConnectListenerClient` | 理解连接状态来源 |
|
||||
| 8 | `BtPhoneManager` / `BluetoothHfpClient` | 理解蓝牙电话 |
|
||||
| 9 | `BtMusicManager` / `BtMusicAudioManager` | 理解蓝牙音乐和焦点 |
|
||||
| 10 | `BluetoothAvrcpClient` / `BluetoothA2dpSinkClient` | 理解音乐控制和音频通道 |
|
||||
| 11 | `BtInfoPushManager` / `DataUtils` | 理解跨模块状态同步 |
|
||||
| 12 | 各 Activity / ViewModel | 理解页面如何消费状态 |
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
|
||||
刷机重启 adb reboot loader
|
||||
|
||||
blink资源修改需要改如下3个地方:
|
||||
|
||||
1.**blink资源替换路径:**
|
||||
Z:\znzc\028_shanxi_tongli\android14.0_rk3562\device\rockchip\rk3562\rk3562_u\firmware\w260\blink
|
||||
|
||||
Y:\tongli\android14.0_rk3562\device\rockchip\rk3562\rk3562_u\firmware\w260\blink
|
||||
|
||||
**2.mk文件路径:**
|
||||
Z:\znzc\028_shanxi_tongli\android14.0_rk3562\device\rockchip\rk3562
|
||||
|
||||
3.bp文件路径:
|
||||
Z:\znzc\028_shanxi_tongli\android14.0_rk3562\device\rockchip\rk3562\rk3562_u\firmware\w260\blink\Android.bp
|
||||
|
||||
adb shell dumpsys appwidget | Select-String "com.yaxon.bluetooth|MusicWidget"
|
||||
|
||||
|
||||
源码git出问题三步走:
|
||||
rm -f .git/index
|
||||
git read-tree HEAD
|
||||
git status
|
||||
|
||||
rm -f .git/refs/notes/ai
|
||||
|
||||
查找源码: find . -name EXEC_KERNEL_IMAGE.bin
|
||||
grep . -rne wcnmodem
|
||||
|
||||
|
||||
|
||||
倒车:
|
||||
adb shell content insert --uri content://com.yaxon.data.provider/state/ --bind BACKCAR_STATE:i:1
|
||||
|
||||
退出倒车:
|
||||
adb shell content insert --uri content://com.yaxon.data.provider/state/ --bind BACKCAR_STATE:i:0
|
||||
|
||||
Z:\znzc\028_shanxi_tongli\android14.0_rk3562\packages\modules\Bluetooth\android\app\src\com\android\bluetooth\btservice\AdapterService.java
|
||||
|
||||
|
||||
1.下载2300条的通讯录数据
|
||||
花费时间 2分40秒
|
||||
去掉头像 2分13秒 2分10秒
|
||||
精简字段: 2分15秒
|
||||
|
||||
app优化后:
|
||||
允辉:1分48秒
|
||||
|
||||
红米手机优化前 3分21秒 3分21秒 3分18秒
|
||||
红米手机优化后 2分26秒 2分30秒
|
||||
|
||||
通话列表限制50条 优化后:
|
||||
允辉:1分47秒 1分49秒 1分50秒
|
||||
红米手机: 1分50秒 2分15秒
|
||||
|
||||
2.下载250条通话记录数据
|
||||
花费时间 20秒
|
||||
去掉头像 16秒
|
||||
精简字段: 17秒 15秒
|
||||
|
||||
app 优化 15秒
|
||||
|
||||
|
||||
Reference in new issue
Block a user