这次折腾的目标很简单:在 PICO 4 Ultra 上替换国际版商店、用户中心和 Matrix。前两个组件顺利安装,Matrix 却同时遇到了禁止降级和受保护应用限制。最终通过官方应用更新 API 找到了版本码更高、保留 PICO 原签名的国际版 Matrix,直接覆盖成功。
本文记录的是 2026 年 10 月 28 日的实际操作。版本和分发策略可能变化,执行前请重新检查自己的设备。
先说结果与适用范围
实测设备是 PICO 4 Ultra,ADB 型号 A9210,代号 sparrow,系统 5.15.8。国际版组件来源包括一份 5.15.7 国际版 OTA 和官方应用更新接口。
| 组件 | 包名 | 安装结果 |
|---|---|---|
| 商店 | com.picovr.store |
从 4.12.5 更新版退回后,覆盖为提取的 4.9.0 |
| 用户中心 | com.picovr.vrusercenter |
同为 5.10.0,签名一致,覆盖成功 |
| Matrix | com.bytedance.pico.matrix |
国际版 6.3.4,版本码 600304021,覆盖成功 |
这里的“替换”是把 APK 安装到 /data/app,作为系统应用更新覆盖运行,没有刷写系统分区、解锁 Bootloader 或获取 Root。内置 APK 仍然存在。
商店和用户中心可以启动,用户中心进入登录页;Matrix 安装后进程正常运行。账号登录、购买、下载及组件间联动尚未完成端到端验证。单独替换组件也不能保证整机变成完整国际版系统。
普通 PICO 4 与 PICO 4 Ultra 的固件不可混用。操作账号组件可能需要重新登录;降级即使保留数据,也存在数据格式不兼容风险。先备份,后操作。
1. 准备工具与连接设备
电脑需要 Android Platform Tools 的 adb、Android SDK Build Tools 的 aapt 和 apksigner。若从 OTA 提取组件,还需要支持 Android OTA 的 payload 提取工具,以及 EROFS 工具包中的 dump.erofs。
在头显内打开 USB 调试,用数据线连接并确认授权:
adb devices -l
adb shell getprop ro.product.model
adb shell getprop ro.product.name
adb shell getprop ro.build.display.id如果连接了多个 Android 设备,后续命令必须加 adb -s <设备序列号>,避免操作错设备。
查看当前组件版本:
for pkg in com.picovr.store com.picovr.vrusercenter com.bytedance.pico.matrix; do
echo "=== $pkg ==="
adb shell pm path "$pkg"
adb shell dumpsys package "$pkg" | grep -E 'codePath=|versionCode=|versionName='
done一个系统应用可能同时显示 /data/app 中的更新版与 /system 中的内置版。要确认实际生效的 APK,使用 pm path。
2. 先备份当前 APK
以下命令适用于本次这些只有单个 APK 的组件。若 pm path 返回多个 split APK,需要逐个备份,不要只取第一行。
mkdir -p backup extracted downloads
for pkg in com.picovr.store com.picovr.vrusercenter com.bytedance.pico.matrix; do
path=$(adb shell pm path "$pkg" | head -n 1 | tr -d '\r' | cut -d: -f2-)
test -n "$path" || exit 1
adb pull "$path" "backup/$pkg.apk" || exit 1
adb shell dumpsys package "$pkg" > "backup/$pkg-package.txt"
done这只是 APK 与包状态备份,不是应用私有数据备份。不要把包含设备信息的诊断文件直接上传到公开仓库。
3. 从国际版 OTA 提取组件
本次使用的文件:
5.15.7-202608080609-RELEASE-user-sparrow-b9111-b2059d5f17.zip可从 PICO 官方系统页面 和社区固件索引 核对型号与版本。索引页是线索,下载后仍需检查包本身;不要把“公开列表最新”当成服务器绝对没有其他版本。
OTA ZIP 内主要是 payload.bin,不能直接 unzip 出 APK。先查看并提取 system 分区。下面是本次所用 payload-dumper 的语法,其他工具的参数可能不同:
payload-dumper --list firmware.zip
payload-dumper firmware.zip -p system -o extracted确认分区提取成功后,定位组件:
dump.erofs --ls --path=/system/priv-app extracted/system.img
dump.erofs --ls --path=/system/app extracted/system.img本次文件路径如下:
dump.erofs --cat --path=/system/priv-app/store2d/store2d.apk \
extracted/system.img > extracted/Store-global.apk
dump.erofs --cat --path=/system/priv-app/VRUserCenter2/VRUserCenter2.apk \
extracted/system.img > extracted/UserCenter-global.apk
dump.erofs --cat --path=/system/app/Matrix/Matrix.apk \
extracted/system.img > extracted/Matrix-global.apk提取器报错时不要直接使用残缺镜像。 本次遇到 operation data hash mismatch:检查 manifest 后发现,操作数据偏移在跨过 4 GiB 时出现回绕,原工具按回绕后的偏移读取了错误位置。针对这份包修正偏移后,剩余操作数据的哈希校验通过,最终提取的 APK 也通过签名验证。这是针对该文件的处理,不能把“所有偏移加 4 GiB”当成通用修复,更不能跳过校验继续安装。
4. 安装前检查版本和签名
aapt dump badging extracted/Store-global.apk | head -n 3
apksigner verify --print-certs extracted/Store-global.apk
apksigner verify --print-certs backup/com.picovr.store.apk对用户中心与 Matrix 重复相同检查。覆盖安装要求包名和签名兼容,版本显示名称相同也不够,Android 主要比较 versionCode。
本次验证的 PICO 签名证书 SHA-256 指纹为:
dc30289e0a61447d03c95d15e5acf63e18d109d545a766b1208f6b53cbdcd482这是公开证书指纹,不是签名私钥。应与自己设备上的原 APK 对照,不能仅凭应用名称判断来源。
5. 商店与用户中心的替换
先尝试保留数据覆盖:
adb install -r extracted/Store-global.apk
adb install -r extracted/UserCenter-global.apk本次用户中心同版本覆盖成功;商店原更新版为 4.12.5,提取版为 4.9.0,触发:
INSTALL_FAILED_VERSION_DOWNGRADEadb install -r -d 并不能强制所有正式版应用降级,设备帮助也明确说明 -d 针对可调试应用。
确认已经备份、接受重新登录与降级数据风险后,本次对商店单独执行:
adb shell pm uninstall -k com.picovr.store
adb install -r extracted/Store-global.apk在这台设备上,第一步成功移除了系统商店更新、退回内置版;随后国际版 APK 覆盖成功。-k 请求保留数据,但不保证旧版本能读取新版本的数据。不要把这一步扩展为批量卸载系统组件。
可分别启动检查:
adb shell am start -W -n com.picovr.store/.MainActivity
adb shell am start -W -n com.picovr.vrusercenter/.MainActivity遇到验证码频率限制,应停止重复请求,稍后通过官方登录流程重试。替换 APK 本身不会解决账号地区或验证码限制。
6. Matrix 为什么不能照搬商店的办法
本次版本码是:
| 来源 | versionName | versionCode |
|---|---|---|
| 头显当前更新版 | 6.3.4 | 600304020 |
| 5.15.7 国际版 OTA 内置版 | 6.3.4 | 600304016 |
提取版更旧,覆盖时被拒绝。尝试卸载更新又遇到:
DELETE_FAILED_INTERNAL_ERROR
Attempted to delete protected package: com.bytedance.pico.matrixpm uninstall-system-updates com.bytedance.pico.matrix 同样失败;正式版系统也拒绝 adb root。此时继续反复加 -d 没有意义,应该寻找 官方签名、版本码不低于当前版本的国际版 APK。
还找到过一个社区 Matrix_GL.apk:版本码被改为 999999999,证书却是第三方签名。它不能直接作为官方系统应用更新安装。相关模块只声明支持 Root 后的普通 PICO 4 OS 5.13.7,不能套到这台 Ultra 上,因此没有安装。
7. 从官方 API 查到新版 Matrix
只搜索 APK 文件名没有找到合适的新版,于是检查了官方组件的实现:
SystemUpdate2.apk:整机 OTA 更新。VersionManager.apk(com.pvr.version):系统应用更新。
可从自己的设备或对应国际版 OTA 提取 APK,用 JADX 本地查看:
jadx --no-res -d updater-src SystemUpdate2.apk
jadx --no-res -d version-src VersionManager.apk客户端实现中的关键位置是 OtaService、AbstractOtaRequest、VersionApi、VersionRepo、RequestFactory。不同版本可能有混淆或路径变化。
整机固件查询
POST https://iot-global-api.picovr.com/open/v3/ota/check请求包含设备型号、产品名、序列号、系统版本、构建时间、构建类型、地区及应用基线等字段,并使用 X-Signature 签名。本次 HTTP 200,业务返回:
{"code":0,"errmsg":"未匹配到合适的策略"}这只能说明本次请求未匹配到分发策略;设备条件、地区、灰度与请求参数都可能影响结果,不能据此断言没有新固件。
系统应用查询:旧接口与新接口不同
旧接口:
POST https://appupdate-global-api.picovr.com/api/upgrade/v1/check本次返回空列表。继续按客户端实现调用新版单应用接口:
POST https://appupdate-global-api.picovr.com/api/upgrade/v1/check/single查询参数有 _timestamp、_nonce,请求头包括 Content-Type: application/json、Locale、X-Signature。请求结构示意:
{
"head": {
"uuid": "自己的设备标识",
"os_version": "客户端对应系统版本",
"rom_version": "客户端对应完整构建版本",
"build_type": "user",
"model": "客户端读取的型号字段",
"product_name": "客户端读取的产品字段",
"android_version": "34",
"category": "vr",
"vendor": "pico",
"app_id": "pico_self_update",
"did": "客户端设备ID",
"country_code": "HK",
"device_bc_flag": 0,
"self_pkg_name": "com.pvr.version"
},
"body": {
"business_id": 74,
"need_upgrade_apps": [{"pkg_name": "com.bytedance.pico.matrix"}]
}
}这是字段说明,不是填上就能直接 curl 的免签接口。字段应依据客户端实际读取逻辑生成:例如 ro.pxr.usebuildinfo 会影响型号和产品名的来源,不能把显示名称一律填到每个字段里。上面的地区也不代表所有设备都应使用 HK。
本次客户端的签名流程是:对查询参数排序、对原始 JSON 请求体计算 MD5,再按 RequestFactory 的格式拼接方法、参数与正文摘要,使用 HMAC-SHA256 后 Base64 编码,组成 X-Signature。JSON 序列化后必须用同一份字节签名和发送。本文不公开客户端签名密钥、设备序列号或账号令牌,也不提供绕过服务端鉴权的方法。
新版接口实际返回的关键字段:
{
"code": 0,
"msg": "success",
"data": {
"apps": [{
"pkg_name": "com.bytedance.pico.matrix",
"version_name": "6.3.4",
"version_code": 600304021,
"file_size": 92457772,
"file_md5": "23abe9130f2647d15862e44f33049fac",
"task_id": 4021
}]
}
}apps 中还会提供 file_url 与备用下载地址。应重新查询并使用当次返回地址,避免把历史 CDN 链接当成永久下载入口。HTTP 200 之后,还要检查业务 code、目标包名与版本码。
8. 下载、验证、覆盖新版 Matrix
从上一步响应的 file_url 下载,保存为 Matrix-oversea-6.3.4-600304021.apk。本次检查:
md5sum downloads/Matrix-oversea-6.3.4-600304021.apk
aapt dump badging downloads/Matrix-oversea-6.3.4-600304021.apk \
| grep -E '^package:|^application-label:'
apksigner verify --print-certs downloads/Matrix-oversea-6.3.4-600304021.apk结果:
- 文件大小:
92457772字节。 - MD5:
23abe9130f2647d15862e44f33049fac,与 API 一致。 - 应用名:
pui_matrix_oversea。 - 包名:
com.bytedance.pico.matrix。 - 版本码:
600304021。 - 签名证书:与原机 PICO 证书一致,APK 签名校验通过。
MD5 用于和分发元数据核对;官方来源判断还要结合 HTTPS 来源及 APK 签名,不能单靠 MD5。
确认后直接覆盖,不再卸载:
adb install -r downloads/Matrix-oversea-6.3.4-600304021.apk本次返回 Success,未主动清除数据。检查安装状态和实际 APK:
adb shell dumpsys package com.bytedance.pico.matrix \
| grep -E 'codePath=|versionCode=|versionName='
path=$(adb shell pm path com.bytedance.pico.matrix | head -n 1 \
| tr -d '\r' | cut -d: -f2-)
adb shell md5sum "$path"
adb shell pidof com.bytedance.pico.matrix最终生效路径位于 /data/app,版本码为 600304021,MD5 与下载文件一致,Matrix 进程存在。至此可以确认安装与进程状态;账号、商店与应用授权行为仍需在头显内逐项测试。
回退与排错
- 签名不一致:停止安装,不要为了提高版本码重签系统 APK。
- 版本降级:寻找官方更高版本;受保护应用不要反复尝试卸载。
- 功能异常:先记录日志和当前版本,不要立即清空所有账号组件数据。
- 需要回退:原 APK 已备份,但高版本覆盖后,低版本备份仍可能被降级规则拦截;备份不等于保证能一键恢复。不要为回退贸然恢复出厂或刷机。
- APK 下载已完成:优先复用本地文件,重新核对哈希即可,无需重复下载整包固件。
这次真正解决问题的不是“强行绕过”,而是区分整机 OTA 与应用更新两条分发链路,并从正确的新接口找到版本码更高、签名匹配的国际版组件。