Skip to content

[RFC] Shizuku/ADB 本机 Android 虚拟桌面输入源方案 #40

Open

Description

@fython

背景与范围

希望在 WheelPlay 中新增“Android 虚拟桌面”输入源:在宿主手机上创建独立虚拟显示屏,启动本机应用,将画面输出到车机浏览器,并将浏览器触控、按键返回到该显示屏。复用 #28 的多输入源框架,独立跟踪其中 Android 桌面方向的工作。

本 Issue 仅记录方案与后续实施计划,不在当前 PR #39 或分支 feat/28-android-projection 中实现,不作为该 PR 的合并前提。后续基于届时主线另开分支/PR。

术语说明:本讨论中的“AVD”指本机 Android 虚拟显示/桌面。它不是 Android Studio 的 Android Virtual Device 模拟器,不启动第二套 Android 系统,也不提供独立用户或应用数据隔离。

目标与用户体验

  • 输入源列表新增独立的 Android 虚拟桌面卡片;打开卡片只进入二级设置页。
  • 首次使用:检测 Shizuku → 引导安装/启动 → 用户授权 WheelPlay → 选择应用或桌面 → 启动投影。
  • 已授权且 Shizuku 正在运行时,能够从二级页直接启动。
  • 展示未安装、未启动、未授权、设备不支持、正在准备、已连接及连接失败等真实状态。
  • 未满足依赖时,在停止当前输入源前拒绝切换;不影响 CarPlay、Android Auto 的独立使用。
  • 不承诺任意应用都支持副屏,也不承诺手机主屏操作完全不受影响;应用任务复用、焦点、横竖屏与锁屏行为须实测。

技术路线:Shizuku 优先,ADB 作为可选后端

优先使用 Shizuku UserService 承载 WheelPlay 的特权辅助进程。WheelPlay 不自行维护 ADB 配对、密钥、网络连接或辅助进程的 ADB 启动流程,但仍负责辅助进程本身的功能和清理。

组件 职责
Shizuku 用户授权、提供 shell/root 执行身份、启动及绑定 UserService
WheelPlay 主进程 输入源注册与状态、会话仲裁、公共视频输出、浏览器控制租约及 UI
WheelPlay UserService 创建/销毁虚拟显示屏、在目标显示屏启动应用、注入触控及按键、报告显示布局与失败
可选 ADB 启动后端 在后续确有需求时,通过用户授权的 ADB 启动同类辅助进程;不作为 Shizuku 首版必做项

抽象“特权后端的可用性、连接、能力、停止”接口,将 Shizuku 与将来的直接 ADB 接入方式留在 Android 平台层。共享多输入源接口不携带 Shizuku Binder 或 ADB 类型。

Shizuku 的 Binder 包装适合简单远程调用,本方案涉及持续持有显示屏和输入状态,优先 UserService。它不是常规 Android 应用进程,不能假设普通 Service/Context 的所有 API 都能工作;需针对实际系统服务与版本做适配。

权限与 API 边界

  1. 默认验证 shell 身份 + DisplayManager/VirtualDisplay + 显示屏定向输入 的路线,可参考 scrcpy 的虚拟显示实现。
  2. Shizuku 经无线调试启动通常提供 shell(UID 2000)身份;root 模式是不同能力,必须实际探测,不将 shell 当成 root。
  3. 不把 VirtualDeviceManager 的创建能力作为普通手机前提。 类可见不等于创建接口对普通 App 开放;CREATE_VIRTUAL_DEVICE、系统角色和伴生关联等限制,不会因为接入 Shizuku 就自动消失。
  4. 系统集成或定制设备可另评估 VDM 后端,独立报告其权限和兼容性。
  5. 官方 Shizuku 说明:非 root 启动在重启后通常需要再次启动;Android 11+ 可使用本机无线调试。UI 要表达这一恢复步骤,不能承诺永久授权后一劳永逸。
  6. 同时验证厂商对 shell 输入注入和后台进程的额外限制;受保护画面与禁止副屏的应用按不支持处理,不以黑屏假装投影成功。

视频、输入与框架接入

视频

建议的数据流:

本机应用
  → UserService 创建的 VirtualDisplay
  → Binder 传入的 Surface
  → WheelPlay 公共画面/编码管线
  → WebRTC 或图像兼容输出
  → 车机浏览器
  • 主进程创建并管理输出 Surface 的生命周期,通过 Binder 传递 Surface 句柄;不通过 Binder 逐帧传输 Bitmap 或大字节数组。
  • 优先验证现有 Surface 视频入口;若需要新增 Surface/EGL → MediaCodec 编码能力,应放在公共 Android 视频管线中,并明确 WebRTC 与图像回退的分流方式。
  • 分辨率、DPI、旋转、内容区域及布局版本是会话状态;输入映射与实际显示布局一致。
  • 首帧、编码配置、浏览器输出就绪分别确认;仅创建显示屏成功不能判定投影可用。
  • 动态尺寸、屏幕休眠、前后台切换和慢浏览器都要验证;队列必须有界。

触控与控制

浏览器输入
  → 公共控制租约/会话校验
  → 虚拟桌面适配器
  → UserService
  → 指定 displayId 的输入事件
  • 首版覆盖单指/多指触控、返回键;Home 的行为与应用选择器/Launcher 方案一起验证。
  • 严格区分目标虚拟屏与手机主屏,禁止因 displayId 丢失而默认为主屏。
  • 为每次会话绑定代次、布局版本和显示屏所有权;拒绝旧会话的迟到输入。
  • 旋转、切源、控制租约失效及断连时释放全部触点/按键;不能丢失抬手事件。
  • 键盘、文本提交、剪贴板和鼠标作为后续能力,不将按键注入等同于完整中文输入支持。

应用与桌面

  • 首个验证目标为在虚拟显示屏启动一个指定应用,完成画面和触控闭环。
  • 然后提供本机应用选择器;按实际可启动 Activity 与系统查询规则列出应用。
  • 如目标设备没有可用的副屏 Launcher,评估自有轻量桌面或显式启动指定 Launcher。
  • 验证应用已在主屏运行、单任务应用、弹窗、权限界面、软键盘及退出后的任务去向;这是共享同一 Android 系统,不是独立应用实例保证。

音频与麦克风

视频和触控 MVP 不承诺浏览器音频或麦克风注入。初期可明确使用本机原有音频行为,并在能力中关闭尚未实现的浏览器音频/麦克风。

后续独立验证目标应用音频捕获、焦点、路由及麦克风;有 shell 权限或虚拟屏,不代表自动具备每应用音频隔离与麦克风注入能力。

生命周期与进程通信

  • 可用性检查只检测,不创建显示屏或启动应用;仅用户启动且运行时接纳会话后执行这些动作。
  • 控制 IPC 使用有版本的 AIDL/Binder 契约,限定创建会话、启动所选应用、输入和停止等操作,不暴露任意 shell 命令执行入口。
  • 校验调用方与会话所有权;主进程退出后,辅助进程通过客户端 Binder 死亡通知释放显示屏和输入状态。
  • 区分 Shizuku 服务断开、UserService 崩溃、授权撤销及主进程死亡;不能只依赖 Activity.onDestroy。
  • 正常停止顺序:停止接收新输入 → 释放手势/按键 → 停止虚拟屏 producer 并确认释放 → 释放 Surface/编码器 → 解除资源占用。
  • 清理失败不得宣称切源完成;恢复时创建新会话,拒绝旧 Binder 回调。
  • 显式实现 UserService 的销毁与退出,验证 unbind 后没有残留进程/显示屏;按 Shizuku 契约处理服务版本和应用升级。

分阶段实施

  • P0:真机可行性验证。选择代表性 Android 版本/设备,使用 shell 模式 Shizuku,验证 UserService、Surface 跨进程传递、虚拟屏创建、应用启动和输入注入;记录需要的厂商设置及最低支持范围。
  • P1:独立输入源 MVP。接入公共会话,完成单虚拟屏、应用选择、视频、触控/返回及明确的不可用状态;首版使用固定尺寸,声明真实音频能力。
  • P2:生命周期与交互完善。验证切源、Binder 死亡、授权撤销、升级、重启恢复、旋转/DPI、输入法及桌面/任务行为。
  • P3:可选扩展。依据实测结果增加浏览器音频、键盘/文本、动态尺寸;有需求再添加直接 ADB 启动后端或系统 VDM 后端。

验收标准

  • 无 Shizuku、未启动、拒绝授权时有清晰说明,且不会拆掉当前 CarPlay/AA 会话。
  • 至少一台未 root 的目标设备,使用 Shizuku shell 模式运行指定本机应用,并从浏览器看到独立虚拟屏、完成触控与返回。
  • 输入不会错误注入主屏;旋转、失焦、断网与切源不会留下卡住的触点。
  • 手机主屏同时操作、锁屏/解锁及同一应用跨屏行为有明确兼容性记录。
  • 停止、Shizuku/UserService/主进程异常退出后,不遗留虚拟屏、编码器、输入状态或不可控后台任务。
  • 重启后能引导恢复 Shizuku;应用升级不会继续绑定旧版本辅助服务。
  • 与 CarPlay、AA 来回切换正常,公共浏览器输出和图像回退行为不退化。
  • 记录设备/系统版本、Shizuku 版本与身份、分辨率/DPI、浏览器、首帧时间、延迟、CPU/内存及持续运行表现;未验证能力保持不支持或实验性。

参考资料

以上为设计与待验证事项,尚未在 WheelPlay 实现或完成真机验证。实施时应固定实际参考版本。

Activity

  1. fython commented on Oct 26, 2026

    @fython
    OwnerAuthor

    同步实施进展:PR #52 已于 2026-10-26 合并到 main,合并提交 ccd01f0。本 Issue 正文中的“尚未实现”是最初 RFC 的状态;当前已实现首版软件链路,但尚未完成真机验收,Issue 仍应保持开放。

    已合并的实现:

    • 独立 Android 虚拟桌面输入源及二级设置页,包含 Shizuku 安装/启动入口、用户主动授权、可启动本机应用选择、启动/停止及状态提示。只打开卡片不会切源;Shizuku 缺失、未启动、未授权或应用不可用等预检查失败时保留当前输入源。设备级显示/输入能力仍需在实际启动时验证。
    • 使用 Shizuku UserService 创建单个独立 VirtualDisplay、在指定 displayId 启动所选应用并注入触控/Back;Android 平台层的 DesktopBackend / DesktopConnection 隔离 Shizuku,公共输入源接口不依赖 Binder/ADB。代码门槛为 Android 10+、Shizuku 服务 API 13+,固定依赖 13.1.5;这不是已经验证的设备支持范围。
    • 默认 1280×720、160 DPI;可保存宽高与 DPI,范围为宽高各 320–3840、总像素不超过 8,294,400、DPI 72–640。参数在下次启动生效;当前会话的布局固定。
    • 主进程创建 Surface,经 Binder 传句柄,由公共 Surface 输出链路提供 JPEG/WebP。显示创建、Surface 首帧和浏览器图像发布分开判断,未就绪时不开启输入;本源尚无 WebRTC 编码输出。
    • AIDL/实现统一位于 moe.feng.wheelplay.projection.desktop。v7 协议包含握手、启动配置、实际显示信息、会话状态快照、健康检查、只读查询、停止和销毁。配置/能力/状态结果使用 structured parcelable;高频 DesktopTouchFrame 与 DesktopStatus 保留自定义紧凑格式。控制调用返回固定错误码及独立诊断,触控使用 oneway,无逐帧响应。
    • 能力分为服务支持、连接协商和会话最终启用,支持请求/必需能力校验及只读降级;仅声明已实现的 Surface、触控、Back 和启动显示配置。支持最多 10 点触控;独立 cancelInput 与 Back 使用输入代次屏障,拒绝迟到旧输入,取消手势不合成 UP/点击。
    • 校验宿主 UID、会话 token、布局及显示所有权,输入不回退到主屏。加入有界输入队列、持续故障报告、客户端 Binder 死亡处理、健康看门狗、唯一服务绑定标识,以及等待助手退出后再释放主进程 Surface 的清理流程。
    • 上游框架同步引入取消输入、阶段/错误/清理状态、协作启动取消及超时机制。AA 使用原生 ACTION_CANCEL,VNC/CarPlay 明确标记 RELEASE_ONLY;插件 API v2 通过可选能力和末尾新增事务提供原生取消,旧插件继续兼容释放。浏览器和控制租约同步接入。

    验证证据:PR 最新提交 80ac0f6 的 Android Debug Build 已通过;PR 中记录了单元测试、浏览器测试、lint 和 arm64 Debug 构建结果。上述属于软件验证,不能代替设备上的真实显示、输入和清理验收。实现边界、固定参考版本及真机记录表见 ANDROID_DESKTOP.md。

    对照本 Issue,剩余工作如下:

    阶段 当前判断 剩余事项
    P0 真机可行性 未完成 至少一台非 root 设备,以 Shizuku shell 身份完成 UserService → Surface → 虚拟屏 → 指定应用 → 浏览器画面、触控和 Back 的闭环;记录厂商设置及实际支持范围。
    P1 独立源 MVP 软件链路已合并,尚未完成验收 真机确认状态引导、依赖失败保留旧源、首帧和浏览器输出、应用选择及触控/返回;验证与 CarPlay/AA 来回切换不退化。启动尺寸/DPI 设置已超出最初固定参数 MVP 的范围,但同样待实测。
    P2 生命周期与交互 机制部分已实现,设备验收未完成 验证停止、断网/失焦、切源、助手/宿主死亡、Shizuku 停止、授权撤销、升级与重启恢复;检查残留显示屏、进程、Surface/编码资源、触点及后台任务。补充主屏同时操作、同应用跨屏/单任务、弹窗、权限页、软键盘、锁屏和任务退出去向的兼容性记录。
    P3 可选扩展 未实现 根据实测与需求决定浏览器音频/麦克风、键盘/文本/剪贴板/鼠标、会话内动态尺寸/旋转/DPI、直接 ADB 或系统 VDM 后端。直接 ADB/VDM 并非 Shizuku 首版的完成前提。

    另有几项需要明确保留在后续范围:

    • 当前只有指定应用启动与应用选择器,尚无专用副屏 Launcher/轻量桌面,也没有 Home 能力;需结合目标设备评估。
    • 会话内旋转、尺寸或 DPI 改变时,当前策略是取消输入并停止,要求重新连接;不能把“启动前参数可设置”视为“动态布局已完成”。
    • 受保护内容可能产生黑帧,目前不能可靠识别画面语义。禁止副屏、DRM/受保护黑屏及任务重定向场景要记录为限制,不能仅以收到首帧判定应用兼容。
    • 尚缺设备/系统/Shizuku 身份与版本、浏览器、分辨率/DPI、首帧时间、端到端延迟、Binder 输入吞吐/延迟、CPU/内存及持续运行表现的实测记录。

    建议下一步优先完成 P0,并按文档记录 P1/P2 验收证据,再判断可关闭哪些验收项;不因 PR 合并而勾选全部验收标准。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions