Files
jiecheng-business/test/voice_helper
freeboss b7b5518834 feat: dev-5.1 分支基线(v1.3.35 发版后代码 + 5.1 声道改造文档)
- 以 main(ccc65af) 为基线提交当前工作区代码
- 新增 5.1 声道改造文档两份
- .gitignore 补充 .vscode/、.screenshots/
2026-11-02 19:25:12 +08:00
..

语音协议广播测试脚本

adb shell am broadcast 形式的联调脚本集合,覆盖 可行性评估文档 §6.1 中定义的统一协议(action=com.pukka.jiecheng.action.VOICE_COMMAND),用于在没有第三方语音 App 时手工驱动 voice 模块。

适用范围:bash(Git Bash 即可)。脚本里所有路径用 Unix 风格。

1. 目录结构

test/voice_helper/
├── lib/
│   └── common.sh          # 公共函数:payload 构造 / 广播发送 / 应用级操作
├── jump_film.sh           # 单片跳转 JUMP/FILM
├── jump_category.sh       # 分类跳转 JUMP/CATEGORY
├── search.sh              # 语音搜索 SEARCH
├── control.sh             # 播放控制 CONTROL/<action>
├── cold_start.sh          # 冷启动单片跳转(force-stop + 投递 + 拉起)
├── throttle_test.sh       # 2 秒内连续投递同类命令(验证节流)
├── security_test.sh       # 非白名单 sourceApp 投递(验证签名校验)
├── listen_callback.sh     # 反向广播回调监听(adb logcat)
├── run_all.sh             # 顺序执行全部用例
└── README.md

2. 协议约定(与文档 §6.1 一致)

action:        com.pukka.jiecheng.action.VOICE_COMMAND
permission:    com.pukka.jiecheng.permission.VOICE_COMMAND
component:     com.pukka.jiecheng/.voice.receiver.VoiceCommandReceiver

extras:
  requestId        string   第三方生成的请求 ID,回传时带回
  sourceApp        string   第三方包名
  sourcePlatform   string   第三方平台标识(用于选择 VendorAParser/BParser)
  commandType      string   JUMP / SEARCH / CONTROL
  payload          string   JSON,业务字段
  callbackAction   string   反向广播 action,由第三方传入
  timestamp        long     毫秒

payload 按 commandType 分支:

commandType payload 字段
JUMP jumpType (FILM/CATEGORY/ACTOR/DIRECTOR) + 对应 *Id/*Name,可带 autoPlay
SEARCH filmName / actorName / directorName / category / unionStyle / region / releaseDate
CONTROL action (PLAY/PAUSE/FULLSCREEN_ENTER/FULLSCREEN_EXIT/SEEK_FORWARD/SEEK_BACKWARD/SEEK_TO/PREV/NEXT/SELECT_INDEX/PAGE_NEXT/PAGE_PREV/GOTO_PAGE) + seconds / index / page

3. 快速开始

# 设备已连接 adb 后:
cd test/voice_helper

# 单片跳转(默认 filmId=film-demo-001 / autoPlay=true)
./jump_film.sh

# 自定义参数
./jump_film.sh film-12345 "我的影片" true

# 分类跳转
./jump_category.sh cat-action "动作片"

# 语音搜索
./search.sh "流浪地球"
./search.sh "流浪地球" "吴京"

# 播放控制
./control.sh PAUSE
./control.sh SEEK_FORWARD seconds=10
./control.sh SEEK_TO seconds=300
./control.sh SELECT_INDEX index=3
./control.sh GOTO_PAGE page=2

# 冷启动(force-stop → 投递 → 拉起 MainActivity)
./cold_start.sh

# 2 秒内连续 5 次 PAUSE,验证节流
./throttle_test.sh PAUSE 5

# 非白名单 sourceApp 投递(验证拦截)
./security_test.sh com.attacker.malicious

# 反向广播监听(需 voice 模块按 tag 打印回调日志,tag 默认 VoiceCommand)
./listen_callback.sh                  # 监听全部
./listen_callback.sh vt-1756000000-12345   # 只过滤指定 requestId

# 一键全量
./run_all.sh

4. 环境变量

变量 默认值 说明
ACTION_VOICE_COMMAND com.pukka.jiecheng.action.VOICE_COMMAND 广播 action
PERMISSION_VOICE com.pukka.jiecheng.permission.VOICE_COMMAND 协议权限
RECEIVER_COMPONENT com.pukka.jiecheng/.voice.receiver.VoiceCommandReceiver 显式组件
MAIN_ACTIVITY_COMPONENT com.pukka.jiecheng/.MainActivity 冷启动入口
TEST_APP_PKG com.pukka.jiecheng 应用包名
DEFAULT_SOURCE_APP com.test.voicehelper 模拟第三方包名
DEFAULT_PLATFORM vendorA 模拟平台
DEFAULT_CALLBACK_ACTION com.test.voicehelper.action.VOICE_CALLBACK 反向广播 action
TEST_REQUEST_PREFIX vt- requestId 前缀
SKIP_PERMISSION_CHECK 0 开发期临时绕开 signature-level permission 校验时置 1
LOG_TAG VoiceCommand listen_callback.sh 监听的 logcat tag

示例:自定义第三方包名

TEST_REQUEST_PREFIX=demo- DEFAULT_SOURCE_APP=com.xiaomi.voice ./jump_film.sh

5. 关于 signature-level permission

文档 §6.2 规定 Receiver 使用自定义 signature-level permission(com.pukka.jiecheng.permission.VOICE_COMMAND)。adb shell 默认以 shell 用户身份投递,不持有第三方签名权限,广播会被系统直接丢弃。

联调期三种处理方式:

  1. 临时降级(推荐):在 app/build.gradle 给 debug flavor 注入 manifestPlaceholder:
    debug {
        manifestPlaceholders = [voiceProtectionLevel: "normal"]
    }
    release {
        manifestPlaceholders = [voiceProtectionLevel: "signature"]
    }
    
    然后在 AndroidManifest.xml:
    <permission
        android:name="com.pukka.jiecheng.permission.VOICE_COMMAND"
        android:protectionLevel="${voiceProtectionLevel}" />
    
  2. 拷贝脚本到端内:在应用内临时放一个 BroadcastSender Activity 直接发广播,绕过 shell 权限。
  3. 改 adb 用户:通过 adb root 切到 root 身份,仅在 userdebug 镜像生效。

脚本本身不强制任何一种处理,遇到权限拦截请按上面方式放开。

6. 验证 checklist(对应文档 §12)

联调完成后逐项打勾:

  • 应用未启动时第三方冷启动并执行命令(cold_start.sh)
  • 应用未激活时被守卫拦截,回传 DEVICE_NOT_ACTIVATED
  • 正在播放时收到搜索 / 分类命令先退出再跳转
  • 2 秒内连续多次控制命令只保留最后一条(throttle_test.sh)
  • 第三方收到成功 / 失败回传(listen_callback.sh 配合 logcat)
  • SELECT_INDEX / GOTO_PAGE 在播放页列表中正确选中
  • 白名单外的 sourceApp 被拦截、不回传(security_test.sh)

7. 调试技巧

# 查看应用包内注册的 Receiver
adb shell dumpsys package com.pukka.jiecheng | grep -i receiver

# 查看设备上所有待发广播
adb shell dumpsys activity broadcasts

# 查看最近一次 am broadcast 的返回结果(带 requestId 过滤)
adb shell am broadcast -a com.pukka.jiecheng.action.VOICE_COMMAND -n ... --es requestId probe

# 实时过滤 voice 模块日志
adb logcat -v threadtime VoiceCommand:V VoiceCommandLogger:V "*:S"