# OPPO Watch S / S2 RTOS 手机真机调试桥 0.2.0 自研部分按 [PolyForm Noncommercial 1.0.0](LICENSE) 公开,仅限许可允许的非商业用途;商业用途须另获许可。版权和第三方条款见 [NOTICE.md](NOTICE.md)。独立公开项目:[rtos-watch-debug-bridge](https://git2.sydxky.cn/sydxky/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 仍未通过。最新状态见[补测记录](../docs/VALIDATION.md);此前 3000 失败报告保留。 本轮 USB 离线后,经核验同一 P30PRO 的已授权网络 ADB `YOUR_PHONE_SERIAL` 完成后续安装及截屏,使用时可将命令的 `--serial YOUR_PHONE_SERIAL` 替换为当前手机实际 ADB 地址;网络地址可能变化。先运行 `adb devices -l` 确认设备,勿选择其他 OWW261。手机 API 仍只监听回环地址,经 ADB forward 访问。 ```text 电脑 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 手表工程共用构建脚本。 ```powershell Set-Location -LiteralPath 'C:\path\to\rtos-watch-debug-bridge\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.2.0-debug.apk`,versionCode 3。 首次安装时解锁手机并处理华为系统的安装确认,保持运动健康已配对、手表唤醒;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。使用本地文件避免凭据进入进程命令行: ```powershell 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 和真实手表回调才构成后续设备证据。 ## 常用命令 ```powershell # 安装项目的圆屏 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 ``` 安装只上传包本身;交给 OPPO 的完整 `dist` 仍须保留 `bundle.pkg`、`manifest.json`、`icon.png`。服务端以回调 `success/failed/progress` 更新作业;电脑退出码 2 表示回调失败或超时,1 表示本地 / HTTP 错误,130 表示用户中断。超时不表示手表操作已取消,避免立即重复安装。`check` 的布尔结果沿用厂商实现,不能替代安装和启动结果。 ## 实际验收脚本 ```powershell 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 记录](../docs/VALIDATION.md),[早期记录](../docs/VALIDATION.md) 保留为历史。 ## 截图、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 端点与隧道未确认 | ```powershell # 手机截图和控件树,文件均代表手机界面。 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/`;`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 官方教程](https://docs.xfaith-tech.com/glyphix/docs/tutorials/)、[测试框架](https://docs.xfaith-tech.com/glyphix/docs/api/system-test.html) 和 [oppo-watch-s-sideload](https://github.com/chengchengking/oppo-watch-s-sideload/tree/main)。参考仓库使用此前本地快照 `162fca4aa51302e18ee9802dc5269e54814c02e8`,本轮未重新拉取。后者验证的是 Watch S / OWW262,不能直接视作本项目 S2 验收。本工程独立实现 Binder 线协议;上游文档 MIT 归 chengchengking,参考助手 APK 的版权单独归其作者,本工程不随源码或交付包分发该 APK / SDK / 反编译输出。未采用该仓库底层文件探针中的认证状态修改方案。