first commit
This commit is contained in:
commit
669f49b1d6
342 files changed
+320811
No files matched your search
@@ -0,0 +1,76 @@
|
||||
# 徐工语音项目总览
|
||||
|
||||
## 一句话结论
|
||||
|
||||
徐工语音项目的核心是 `YX_Voice` 系统应用,它作为同行者 TXZ 语音助手与车载业务模块之间的桥接层,负责语音指令接收、协议分发、IPC 调用、车辆状态同步和语音相关问题排查。
|
||||
|
||||
## 当前定位
|
||||
|
||||
| 项目项 | 内容 |
|
||||
|---|---|
|
||||
| 项目名称 | 徐工语音项目 |
|
||||
| 核心模块 | `YX_Voice` |
|
||||
| 包名 | `com.yaxon.voice` |
|
||||
| 应用类型 | Android System Application |
|
||||
| 进程属性 | 系统持久化进程,`persistent=true` |
|
||||
| 运行身份 | `android.uid.system` |
|
||||
| 语音方案 | 同行者 TXZ 语音助手 |
|
||||
| 主要职责 | TXZ 连接、语音指令分发、协议处理、IPC 调用、状态同步 |
|
||||
|
||||
## 核心链路
|
||||
|
||||
```text
|
||||
用户语音
|
||||
-> TXZ 语音助手
|
||||
-> VoiceService
|
||||
-> ProtocolManager
|
||||
-> YxProtocolHandler
|
||||
-> 具体 Protocol
|
||||
-> VoiceEventHelper
|
||||
-> YxIPC / 业务模块
|
||||
-> 状态同步回 TXZ
|
||||
```
|
||||
|
||||
## 已有资料索引
|
||||
|
||||
| 文档 | 用途 |
|
||||
|---|---|
|
||||
| [[YX_Voice_架构文档]] | 系统架构、模块分层、核心链路 |
|
||||
| [[YX_Voice_模块详细文档]] | 应用入口、服务、管理器、Helper、Receiver 等详细说明 |
|
||||
| [[YX_Voice_协议设计文档]] | 协议接口、命令映射、Bundle 消息格式、状态同步 |
|
||||
| [[YX_Voice_配置文档]] | Gradle、Manifest、权限、IPC、TXZ 连接配置 |
|
||||
| [[同行者可见即可说自动注册框架对接方案_快速阅读]] | 可见即可说接入原则、控件要求、AIDL/广播链路 |
|
||||
| [[../语音.md]] | 调试命令、账号、问题汇总、资源路径 |
|
||||
| [[../语音_整理.md]] | 原始整理记录 |
|
||||
| [[../语音唤醒异常问题分析.md]] | AudioFlinger dump 与唤醒异常排查 |
|
||||
| [[../log 录音分析.md]] | 录音/音频相关原始分析材料 |
|
||||
|
||||
## 当前核心难点
|
||||
|
||||
| 难点 | 说明 | 风险 |
|
||||
|---|---|---|
|
||||
| TXZ 连接与状态同步 | 连接成功后需同步车辆配置、蓝牙、音量、亮度、设置等状态 | 状态不同步会导致语音反馈与车机实际状态不一致 |
|
||||
| 协议映射完整性 | 语音指令需要映射到正确协议和业务模块 | 漏映射会出现语音识别成功但功能无响应 |
|
||||
| IPC 可靠性 | VoiceEventHelper 通过 IPC 控制音乐、设置、空调等模块 | 业务模块未绑定或接口变更会导致调用失败 |
|
||||
| 可见即可说接入 | 控件需要唯一 ID、文本/隐藏标签、状态型描述动态更新 | UI 可见但语音无法命中或命中错误状态 |
|
||||
| 音频唤醒问题 | 涉及 AudioFlinger、AudioPolicy、录音 dump 和硬件输入链路 | 需要日志、dump 和录音文件联合判断 |
|
||||
|
||||
## 近期优先级
|
||||
|
||||
1. 固化调试命令和日志过滤方式,减少重复查找。
|
||||
2. 维护 Bug 记录,区分现象、根因、修复和验证结果。
|
||||
3. 建立协议/模块变更记录,避免接口变更后文档失真。
|
||||
4. 用测试验证记录沉淀每次构建、安装、语音唤醒、指令执行、状态同步结果。
|
||||
5. 后续进入代码修改时,再联动 `F:\ZDCode\xugong` 源码工程。
|
||||
|
||||
## Agent 使用入口
|
||||
|
||||
每次让 Agent 处理本项目任务,建议先说:
|
||||
|
||||
```text
|
||||
先读取 agent.md 和 项目文档/徐工/语音/00_项目总览.md。
|
||||
本次目标是:……
|
||||
涉及日志/代码/文档是:……
|
||||
先判断风险等级;如果要改文件,先问我要不要备份。
|
||||
完成后把原因、处理方式、验证结果、遗留问题写入对应记录文档。
|
||||
```
|
||||
@@ -0,0 +1,51 @@
|
||||
# 徐工语音模块清单
|
||||
|
||||
## 模块总览
|
||||
|
||||
| 模块 | 文件/类 | 职责 | 关联文档 |
|
||||
|---|---|---|---|
|
||||
| 应用入口 | `YxApplication` | 初始化车载 SDK、IPC、崩溃处理和语音服务 | [[YX_Voice_模块详细文档]] |
|
||||
| 语音服务 | `VoiceService` | TXZ 连接、指令接收、状态初始化、Receiver 注册 | [[YX_Voice_模块详细文档]] |
|
||||
| 协议管理 | `ProtocolManager` | 接收 IPC 消息并分发到协议处理器 | [[YX_Voice_模块详细文档]] |
|
||||
| 协议处理 | `YxProtocolHandler` | 维护包名到协议逻辑类映射,后台线程分发协议 | [[YX_Voice_模块详细文档]] |
|
||||
| 状态管理 | `VoiceManager` | 管理 TXZ 绑定、AVM/DVR 状态、车辆状态回调 | [[YX_Voice_模块详细文档]] |
|
||||
| 事件封装 | `VoiceEventHelper` | 封装语音控制操作,通过 IPC 调业务模块 | [[YX_Voice_模块详细文档]] |
|
||||
| 协议实现 | `BaseProtocol` 及子类 | 实现车辆、空调、设置、媒体等协议逻辑 | [[YX_Voice_协议设计文档]] |
|
||||
| TXZ 通信 | `TxzProtocolManager` | 与同行者语音助手建立协议通信 | [[YX_Voice_架构文档]] |
|
||||
| IPC 通信 | `YxIPC` | 跨进程调用音乐、设置、空调等模块 | [[YX_Voice_架构文档]] |
|
||||
| 可见即可说 | 无障碍扫描 / AIDL / 广播 | 控件语音热词注册和命中回调 | [[同行者可见即可说自动注册框架对接方案_快速阅读]] |
|
||||
|
||||
## 关键依赖
|
||||
|
||||
| 依赖 | 用途 |
|
||||
|---|---|
|
||||
| `YX_IPC_SDK` | 跨进程通信 |
|
||||
| `YX_Lib_CommonBase` | 公共基础能力 |
|
||||
| `YX_AutoMotiveSDK` | 车载 SDK |
|
||||
| `library-release-0127.aar` | TXZ 协议库 |
|
||||
| `tools.jar` | 工具库 |
|
||||
| `framework_classes.jar` | 系统框架编译依赖 |
|
||||
| `serial-0.1.6_classes.jar` | 串口相关依赖 |
|
||||
|
||||
## 协议类别
|
||||
|
||||
| 类别 | 示例 | 验证重点 |
|
||||
|---|---|---|
|
||||
| 车辆控制 | 巡航、车道偏离、车窗等 | 指令是否映射到正确 CAN/业务接口 |
|
||||
| 空调控制 | 开关、温度、风速、模式 | 状态反馈是否同步到 TXZ |
|
||||
| 系统设置 | 语言、单位、亮度、熄屏 | 设置值是否落库并广播 |
|
||||
| 媒体控制 | 上一首、播放状态、媒体焦点 | 媒体焦点和播放状态是否一致 |
|
||||
| 蓝牙相关 | 蓝牙状态、电话、连接 | 蓝牙状态同步和权限边界 |
|
||||
|
||||
## 模块变更记录模板
|
||||
|
||||
| 日期 | 模块 | 变更类型 | 变更内容 | 影响范围 | 验证方式 | 结论 |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 待填写 | 待填写 | 新增/修改/删除 | 待填写 | 待填写 | 待填写 | 待验证 |
|
||||
|
||||
## 模块验收标准
|
||||
|
||||
- 每个语音指令都有明确协议入口、参数格式和目标业务模块。
|
||||
- 每个状态同步都有触发时机、数据来源和 TXZ 通知路径。
|
||||
- 每个跨模块调用都有失败处理和日志。
|
||||
- 每次模块变更都在本文件记录影响范围和验证方式。
|
||||
@@ -0,0 +1,137 @@
|
||||
# 徐工语音 Bug 记录
|
||||
|
||||
## 使用规则
|
||||
|
||||
每个 Bug 都按“现象 -> 证据 -> 根因 -> 修复 -> 验证 -> 遗留风险”记录,避免只留下口头结论。
|
||||
|
||||
## Bug 列表
|
||||
|
||||
| ID | 日期 | 问题现象 | 模块 | 优先级 | 状态 | 负责人/来源 | 关联记录 |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| VOICE-001 | 2026-06-15 | 语音唤醒异常 | 音频/TXZ/AudioFlinger | P1 | 待复现 | 已有文档沉淀 | [[../语音唤醒异常问题分析]]、[[../log 录音分析]] |
|
||||
| VOICE-002 | 待填写 | 语音识别成功但功能无响应 | 协议/IPC | P1 | 待分析 | 待填写 | 待补充 |
|
||||
| VOICE-003 | 待填写 | 状态同步不准确 | 状态同步/TXZ | P2 | 待分析 | 待填写 | 待补充 |
|
||||
|
||||
## Bug 详情
|
||||
|
||||
### VOICE-001:语音唤醒异常
|
||||
|
||||
| 字段 | 内容 |
|
||||
|---|---|
|
||||
| 发现日期 | 历史问题,2026-06-15 补充到 Bug 记录 |
|
||||
| 影响版本 | 待确认 |
|
||||
| 问题模块 | 音频输入链路、TXZ 唤醒、AudioFlinger/AudioPolicy |
|
||||
| 触发条件 | 用户尝试语音唤醒同行者时,出现唤醒失败或录音链路异常 |
|
||||
| 用户影响 | 无法稳定通过语音唤醒进入后续指令流程 |
|
||||
| 当前状态 | 待复现 / 待根因确认 |
|
||||
|
||||
#### 现象
|
||||
|
||||
已有资料将该问题归类为音频唤醒异常,排查方向集中在 AudioFlinger dump、AudioPolicy、录音 dump 和硬件输入链路。当前 Bug 记录先沉淀入口,具体现场表现还需要结合最新 logcat、dump 和录音文件补齐。
|
||||
|
||||
#### 复现步骤
|
||||
|
||||
1. 确认 TXZ/同行者语音助手处于可唤醒状态。
|
||||
2. 多次使用唤醒词触发语音唤醒。
|
||||
3. 记录是否出现无法唤醒、唤醒不稳定、录音异常或 TXZ 无响应。
|
||||
4. 同步抓取 logcat、AudioFlinger、AudioPolicy、audio dumpsys 和 PCM dump。
|
||||
|
||||
#### 证据
|
||||
|
||||
| 证据类型 | 路径/命令 | 关键内容 |
|
||||
|---|---|---|
|
||||
| 分析文档 | [[../语音唤醒异常问题分析]] | 记录 AudioFlinger dump 识别方式、常用 dump 命令和唤醒异常排查步骤 |
|
||||
| 原始分析材料 | [[../log 录音分析]] | 录音/音频相关原始分析材料 |
|
||||
| AudioFlinger dump | `adb shell dumpsys media.audio_flinger > audio_flinger.log` | 关注 Input thread、Frames read、采样率、通道、设备和错误统计 |
|
||||
| AudioPolicy dump | `adb shell dumpsys media.audio_policy > audio_policy.log` | 关注输入设备选择、路由策略和音频源 |
|
||||
| 完整音频状态 | `adb shell dumpsys audio > audio.log` | 关注音频服务整体状态 |
|
||||
| PCM dump | `setprop persist.pcm.dump 9` 后复现,再 `adb pull /data/misc/audioserver/dump_audio_9.pcm` | 判断麦克风是否有有效输入音频 |
|
||||
|
||||
#### 根因分析
|
||||
|
||||
| 候选根因 | 证据 | 可信度 |
|
||||
|---|---|---|
|
||||
| 输入链路没有采集到有效音频 | 需要检查 Input thread 状态、Frames read 变化和 PCM dump 内容 | 中 |
|
||||
| 音频设备或路由选择异常 | 需要对比 AudioPolicy dump 中的 input device / audio source | 中 |
|
||||
| 采样率、通道或 HAL 格式与 TXZ 期望不一致 | 需要检查 AudioFlinger 中 Sample rate、HAL format、Channel count | 低 |
|
||||
| TXZ 唤醒侧状态异常 | 需要补充 TXZ/VoiceService 相关 logcat | 低 |
|
||||
|
||||
#### 修复方案
|
||||
|
||||
暂不直接给代码修复。下一步先按证据清单复现并抓取日志,确认问题落在音频输入链路、AudioPolicy 路由、TXZ 唤醒状态,还是 `YX_Voice` 与 TXZ 的连接/状态同步链路。
|
||||
|
||||
#### 验证结果
|
||||
|
||||
| 验证项 | 命令/步骤 | 结果 |
|
||||
|---|---|---|
|
||||
| 唤醒复现 | 多次触发唤醒词并记录成功率 | 待验证 |
|
||||
| 输入采集 | 检查 `adb shell dumpsys media.audio_flinger` 中 Input thread 和 Frames read | 待验证 |
|
||||
| PCM 有效性 | 拉取 `/data/misc/audioserver/dump_audio_9.pcm` 并听取/分析波形 | 待验证 |
|
||||
| TXZ 状态 | 过滤 TXZ、VoiceService、唤醒相关 logcat | 待验证 |
|
||||
|
||||
#### 遗留风险
|
||||
|
||||
当前只有历史分析文档和排查方法,还缺少同一现场下的完整 logcat、dump 和 PCM 文件,因此不能直接判定根因。后续每次复现都应把日志、dump、录音文件路径回填到本 Bug。
|
||||
|
||||
## Bug 详情模板
|
||||
|
||||
### VOICE-XXX:问题标题
|
||||
|
||||
| 字段 | 内容 |
|
||||
|---|---|
|
||||
| 发现日期 | 待填写 |
|
||||
| 影响版本 | 待填写 |
|
||||
| 问题模块 | 待填写 |
|
||||
| 触发条件 | 待填写 |
|
||||
| 用户影响 | 待填写 |
|
||||
| 当前状态 | 待分析 / 修复中 / 待验证 / 已关闭 |
|
||||
|
||||
#### 现象
|
||||
|
||||
待填写。
|
||||
|
||||
#### 复现步骤
|
||||
|
||||
1. 待填写。
|
||||
2. 待填写。
|
||||
3. 待填写。
|
||||
|
||||
#### 证据
|
||||
|
||||
| 证据类型 | 路径/命令 | 关键内容 |
|
||||
|---|---|---|
|
||||
| logcat | 待填写 | 待填写 |
|
||||
| dumpsys | 待填写 | 待填写 |
|
||||
| 截图/录音 | 待填写 | 待填写 |
|
||||
|
||||
#### 根因分析
|
||||
|
||||
| 候选根因 | 证据 | 可信度 |
|
||||
|---|---|---|
|
||||
| 待填写 | 待填写 | 高/中/低 |
|
||||
|
||||
#### 修复方案
|
||||
|
||||
待填写。
|
||||
|
||||
#### 验证结果
|
||||
|
||||
| 验证项 | 命令/步骤 | 结果 |
|
||||
|---|---|---|
|
||||
| 正常路径 | 待填写 | 待验证 |
|
||||
| 异常路径 | 待填写 | 待验证 |
|
||||
| 回归项 | 待填写 | 待验证 |
|
||||
|
||||
#### 遗留风险
|
||||
|
||||
待填写。
|
||||
|
||||
## 常用问题分类
|
||||
|
||||
| 分类 | 典型表现 | 优先看 |
|
||||
|---|---|---|
|
||||
| TXZ 连接 | 初始化失败、绑定状态异常 | `VoiceService.onConnected()`、TXZ 初始化日志 |
|
||||
| 协议分发 | 指令收到但无动作 | `ProtocolManager`、`YxProtocolHandler`、协议映射 |
|
||||
| IPC 调用 | 业务模块无响应 | `VoiceEventHelper`、YxIPC 绑定状态 |
|
||||
| 状态同步 | TXZ 反馈和车机状态不一致 | 初始化状态同步、通知方法 |
|
||||
| 音频唤醒 | 唤醒失败、录音异常 | AudioFlinger、AudioPolicy、PCM dump |
|
||||
@@ -0,0 +1,96 @@
|
||||
# 徐工语音日志分析记录
|
||||
|
||||
## 日志分析流程
|
||||
|
||||
```text
|
||||
确认问题现象
|
||||
-> 确认时间点
|
||||
-> 收集 logcat / dumpsys / 录音 / 截图
|
||||
-> 提取关键字
|
||||
-> 建立时间线
|
||||
-> 区分现象、直接原因、根因
|
||||
-> 给出验证动作
|
||||
```
|
||||
|
||||
## 常用调试命令
|
||||
|
||||
### 语音唤醒与调用
|
||||
|
||||
```bash
|
||||
adb shell am broadcast -a android.intent.action.start_txzvoice
|
||||
adb shell am start com.txzing.voiceassistant/com.txzing.assistant.core.console.ui.ConsoleActivity
|
||||
adb shell am broadcast -a com.txznet.txz.invoke -d "txznet://com.txznet.txz/comm.asr.startWithRawText?打开空调"
|
||||
```
|
||||
|
||||
### 缓存清理
|
||||
|
||||
```bash
|
||||
adb shell pm clear com.txzing.voiceassistant
|
||||
adb shell pm clear com.yaxon.voice
|
||||
```
|
||||
|
||||
### 音频排查
|
||||
|
||||
```bash
|
||||
adb shell setprop persist.pcm.dump 9
|
||||
adb shell dumpsys media.audio_flinger > audio_flinger.log
|
||||
adb shell dumpsys media.audio_policy > audio_policy.log
|
||||
adb shell dumpsys audio > audio.log
|
||||
adb shell setprop persist.pcm.dump 0
|
||||
adb pull /data/misc/audioserver/dump_audio_9.pcm
|
||||
```
|
||||
|
||||
## 常用过滤关键字
|
||||
|
||||
| 场景 | 关键字 |
|
||||
|---|---|
|
||||
| 中间件报文 | `processBodyControl` |
|
||||
| 语音模块 | `package:com.yaxon.voice`、`VoiceEventHelper`、`sendCommandTxz` |
|
||||
| 协议逻辑 | `VoiceProtocol`、`ProtocolManager`、`YxProtocolHandler` |
|
||||
| 同行者状态 | `defaultRegisterHandler`、`TxzProtocolManager` |
|
||||
| 激活状态 | `onActivationSuccess` |
|
||||
| 初始化 | `initialize: versions` |
|
||||
| 音频 dump | `AudioFlinger`、`Input thread`、`Output thread`、`Frames read` |
|
||||
|
||||
## 分析记录模板
|
||||
|
||||
### LOG-YYYYMMDD-XXX:问题标题
|
||||
|
||||
| 字段 | 内容 |
|
||||
|---|---|
|
||||
| 日期 | 待填写 |
|
||||
| 关联 Bug | 待填写 |
|
||||
| 日志来源 | 待填写 |
|
||||
| 时间范围 | 待填写 |
|
||||
| 设备/版本 | 待填写 |
|
||||
| 分析状态 | 待分析 / 已定位 / 待复测 |
|
||||
|
||||
#### 问题现象
|
||||
|
||||
待填写。
|
||||
|
||||
#### 关键时间线
|
||||
|
||||
| 时间 | 进程/模块 | 日志摘要 | 判断 |
|
||||
|---|---|---|---|
|
||||
| 待填写 | 待填写 | 待填写 | 待填写 |
|
||||
|
||||
#### 关键证据
|
||||
|
||||
```text
|
||||
粘贴关键日志片段,避免贴整份日志。
|
||||
```
|
||||
|
||||
#### 初步结论
|
||||
|
||||
待填写。
|
||||
|
||||
#### 需要补充的证据
|
||||
|
||||
- 待填写。
|
||||
|
||||
## 已有关联资料
|
||||
|
||||
- [[../语音唤醒异常问题分析]]
|
||||
- [[../log 录音分析]]
|
||||
- [[../语音]]
|
||||
@@ -0,0 +1,80 @@
|
||||
# 徐工语音测试验证记录
|
||||
|
||||
## 验证目标
|
||||
|
||||
将每次语音模块修改、配置调整、资源替换和问题修复都沉淀为可复用的验证记录,覆盖主流程、异常流程和回归项。
|
||||
|
||||
## 基础验证环境
|
||||
|
||||
| 项 | 内容 |
|
||||
|---|---|
|
||||
| 项目 | 徐工 X9HP / 语音 |
|
||||
| 语音助手 | 同行者 TXZ |
|
||||
| 语音包名 | `com.txzing.voiceassistant` |
|
||||
| 语音模块包名 | `com.yaxon.voice` |
|
||||
| 测试账号 | `T9999911` / `xgtest010002` |
|
||||
| 代码工程 | `F:\ZDCode\xugong` |
|
||||
| 文档工程 | `F:\AI\Obsidian\项目文档\徐工\语音` |
|
||||
|
||||
## 通用验证前置
|
||||
|
||||
```bash
|
||||
adb devices
|
||||
adb shell pm clear com.txzing.voiceassistant
|
||||
adb shell pm clear com.yaxon.voice
|
||||
adb shell am start com.txzing.voiceassistant/com.txzing.assistant.core.console.ui.ConsoleActivity
|
||||
```
|
||||
|
||||
## 验证清单
|
||||
|
||||
| 验证项 | 操作 | 期望结果 | 状态 |
|
||||
|---|---|---|---|
|
||||
| TXZ 初始化 | 启动语音助手 | 初始化成功,有版本和连接日志 | 待验证 |
|
||||
| 语音服务启动 | 重启设备或启动服务 | `VoiceService` 正常创建并连接 TXZ | 待验证 |
|
||||
| 方控唤醒 | `adb shell am broadcast -a android.intent.action.start_txzvoice` | 语音界面或唤醒状态正常 | 待验证 |
|
||||
| 直接语音指令 | 发送 `startWithRawText` 指令 | TXZ 识别并分发到 YX_Voice | 待验证 |
|
||||
| 协议分发 | 执行车辆/空调/媒体指令 | `ProtocolManager` 和目标 Protocol 有日志 | 待验证 |
|
||||
| IPC 调用 | 执行业务控制 | 目标业务模块收到并执行 | 待验证 |
|
||||
| 状态同步 | 连接成功后同步状态 | 蓝牙、音量、亮度、车辆设置状态正确 | 待验证 |
|
||||
| 可见即可说 | 当前界面说出控件名称 | 控件被命中并触发点击 | 待验证 |
|
||||
| 异常恢复 | 清缓存后重新初始化 | 能恢复连接和指令处理 | 待验证 |
|
||||
|
||||
## 验证记录模板
|
||||
|
||||
### TEST-YYYYMMDD-XXX:验证标题
|
||||
|
||||
| 字段 | 内容 |
|
||||
|---|---|
|
||||
| 日期 | 待填写 |
|
||||
| 关联 Bug/需求 | 待填写 |
|
||||
| 版本/构建号 | 待填写 |
|
||||
| 测试设备 | 待填写 |
|
||||
| 测试人员 | 待填写 |
|
||||
| 结论 | 通过 / 不通过 / 部分通过 |
|
||||
|
||||
#### 验证步骤
|
||||
|
||||
1. 待填写。
|
||||
2. 待填写。
|
||||
3. 待填写。
|
||||
|
||||
#### 实际结果
|
||||
|
||||
待填写。
|
||||
|
||||
#### 关键日志
|
||||
|
||||
```text
|
||||
待填写。
|
||||
```
|
||||
|
||||
#### 遗留问题
|
||||
|
||||
待填写。
|
||||
|
||||
## 回归要求
|
||||
|
||||
- 修改协议映射后,至少验证目标协议、相邻协议和未知指令处理。
|
||||
- 修改 TXZ 连接逻辑后,至少验证清缓存、冷启动、重启后连接。
|
||||
- 修改状态同步后,至少验证初始同步和状态变化后的再次同步。
|
||||
- 修改音频/唤醒相关逻辑后,至少保留 AudioFlinger/AudioPolicy dump 和录音文件结论。
|
||||
@@ -0,0 +1,52 @@
|
||||
# 徐工语音决策记录
|
||||
|
||||
## 使用规则
|
||||
|
||||
本文件记录影响项目方向、接口契约、模块边界、测试策略、资源路径和风险取舍的决策。不要删除旧决策;如果结论变化,用“更新标记”追加。
|
||||
|
||||
## 决策列表
|
||||
|
||||
| ID | 日期 | 决策 | 原因 | 影响范围 | 状态 |
|
||||
| ------- | ---------- | ---------------------------------------------------- | ---------------------------- | ----------- | --- |
|
||||
| ADR-001 | 2026-06-15 | 先在 Obsidian 建立语音项目工程化文档骨架,不直接改 `F:\ZDCode\xugong` 源码 | 当前目标是建立长期记忆和协作流程,不是修具体代码 Bug | 文档工程 | 生效 |
|
||||
| ADR-002 | 2026-06-15 | 语音项目入口文档使用 `00_项目总览.md` | 让 Agent 和人都能先读一个入口文件快速进入上下文 | Obsidian 文档 | 生效 |
|
||||
| ADR-003 | 2026-06-15 | Bug、日志、测试、决策分文件记录 | 避免问题分析、验证结论和需求设计混在同一文档中 | 项目管理方式 | 生效 |
|
||||
|
||||
## 决策模板
|
||||
|
||||
### ADR-XXX:标题
|
||||
|
||||
| 字段 | 内容 |
|
||||
|---|---|
|
||||
| 日期 | 待填写 |
|
||||
| 背景 | 待填写 |
|
||||
| 决策 | 待填写 |
|
||||
| 备选方案 | 待填写 |
|
||||
| 选择原因 | 待填写 |
|
||||
| 影响范围 | 待填写 |
|
||||
| 风险 | 待填写 |
|
||||
| 验证方式 | 待填写 |
|
||||
| 状态 | 生效 / 废弃 / 被替代 |
|
||||
|
||||
#### 背景
|
||||
|
||||
待填写。
|
||||
|
||||
#### 决策
|
||||
|
||||
待填写。
|
||||
|
||||
#### 影响
|
||||
|
||||
待填写。
|
||||
|
||||
#### 更新记录
|
||||
|
||||
- 待填写。
|
||||
|
||||
## 当前约束
|
||||
|
||||
- 项目文档放在 `F:\AI\Obsidian\项目文档\徐工\语音`。
|
||||
- 代码工程位于 `F:\ZDCode\xugong`,只有进入具体开发/修复任务时才修改。
|
||||
- 高风险变更包括协议契约、权限、状态同步、TXZ 连接、IPC 接口、并发/生命周期逻辑。
|
||||
- 高风险变更必须先给计划并等待确认。
|
||||
@@ -0,0 +1,91 @@
|
||||
# 徐工语音 Agent 协作说明
|
||||
|
||||
## 目标
|
||||
|
||||
让 Agent 在处理徐工语音项目时,固定遵循“读取上下文、判断风险、执行任务、验证结果、记录结论”的工程闭环。
|
||||
|
||||
## 默认上下文读取顺序
|
||||
|
||||
1. 根目录 `agent.md`
|
||||
2. [[00_项目总览]]
|
||||
3. 与任务相关的专项文档:
|
||||
- 架构/模块:[[YX_Voice_架构文档]]、[[YX_Voice_模块详细文档]]
|
||||
- 协议:[[YX_Voice_协议设计文档]]
|
||||
- 配置:[[YX_Voice_配置文档]]
|
||||
- 可见即可说:[[同行者可见即可说自动注册框架对接方案_快速阅读]]
|
||||
- Bug:[[02_Bug记录]]
|
||||
- 日志:[[03_日志分析记录]]
|
||||
- 测试:[[04_测试验证记录]]
|
||||
- 决策:[[05_决策记录]]
|
||||
|
||||
## 常用任务口令
|
||||
|
||||
### 分析日志
|
||||
|
||||
```text
|
||||
先读取 agent.md 和 项目文档/徐工/语音/00_项目总览.md。
|
||||
按日志分析流程分析以下日志/现象:……
|
||||
请输出时间线、证据链、根因候选、修复建议和验证方案。
|
||||
如果需要写入记录,追加到 03_日志分析记录.md。
|
||||
```
|
||||
|
||||
### 记录 Bug
|
||||
|
||||
```text
|
||||
先读取 agent.md、00_项目总览.md 和 02_Bug记录.md。
|
||||
把下面的问题按 Bug 模板记录:……
|
||||
区分现象、复现步骤、证据、根因假设、修复方案、验证结果和遗留风险。
|
||||
```
|
||||
|
||||
### 设计模块
|
||||
|
||||
```text
|
||||
先读取 agent.md、00_项目总览.md、YX_Voice_架构文档.md 和 YX_Voice_模块详细文档.md。
|
||||
围绕以下需求做模块设计:……
|
||||
请输出模块目标、接口、数据结构、控制流、异常路径、测试用例和 ASPICE 对齐建议。
|
||||
```
|
||||
|
||||
### 准备改代码
|
||||
|
||||
```text
|
||||
先读取 agent.md 和 00_项目总览.md。
|
||||
本次准备修改 F:\ZDCode\xugong 中的代码,目标是:……
|
||||
请先判断风险等级,列出涉及文件、备份建议、修改方案和验证命令。
|
||||
在我确认前不要改代码。
|
||||
```
|
||||
|
||||
### 做验证
|
||||
|
||||
```text
|
||||
先读取 agent.md、00_项目总览.md 和 04_测试验证记录.md。
|
||||
按测试验证模板验证:……
|
||||
请输出验证步骤、实际结果、关键日志、结论和遗留问题。
|
||||
```
|
||||
|
||||
## 风险分级
|
||||
|
||||
| 等级 | 判定条件 | 处理方式 |
|
||||
|---|---|---|
|
||||
| 高风险 | 协议契约、权限、状态同步、TXZ 连接、IPC 接口、并发、生命周期、架构调整 | 先给计划,等待确认 |
|
||||
| 中风险 | 单模块多点修改、已有逻辑重构、测试影响不明确 | 先给简要计划 |
|
||||
| 低风险 | 文档整理、命令记录、单处说明补充、非功能性笔记整理 | 可直接执行 |
|
||||
|
||||
## 写入规则
|
||||
|
||||
- 修改文件前必须确认是否备份。
|
||||
- 不删除旧结论;结论变化时使用“更新标记”追加。
|
||||
- Bug 修复后必须记录验证结果。
|
||||
- 无法验证时必须明确写“未验证”,不能假装通过。
|
||||
- 涉及真实代码工程 `F:\ZDCode\xugong` 时,必须先确认目标和风险。
|
||||
|
||||
## 推荐输出格式
|
||||
|
||||
```text
|
||||
结论
|
||||
范围
|
||||
依据
|
||||
执行/建议
|
||||
验证
|
||||
风险
|
||||
下一步
|
||||
```
|
||||
@@ -0,0 +1,136 @@
|
||||
# YX_Voice 协议设计文档
|
||||
|
||||
## 1. 协议接口定义
|
||||
|
||||
### 1.1 IProtocolHandler (协议处理接口)
|
||||
|
||||
```java
|
||||
public interface IProtocolHandler {
|
||||
void onHandleProtocol(long msgSendTime, String remoteName, Bundle data);
|
||||
}
|
||||
```
|
||||
|
||||
### 1.2 IProtocolLogic (协议逻辑接口)
|
||||
|
||||
```java
|
||||
public interface IProtocolLogic {
|
||||
void onProtocolLogic(Bundle data);
|
||||
}
|
||||
```
|
||||
|
||||
## 2. 协议基类 (BaseProtocol)
|
||||
|
||||
```java
|
||||
public abstract class BaseProtocol implements IProtocolLogic {
|
||||
@Override
|
||||
public void onProtocolLogic(Bundle data) {
|
||||
String cmd = data.getString(VoiceConst.PARAMS_CMD_KEY, "");
|
||||
switch (cmd) {
|
||||
case CMD_SWITCH_TXZ_WINDOW: // 切换TXZ窗口
|
||||
case CMD_PLAY_TTS: // 播放TTS
|
||||
default:
|
||||
onProtocolParse(data); // 子类实现具体解析
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void onProtocolParse(Bundle data);
|
||||
}
|
||||
```
|
||||
|
||||
## 3. 协议映射表
|
||||
|
||||
```java
|
||||
protocolLogicMap.put(CAR_CAR_CONTROL_PKG, new CarControlProtocol()); // 车辆控制
|
||||
protocolLogicMap.put(TXZ_PKG_NEW, new VoiceProtocol()); // 语音协议
|
||||
protocolLogicMap.put(AIR_PKG, new AirProtocol()); // 空调协议
|
||||
protocolLogicMap.put(BLUETOOTH_PKG, new BluetoothProtocol()); // 蓝牙协议
|
||||
protocolLogicMap.put(MUSIC_PKG, new MediaProtocol()); // 媒体协议
|
||||
protocolLogicMap.put(VIDEO_PKG, new MediaProtocol()); // 视频协议
|
||||
protocolLogicMap.put(PHOTO_PKG, new MediaProtocol()); // 图库协议
|
||||
protocolLogicMap.put(RADIO_PKG, new MediaProtocol()); // 收音机协议
|
||||
protocolLogicMap.put(YX_VOICE_PKG, new YxProtocol()); // 内部协议
|
||||
protocolLogicMap.put(SETTING_PKG, new SettingProtocol()); // 设置协议
|
||||
protocolLogicMap.put(SYSTEM_UI_PKG, new SystemUIProtocol()); // 系统UI协议
|
||||
protocolLogicMap.put(FACTORY_PKG, new FactoryProtocol()); // 工厂模式协议
|
||||
protocolLogicMap.put(AVM_PKG, new AvmProtocol()); // 360环视协议
|
||||
protocolLogicMap.put(DVR_PKG, new DvrProtocol()); // 行车记录仪协议
|
||||
```
|
||||
|
||||
## 4. 协议命令常量
|
||||
|
||||
### 4.1 车辆控制类
|
||||
|
||||
| 命令常量 | 命令名称 | 说明 |
|
||||
|----------|----------|------|
|
||||
| CMD_OPEN_SUNROOF | openSunroof | 打开天窗 |
|
||||
| CMD_CLOSE_SUNROOF | closeSunroof | 关闭天窗 |
|
||||
| CMD_OPEN_WINDOW | openWindow | 打开车窗 |
|
||||
| CMD_CLOSE_WINDOW | closeWindow | 关闭车窗 |
|
||||
| CMD_OPEN_MIRROR_HEAT | openMirrorHeat | 打开后视镜加热 |
|
||||
| CMD_OPEN_AVM | openAvm | 打开360环视 |
|
||||
|
||||
### 4.2 空调控制类
|
||||
|
||||
| 命令常量 | 命令名称 | 说明 |
|
||||
|----------|----------|------|
|
||||
| CMD_OPEN_AC | openAc | 打开空调 |
|
||||
| CMD_CLOSE_AC | closeAc | 关闭空调 |
|
||||
| CMD_SET_AC_WIND_SPEED_LEVEL | setAcWindSpeedLevel | 设置风速档位 |
|
||||
| CMD_SET_AC_TEMP_VALUE | setAcTempValue | 设置温度 |
|
||||
|
||||
### 4.3 系统设置类
|
||||
|
||||
| 命令常量 | 命令名称 | 说明 |
|
||||
|----------|----------|------|
|
||||
| CMD_OPEN_BLUETOOTH | openBluetooth | 打开蓝牙 |
|
||||
| CMD_OPEN_WIFI | openWifi | 打开WiFi |
|
||||
| CMD_SET_VOLUME_TO_VALUE | setVolumeToValue | 设置音量 |
|
||||
| CMD_SET_SCREEN_BRIGHTNESS_VALUE | setScreenBrightnessValue | 设置亮度 |
|
||||
| CMD_SWITCH_VOICE_WAKEUP | switchVoicewakeup | 语音唤醒开关 |
|
||||
| CMD_CUSTOM_WAKE_UP_WORD | customWakeupWord | 自定义唤醒词 |
|
||||
|
||||
### 4.4 媒体控制类
|
||||
|
||||
| 命令常量 | 命令名称 | 说明 |
|
||||
|----------|----------|------|
|
||||
| CMD_PLAY_PAUSE | playPause | 暂停播放 |
|
||||
| CMD_PLAY_RESUME | playResume | 继续播放 |
|
||||
| CMD_PLAY_PREV | playPrev | 上一首 |
|
||||
| CMD_PLAY_NEXT | playNext | 下一首 |
|
||||
| CMD_OPEN_APP | openApp | 打开应用 |
|
||||
|
||||
## 5. 消息格式
|
||||
|
||||
### 5.1 Bundle格式
|
||||
|
||||
```java
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(VoiceConst.PARAMS_CMD_KEY, "命令类型");
|
||||
bundle.putInt(VoiceConst.PARAMS_NUM_KEY, 数值);
|
||||
bundle.putBoolean(VoiceConst.PARAMS_SWITCH_KEY, 开关状态);
|
||||
bundle.putString(VoiceConst.PARAMS_TYPE_KEY, "类型");
|
||||
```
|
||||
|
||||
### 5.2 参数说明
|
||||
|
||||
| 参数Key | 类型 | 说明 |
|
||||
|---------|------|------|
|
||||
| PARAMS_CMD_KEY | String | 命令类型 |
|
||||
| PARAMS_NUM_KEY | int | 数值参数 |
|
||||
| PARAMS_SWITCH_KEY | boolean | 开关状态 |
|
||||
| PARAMS_TYPE_KEY | String | 类型参数 |
|
||||
|
||||
## 6. 状态同步命令
|
||||
|
||||
| 命令 | 说明 |
|
||||
|------|------|
|
||||
| syncAcStatus | 同步空调状态 |
|
||||
| syncBlueToothStatus | 同步蓝牙状态 |
|
||||
| syncWiFiStatus | 同步WiFi状态 |
|
||||
| syncMediaVolume | 同步媒体音量 |
|
||||
| syncScreenBrightness | 同步屏幕亮度 |
|
||||
| syncVoiceWakeUpStatus | 同步语音唤醒开关 |
|
||||
|
||||
---
|
||||
|
||||
*文档整理日期: 2026-05-27*
|
||||
@@ -0,0 +1,156 @@
|
||||
# YX_Voice 架构文档
|
||||
|
||||
## 1. 概述
|
||||
|
||||
YX_Voice 是车载语音助手服务模块,作为第三方语音助手(同行者TXZ)与车载各功能模块之间的桥梁,负责语音指令的分发、处理以及车辆状态的同步。
|
||||
|
||||
| 项目信息 | 说明 |
|
||||
|----------|------|
|
||||
| 包名 | `com.yaxon.voice` |
|
||||
| 应用类型 | Android System Application |
|
||||
| 进程类型 | 系统持久化进程 (`persistent=true`) |
|
||||
| 共享UID | `android.uid.system` |
|
||||
|
||||
## 2. 整体架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ YX_Voice 架构图 │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ TXZ协议 ┌──────────────────────────────┐ │
|
||||
│ │ TXZ语音 │◄────────────►│ VoiceService │ │
|
||||
│ │ 助手模块 │ │ (服务入口 & TXZ连接管理) │ │
|
||||
│ └──────────────┘ └──────────────┬───────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────────────────────┼────────────────┐ │
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌──────────────────────┐ ┌──────────────────────┐ ┌──────────┐│
|
||||
│ │ ProtocolManager │ │ VoiceManager │ │ Helpers ││
|
||||
│ │ (协议分发管理) │ │ (核心状态管理) │ │ (辅助类) ││
|
||||
│ └──────────┬───────────┘ └──────────┬───────────┘ └──────────┘│
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌──────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Protocol Implementations │ │
|
||||
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌────────┐ │ │
|
||||
│ │ │ Voice │ │ Air │ │ Setting │ │ Media │ │ Car │ │ │
|
||||
│ │ │Protocol │ │Protocol │ │Protocol │ │Protocol │ │Control │ │ │
|
||||
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └────────┘ │ │
|
||||
│ └──────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────┐ │
|
||||
│ │ IPC Communication Layer │ │
|
||||
│ │ YxIPC (跨进程通信框架) │ │
|
||||
│ └──────────────────────────┬───────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────────────────────┼───────────────────────┐ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||||
│ │ 音乐 │ │ 设置 │ │ 空调 │ │
|
||||
│ │ 模块 │ │ 模块 │ │ 模块 │ │
|
||||
│ └─────────┘ └─────────┘ └─────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 3. 模块分层
|
||||
|
||||
| 层级 | 模块 | 职责 |
|
||||
|------|------|------|
|
||||
| 应用层 | VoiceService | 服务入口、生命周期管理 |
|
||||
| 核心层 | ProtocolManager, VoiceManager | 协议分发、状态管理 |
|
||||
| 协议层 | BaseProtocol及子类 | 具体协议解析与执行 |
|
||||
| 辅助层 | Helpers, Receivers, Observers | 状态监听、辅助功能 |
|
||||
| 通信层 | YxIPC, TxzProtocolManager | 跨进程通信 |
|
||||
|
||||
## 4. 核心模块
|
||||
|
||||
| 模块 | 职责 | 设计模式 |
|
||||
|------|------|----------|
|
||||
| VoiceService | 与TXZ语音助手建立连接、接收并分发语音指令 | - |
|
||||
| ProtocolManager | 实现IPC消息监听接口、将消息分发给协议处理器 | 单例模式 |
|
||||
| YxProtocolHandler | 维护包名到协议逻辑类的映射、在后台线程处理协议分发 | - |
|
||||
| VoiceManager | 管理TXZ绑定状态、AVM/DVR前台状态、注册车辆状态回调 | 单例模式 |
|
||||
| VoiceEventHelper | 封装所有语音控制操作、与各模块进行IPC通信 | - |
|
||||
|
||||
## 5. 通信架构
|
||||
|
||||
### 5.1 协议处理流程
|
||||
|
||||
```
|
||||
TXZ语音指令
|
||||
│
|
||||
▼
|
||||
TxzProtocolManager.setDefaultHandler()
|
||||
│
|
||||
├── 解析 commandType (协议名称)
|
||||
├── 解析 Bundle 参数
|
||||
├── 转换为JSON格式
|
||||
│
|
||||
▼
|
||||
ProtocolManager.onResponse()
|
||||
│
|
||||
▼
|
||||
YxProtocolHandler.onHandleProtocol()
|
||||
│
|
||||
▼
|
||||
具体Protocol实现类.onProtocolLogic()
|
||||
```
|
||||
|
||||
### 5.2 IPC通信
|
||||
|
||||
```
|
||||
┌─────────────────┐ YxIPC ┌─────────────────┐
|
||||
│ YX_Voice │◄──────────────►│ YX_Music │
|
||||
│ (Server) │ │ (Client) │
|
||||
└────────┬────────┘ └─────────────────┘
|
||||
│
|
||||
│ YxIPC
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ YX_Setting │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### 5.3 TXZ协议通信
|
||||
|
||||
```
|
||||
┌─────────────────┐ TxzProtocolManager ┌─────────────────┐
|
||||
│ YX_Voice │◄─────────────────────►│ TXZ语音助手 │
|
||||
│ (ConnectionService) │ (AIDL Service) │
|
||||
└─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
## 6. 模块依赖
|
||||
|
||||
```
|
||||
YX_Voice
|
||||
├── YX_IPC_SDK (IPC通信)
|
||||
├── YX_Lib_CommonBase (公共基础库)
|
||||
├── YX_AutoMotiveSDK (车载SDK)
|
||||
├── library-release-0127.aar (TXZ协议库)
|
||||
├── tools.jar (工具库)
|
||||
├── framework_classes.jar (系统框架)
|
||||
└── serial-0.1.6_classes.jar (串口库)
|
||||
```
|
||||
|
||||
## 7. 包名依赖
|
||||
|
||||
| 包名 | 说明 |
|
||||
|------|------|
|
||||
| com.txzing.voiceassistant | TXZ语音助手 |
|
||||
| com.yaxon.music | 音乐模块 |
|
||||
| com.yaxon.radio | 收音机模块 |
|
||||
| com.yaxon.hvac | 空调模块 |
|
||||
| com.yaxon.bluetooth | 蓝牙模块 |
|
||||
| com.yaxon.setting | 设置模块 |
|
||||
| com.yaxon.carcontrol | 车辆控制模块 |
|
||||
| com.yaxon.avm | 360环视模块 |
|
||||
| com.yaxon.dvr | 行车记录仪模块 |
|
||||
| com.android.systemui | 系统UI |
|
||||
|
||||
---
|
||||
|
||||
*文档整理日期: 2026-05-27*
|
||||
@@ -0,0 +1,254 @@
|
||||
# YX_Voice 模块详细文档
|
||||
|
||||
## 1. 应用入口 (YxApplication)
|
||||
|
||||
**文件路径**: `com/yaxon/voice/YxApplication.java`
|
||||
|
||||
**职责**:
|
||||
- 继承 `AutoMotiveSDKApplication`,提供车载SDK上下文
|
||||
- 初始化IPC通信框架
|
||||
- 初始化崩溃处理机制
|
||||
- 启动语音服务
|
||||
|
||||
**初始化流程**:
|
||||
```
|
||||
onCreate()
|
||||
├── ToolInit.init() // 工具类初始化
|
||||
├── CrashExceptionHandler // 崩溃处理
|
||||
├── YxIPC.bind() // IPC绑定
|
||||
│ └── ProtocolManager // 设置消息监听
|
||||
├── PackagePermissionManager // 权限管理
|
||||
└── startVoiceService() // 启动服务
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 语音服务 (VoiceService)
|
||||
|
||||
**文件路径**: `com/yaxon/voice/service/VoiceService.java`
|
||||
|
||||
**继承关系**: `VoiceService extends BaseVoiceService implements ConnectionListener`
|
||||
|
||||
**职责**:
|
||||
- 与TXZ语音助手建立连接
|
||||
- 接收并分发语音指令
|
||||
- 管理各模块监听器生命周期
|
||||
|
||||
**初始化流程**:
|
||||
```
|
||||
onCreate()
|
||||
├── initTxz() // 初始化TXZ连接
|
||||
│ ├── TxzProtocolManager.initialize()
|
||||
│ ├── TxzProtocolManager.connect()
|
||||
│ └── addConnectionListener()
|
||||
├── registerTxzCommandReceiver() // 注册指令接收器
|
||||
├── BlueToothHelper.register() // 蓝牙监听
|
||||
├── VoiceManager.registerCallbacks() // 车辆状态监听
|
||||
└── 注册各种Receiver和Callback
|
||||
```
|
||||
|
||||
**TXZ连接成功同步**:
|
||||
```java
|
||||
public void onConnected() {
|
||||
VoiceManager.getInstance().setVoiceBind(true);
|
||||
VoiceManager.VOICE_EVENT_HELPER.sendVoiceBindSuccess(null);
|
||||
AppHelper.getInstance().startScanApp();
|
||||
initNotifyCarConfig(); // 车辆配置
|
||||
initNotifyBluetoothStatus(); // 蓝牙状态
|
||||
initNotifyVolumeStatus(); // 音量状态
|
||||
initNotifyCarSettingStatus(); // 车辆设置状态
|
||||
sendBrightnessStatus(); // 亮度状态
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 协议管理器 (ProtocolManager)
|
||||
|
||||
**文件路径**: `com/yaxon/voice/core/ProtocolManager.java`
|
||||
|
||||
**设计模式**: 单例模式
|
||||
|
||||
**职责**:
|
||||
- 实现IPC消息监听接口 (`MessageListener`, `RemoteListener`)
|
||||
- 将消息分发给协议处理器
|
||||
|
||||
**类图**:
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ ProtocolManager │
|
||||
├─────────────────────────────────┤
|
||||
│ - sInstance: ProtocolManager │
|
||||
│ - mProtocolHandler: IProtocolHandler │
|
||||
├─────────────────────────────────┤
|
||||
│ + getInstance() │
|
||||
│ + setProtocolHandler() │
|
||||
│ + onResponse() │ ← MessageListener
|
||||
│ + onBindRemote() │ ← RemoteListener
|
||||
│ + release() │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 协议处理器 (YxProtocolHandler)
|
||||
|
||||
**文件路径**: `com/yaxon/voice/core/YxProtocolHandler.java`
|
||||
|
||||
**职责**:
|
||||
- 维护包名到协议逻辑类的映射
|
||||
- 在后台线程处理协议分发
|
||||
|
||||
---
|
||||
|
||||
## 5. 语音管理器 (VoiceManager)
|
||||
|
||||
**文件路径**: `com/yaxon/voice/core/VoiceManager.java`
|
||||
|
||||
**设计模式**: 单例模式
|
||||
|
||||
**职责**:
|
||||
- 管理TXZ绑定状态
|
||||
- 管理AVM/DVR前台状态
|
||||
- 注册车辆状态回调(空调、设置、智能驾驶)
|
||||
- 提供AudioTrackPlayer实例
|
||||
|
||||
**状态管理**:
|
||||
```java
|
||||
private boolean isVoiceBind; // TXZ绑定状态
|
||||
private AtomicBoolean isAvm; // AVM前台状态
|
||||
private AtomicBoolean isDvr; // DVR前台状态
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 语音事件助手 (VoiceEventHelper)
|
||||
|
||||
**文件路径**: `com/yaxon/voice/helper/VoiceEventHelper.java`
|
||||
|
||||
**职责**:
|
||||
- 封装所有语音控制操作
|
||||
- 与各模块进行IPC通信
|
||||
- 通知TXZ状态变化
|
||||
|
||||
**主要功能分类**:
|
||||
|
||||
| 类别 | 方法示例 | 说明 |
|
||||
|------|----------|------|
|
||||
| 空调控制 | sendAirSwitch, sendAcSwitch, sendAirTempTo | 温度、风速、模式控制 |
|
||||
| 音量控制 | sendVolumeTo, sendVolumeMute, sendVolumeElevator | 音量调节、静音 |
|
||||
| 屏幕控制 | setMpuBrightnessLevel, sendScreenOff, sendScreenClean | 亮度、熄屏、清洁 |
|
||||
| 系统设置 | switchSystemLanguage, switchDistanceUnit | 语言、单位切换 |
|
||||
| 车窗控制 | sendWindowSwitch, sendWindowPercent | 开关、百分比控制 |
|
||||
| 语音设置 | sendSwitchVoiceWakeup, customWakeupWord, switchVoiceMan | 唤醒词、发音人设置 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 接收器与观察者
|
||||
|
||||
### 7.1 BroadcastReceiver
|
||||
|
||||
| 类名 | 监听Action | 功能 |
|
||||
|------|------------|------|
|
||||
| BootReceiver | ACTION_BOOT_COMPLETED | 开机启动服务 |
|
||||
| PowerReceiver | ACTION_SCREEN_ON/OFF | 屏幕亮灭监听 |
|
||||
| NetworkChangedReceiver | WIFI_STATE_CHANGED | WiFi状态变化 |
|
||||
| BluetoothMonitorReceiver | Bluetooth状态广播 | 蓝牙连接状态 |
|
||||
| HomeStatusReceiver | ACTION_HOME_STATUS_CHANGED | 主页状态变化 |
|
||||
| VolumeChangedCallback | 音量变化回调 | 音量变化监听 |
|
||||
| SettingReceiver | STREAM_MUTE_CHANGED_ACTION | 静音状态变化 |
|
||||
|
||||
### 7.2 ContentObserver
|
||||
|
||||
| 类名 | 监听URI | 功能 |
|
||||
|------|---------|------|
|
||||
| ScreenSaversObserver | STATE_URI + STANDBY_DIALOG_STATE | 屏保状态 |
|
||||
| MediaObserver | MEDIA_SOURCE_URI, MUSIC_INFO_URI | 媒体信息 |
|
||||
| ReverseObserver | 倒车相关URI | 倒车状态 |
|
||||
| BrightnessObserver | MPU_BRIGHTNESS_LEVEL | 亮度变化 |
|
||||
| SettingCommonObserver | VIDEO_LIMIT_URI等 | 通用设置 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 文件结构
|
||||
|
||||
```
|
||||
YX_Voice/
|
||||
├── src/main/java/com/yaxon/voice/
|
||||
│ ├── YxApplication.java # 应用入口
|
||||
│ ├── api/ # 接口定义
|
||||
│ │ ├── IProtocolHandler.java
|
||||
│ │ └── IProtocolLogic.java
|
||||
│ ├── constant/ # 常量定义
|
||||
│ │ ├── PackageConst.java
|
||||
│ │ ├── VoiceNewProtocolConst.java
|
||||
│ │ └── VoiceProtocolConst.java
|
||||
│ ├── core/ # 核心类
|
||||
│ │ ├── PackagePermissionManager.java
|
||||
│ │ ├── ProtocolManager.java
|
||||
│ │ ├── VoiceManager.java
|
||||
│ │ └── YxProtocolHandler.java
|
||||
│ ├── crash/ # 崩溃处理
|
||||
│ │ └── CrashExceptionHandler.java
|
||||
│ ├── helper/ # 辅助类
|
||||
│ │ ├── AppHelper.java
|
||||
│ │ ├── AudioFocusHelper.java
|
||||
│ │ ├── AudioTrackPlayer.java
|
||||
│ │ ├── BlueToothHelper.java
|
||||
│ │ ├── BrightnessHelper.java
|
||||
│ │ ├── ContactHelper.java
|
||||
│ │ ├── HandlerHelper.java
|
||||
│ │ ├── JsonHelper.java
|
||||
│ │ ├── McuHelper.java
|
||||
│ │ ├── VoiceEventHelper.java
|
||||
│ │ ├── VolumeHelper.java
|
||||
│ │ └── WifiHelper.java
|
||||
│ ├── impl/ # 回调实现
|
||||
│ │ ├── CarAirCallback.java
|
||||
│ │ ├── CarIntelligentDrivingCallBack.java
|
||||
│ │ └── CarSettingCallback.java
|
||||
│ ├── protocol/ # 协议实现
|
||||
│ │ ├── AirProtocol.java
|
||||
│ │ ├── AvmProtocol.java
|
||||
│ │ ├── BaseProtocol.java
|
||||
│ │ ├── BluetoothProtocol.java
|
||||
│ │ ├── CarControlProtocol.java
|
||||
│ │ ├── DvrProtocol.java
|
||||
│ │ ├── FactoryProtocol.java
|
||||
│ │ ├── MediaProtocol.java
|
||||
│ │ ├── SettingProtocol.java
|
||||
│ │ ├── SystemUIProtocol.java
|
||||
│ │ ├── VoiceProtocol.java
|
||||
│ │ └── YxProtocol.java
|
||||
│ ├── provider/ # ContentObserver
|
||||
│ │ ├── BrightnessObserver.java
|
||||
│ │ ├── MediaObserver.java
|
||||
│ │ ├── ReverseObserver.java
|
||||
│ │ ├── ScreenSaversObserver.java
|
||||
│ │ └── SettingCommonObserver.java
|
||||
│ ├── receiver/ # 广播接收器
|
||||
│ │ ├── BluetoothMonitorReceiver.java
|
||||
│ │ ├── BootReceiver.java
|
||||
│ │ ├── HomeStatusReceiver.java
|
||||
│ │ ├── NetworkChangedReceiver.java
|
||||
│ │ ├── PowerReceiver.java
|
||||
│ │ ├── SettingReceiver.java
|
||||
│ │ ├── TestReceiver.java
|
||||
│ │ └── VolumeChangedCallback.java
|
||||
│ ├── service/ # 服务
|
||||
│ │ ├── BaseVoiceService.java
|
||||
│ │ └── VoiceService.java
|
||||
│ └── utils/ # 工具类
|
||||
│ ├── AppUtils.java
|
||||
│ ├── BroadcastUtils.java
|
||||
│ └── DataConvert.java
|
||||
├── libs/ # 依赖库
|
||||
│ ├── library-release-0127.aar
|
||||
│ └── tools.jar
|
||||
├── assets/tts/ # TTS音频资源
|
||||
└── build.gradle
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*文档整理日期: 2026-05-27*
|
||||
@@ -0,0 +1,120 @@
|
||||
# YX_Voice 配置文档
|
||||
|
||||
## 1. Gradle配置
|
||||
|
||||
```groovy
|
||||
android {
|
||||
defaultConfig {
|
||||
applicationId "com.yaxon.voice"
|
||||
}
|
||||
|
||||
aaptOptions {
|
||||
noCompress "pcm" // 不压缩PCM音频文件
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
outputFileName = "YX_Voice.apk"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Manifest配置
|
||||
|
||||
```xml
|
||||
<application
|
||||
android:name=".YxApplication"
|
||||
android:directBootAware="true"
|
||||
android:persistent="true"
|
||||
android:sharedUserId="android.uid.system">
|
||||
```
|
||||
|
||||
## 3. 权限声明
|
||||
|
||||
```xml
|
||||
<!-- 系统权限 -->
|
||||
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"/>
|
||||
<uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.DEVICE_POWER"/>
|
||||
|
||||
<!-- 网络权限 -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||
|
||||
<!-- 蓝牙权限 -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
||||
|
||||
<!-- 存储权限 -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<!-- 其他权限 -->
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
|
||||
```
|
||||
|
||||
## 4. IPC配置
|
||||
|
||||
```java
|
||||
YxIpcConfig yxIpcConfig = new YxIpcConfig();
|
||||
yxIpcConfig.addRemoteStartService(PackageConst.MUSIC_PKG);
|
||||
yxIpcConfig.addRemoteStartService(PackageConst.SETTING_PKG);
|
||||
yxIpcConfig.setRemoteListener(ProtocolManager.getInstance());
|
||||
YxIPC.getInstance().bind(this, yxIpcConfig);
|
||||
```
|
||||
|
||||
## 5. TXZ连接配置
|
||||
|
||||
```java
|
||||
TxzProtocolManager.initialize(this);
|
||||
TxzProtocolManager.connect(PackageConst.TXZ_PKG_NEW);
|
||||
TxzProtocolManager.getConnection(PackageConst.TXZ_PKG_NEW).addConnectionListener(this);
|
||||
```
|
||||
|
||||
## 6. 模块依赖
|
||||
|
||||
```
|
||||
YX_Voice
|
||||
├── YX_IPC_SDK (IPC通信)
|
||||
├── YX_Lib_CommonBase (公共基础库)
|
||||
├── YX_AutoMotiveSDK (车载SDK)
|
||||
├── library-release-0127.aar (TXZ协议库)
|
||||
├── tools.jar (工具库)
|
||||
├── framework_classes.jar (系统框架)
|
||||
└── serial-0.1.6_classes.jar (串口库)
|
||||
```
|
||||
|
||||
## 7. 包名依赖
|
||||
|
||||
| 包名 | 说明 |
|
||||
|------|------|
|
||||
| com.txzing.voiceassistant | TXZ语音助手 |
|
||||
| com.yaxon.music | 音乐模块 |
|
||||
| com.yaxon.radio | 收音机模块 |
|
||||
| com.yaxon.hvac | 空调模块 |
|
||||
| com.yaxon.bluetooth | 蓝牙模块 |
|
||||
| com.yaxon.setting | 设置模块 |
|
||||
| com.yaxon.carcontrol | 车辆控制模块 |
|
||||
| com.yaxon.avm | 360环视模块 |
|
||||
| com.yaxon.dvr | 行车记录仪模块 |
|
||||
| com.android.systemui | 系统UI |
|
||||
|
||||
## 8. 版本历史
|
||||
|
||||
| 版本 | 日期 | 作者 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 1.0 | 2024-01-05 | 张博威 | 初始版本 |
|
||||
| 1.1 | 2024-02-19 | mango | TXZ协议集成 |
|
||||
| 1.2 | 2024-07-02 | ZhangBoWei | 协议抽象优化 |
|
||||
| 1.3 | 2025-03-13 | - | 唤醒词修改功能 |
|
||||
|
||||
---
|
||||
|
||||
*文档整理日期: 2026-05-27*
|
||||
Binary file not shown.
@@ -0,0 +1,467 @@
|
||||
# 同行者可见即可说自动注册框架对接方案 - 快速阅读版
|
||||
|
||||
> 来源文档:`F:/AI/Obsidian/项目文档/徐工/语音/同行者可见即可说自动注册框架对接方案.docx`
|
||||
> 整理日期:2026-06-13
|
||||
> 目标:把原 Word 文档整理成工程接入时能快速查阅的 Markdown 速查文档。
|
||||
|
||||
## 1. 一句话结论
|
||||
|
||||
“可见即可说”主要依赖 Android 无障碍服务扫描当前界面控件,通过控件的 `android:id`、`android:text`、`android:contentDescription`、`clickable`、`scrollable` 等信息自动注册语音热词。用户说出界面上可见或已通过隐藏标签声明的词后,语音助手命中热词,再回调触发目标控件事件。
|
||||
|
||||
如果界面元素无法被无障碍扫描,例如小程序、网页、自绘界面,则需要应用主动通过 AIDL 或广播向语音发送插词列表,语音命中后再把命中的插词回传给应用,由应用自行执行动作。
|
||||
|
||||
## 2. 整体链路
|
||||
|
||||
### 2.1 普通 Android 控件链路
|
||||
|
||||
1. 应用界面展示控件。
|
||||
2. Android 无障碍服务扫描界面控件。
|
||||
3. 语音助手读取控件文本或隐藏标签。
|
||||
4. 语音助手把文本注册为可见即可说热词。
|
||||
5. 用户说出对应词,例如“每日推荐”或“打开每日推荐”。
|
||||
6. 热词模块命中控件节点。
|
||||
7. 无障碍服务触发控件点击或滑动等事件。
|
||||
8. 应用执行原控件逻辑。
|
||||
|
||||
### 2.2 图标控件链路
|
||||
|
||||
图标本身不显示文字时,需要通过 `contentDescription` 提供隐藏标签。例如图标按钮没有文字,但设置了 `android:contentDescription="向下滑"`,语音仍可识别“向下滑”并触发该图标。
|
||||
|
||||
### 2.3 非常规界面链路
|
||||
|
||||
适用于小程序、网页、自绘页面等无障碍拿不到元素的场景。
|
||||
|
||||
1. 应用整理当前界面可执行插词列表。
|
||||
2. 应用通过 AIDL 或广播发送给语音。
|
||||
3. 语音收到后注册插词。
|
||||
4. 用户说出插词。
|
||||
5. 语音识别命中。
|
||||
6. 语音通过 AIDL 或广播把命中插词回传给应用。
|
||||
7. 应用根据插词匹配具体控件或业务动作。
|
||||
|
||||
## 3. 接入总原则
|
||||
|
||||
| 原则 | 说明 |
|
||||
|---|---|
|
||||
| 必须有唯一 ID | 所有需要语音响应的控件都应设置唯一 `android:id`。 |
|
||||
| 文本优先 | 文本控件优先使用 `android:text` 暴露插词。 |
|
||||
| 图标补标签 | 图标类控件使用 `android:contentDescription` 暴露隐藏插词。 |
|
||||
| 多说法用 `#` | 多个插词使用 `#` 分隔,例如 `打开#启动`。 |
|
||||
| 状态要同步 | 播放/暂停、收藏/取消收藏等状态型图标必须动态更新 `contentDescription`。 |
|
||||
| 点击看 `clickable` | 控件是否响应与 `clickable` 状态有关,`true` 表示可点击。 |
|
||||
| 滚动看 `scrollable` | 滑动控件本身需要是可滑动节点,即 `Scrollable=true`。 |
|
||||
| 弹窗用标准 Dialog | 建议使用标准 `Dialog` 或依附 Activity 的自定义 Dialog。 |
|
||||
|
||||
## 4. 常见控件接入方式
|
||||
|
||||
## 4.1 文本类控件
|
||||
|
||||
适用对象:`TextView`、`Button`、带文本的布局项等。
|
||||
|
||||
推荐做法:
|
||||
|
||||
```xml
|
||||
<TextView
|
||||
android:id="@+id/tv_daily_recommend"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:text="每日推荐" />
|
||||
```
|
||||
|
||||
支持泛化说法时,可使用 `contentDescription`:
|
||||
|
||||
```xml
|
||||
<TextView
|
||||
android:id="@+id/tv_daily_recommend"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:text="每日推荐"
|
||||
android:contentDescription="每日推荐#打开每日推荐#我想打开每日推荐" />
|
||||
```
|
||||
|
||||
注意:
|
||||
|
||||
- `contentDescription` 中的插词文本必须包含 `text` 中的文本。
|
||||
- 控件要能响应点击,需确保 `clickable=true` 或实际可点击。
|
||||
|
||||
## 4.2 图标类控件
|
||||
|
||||
适用对象:只有图片、没有文本的按钮或图标。
|
||||
|
||||
```xml
|
||||
<ImageView
|
||||
android:id="@+id/iv_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:contentDescription="搜索#查找" />
|
||||
```
|
||||
|
||||
注意:
|
||||
|
||||
- 图标没有显示文本时,必须用 `contentDescription` 提供语音插词。
|
||||
- 多个插词用 `#` 分隔。
|
||||
- 控件是否响应仍与 `clickable` 状态有关。
|
||||
|
||||
## 4.3 同一图标多状态控件
|
||||
|
||||
典型场景:播放/暂停、收藏/取消收藏。
|
||||
|
||||
错误做法:
|
||||
|
||||
```xml
|
||||
android:contentDescription="播放#暂停"
|
||||
```
|
||||
|
||||
这种做法可能导致当前处于暂停状态时,用户说“暂停”反而触发点击,结果开始播放。
|
||||
|
||||
正确做法:根据状态动态更新。
|
||||
|
||||
```java
|
||||
if (isPlaying) {
|
||||
playButton.setContentDescription("暂停");
|
||||
} else {
|
||||
playButton.setContentDescription("播放");
|
||||
}
|
||||
```
|
||||
|
||||
原则:
|
||||
|
||||
- 当前正在播放,插词应是“暂停”。
|
||||
- 当前已经暂停,插词应是“播放”。
|
||||
- 当前已收藏,插词应是“取消收藏”。
|
||||
- 当前未收藏,插词应是“收藏”。
|
||||
|
||||
## 4.4 常规滑动控件
|
||||
|
||||
适用对象:`ScrollView`、`RecyclerView`、`ListView` 等。
|
||||
|
||||
基础要求:
|
||||
|
||||
- 控件本身应可滑动,即无障碍节点 `Scrollable=true`。
|
||||
- 如果每个 item 需要响应语音,item 需要有唯一 ID。
|
||||
- item 可使用 `contentDescription` 声明插词。
|
||||
- 如需响应 item 内部 child 控件,child 按文本类或图标类控件处理。
|
||||
|
||||
示例:
|
||||
|
||||
```xml
|
||||
<RecyclerView
|
||||
android:id="@+id/rv_station_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
```
|
||||
|
||||
item 示例:
|
||||
|
||||
```xml
|
||||
<TextView
|
||||
android:id="@+id/tv_station_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:text="88.6MHz"
|
||||
android:contentDescription="88.6MHz#播放88.6" />
|
||||
```
|
||||
|
||||
## 4.5 翻页控制
|
||||
|
||||
文档中特别强调:如果要让可见即可说支持“上一页 / 下一页”这类翻页逻辑,应用需要预留两个大小为 0 的控件。
|
||||
|
||||
要求:
|
||||
|
||||
- 控件大小为 0。
|
||||
- 不能设置为 `GONE`。
|
||||
- 分别添加“上一页”“下一页”等 `contentDescription`。
|
||||
- 应用自己实现点击事件,点击后控制对应滚动控件翻页。
|
||||
- 如果页面中有多个同方向滚动控件,只建议配置用户最可能使用的那个。
|
||||
- 多组 0 大小翻页控件可能导致目标滚动控件不符合预期。
|
||||
|
||||
示例:
|
||||
|
||||
```xml
|
||||
<View
|
||||
android:id="@+id/voice_page_prev"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clickable="true"
|
||||
android:contentDescription="上一页" />
|
||||
|
||||
<View
|
||||
android:id="@+id/voice_page_next"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clickable="true"
|
||||
android:contentDescription="下一页" />
|
||||
```
|
||||
|
||||
```java
|
||||
voicePagePrev.setOnClickListener(v -> recyclerView.smoothScrollBy(0, -recyclerView.getHeight()));
|
||||
voicePageNext.setOnClickListener(v -> recyclerView.smoothScrollBy(0, recyclerView.getHeight()));
|
||||
```
|
||||
|
||||
如果不预留翻页控制控件,默认不支持翻页逻辑。
|
||||
|
||||
## 4.6 SeekBar 等特殊滑动控件
|
||||
|
||||
适用对象:亮度、音量、进度条等 `SeekBar` 控件。
|
||||
|
||||
接入目标:支持类似“调高屏幕亮度”“降低音量”“屏幕亮度调大一点”等语音指令。
|
||||
|
||||
推荐做法:
|
||||
|
||||
```xml
|
||||
<SeekBar
|
||||
android:id="@+id/sb_screen_brightness"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:contentDescription="屏幕亮度" />
|
||||
```
|
||||
|
||||
父布局建议:
|
||||
|
||||
```xml
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
```
|
||||
|
||||
原因:
|
||||
|
||||
- 框架根据控件宽高计算百分比拖动距离。
|
||||
- 无法直接读取控件内部业务值。
|
||||
- `SeekBar` 默认内边距会造成拖动精度误差。
|
||||
- 将 `SeekBar` 内边距设为 0,并允许子控件超出父布局边界,可减少误差。
|
||||
|
||||
## 4.7 Switch 开关类控件
|
||||
|
||||
原生 `Switch`:通常无需额外适配。
|
||||
|
||||
自定义开关 View:需要重写 `onInitializeAccessibilityNodeInfo`。
|
||||
|
||||
```java
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(info);
|
||||
info.setCheckable(true);
|
||||
info.setChecked(isChecked());
|
||||
}
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 设置 `checkable=true`。
|
||||
- 根据真实开关状态同步 `checked`。
|
||||
- 状态变化时及时刷新无障碍信息。
|
||||
|
||||
## 5. 非常规界面 AIDL / 广播对接字段
|
||||
|
||||
文档流程图给出的字段含义如下。
|
||||
|
||||
## 5.1 应用发送给语音:注册或取消注册
|
||||
|
||||
| 字段 | 含义 | 示例 |
|
||||
| ------------- | --------------------- | ------------------------------------------------------ |
|
||||
| `key_type` | 要处理的类型,`2600` 表示可见即可说 | `2600` |
|
||||
| `action` | 动作 | `shadow.register` / `shadow.unregister` |
|
||||
| `packageName` | 应用包名,可不填 | `com.yaxon.carcontrol` |
|
||||
| `className` | 页面类名,可不填 | `com.yaxon.carcontrol.activity.CarControlMainActivity` |
|
||||
| `pageName` | 页面名称,可不填 | `voiceSetting` |
|
||||
| `keywordList` | 插词列表,泛化词用 `#` 分隔 | `打开#启动` |
|
||||
|
||||
示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"key_type": 2600,
|
||||
"action": "shadow.register",
|
||||
"packageName": "com.yaxon.carcontrol",
|
||||
"className": "com.yaxon.carcontrol.activity.CarControlMainActivity",
|
||||
"pageName": "voiceSetting",
|
||||
"keywordList": "打开#启动"
|
||||
}
|
||||
```
|
||||
|
||||
取消注册:
|
||||
|
||||
```json
|
||||
{
|
||||
"key_type": 2600,
|
||||
"action": "shadow.unregister",
|
||||
"packageName": "com.yaxon.carcontrol",
|
||||
"pageName": "voiceSetting",
|
||||
"keywordList": "打开#启动"
|
||||
}
|
||||
```
|
||||
|
||||
## 5.2 语音回传给应用:命中执行
|
||||
|
||||
| 字段 | 含义 | 示例 |
|
||||
| ---------- | --------------------- | ---------------- |
|
||||
| `key_type` | 回传类型,`1600` 表示可见即可说执行 | `1600` |
|
||||
| `action` | 动作 | `shadow.execute` |
|
||||
| `cmd` | 命中的插词原文 | `打开` |
|
||||
|
||||
示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"key_type": 1600,
|
||||
"action": "shadow.execute",
|
||||
"cmd": "打开"
|
||||
}
|
||||
```
|
||||
|
||||
应用收到后,应根据 `cmd` 做业务分发。
|
||||
|
||||
## 6. 已知问题与规避方式
|
||||
|
||||
## 6.1 `com.android.systemui` 扫描冲突
|
||||
|
||||
问题:
|
||||
|
||||
- 底部 touch 栏中可能存在很多图标插词。
|
||||
- 这些插词可能和桌面或其他应用重复,例如“车主手册”。
|
||||
- `com.android.systemui` 所在 window 可能一直可见,即使视觉上隐藏,也可能被无障碍服务扫描到。
|
||||
- 用户说“车主手册”时,可能命中 SystemUI 上隐藏的控件,导致结果不符合预期。
|
||||
|
||||
建议:
|
||||
|
||||
- SystemUI 隐藏时,临时清空相关控件的 `android:text` 和 `android:contentDescription`。
|
||||
- SystemUI 重新显示时,再恢复文本和隐藏标签。
|
||||
|
||||
示例:
|
||||
|
||||
```java
|
||||
if (isSystemUiHidden) {
|
||||
view.setContentDescription(null);
|
||||
textView.setText("");
|
||||
} else {
|
||||
view.setContentDescription("车主手册");
|
||||
textView.setText("车主手册");
|
||||
}
|
||||
```
|
||||
|
||||
## 6.2 同一图片不同插词
|
||||
|
||||
问题:
|
||||
|
||||
- 同一图片可能对应不同状态,例如播放/暂停。
|
||||
- 如果同时注册“播放#暂停”,当前状态下可能执行反向动作。
|
||||
|
||||
建议:
|
||||
|
||||
- 状态变化时动态更新 `contentDescription`。
|
||||
- 当前能执行什么动作,就只暴露什么插词。
|
||||
|
||||
## 6.3 部分弹框扫描不到
|
||||
|
||||
问题:
|
||||
|
||||
- 一些通过 Window 直接创建的弹框,可能与 Activity 界面不匹配或层级冲突。
|
||||
- 无障碍服务可能扫描不到弹框里的控件。
|
||||
|
||||
建议:
|
||||
|
||||
- 优先使用标准 `Dialog`。
|
||||
- 自定义 Dialog 应依附于 Activity。
|
||||
- 避免直接用独立 Window 承载需要语音响应的弹框。
|
||||
|
||||
## 7. 工程接入检查清单
|
||||
|
||||
## 7.1 页面级检查
|
||||
|
||||
- [ ] 页面中需要语音响应的控件是否都有唯一 `android:id`。
|
||||
- [ ] 文本控件是否有明确 `android:text`。
|
||||
- [ ] 图标控件是否设置了 `android:contentDescription`。
|
||||
- [ ] 多说法是否使用 `#` 分隔。
|
||||
- [ ] 控件是否实际可点击或可滑动。
|
||||
- [ ] 动态状态控件是否会更新 `contentDescription`。
|
||||
- [ ] 列表 item 是否有唯一 ID 或稳定的可识别标签。
|
||||
- [ ] 滚动页面是否需要预留上一页/下一页控制控件。
|
||||
- [ ] 弹框是否使用标准 Dialog 或依附 Activity。
|
||||
|
||||
## 7.2 状态型控件检查
|
||||
|
||||
- [ ] 播放状态:播放中只暴露“暂停”。
|
||||
- [ ] 暂停状态:暂停中只暴露“播放”。
|
||||
- [ ] 已收藏:只暴露“取消收藏”。
|
||||
- [ ] 未收藏:只暴露“收藏”。
|
||||
- [ ] 开关类自定义 View 是否正确设置 `checkable` 和 `checked`。
|
||||
|
||||
## 7.3 SystemUI 检查
|
||||
|
||||
- [ ] 隐藏状态是否仍可能被无障碍扫描。
|
||||
- [ ] 隐藏时是否清空 `text/contentDescription`。
|
||||
- [ ] 显示时是否恢复 `text/contentDescription`。
|
||||
- [ ] 是否存在与 Launcher 或 App 页面重复的插词。
|
||||
|
||||
## 7.4 非常规界面检查
|
||||
|
||||
- [ ] 是否确认无障碍无法获取页面元素。
|
||||
- [ ] 是否整理了当前页面插词列表。
|
||||
- [ ] 是否支持注册和取消注册。
|
||||
- [ ] 是否能接收语音命中的 `cmd`。
|
||||
- [ ] `cmd` 到业务动作是否有明确映射表。
|
||||
- [ ] 页面销毁或切换时是否取消旧插词。
|
||||
|
||||
## 8. 当前徐工项目建议落地顺序
|
||||
|
||||
1. 先验证 `YX_Voice` 与同行者之间的 `shadow.register` / `shadow.execute` 链路。
|
||||
2. 在 `YX_CarControl` 做一个测试插词,不绑定真实业务动作,只看日志是否能完整闭环。
|
||||
3. 链路确认后,再选一个真实页面做最小闭环,例如语音设置页或声音设置页。
|
||||
4. 对原生 Android 控件,优先走无障碍自动扫描,不额外走 AIDL/广播。
|
||||
5. 对自绘、网页、小程序、复杂浮窗,走 AIDL/广播注册插词。
|
||||
6. 对 SystemUI、Launcher、Music、Radio 这类插词多且易冲突的模块,先做页面级插词清单,再逐个治理冲突。
|
||||
|
||||
## 9. 日志验证建议
|
||||
|
||||
注册阶段重点看:
|
||||
|
||||
```text
|
||||
registerVisibleSpeakKeywords
|
||||
shadow.register
|
||||
keywordList
|
||||
```
|
||||
|
||||
命中阶段重点看:
|
||||
|
||||
```text
|
||||
shadow.execute
|
||||
cmd
|
||||
handleVisibleSpeakExecute
|
||||
```
|
||||
|
||||
异常排查重点看:
|
||||
|
||||
```text
|
||||
keywordList is empty
|
||||
TXZ not connected
|
||||
protocolLogic is null
|
||||
packageName or cmd is empty
|
||||
```
|
||||
|
||||
## 10. 快速判断表
|
||||
|
||||
| 现象 | 优先排查 |
|
||||
| ------------ | --------------------------------------------- |
|
||||
| 说了没反应 | 控件是否有 ID、是否 clickable、是否注册成功 |
|
||||
| 图标不能说 | 是否设置 `contentDescription` |
|
||||
| 状态动作反了 | 是否动态更新 `contentDescription` |
|
||||
| 列表不能翻页 | 是否预留 0 大小上一页/下一页控件 |
|
||||
| SeekBar 拖动不准 | 是否去掉 SeekBar 内边距,父布局是否设置 `clipChildren=false` |
|
||||
| 弹框扫不到 | 是否用标准 Dialog 或依附 Activity |
|
||||
| 命中到错误应用 | 是否存在 SystemUI / Launcher / 当前页面插词冲突 |
|
||||
| 非常规页面无元素 | 改走 AIDL 或广播插词注册 |
|
||||
|
||||
## 11. 后续需求明确后需要补充的内容
|
||||
|
||||
- 每个模块的可见即可说页面清单。
|
||||
- 每个页面的控件 ID、显示文本、隐藏标签、状态规则。
|
||||
- 插词冲突表,尤其是 SystemUI、Launcher、CarControl、Music、Radio。
|
||||
- 非常规界面的 AIDL / 广播接口定义。
|
||||
- 命中 `cmd` 到实际业务动作的映射表。
|
||||
- 现场日志验证结果。
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
| 项目 | 值 | 类型 |
|
||||
| --- | --- | --- |
|
||||
| 请求名称 | `syncAppList` | String |
|
||||
| 参数名称 | `appList` | String |
|
||||
| 参数内容 | 应用列表 JSON 字符串 | String |
|
||||
|
||||
```java
|
||||
BundleMutablePayload params = new BundleMutablePayload();
|
||||
params.putString("appList", appListJson);
|
||||
|
||||
Request request = new Request("syncAppList", params);
|
||||
sendCommandTxz(request);
|
||||
```
|
||||
|
||||
注意:`appList` 参数本身是一个字符串,字符串内容才是应用列表 JSON,不是直接向参数中放入 JSON 对象。
|
||||
|
||||
##应用列表 JSON 格式
|
||||
```json
|
||||
{
|
||||
"list": [
|
||||
{
|
||||
"app.name": "空调",
|
||||
"app.package": "com.yaxon.hvac"
|
||||
},
|
||||
{
|
||||
"app.name": "音乐",
|
||||
"app.package": "com.yaxon.music"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 字段定义
|
||||
|
||||
| 字段 | 类型 | 是否必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `list` | JSON Array | 是 | 应用信息数组 |
|
||||
| `app.name` | String | 是 | 提供给语音识别使用的应用名称 |
|
||||
| `app.package` | String | 是 | 应用包名或约定的应用功能标识 |
|
||||
|
||||
每个应用元素当前只包含 `app.name` 和 `app.package` 两个字段。
|
||||
|
||||
```java
|
||||
private void scanNativeApp() {
|
||||
mThreadPoolTool.execute(() -> {
|
||||
JsonHelper jsonHelper = new JsonHelper();
|
||||
PackageManager packageManager =
|
||||
YxApplication.getApplication().getPackageManager();
|
||||
List<PackageInfo> packageInfoList =
|
||||
packageManager.getInstalledPackages(0);
|
||||
JSONArray jsonArray = jsonHelper.createJsonArray();
|
||||
|
||||
for (PackageInfo packageInfo : packageInfoList) {
|
||||
ApplicationInfo applicationInfo = packageInfo.applicationInfo;
|
||||
String appName = applicationInfo.loadLabel(packageManager).toString();
|
||||
String packageName = packageInfo.packageName;
|
||||
if (mAppInfoMap.containsKey(packageName)) {
|
||||
appName = mAppInfoMap.get(packageName);
|
||||
}
|
||||
JSONObject item = jsonHelper.createJsonObject(
|
||||
new Pair<>("app.name", appName),
|
||||
new Pair<>("app.package", packageName));
|
||||
if (item != null) {
|
||||
jsonArray.put(item);
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> app : mCustomAppMap.entrySet()) {
|
||||
JSONObject item = jsonHelper.createJsonObject(
|
||||
new Pair<>("app.name", app.getValue()),
|
||||
new Pair<>("app.package", app.getKey()));
|
||||
if (item != null) {
|
||||
jsonArray.put(item);
|
||||
}
|
||||
}
|
||||
|
||||
jsonHelper.putJsonArray("list", jsonArray);
|
||||
VoiceManager.VOICE_EVENT_HELPER
|
||||
.sendAppListScanComplete(jsonHelper.toJson());
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
# 车机系统 CPU / 内存监控问题报告
|
||||
|
||||
**日期**: 2026-09-05
|
||||
**设备**: T9999916 · Android 10 · 6核(600%) · RAM 6.1G + swap 2.4G
|
||||
**监控窗口**: 10:10 – 11:07(约 57 分钟,10 秒采样,持续报文压测中)
|
||||
**监控方式**: `top` 10s 轮询 + `dumpsys meminfo` + 线程级 `top -H` + `/proc` 快照
|
||||
|
||||
---
|
||||
|
||||
## 结论总览
|
||||
|
||||
| 等级 | 进程 | 问题 | 证据强度 |
|
||||
|---|---|---|---|
|
||||
| 🔴 P0 | `com.txzing.voiceassistant` (PID 4733) | **Native 层内存泄漏 + 持续高 CPU** | 确凿 |
|
||||
| 🟡 P1 | `com.yaxon.fota` (PID 5037) | 常驻高 CPU(升级服务压测下异常) | 高 |
|
||||
| 🟡 P2 | `com.yaxon.dms` (PID 5056) | CPU 波动大(可能为正常视觉推理负载) | 中 |
|
||||
| ⚪ 观察 | system_server / systemui / surfaceflinger / logd / logcollector | 二级负载,随报文流量波动 | 信息 |
|
||||
|
||||
---
|
||||
|
||||
## 🔴 P0: com.txzing.voiceassistant — Native 内存泄漏(核心发现)
|
||||
|
||||
### 内存增长曲线(RSS)
|
||||
|
||||
- 10:10 起始 ~562MB → 10:45 ~730MB → 11:00 ~770MB → **11:07 停止监控时 754MB(峰值 793MB)**
|
||||
- **约 57 分钟增长 ~200MB(+35%)**,锯齿形单调上行,无平台期,无回落,未观察到 GC 释放
|
||||
- 全局 MemAvailable 同步从 ~1.98G 降至 ~1.70–1.77G,与该进程泄漏吻合
|
||||
|
||||
### 泄漏定位在 Native 层(非 Java)
|
||||
|
||||
停止监控前最终 `dumpsys meminfo` 快照:
|
||||
|
||||
```
|
||||
Pss Private Heap
|
||||
Total Dirty Alloc
|
||||
Native Heap 378885 378784 378358 ← 泄漏主体
|
||||
Dalvik Heap 113174 113112 100795
|
||||
TOTAL PSS: 704888 (Views: 9837, ViewRootImpl: 29)
|
||||
```
|
||||
|
||||
- **Native Heap: 378MB**(Heap Alloc 378.4MB / Size 386MB,已接近上限)
|
||||
- Java Heap: 仅 113MB — 若是 Java 泄漏 GC/lmkd 可回收,Native 才解释 RSS 单调涨
|
||||
- Views: **9837 个 / ViewRootImpl: 29**(UI 对象也在累积,但量级远小于 native heap)
|
||||
|
||||
### CPU 与热点线程(共 104 线程)
|
||||
|
||||
```
|
||||
TID 4942 MDS_SERVER R 94.5% 累计 57:31.58 ← 热点
|
||||
TID 5018 RenderThread S 2.7% 累计 3:36.31
|
||||
TID 4962 engine_proc S 2.7% 累计 1:21.77
|
||||
```
|
||||
|
||||
- 进程 CPU 常驻 90–140%,峰值 193%
|
||||
- **热点线程 TID 4942 = `MDS_SERVER`:单线程 94.5%,57 分钟内累计 57 分 31 秒 CPU 时间** —— 几乎吃满一个核,处于报文/流处理路径;内存与 CPU 异常同源
|
||||
|
||||
### 判断
|
||||
|
||||
MDS_SERVER(native 报文/数据服务线程)存在分配未释放(缓冲区/会话对象累积),同时该路径处理消耗持续 CPU。按当前 ~3.5MB/min 速率,连续运行数小时将逼近 Native Heap 上限并触发 OOM/崩溃。
|
||||
|
||||
### 建议动作
|
||||
|
||||
1. `debuggerd -j 4733` 抓 MDS_SERVER 调用栈,确认其在忙什么系统调用/库
|
||||
2. 对比"停止发报文"前后 RSS 斜率,闭环验证报文触发
|
||||
3. native 内存定位:`adb shell setprop wrap.com.txzing.voiceassistant "LIBC_MALLOC_DEBUG=1"` 后复测
|
||||
4. 交 txzing 语音助手团队:重点审 MDS_SERVER 线程的报文缓冲生命周期
|
||||
|
||||
---
|
||||
|
||||
## 🟡 P1: com.yaxon.fota — 常驻高 CPU
|
||||
|
||||
- 全程 40–90% CPU(峰值 100%),RSS 稳定 ~141MB(无内存问题)
|
||||
- 升级服务在报文压测下持续高 CPU 不正常——怀疑频繁解析/重试报文或轮询过密。建议查其日志与轮询策略
|
||||
|
||||
## 🟡 P2: com.yaxon.dms
|
||||
|
||||
- CPU 7–91% 波动,RSS 稳定 ~158MB。若 DMS 在做视觉推理属正常负载,峰值偏高,建议确认
|
||||
|
||||
---
|
||||
|
||||
## ⚪ 二级负载(未见泄漏,供参考)
|
||||
|
||||
| 进程 | CPU 范围 | 备注 |
|
||||
|---|---|---|
|
||||
| system_server | 20–91% 突发 | 随报文/窗口活动波动 |
|
||||
| com.android.systemui | 17–64% | 正常偏高 |
|
||||
| surfaceflinger | 20–47% | 渲染负载 |
|
||||
| logd | 峰值 77% | 日志量随报文增大 |
|
||||
| logcollector | 突发 116% | 周期性日志收集 |
|
||||
| com.yaxon.datacenter_service | 14–57% | 疑似报文接收方,CPU 合理 |
|
||||
|
||||
---
|
||||
|
||||
## 附录:关键证据命令(可复现)
|
||||
|
||||
```bash
|
||||
adb shell dumpsys meminfo com.txzing.voiceassistant # Native 378MB vs Java 113MB
|
||||
adb shell top -H -b -n 1 -q -p 4733 # MDS_SERVER 94.5% / 57m31s
|
||||
adb shell cat /proc/4733/task/4942/comm # → MDS_SERVER
|
||||
adb shell ls /proc/4733/task | wc -l # → 104 线程
|
||||
adb shell dumpsys meminfo -c # 全进程 PSS 排名
|
||||
```
|
||||
|
||||
### 全进程 PSS Top(11:07 快照)
|
||||
|
||||
| 进程 | PID | PSS (KB) |
|
||||
|---|---|---|
|
||||
| com.txzing.voiceassistant | 4733 | 693,609 |
|
||||
| system | 3288 | 120,731 |
|
||||
| com.yaxon.dms | 5056 | 90,670 |
|
||||
| com.yaxon.music | 4806 | 53,318 |
|
||||
| com.yaxon.factory | 5074 | 38,285 |
|
||||
| com.yaxon.voice | 4677 | 36,104 |
|
||||
| com.yaxon.logcat | 5031 | 32,314 |
|
||||
| com.yaxon.bluetooth | 4721 | 33,078 |
|
||||
Reference in new issue
Block a user