ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Aerial 在 TCL MT9655(雷鸟 55S595C Ultra)上的实测:ADB over TLS 授权死锁的排查与 T-Cast 6553 无 ADB 安装、远程诊断方案

Aerial 在 TCL MT9655(雷鸟 55S595C Ultra)上的实测:ADB over TLS 授权死锁的排查与 T-Cast 6553 无 ADB 安装、远程诊断方案

【免费下载链接】aerial-tv

给国产电视的一块干净桌面:参照 tvOS 设计的开源 Android TV 桌面,没有广告,开机自动接管。A tvOS-style launcher for Xiaomi, TCL and other China-market TVs.

项目地址:https://gitcode.com/gh_mirrors/ae/aerial-tv
点击查看免费下载

本文基于 aerial-tv 仓库中 TCL MT9655 机型实测笔记 展开:记录一台雷鸟 55S595C Ultra(MediaTek MT9655,4K)上 Aerial 从「能装进去」到「无法接管 HOME」的完整排查过程,包括 ADB over TLS 的逐条实测证据、adb pair/adb connect为何全部失败、无 ADB 授权时如何通过 TCL 多屏互动(T-Cast,TCP 6553)完成安装与远程诊断,以及目前仍未解决的死锁点。读完本文,你可以复现这套对「只开放无线调试」的国行电视的排查思路,并掌握 T-Cast 高级指令(发任意 Intent、电视截图、模拟遥控按键)的具体用法与坑位。

一、测试机与平台概况

以下信息来自实测笔记的机型档案,也是后文所有结论的适用前提:

  • 零售型号:雷鸟55S595C Ultra;设备串号FF-CN-0015-S595CPRO-TX;固件V8-0015T11-LF1V487。
  • 平台 MediaTekMT9655,3840×2160,4 GB / 64 GB。
  • 原桌面:TCL 自有桌面。已确认com.android.settings与com.android.tv.settings两个包都不存在(用 T-Cast263指令以多个 class 试过,画面无变化;android.settings.SETTINGS/android.settings.ACCESSIBILITY_SETTINGS以 action-only 方式发送也没有 Activity 响应)。
  • 安装的 flavor:guard(standard被 TCL 的LauncherStrategy拒绝,与 MT5879 机型 一致)。
  • 实测结论:APK 能装进去,但拿不到 ADB 授权 ⇒ 无法完成 HOME 接管。

这里先解释一下guard与standard两个 flavor 的差异,它决定了这台电视上「声明 HOME 的包根本装不进去」。app/build.gradle.kts 中的注释说明了设计意图:

// standard: a normal HOME app. guard: no HOME intent filter at all, for China-market firmwares // (some TCL / Hisense builds) that refuse to install any package declaring CATEGORY_HOME. The guard // build takes over Home through its accessibility service instead. flavorDimensions += "home" productFlavors { create("standard") { dimension = "home" } create("guard") { dimension = "home" versionNameSuffix = "-guard" } }

从源码结构看,HOME 声明只存在于standardflavor 的 AndroidManifest.xml 中(MainActivity额外挂上android.intent.category.HOME),而公共 AndroidManifest.xml 的MainActivity只有LEANBACK_LAUNCHER。也就是说:

  • standard:正常声明 HOME,在允许安装 launcher 的固件上可以直接设为默认桌面;
  • guard:不声明 HOME,绕过 TCL 校验链里的LauncherStrategy(见 MT5879 笔记:APK 声明了 MAIN + HOME 且签名与平台不一致即拒绝),转而靠无障碍服务HomeGuardService(app.orchard.tv.guard.HomeGuardService)接管 HOME 键。

这也解释了 MT9655 上standard版走stage 3 → stage 4(被拒)、guard版一次通过的现象。但注意:guard flavor 解决了「装不进去」,解决不了「装进去后没有 shell 权限」的问题——这正是后文死锁的来源。

二、ADB 授权为什么走不通:ADB over TLS 的实测证据

MT9655 上拿不到 ADB 授权,不是「没找到开关」,而是协议层面就没有留给客户端的授权入口。以下是实测笔记中逐条记录的证据链:

  1. 对调试端口发标准 ADBCNXN(24 字节头,含crc32与magic),设备回的不是CNXN/AUTH,而是STLS(arg0=0x01000000,magic0xacb3abac校验通过)。

  2. 故意不升级 TLS 再发一次CNXN,设备仍然回STLS⇒ 强制 TLS,没有任何明文回落。

  3. STLS协商后 TLS 握手可成功(TLSv1.3 /TLS_AES_256_GCM_SHA384),但服务端随后拒绝客户端证书:

    • 带证书(~/.android/adbkey派生、CN=adb 自签)→CERTIFICATE_UNKNOWN
    • 不带证书 →CERTIFICATE_REQUIRED

    持续重试 40 次全部失败,说明「远程自证」被协议禁止,授权只能在电视侧完成。

  4. adb connect→failed to connect;adb pair→protocol fault。

  5. 扫描 30000–50000 发现过两个端口:42803(调试端口,发CNXN回STLS)与37115(TCP 可连但发CNXN后 4 秒零回应,符合配对服务特征)。对37115发STLS同样零回应,用 6 位投屏码做adb pair也无响应 ⇒投屏码不是 ADB 配对码。

一个容易踩的排查提醒:ADB 消息头是24 字节(cmd, arg0, arg1, data_length, data_crc32, magic,小端),只发 16 字节会让设备不回应,容易误判成「端口开着但不是 adbd」。做这类协议级排查时,字节长度本身就是第一嫌疑。

与 MT5879 的关键差异

这张对比表把 MT9655 的问题定位得非常清楚——两个平台虽然都是 TCL 国行、都需要 guard flavor,但 ADB 行为完全不同(来源:tcl-mt9655-cn.md):

项MT5879(已验证机型)MT9655(本机)
ADB 类型传统 adbd,明文 5555,弹「允许 USB 调试吗?」ADB over TLS(Android 11+ 无线调试),无弹窗
端口固定 5555每次开关都变,实测 34007 → 33837 → 40357 →42803
授权方式电视上点允许无配对码入口,无法授权
5555/5554/5037开全程 closed(连发两次CNXN均被强制STLS)
无障碍设置页可打开设置里没有该入口

要点总结:

  • 传统 adbd 的授权是「电视弹窗 → 人点允许」,脚本可以靠uiautomator+input tap自动完成(MT5879 笔记中就是这么自动同意多屏互动安装提示框的);而 MT9655 的无线调试授权走配对码 + 证书,电视侧没有任何入口展示配对码或接受新设备。
  • 端口每次重启都变,意味着即便找到了授权方法,工具也得先做端口发现;adb connect硬编码的 5555 直接出局。
  • 无障碍设置页不存在,则 Aerial 的 HOME 接管依赖的enabled_accessibility_services写入也无法通过设置界面手动完成(详见第六节)。

三、安装:多屏互动仍然可行,但下载地址必须是公网 URL

3.1 实测结果

aerial-guard.apkv1.14 一次通过(PROGRESS stage 3 → stage 5);standard版走stage 3 → stage 4(被 TCL 安装校验拒绝,原因见 MT5879 笔记中的系统校验链:PmStrategy拒绝 ADB/pm 安装、LauncherStrategy拒绝非平台签名的 HOME 声明包、ThridStrategy只放行系统应用发起的显式安装,而多屏互动作为 system uid 1000 的应用用PackageInstallersession 安装,恰好能过链)。

⚠与 MT5879 的做法不同:MT5879 文档用adb reverse tcp:8765 tcp:8765+http://127.0.0.1:8765/Aerial.apk。本机没有 ADB,做不了 reverse。实测电视不接受局域网http://<Mac IP>:<非标端口>/...的 URL——HTTP 服务日志里完全没有来自电视的请求(本机 macOS 防火墙为 disabled,已排除)。

改用公网可访问 URL即可成功,例如https://gh-proxy.com/https://github.com/pengchujin/aerial-tv/releases/download/v1.14/aerial-guard.apk。

⇒ 由此得出的改进建议:install.sh在没有 ADB 授权的场景下,把下载地址参数改成可配置的外网 URL,而不是默认走adb reverse。

3.2 协议实现:tools/tcast-push.py

这条安装链路的协议实现在 tools/tcast-push.py,文件头注释本身就是一份精炼的协议说明,与 T-Cast 协议文档 相互印证:

  • TCP 端口 6553;每条消息是「4 字节大端长度 + UTF-8 文本」,字段之间用>>分隔。
  • 握手:第一条消息发159>>1>>0(明文握手),电视回253>>1>>0以及一条159>>…设备信息。
  • 心跳:发150>>,电视回150>>YES;会话安静太久会被电视断开(源码中每 5 秒发一次心跳,电视约 20 秒无流量会断链)。
  • 安装指令:223>>INSTALL>>包名>>名字>>下载地址>>2>>versionCode>>大小MB>>>>>>>>apkPathMd5。来源填2(本地)并带上apkPathMd5,就会跳过商店查询,也跳过版本和签名检查,直接在电视右上角弹「多屏互动:正在发起应用推送,同意后将接收应用并进行安装 [拒绝] [同意]」。
  • 回复:223>>INSTALL>>…>>confirm_pending|denied;同意之后会连续收到223>>PROGRESS>>包名>>名字>>阶段>>百分比>>…,阶段 1 是下载中、3 是安装中、5 是装好了、2 是失败。

脚本用法与源码行为对照如下:

tools/tcast-push.py <tv-ip> <url> <package> <label> <versionCode> [timeout-seconds]
# tools/tcast-push.py(节选,L49-L98 的核心逻辑) sock = socket.create_connection((tv, PORT), timeout=5) # PORT = 6553 sock.settimeout(1) send(sock, "159>>1>>0") # 明文握手 path_md5 = hashlib.md5(url.encode()).hexdigest() send(sock, ">>".join(["223", "INSTALL", package, label, url, "2", version, "20", "", "", "", path_md5])) # 之后进入循环:解析 INSTALL/PROGRESS 消息,stage 5 返回 0(装好)、stage 2 返回 1(失败) # 每 5 秒补发 "150>>" 心跳,防止电视断开安静会话(会话一断,进行中的安装也会丢)

两个值得注意的实现细节:

  1. tcast_install()在 tools/install.sh 中的完整形态是:先nc -z探活 6553 端口,本机起一个只绑127.0.0.1:8765的python3 -m http.server,再adb reverse tcp:8765 tcp:8765把电视的127.0.0.1:8765转发到本机服务,电视下载的就是http://127.0.0.1:8765/Aerial.apk,不需要在局域网上开端口。MT9655 恰好卡在这一步——没有 ADB 就没有 reverse,且实测电视不请求局域网非标端口,于是只能换成公网 URL。
  2. 多屏互动的安装提示框默认焦点在「拒绝」上,遥控器要先按「右」再按 OK(T-Cast 协议文档 列为必踩坑之一)。

3.3 加密握手模式(扩展)

T-Cast 协议文档 还记录了第二种握手格式:

159>><clientName>>1>><clientId>>1

电视回包的第 6 个字段是algorithm,当它= 1时,之后所有消息(收与发)都是 AES 加密的:

参数值
算法AES-128-CBC,PKCS7 填充
keytnscreentnscreen(16 字节 ASCII)
IV字节1234567890abcdef1234567890abcdef(不是这串 ASCII 文本本身,而是其十六进制解码)

实测中用明文发指令也能被电视接受(223>>INSTALL明文发送照样成功),但此时回包是密文,需要用上面的 key/IV 解密才能看懂;解密时不要重复调finalize(),否则会抛异常被吞掉、误判成「密钥不对」。对只需要安装/截图/按键的用途,走159>>1>>0明文握手即可。

四、设置面板测绘:9 个分类,没有无障碍

com.tcl.settings/.ui.MainActivity打开左侧悬浮面板,共 9 类:图像 / 声音 / 网络 / 蓝牙 / 信号源 / AI智能 / 通用 / 个性化 / 关于。逐类翻查的结论:

  • 通用= 语言、位置、输入法、开关机设置、快捷指令、呼吸灯、气泡说明 →无无障碍;
  • 个性化主题= 桌面壁纸(选取壁纸)、氛围屏保(「选取屏保」为禁用态,与「屏保时间=关闭」联动)、屏保时间;
  • 关于本机= 电视名称、本机信息、网络信息、软件更新。

223>>GET解出只有12 个可启动应用:云视听小电视、天气预报、应用商店、多屏互动、影视仓、用户中心、机顶盒设置、com.tcl.settings(设置)、app.orchard.tv(Aerial)、VidHub、媒体中心、网易云音乐。

⚠每次新建 TCP 连接都会让 TCL 侧边设置面板自动关闭(相当于「手机已连接」提示抢焦点)。所以「打开设置 → 按键导航 → 截图确认」必须在同一个连接里一口气跑完,否则按键会全部落到桌面上。这是无 ADB 诊断流程中最容易翻车的点。

五、无 ADB 时的补救:T-Cast 6553 的高级指令

多屏互动除了223>>INSTALL,还支持更多指令(完整协议与加密协商见 docs/tcast-protocol.md):

指令作用本机实测
263>><1 activity / 2 broadcast>><intentJSON>发任意 Intent(等于远程am start),可指定component{pkg,cls}✅ 拉起app.orchard.tv/.MainActivity成功
225>>电视截图,回包带图片 URL✅ 可拿到 89 KB PNG(视频层截不到,字幕/时钟可见)
149>><keyCode>模拟遥控按键(up=11/down=12/left=13/right=14/ok=15/back=16/menu=18/home=19)✅ 可用于盲导航
223>>GET应用列表(回包按>切分,每条包名::显示名)✅ 解出 12 个应用

协议文档中的完整指令表还包括:223>>OPEN>><包名>(启动应用,只接受包名,不接受 component)、151>>x>>y(鼠标移动)、155>><text>(IME 文本注入)、280>>2 / 280>>3(亮度)、242>>(系统音量)、160>><imei>><name>(连接提示);149的 keyCode 完整映射为 up=11 down=12 left=13 right=14 ok=15 back=16 menu=18 home=19 power=20 vol_up=21 mute=23 source=29 enter=68,数字 1-9 = 1-9、0 = 10。

263的 Intent JSON 字段格式:

{ "action": "android.intent.action.MAIN", "category": null, "component": { "pkg": "app.orchard.tv", "cls": "app.orchard.tv.MainActivity" }, "extraList": [ { "type": 0, "key": "k", "value": "v" } ], "flagList": [268435456], "launchType": 1 }
  • extraList的type:0=String、1=int、2=boolean
  • flagList常用268435456(FLAG_ACTIVITY_NEW_TASK)
  • launchType:0=service/window、1=activity

⚠ 实测关键限制:component置null走 action-only 时,电视似乎不派发(android.settings.SETTINGS、android.settings.ACCESSIBILITY_SETTINGS均无反应)。要拉起具体页面必须指定 component,而这需要先知道固件里真实的包名/类名(可用223>>GET拿)。

这套指令组合起来就是完整的无 ADB 远程诊断能力:225截图看画面 →263发 Intent 打开目标页面 →149盲导航 → 再225确认。但也必须明确其边界——仍无法替代 ADB:无障碍开关、appops 自启动放行、screensaver_components屏保组件替换,这三样都需要 shell 权限(在 tools/install.sh 中对应的正是settings put secure enabled_accessibility_services、appops set APP_AUTO_START、settings put secure screensaver_components这几条adb shell命令)。

六、仍未解决:无障碍入口 + 无授权 ADB 构成的死锁

现状:无障碍入口被固件删除 ⇒ 无法手动开启「Aerial 桌面守护」;ADB 又是 TLS-only 且无授权通道 ⇒ 死锁。现状:Aerial 只能当普通 App 用(点图标进,按 HOME 回 TCL 桌面)。

对照源码可以精确描述这个死锁的两侧:

  • 接管侧:guardflavor 的 HOME 接管完全依赖无障碍服务 HomeGuardService。GuardSetup 的类注释说明了机制:需要WRITE_SECURE_SETTINGS(开发权限,tools/install.sh通过 ADB 授予,界面上无法申请)才能在系统把服务从启用列表移除后重新写回enabled_accessibility_services;rebindIfStalled()处理「已启用但没绑定」状态(先移除、1.5 秒后加回触发重新绑定)。这些操作在 MT9655 上全都够不到:没有 ADB 授不了权限,设置里又没有无障碍入口。
  • 屏保侧:install.sh会把secure screensaver_components换成app.orchard.tv/app.orchard.tv.dream.AerialDream并通过ConfigReceiver广播own_screensaver=true(配合 GuardSetup.keepScreensaver 的开机自检),同样需要 ADB。

已试过且无效的手段(避免重复排查):

  • adb pair/adb connect(含投屏码)
  • 自建 ADB-over-TLS 客户端自签证书
  • android.settings.SETTINGS/ACCESSIBILITY_SETTINGS(action-only 与指定 class 均无效)
  • com.android.settings/com.android.tv.settings(包不存在)
  • TCL 设置 9 个分类逐个翻查(无障碍不在其中,屏保只列自家内容)
  • 工厂菜单路径(信源 → 模拟接受 → 菜单 → 设置 → 显示 → 专业设定 → 对比度 → 数字键1950)未验证成功

待作者确认的三个问题

实测笔记以三个开放问题收尾,这也是该机型状态的最新边界:

  1. MT9655 平台是否有别的 ADB 入口?工厂菜单那条路径开出的是不是传统 adbd(明文 5555 + 弹窗授权)?
  2. 完全没有 ADB 时,guardflavor 是否还有其他接管 HOME 的可能(不依赖无障碍)?
  3. 需要补哪些 logcat /dumpsys才能定位授权通道?

七、给同平台排障者的要点清单

综合以上实测,针对「只开放 Android 11+ 无线调试、且无线调试无配对入口」这一类国行电视,可以沉淀出以下排查顺序:

  1. 先确认 ADB 形态:扫 30000–50000 端口,对候选端口发完整 24 字节的 ADBCNXN头。回STLS即 TLS-only 调试端口;回CNXN/AUTH才是传统 adbd。注意 24 字节头的完整性,否则会被误判成非 adbd。
  2. TLS-only 时不要指望adb pair/投屏码:配对服务端口对CNXN/STLS零回应、投屏码与 ADB 配对码不是同一套东西,这条路在 MT9655 上已封死。
  3. 安装改走多屏互动(6553):用tools/tcast-push.py或等效客户端,明文握手159>>1>>0+223>>INSTALL(source=2 + apkPathMd5),下载地址用公网 URL,5 秒一次心跳保活,电视端先按「右」再按 OK。
  4. 诊断用 263/225/149/223 组合:发 Intent 要带明确component(action-only 不派发);截图注意视频层是黑的(独立硬件图层,字幕与时钟可见);所有「打开设置 → 导航 → 截图」操作放在同一个 TCP 连接内完成。
  5. 明确接管依赖再下结论:guard flavor 的 HOME 接管链路是WRITE_SECURE_SETTINGS+ 无障碍服务 + 屏保组件替换,三者全要 shell 权限;固件删了无障碍入口且 ADB 无授权通道时,就是本文所述的死锁,当前唯一可用形态是普通 App。

适用前提与限制:本文全部结论基于雷鸟 55S595C Ultra(固件V8-0015T11-LF1V487)单台设备的实测,同平台不同固件的 ADB 形态与设置面板可能不同;T-Cast 6553 指令集来源于 TCL 多屏互动 5.30 的逆向(见 docs/tcast-protocol.md),不同固件版本的行为需要另行验证。

【免费下载链接】aerial-tv

给国产电视的一块干净桌面:参照 tvOS 设计的开源 Android TV 桌面,没有广告,开机自动接管。A tvOS-style launcher for Xiaomi, TCL and other China-market TVs.

项目地址:https://gitcode.com/gh_mirrors/ae/aerial-tv
点击查看免费下载

相关推荐

上一篇:Apereo CAS 指标存储(Simple):Micrometer 内存后端的回退机制与配置实战
下一篇:Win-ACME 完整指南:让 Windows 服务器 SSL 证书自动续期

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进