15 KiB
OPPO Watch S / S2 RTOS 手机真机调试桥 0.3.0
自研部分按 PolyForm Noncommercial 1.0.0 公开,仅限许可允许的非商业用途;商业用途须另获许可。版权和第三方条款见 NOTICE.md。独立公开项目:rtos-watch-debug-bridge。
适用机型为 OPPO Watch S / OWW262 与 Watch S2 / OWW265;本项目仅在 S2 完成下述真机验收,Watch S 待单独验收。Android/Wear OS 与 HarmonyOS 手表不在兼容声明内。
独立 Android 手机工程,包名 com.sydxky.rtos.bridge。供 Windows 电脑通过 USB ADB 操作手机上已配对的 OPPO Watch S / S2(RTOS / Glyphix)。APK 安装到手机,Glyphix bundle.pkg 安装到手表。
2026-11-14 补测:恢复健康服务并等待重连后,S2 探针安装与设备信息请求成功。实际型号 OWW265 / runtime 0.8.0-5。探针 1.0.3 单次常亮请求实测失败;1.0.4 增加前台亮屏续期后,静置至少 159 秒仍显示探针,用户确认实体屏幕仍亮,随后手动点击计数由 0 变成 1,均保留官方截图。远程调至前台、通用手表操控及真机 Inspector 仍未通过。最新状态见补测记录;此前 3000 失败报告保留。
本轮 USB 离线后,经核验同一 P30PRO 的已授权网络 ADB YOUR_PHONE_SERIAL 完成后续安装及截屏,使用时可将命令的 --serial YOUR_PHONE_SERIAL 替换为当前手机实际 ADB 地址;网络地址可能变化。先运行 adb devices -l 确认设备,勿选择其他 OWW261。手机 API 仍只监听回环地址,经 ADB forward 访问。
电脑 bridge.py
→ adb forward tcp:18765 tcp:18765
→ 手机调试桥(127.0.0.1:18765,随机 Bearer 令牌)
→ bindService + Binder.transact
→ 手机运动健康 WearEngineService
→ 厂商蓝牙 / 互联传输
→ S2 手表 / Glyphix 应用
构建和首次连接
使用非 MSIX PowerShell 7。工程不引用运动健康私有 APK 或 SDK,不与现有 Android 手表工程共用构建脚本。
Set-Location -LiteralPath '.\phone-debug-bridge'
.\build.ps1 -JavaHome 'C:\path\to\jdk17'
python -m unittest discover -s tests -v
python .\bridge.py --serial YOUR_PHONE_SERIAL setup
python .\bridge.py --serial YOUR_PHONE_SERIAL connect
python .\bridge.py --serial YOUR_PHONE_SERIAL wait-link --seconds 45
python .\bridge.py --serial YOUR_PHONE_SERIAL link
python .\bridge.py --serial YOUR_PHONE_SERIAL info
工具链:JDK 17、Gradle 8.13、Android Gradle Plugin 8.13.1、compileSdk 35、targetSdk 34、minSdk 27。JDK / Android SDK 可通过 build.ps1 -JavaHome ... -AndroidSdk ... 指定。ANDROID_HOME 只对当前构建进程设置。产物:artifacts/RTOS-Phone-Bridge-0.3.0-debug.apk,versionCode 4。
首次安装时解锁手机并处理华为系统的安装确认,保持运动健康已配对、手表唤醒;Android 13 及以后可允许调试桥通知。手机界面也提供连接、设备信息、选包安装、启动与日志按钮。setup 最长等待安装 45 秒;遇到系统确认超时,先在手机完成确认,再重新运行。
P30PRO 若返回 bind_rejected,先打开已经配对的运动健康,再执行 connect。2026-11-14 实测启动 com.heytap.health/.oobe.LaunchActivity 后绑定成功,不需要修改配对数据或手机认证设置。系统安装确认期间不要执行会打开旧版桥接界面的命令,以免遮住安装页面。
绑定成功可能早于手表完成重连。wait-link 只轮询在线查询(1–120 秒,默认 45 秒);未上线时退出码为 2。它不会重复安装或其他写操作。持续 3000 的一次会话在重启健康并等待重连后恢复;这不是已确定的 SDK 根因。
默认互联 appId / license 为参考助手演示使用的 test / test,仅为开发尝试值,不能证明厂商授权。正式互联消息需要匹配应用的 appId 和 license。使用本地文件避免凭据进入进程命令行:
python .\bridge.py --serial YOUR_PHONE_SERIAL connect --config .\connection.local.json
本地 JSON 含 appId、license、可选 service,已忽略 *.local.json。默认服务包 com.heytap.health;其他配套应用需先通过 /status 的 services 确认实际实现,再在本地配置中选择。state=bound 只表示手机 Binder 已就绪;link 返回 true 和真实手表回调才构成后续设备证据。
常用命令
# 安装项目的圆屏 QuickApp 包。先按对应应用的构建说明生成包。
python .\bridge.py --serial YOUR_PHONE_SERIAL install '..\com.sydxky.rtos.deviceprobe\.glyphix-work\dist\generic-watch-466x466-quickapp\com.sydxky.rtos.deviceprobe\bundle.pkg'
python .\bridge.py --serial YOUR_PHONE_SERIAL check com.sydxky.rtos.deviceprobe
python .\bridge.py --serial YOUR_PHONE_SERIAL launch com.sydxky.rtos.deviceprobe
# 开启手表日志后读取事件;Ctrl+C 只停止电脑读取。
python .\bridge.py --serial YOUR_PHONE_SERIAL logs on
python .\bridge.py --serial YOUR_PHONE_SERIAL events --follow
python .\bridge.py --serial YOUR_PHONE_SERIAL logs off
# 消息/文件必须对应支持互联的目标应用,263 消息会检查授权握手。
python .\bridge.py --serial YOUR_PHONE_SERIAL message '{"type":"ping"}'
python .\bridge.py --serial YOUR_PHONE_SERIAL send-file '.\sample.txt' --remote 'internal://files/sample.txt'
# 仅向明确支持的方法发送 RPC;参数是 JSON 字符串。
python .\bridge.py --serial YOUR_PHONE_SERIAL rpc toggle_rpc_log_feature --params '{"status":0}'
# 结束调试:先关闭日志、断开服务,再清手机上传缓存并停止进程。
python .\bridge.py --serial YOUR_PHONE_SERIAL disconnect
python .\bridge.py --serial YOUR_PHONE_SERIAL cleanup
python .\bridge.py --serial YOUR_PHONE_SERIAL stop
0.3.0 安装先解析包名与图标,转标准 PNG 后发送 /user/jsapps/<包名>.png,收到文件终态成功且数字 code=200 后才发送并安装 .pkg。完整 dist 须保留 bundle.pkg、manifest.json、icon.png;PGF 图标优先使用同目录 PNG,亦可 install <包> --icon <对应PNG>。263 文件互联授权不足、图标失败或超时均停止安装,见完整流程与限制。服务端以回调 success/failed/progress 更新作业;电脑退出码 2 表示回调失败或超时,1 表示本地 / HTTP 错误,130 表示用户中断。超时不表示手表操作已取消,避免立即重复安装。check 的布尔结果沿用厂商实现,不能替代安装和启动结果。
实际验收脚本
python .\verify.py --serial YOUR_PHONE_SERIAL `
--probe '..\com.sydxky.rtos.deviceprobe\.glyphix-work\dist\generic-watch-466x466-quickapp\com.sydxky.rtos.deviceprobe\bundle.pkg' `
--output '.\artifacts\device-validation.json'
这个命令会安装独立探针、启用 RPC 日志、启动应用并查找 RTOS_DEVICE_PROBE_READY_V1,最后关闭日志。可用 --ready-wait 60 延长日志等待,范围 1–300 秒。报告仅保留明确允许的模型/版本字段及探针标记,省略令牌、license、原始日志和设备唯一标识。可选 --config 使用匹配的互联参数。手表离线时停止后续安装;手机绑定失败也写入具体阶段。安装、启动、设备信息的条目使用 _callback 后缀,分别表示厂商成功回调;空设备信息不能推断型号,回调不能替代页面运行或人工点击。当前实际状态见 2026-11-14 记录,早期记录 保留为历史。
截图、UI 检查与操控
手机 APK 新增“截图与 UI 检查”:打开运动健康、提示官方手表截屏路径、通过系统文件选择器导入图片、显示原比例预览和圆屏 5% 安全区参考线。导入上限 8 MiB / 2048×2048,转换 PNG 后保存在应用私有目录。参考线只显示在预览中;来源标注为用户选择、未经设备身份确认。
电脑工具 ui.py 仅使用 Python 标准库,所有操作必须显式选择目标:
| target | 截图来源 | 控件树与操控 | 当前证据 |
|---|---|---|---|
phone |
ADB 手机屏幕 | uiautomator、点击、滑动、文字/ID 断言 | 依赖手机解锁;这是手机界面 |
watch-health |
自动导航运动健康的“设备 → 更多功能 → 手表截屏”,等待官方目录中新保存的图片 | 只提供官方截屏导航 | P30PRO + S2 实测自动导出 480×464 JPEG;50 秒无图则报错 |
watch-import |
APK 中用户选择的图片,导出前核验 SHA-256 | 私有图片导出 | 已验证官方 JPEG 导入、预览和 PNG 导出;来源仍标注用户选择 |
inspector |
显式 Glyphix Inspector 的原生快照 | @system.test 点击/滑动/等待,控件快照、步骤报告 |
圆/方模拟器实测通过;S2 端点与隧道未确认 |
# 手机截图和控件树,文件均代表手机界面。
python .\ui.py --target phone --serial YOUR_PHONE_SERIAL screenshot --output '.\artifacts\phone.png'
python .\ui.py --target phone --serial YOUR_PHONE_SERIAL tree --output '.\artifacts\phone.xml'
python .\ui.py --target phone --serial YOUR_PHONE_SERIAL click --by text --value '截图与 UI 检查'
# 官方截屏;仅当健康将新图片保存到公开图库时可自动导出。
python .\ui.py --target watch-health --serial YOUR_PHONE_SERIAL screenshot --output '.\artifacts\s2.jpg'
# 若官方只保存在私有缓存,先用健康的保存功能,再到本 APK 选择图片。
python .\ui.py --target watch-import --serial YOUR_PHONE_SERIAL screenshot --output '.\artifacts\selected-watch.png'
# 已独立确认的 Inspector。以下端口通常属于本机模拟器。
python .\ui.py --target inspector --inspector http://127.0.0.1:14201 tree --output '.\artifacts\runtime.tree.json'
python .\ui.py --target inspector --inspector http://127.0.0.1:14201 run '.\examples\probe-inspector.json' --output '.\artifacts\ui-run'
run 接受 1–50 步 JSON,白名单为 click、scroll、assert-visible、screenshot;第一步失败即停止并写 report.json,退出码 2。手机选择器为 id/text/description,重复匹配拒绝点击;Inspector 为 id/text/tag/class。示例计划要求探针点击计数从 0 开始。scroll 的 dx/dy 是像素偏移;assert-visible 在 Inspector 中会等元素并尝试滚入视野,不承诺全程静止检查。每次 Inspector 快照均在 finally 恢复运行时,防止截图后暂停计时器。
此次健康 6.10.15 将手表截图保存到公开 Pictures/com.heytap.health/screenshots/watch_screen_shot.jpeg,后续同名图自动增加 (1) 等编号。工具只读取此目录内匹配的官方文件名,并比较图片 ID、修改时间及内容 hash。原图可能因显示缓冲区对齐而为 480×464,不要求严格方形。JPEG 保留原字节;若 --output 扩展名不符,会使用实际格式的 .jpg 或 .png 并在结果中报告最终路径。图片导入 APK 后转为 PNG,因此与 JPEG 的 SHA 不同;导出会与 APK 保存的 PNG 核验一致。其他健康版本若改变保存路径,须重新验证适配。
可用 python tests/native_ui.py --seed '<已初始化的厂商圆屏镜像目录>' --output '.\artifacts\native-ui' 复现两个原生模拟器配置,要求本机厂商 SDK、探针圆/方包,以及兼容的 global/launcher 资源。默认读取探针自身的圆屏 image 目录,可先构建普通镜像并按厂商教程初始化模拟器资源。端口被占用时拒绝附加到其他测试。该命令只终止自己启动的模拟器,源码交付不包含厂商工具或全局镜像。
Wear Engine 263 当前已确认安装/启动等能力,未发现通用 S2 触摸注入、控件树或 Inspector 转发接口。因此 phone 操作不能用作 S2 点击证据;inspector 的端点身份必须另行核验。官方截屏失败时不会回退保存手机截图。
接口与资源边界
- 手机仅监听
127.0.0.1:18765,不监听 Wi-Fi 地址;所有接口要求随机 256-bit Bearer 令牌,拒绝浏览器 Origin 请求,不提供 CORS。 bridge.py通过当前已授权 USB ADB 的run-as读取手机应用私有令牌,令牌不写入电脑文件或日志。这是供本地调试使用的 debug 签名 APK,未制作上架版。- 只有 Launcher Activity 导出,桥接 Service 和图片检查 Activity 不导出;无需存储、蓝牙、位置、麦克风或无障碍权限。文件通过文件选择器 / 认证上传接口进入应用私有目录,跨进程只传只读文件描述符。
- HTTP:
GET /status、GET /events?after=N、GET /jobs/<id>;POST /connect、/disconnect、/command、/cleanup;PUT /files/<简单文件名>。连接 / 命令返回 202,命令返回id后轮询作业。 - 单文件最多 32 MiB,电脑上传缓存最多 4 个文件 / 64 MiB;HTTP 客户端并发 2,等待队列 4;事件最多 1000 条,作业最多 200 条,同时 pending 作业最多 8 条。离开手机界面后前台服务继续工作,通知可停止;不自动复活进程。
- 日志只在手机进程内保留。运行中的事件接口可能含手表应用自己的内容,分享前自行筛选;验收脚本只保存固定探针标记。结束后执行
logs off和stop。 rpc可调用厂商方法,但不自动执行卸载、系统改写、认证设置修改或桌面槽位替换。不同固件的支持范围以当前手表回调为准。- 未实现蓝牙底层协议、手表 ADB、Inspector 端口隧道或通用手表触摸注入。官方截屏导航和用户图片导入在
ui.py/ APK 图片检查页提供;未来应用真机验证可先通过安装 / 启动 / 生命周期日志进入。
协议与参考
发现 Action:com.xfaith.glyphix.WEAR_ENGINE_ACTION。绑定传 packageName、appId、license。基础接口 com.glyphix.mas.GlyphixWear 的 transaction 14 查询版本;版本至少 2006003 时 transaction 18 的参数为 263,返回 com.glyphix.mas.GlyphixWear263。
| 功能 | 263 | 旧版 |
|---|---|---|
| 手表连接状态 | 1 | 1 |
| 设备信息 | 7 | 4 |
| 检查应用 | 8 | 5 |
| 启动应用 | 9 | 6 |
| 发送消息 | 10 | 7 |
| 安装应用 | 16 | 15 |
| 发送文件 | 15 | 12 |
| execLpc / RPC | 4 | 17 |
263 的设备信息 / 检查 / 启动 / 连接状态订阅传手机包名;安装传 appId。安装的字符串参数是手表目标 URI,使用 remote://mass/bridge_<时间>.pkg;只传文件名会在此次目标设备返回 4008 rename remote file failed。消息参数为手机包名、appId、正文;文件参数为 fd、文件名、目标 URI、appId。消息和文件在 263 模式都先检查互联授权。回调 WearEngineProgressResolver:1=成功、2=失败、3=进度。消息授权使用 wear-engine-auth-<手机包名>,普通消息订阅使用 wear-engine-<手机包名>。
参考 Glyphix 官方教程、测试框架 和 oppo-watch-s-sideload。参考仓库使用此前本地快照 162fca4aa51302e18ee9802dc5269e54814c02e8,本轮未重新拉取。后者验证的是 Watch S / OWW262,不能直接视作本项目 S2 验收。本工程独立实现 Binder 线协议;上游文档 MIT 归 chengchengking,参考助手 APK 的版权单独归其作者,本工程不随源码或交付包分发该 APK / SDK / 反编译输出。未采用该仓库底层文件探针中的认证状态修改方案。