# CarClusterMirror **Repository Path**: zombies/car-cluster-mirror ## Basic Information - **Project Name**: CarClusterMirror - **Description**: 车机中控投仪表屏方案 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-10-15 - **Last Updated**: 2026-10-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Car Cluster Mirror · 仪表盘投屏 把**车机中控屏上当前打开的画面**整屏镜像到**仪表盘辅助屏**。 面向已 root、可用 adb 安装任意应用的车机(Android 9 系车机系统)。 > ⚠️ **使用前必读**:[DISCLAIMER.md](DISCLAIMER.md) > 本项目仅供个人自有车辆的学习与自用,需要 root 权限并会修改系统分区, > 可能导致保修失效甚至车机故障,风险自负。 --- ## ⚠️ 实测车型(先看这条) | 项目 | 内容 | |---|---| | **实测车型** | **长安 UNI-V 2022款 尊贵版** | | 车机系统 | 飞鱼 OS / Android 9 | | 测试结论 | 唯一实测通过的车型,可正常投屏 | > **除此之外的其它车型,本项目一律未做任何测试。** > > 不同车型 / 不同年款之间,车机系统版本、系统服务(尤其是"仪表投影"的握手协议)、 > 屏幕拓扑结构**可能存在本质差异**。本项目在其它车型上: > > - **可能完全无法使用**(找不到仪表盘屏、投不上去、黑屏); > - **也可能引发车机异常**(开机自检失败、服务冲突等)。 > > **请勿盲目套用。** 如要在其它车型上尝试,请先自行评估风险, > 并务必提前做好完整备份与回滚准备 > (见 `deploy/全新车完整安装教程.txt` 的备份 / 回滚章节)。 --- ## 🚀 要装车,只看这一个 → [`docs/安装指南.md`](docs/安装指南.md) 一页纸,两个脚本: | 脚本(在 `deploy\`) | 干什么 | |---|---| | `uninstall_all.bat` | **一键彻底清除**(恢复到"从没装过",可选) | | `install.bat` | **一键完整安装**(放 priv-app + 写 init 服务 + 装 App + 自动重启 + 自检) | ``` 双击 uninstall_all.bat → 输入 YES → 自动重启 (可选,只为干净验证) 双击 install.bat → 直接回车选默认 APK → 自动装完并重启(约 3 分钟) 车机上:切 U 盘模式 → 点【开始投屏】 (v1.37 起不用选引擎,界面已固定) ``` > ⚠️ **不能只装 APK。** 实测:App 执行 `/system/xbin/su` 被拒(`error=13 Permission denied`), > 所以必须保留「init 启动的 root 守护进程」。详见 [`docs/安装指南.md`](docs/安装指南.md) 开头。 > 🆕 **v1.37 起界面只保留能用的方案**:引擎选择器已移除(代码保留)。 > 实测「自动 / Root 帧流」可用、「直连镜像 / 媒体投影 / Root 截屏」不可用。 --- ## 📍 当前进度(2026-10-15) | 项 | 状态 | |---|---| | 当前版本 | **v1.37-only-ok**(versionCode 29,md5 `87e1cc5491eea7db6470ec7630baf3f7`) | | **v1.37 界面精简** | 按实测结果,**引擎选择器已从界面移除**(代码与降级链保留):
保留「自动 / Root 帧流」(同一段代码,走 root 守护进程)
移除「直连镜像 / 媒体投影」(虚拟显示帧全 0)、「Root 截屏」(App 无权执行 su) | | **★ 虚拟显示已定案作废** | 5 种 flag 变体 + 直连镜像(FLAG_SECURE) + 媒体投影,**全部** `alpha0=100% 首像素=0x00000000 判定=整块缓冲全 0(零填充,从未合成)`。
→ **与 flag 组合无关,本车拿不到画面。** 换 flag 救不回来 | | ⚠️ 已作废的旧结论(两条) | ① 「直连镜像有图 → 普通 AUTO_MIRROR 可用」——错,见上;
② 「`CAPTURE_SECURE_VIDEO_OUTPUT` 必须平台签名、拿不到」——**也错**,实测 `granted=true`。但拿到也没用,虚拟显示照样全黑 | | 实际能出图的(只有两条) | `root_socket`(守护进程 socket;**「自动」和「Root 帧流」是同一段代码**,`MainActivity:250`)
`root_capture`(`su` + `screencap` 循环)。实测 **10~14 fps**,瓶颈在采集侧 | | 另一发现 | 车机上两个同名包并存:`/data/app` v1.35,`/system/priv-app` 里那份**一直是 1.27** —— 热更新从没写进过 priv-app。排查:`deploy\check_dup_pkg.bat` | | **★ 安装方案(已修正)** | ⚠️ 上一版说的「只装一个 APK」**实测不成立,已撤回**:App 执行 `/system/xbin/su` 被拒(`error=13 Permission denied`),三条降级链全断。
→ **必须保留「init 启动的 root 守护进程」**,走完整安装:`deploy\install.bat` · [`docs/安装指南.md`](docs/安装指南.md) | | 想干净验证新版本 | `deploy\uninstall_all.bat` → [`docs/彻底清除与干净重装.md`](docs/彻底清除与干净重装.md) | | su 排查(只读) | `deploy\diag_su.bat`(查 App 的 SELinux 域 / su 标签 / avc denied) | | 背景资料(装车不需要看) | [`docs/本轮实车结论与下一步.md`](docs/本轮实车结论与下一步.md) · [`docs/实车验证清单.md`](docs/实车验证清单.md) | --- ## 目录结构 ``` ClusterMirror/ Android 工程(纯 Java,无 NDK) ├─ app/src/main/java/ 业务源码 ├─ gradlew / gradlew.bat └─ README.md 架构说明 / 双引擎 / 版本演进(先看这个) deploy/ 部署与安装 ├─ install_min.bat ★★ 新车最小安装(v1.36 新增):只装 APK,不碰 /system、不重启 ├─ uninstall_all.bat/.sh ★★ 彻底清除(v1.36 新增):恢复到"从没装过",用于干净验证新版本 │ 清 init.aee.rc 里的服务定义 / priv-app / 白名单 / 数据区包 / │ 应用数据 / 外部数据 / tmp 遗留;带备份 + 5 项校验 ├─ 全新车完整安装教程.txt ★ 从零装到一辆新车的完整流程(含边界情况、回滚) ├─ install.bat Windows 一键安装(自动 push → 安装 → 校验) ├─ install_new_car.sh 车机端一键安装脚本(真正干活的) ├─ update_app.bat / update_app.sh ★ 热更新(换 APK + 重启守护进程,不重启车机;bat 为单文件版) │ ★ v1.35 修时序:改成「你测完再取日志」,并补采 logcat │ ★ v1.36 加 priv-app 写入校验:cp 之后两端 md5sum 比对, │ 不一致直接报错(原先 ls -l 看不出 cp 静默失败) ├─ check_dup_pkg.bat ★★ 重复包 / priv-app 真实版本核对(v1.36 新增,只读) │ 装了几份 / 跑的是哪份 / priv-app 里那份真实 versionName(aapt2 读) ├─ recon.bat ★ 环境侦察(adb 模式下一次性采集所有关键环境信息,单文件) ├─ test_mp.bat ★★ 引擎对比 + 虚拟显示取证(v1.36 起 3 轮): │ 第1轮 直连镜像 / 第2轮 媒体投影 / 第3轮 虚拟显示取证(5 种 flag 各存一帧 PNG) ├─ collect_all.bat ★ 一键取证(只读不改):logcat/App日志/结论/首帧/环境快照/虚拟显示取证 ├─ logconv.py ★ 日志编码转换(v1.35 新增):UTF-8 → GBK,解决控制台中文乱码 ├─ diag_daemon.sh 守护进程状态诊断 ├─ fix_daemon_autostart.sh 老车自启修复(仅旧版安装需要) ├─ head.txt / 守护进程自启修复说明.txt ├─ start_app.bat 免密启动 App(adb shell 有密码门,需管道喂口令) └─ 【T2 实验】T2测试安装说明.txt / install_t2.bat / install_t2.sh collect_t2_log.bat(切回 adb 后取日志) 验证"安全虚拟显示能否替代守护进程"(三段式:装→U盘模式测→取日志) ※ 已被 test_mp.bat 取代,仅供对照 > 📌 **日志标记约定(v1.35 起,重要)** > App 侧所有关键日志的标记都是 **ASCII**,`findstr` / `grep` 可以直接匹配, > 不受控制台代码页影响(Android 日志是 UTF-8,Windows 控制台默认 GBK —— 用中文词永远匹配不到,踩过): > > | 标记 | 含义 | > |---|---| > | `[ENG]` | 引擎切换 / 启动 | > | `[CHK]` | 帧内容检测(平均亮度 / 黑色占比 / 判定) | > | `[FPS]` | 帧率(送帧 fps / 上屏 fps) | > | `[T2]` | 安全虚拟显示实验 + 无帧看门狗 | > | `[VDP]` | 虚拟显示取证(v1.36 新增:5 种 flag 各存一帧 PNG + 像素统计判定) | > | `[ERR]` | 异常 / 失败(原先是 `! ` 前缀) | > > 抓日志一行命令(adb 模式): > ```bat > adb shell logcat -d -s ClusterMirror/Log:V > ``` > ⚠️ **维护注意(重要,踩过坑)** > `deploy/` 与根目录下的 **`.bat` 文件是 GBK(cp936) 编码 + CRLF 行尾**,且内部用 `chcp 936`。 > 这是必须的,不要改成 UTF-8: > - 纯 LF 行尾 → cmd 报「命令语法不正确」; > - `chcp 65001` + UTF-8 中文 → cmd 重读批处理时字节错位,会把 `rem`/`echo` 行从中间截断, > 残段被当命令执行(实测复现)。 > > 因此:**不要用 UTF-8 编辑器直接改这些 .bat**。项目里带了一个转换器, > 改完(改 UTF-8 源文件)跑一次就自动归一化: > ```bash > python .tmp_test/to_gbk_bat.py deploy # UTF-8 → GBK + CRLF > ``` > 手工版: > ```bash > sed -i 's/chcp 65001 >nul/chcp 936 >nul/' x.bat > iconv -f UTF-8 -t GBK x.bat > x.gbk && mv x.gbk x.bat > sed -i 's/\r$//' x.bat && sed -i 's/$/\r/' x.bat > ``` > ⚠️ **还有一个坑(踩过两次)**:用 `sed -i` 或用 Python 的文本模式 > (`open(f, encoding='gbk')` 读 + `open(f,'w',newline='')` 写)改这些文件, > **会把 CRLF 弄丢**,之后 cmd 会再次报「命令语法不正确」。 > 正确写法是**按字节读写、显式写 CRLF**(见 `to_gbk_bat.py`)。 > 改完务必确认: > ```bash > od -c x.bat | grep -c '\r' # 应与行数相等 > ``` > 另外 GBK 不支持 `✅❌⚠★✔≥→` 等字符,正文里请用 `[OK]/[X]/[!]/*/>=/->` 代替。 docs/ 技术文档 ├─ 本轮实车结论与下一步.md ★★ 最新(2026-10-15):直连镜像出图 = 突破;日志取不到的三个根因;架构三种结局 ├─ 实车验证清单.md ★★ 实车操作总清单(你要做的全部事情,唯一权威版) ├─ 截屏链路评估与优化方案.md ★ 截屏成本拆解 + 备选捕获通道 + 录屏方案 + 验证计划 ├─ 去守护进程改造方案.md ★ 目标架构(App 内虚拟显示)+ 延迟归因 + 分阶段改造 ├─ 去特权化路径评估.md ★ 能否砍掉 priv-app/白名单/init.aee.rc/重启(含判定实验) ├─ JPEG传输改造与实车验证.md ★ v1.33 传输改造说明 + 实车验证步骤 + 回滚 ├─ 实车侦察结果与发现.md ★ 2026-10-15 实车侦察(含 userdebug/test-keys 重大发现) └─ 竞品分析_UNIV_ADB_Manager.md ★ 同类 App 架构对比(shell+ADB 路线 / JPEG 传输) clustermirror.rc init 服务定义(参考) install_privapp.bat priv-app 手工部署辅助脚本 privapp部署手册.txt / v1.26部署说明.txt 历史部署说明 ``` --- ## 快速开始 ### 1. 编译 前置:Android Studio + JDK 17/21 + Android SDK。 ```bat cd ClusterMirror gradlew.bat assembleDebug ``` 产物:`ClusterMirror\app\build\outputs\apk\debug\app-debug.apk` > 命令行直接编译时,`ClusterMirror\local.properties` 需要有一行 `sdk.dir=...` 指向你的 SDK。 > Android Studio 打开工程会自动生成;本项目未把它入库(每台机器路径不同)。 ### 2. 部署到车机 见 **`deploy/全新车完整安装教程.txt`**(完整版,含边界情况与回滚)。 最省事的方式: ```bat deploy\install.bat ``` 它会自动:推送文件 → 请求 root → 执行安装脚本 → 等待重启 → 校验守护进程状态。 --- ## 它是怎么工作的(一段话) 车机中控的画面要投到仪表盘,有一个绕不开的前提:**普通应用拿不到中控屏的合成帧** (系统级截图接口不对外,`MediaProjection` 在部分车机 ROM 上返回黑帧), 而仪表盘的 HDMI 管线**只转发应用窗口层**(不转发悬浮窗)。 所以本项目分成两部分,用的是同一个 APK: | 角色 | 说明 | |---|---| | **守护进程** | 由 `init` 以 root 身份开机启动,用系统截图接口抓中控整屏,经本地 TCP 回环推给 App | | **App** | 普通安装在数据区,用 `Presentation` 把画面显示到仪表盘辅助屏 | 详细的架构、双引擎、版本演进见 `ClusterMirror/README.md`。 --- ## 合规与免责 - 本项目需要车机 root 权限,**请自行通过合法途径获取**;本项目不提供、不鼓励任何绕过厂商安全机制的行为。 - 会修改系统分区与 init 服务定义,**可能导致保修失效或车机异常**,风险自负。 - 与任何汽车制造商、车机厂商、导航服务商**无关联**,未获其授权。文中商标归各自权利人所有。 - **禁止商业用途**,禁止用于非自有设备。**请勿在驾驶过程中操作**。 完整条款见 [DISCLAIMER.md](DISCLAIMER.md)。