ShizuStore

Virtual Screen

lejw0925

0.2.0 · GitHub

Download APK
AI agents Android 13+ 2 weeks ago PolyForm-Noncommercial-1.0.0
423 ShizuStore
1.5k GitHub
37 Stars
53 MB Size

More about this app

Gives an AI agent its own Android display to launch and operate apps on while you keep using the main screen, with an on-phone MCP server, PiP progress and take-over control

Virtual Screen

Virtual Screen · 虚拟屏

A separate Android display for your agent. Your phone stays yours.

简体中文 · English

Release 0.2.0 Build Android 13+ PolyForm Noncommercial

Virtual Screen is an Android app that gives an AI agent an isolated virtual display and runs an authenticated MCP server on the phone. The agent can discover, launch, and operate apps on that display while you keep using the phone's main screen. You can view, take over, or stop an operation at any time.

PiP preview: the phone stays usable Permissions and backend screen Display and control screen MCP connection settings

Release 0.2.0

Download the APK for your architecture plus SHA256SUMS from GitHub Releases: virtual-screen-0.2.0-arm64-v8a.apk, virtual-screen-0.2.0-armeabi-v7a.apk, virtual-screen-0.2.0-x86_64.apk (emulators), or virtual-screen-0.2.0-universal.apk when the architecture is unknown. The app requires Android 13 (API 33) or later and either a working Root su or a running, authorized Shizuku / Stellar service. Device compatibility and background behavior can vary by ROM.

Features

  • Isolated virtual display. Agent launches and input are scoped to a display created by this app. Failed operations never fall back to the phone's main screen. Cross-display conflicts require phone approval before an app is restarted, or can be auto-approved via a Display & control switch.
  • Visible progress and takeover. PiP shows the remote display; PiP is read-only and can be turned off entirely in settings. Expand the app's full-screen preview or use the notification to take over locally, which revokes the remote control lease.
  • 19 MCP tools. Control, display, app, observation, input, and wait operations. Tree observations can skip screenshots; fresh observation IDs and session receipts reject stale operations and let clients check uncertain results without replaying input.
  • Root and Shizuku / Stellar. Both privilege backends share the virtual-display engine, MCP protocol, and input constraints; devices running Stellar automatically use its native API.
  • Flexible connections. Loopback, LAN, frpc, and Cloudflare Tunnel. MCP and tunnels start disabled; starting MCP restores the previously connected tunnel; credentials are stored in the app's private encrypted storage.
  • On-device settings. English, Simplified Chinese, and Traditional Chinese; light and dark themes, dynamic color, onboarding, and local activity logs.

Get Started

  1. Install the 0.2.0 APK and install a compatible Root manager or Shizuku / Stellar. If using Shizuku or Stellar, start its service first.

  2. Open Virtual Screen, select Root or Shizuku / Stellar under Permissions and backend, and grant access. Enable the app's accessibility service for node targeting and Unicode text editing. Allow notifications for approval and takeover actions, and PiP for automatic previews.

  3. Enable MCP. For a USB debugging connection, run this on the computer:

    adb forward tcp:8732 tcp:8732
    

    The default MCP endpoint is http://127.0.0.1:8732/mcp. Enable LAN access in settings for a computer on the same network, or configure frpc or Cloudflare Tunnel for public access.

  4. Put the phone-generated Bearer Token in your MCP client configuration:

    {
      "mcpServers": {
        "android-virtual-screen": {
          "type": "http",
          "url": "http://127.0.0.1:8732/mcp",
          "headers": {
            "Authorization": "Bearer <phone-generated-token>"
          }
        }
      }
    }
    
  5. The agent acquires exclusive control, creates a virtual display, discovers and launches an app, observes its nodes or screenshot, and performs actions. Release control when finished. See MCP integration for protocol details, tool parameters, and client-specific notes.

Use Case Diagram

flowchart LR
    owner[Phone owner]
    agent[AI agent / MCP client]
    subgraph app[Virtual Screen Android app]
        authorize([Select and authorize Root / Shizuku / Stellar])
        configure([Configure MCP and network access])
        approve([Approve control requests and app restarts])
        takeover([View preview, take over, or stop])
        authenticate([Authenticate with Bearer Token and discover tools])
        lease([Acquire / release exclusive control])
        manage([Create display and launch apps])
        observe([Read nodes / capture screenshots])
        operate([Perform display-scoped input])
    end
    owner --> authorize
    owner --> configure
    owner --> approve
    owner --> takeover
    agent --> authenticate
    agent --> lease
    agent --> manage
    agent --> observe
    agent --> operate
    configure -. optional .-> tunnel[frpc / Cloudflare Tunnel]
    takeover --> display[App on the virtual display]
    manage --> display
    observe --> display
    operate --> display

Architecture

flowchart TB
    client[AI agent / MCP client]
    subgraph phone[Android phone]
        subgraph app[Virtual Screen app]
            ui[Compose home, settings, and preview]
            service[Foreground service and runtime coordination]
            mcp[Ktor Streamable HTTP MCP]
            auth[Bearer auth, sessions, and request receipts]
            lease[Control leases, approvals, and observation checks]
            tools[19-tool MCP registry]
            session[VirtualScreenSessionManager]
            backend[VirtualScreenBackend interface]
            root[RootBackend / su process]
            shizuku[ShizukuBackend / UserService or Stellar native API]
            engine[Shared PrivilegedDisplayEngine]
            display[Android virtual display and target app]
            access[Accessibility node service]
            preview[Surface mirror and PiP / full-screen preview]
            tunnel[TunnelManager]
            frpc[Bundled frpc / cloudflared]
        end
    end
    client -->|HTTP + Bearer Token| mcp
    mcp --> auth --> tools --> lease --> session
    ui --> service
    service --> mcp
    service --> tunnel --> frpc
    session --> backend
    backend --> root --> engine
    backend --> shizuku --> engine
    engine --> display
    access --> session
    display --> preview
    owner[Phone owner] --> ui
    owner -->|Local takeover| preview
    frpc -. tunnel connection .-> client

Security and Behavior Boundaries

  • All remote MCP requests require a Bearer Token. Rotating it invalidates old tokens. Do not commit tokens or put them in logs or public messages.
  • Device operations require an exclusive lease owned by the current session. Each authorized operation extends its five-minute idle deadline. Expired leases, stale observations, and ambiguous selectors are rejected.
  • Input is restricted to the virtual display. Remote PiP only displays the screen; phone touch or notification takeover revokes the remote lease. An agent cannot approve permission dialogs on the phone's main display.
  • MCP and tunnels start disabled. LAN and public tunnels increase network reachability; enable them only when needed and protect the client token.
  • Accessibility provides node access and assists text entry. Node features are limited without it. Multi-display, PiP, and background behavior varies across apps and ROMs.

Development and Validation

Use JDK 25 and Android SDK 37 (platforms;android-37.0, build-tools;37.0.0):

./gradlew :app:testDebugUnitTest :app:lintDebug :app:assembleDebug

Run the same full build used by GitHub Actions:

./gradlew --no-daemon :app:testDebugUnitTest :app:lintDebug :app:assembleDebug :app:assembleRelease :device-fixture:assembleDebug :app:assembleDebugAndroidTest

Actions run JVM tests, Lint, Debug / unsigned Release, fixture, and instrumentation APK builds on main, pull requests, and manual dispatch. A matching vX.Y.Z or vX.Y.Z-beta[.N] tag runs signing and publishes the APK with SHA256SUMS; beta tags become GitHub prereleases. Signing material stays in repository secrets. See Build and release for the toolchain and the pinned provenance and build steps for frpc / cloudflared.

See the changelog and 0.1.0 device report for current fixes and validation. The previous physical Android 17 / HyperOS 4 Root run passed all 19 tools; see Android 17 and home validation. Shizuku's Android 15 emulator results are in Beta backend comparison. See 1033 validation for continuous Cloudflare health checks and the 200-second background device test, and background connection validation for vendor freezing, the app-specific unrestricted battery setting, and screen-off testing while charging. Unplugged deep Doze and all ROM combinations remain untested. Historical results are in home layout validation and release validation.

Guide Contents
MCP integration Authentication, client setup, tools, leases, observations, and receipts
Public tunnels frpc, Cloudflare, credentials, and network requirements
Build and release Toolchain, native programs, signing, and GitHub Actions
Release validation Device coverage, measurements, and known limits
Getting started and testing Authorization and device validation workflows
Contributing Repository structure, conventions, tests, and security boundaries

Credits and License

Parts of the virtual-display engine are adapted from ETA. The UI uses Jetpack Compose Material 3; tunnels use frp and cloudflared. Tool design draws on research into Mobile Next, Android-MCP, android-remote-control-mcp, and PhoneUse.

Licensed under PolyForm Noncommercial 1.0.0 with upstream Required Notices preserved. See THIRD_PARTY_NOTICES.md for component licenses and native provenance.

Close

How Shizuku is used

Can create a second display and launch, view and control apps on it via `DisplayManager.createVirtualDisplay` through Shizuku

This is an AI-assisted analysis of Shizuku-related usages in the app's public source code. It is best effort, so it may not catch every single usage.

How this app uses Shizuku

Shizuku runs the virtual display engine with shell privileges so an AI agent gets its own display while you keep using the main screen.

  • Create second display: creates a separate virtual display with chosen size, density and rotation for the agent session.
  • Launch apps separately: starts supported apps directly on the virtual display, and can stop a conflicting instance on the phone first after confirmation.
  • Capture screen image: supplies the display surface and captures frames so the agent can observe screenshots and status.
  • Tap, swipe and keys: injects taps, long presses, multi point swipes, scrolls and key presses (including back) targeted at the virtual display with input injection.
  • Type text: pastes text into the focused editor on the virtual display through the clipboard plus key events.
  • Show live preview: mirrors the virtual display into a phone side viewer and can open it as a picture in picture window.
  • Rotate with apps: follows the top app orientation request and freezes the virtual display rotation to match.

Android APIs or commands used

  • DisplayManager.createVirtualDisplay
  • InputEvent.setDisplayId
  • InputManagerGlobal.injectInputEvent
  • IClipboard.setPrimaryClip
  • IClipboard.getPrimaryClip
  • IClipboard.clearPrimaryClip
  • IWindowManager.freezeDisplayRotation
  • IWindowManager.mirrorDisplay
  • IActivityTaskManager.registerTaskStackListener
  • ActivityTaskManager.getTasks
  • IActivityManager.startActivityAsUserWithFeature
  • ActivityThread.systemMain
  • PowerManager.newWakeLock
  • am start --display
  • am force-stop
  • input keyboard
  • settings get
  • settings put

Notable details

Reading the UI element tree still uses the accessibility service. Shizuku turns on the app's own accessibility service automatically via system settings, so no manual toggle is needed.

Close

Changelog

What's new for version 0.2.0

虚拟屏 0.2.0

界面重做与包体优化版本:首页改为双卡片布局,运行日志改为卡片式展示并统一到 Material 3 规范,安装包按 CPU 架构拆分后约 20 MB。要求 Android 13 或更新版本,并使用已授权的 Root 或 Shizuku / Stellar 后端。

主要更新

  • 安装包按架构分发:隧道二进制占安装包主要体积,现改为每个架构单独出包(arm64-v8a、armeabi-v7a、x86_64),并保留 universal 包供不确定架构时使用。单架构包约 20 MB,此前单包 98.8 MB。
  • 启用 R8 与资源压缩:Release 构建裁掉未使用的依赖代码,其中主要是整套 Material 图标(库内 11,100 个类,实际仅使用 46 个)。
  • 首页结构:移除大标题与页面级滚动,只保留卡片内部滚动;后端状态移到左上角,无障碍与设置合并为同一色调的图标按钮,边距与卡片对齐。
  • 运行日志:改为按条卡片展示,严重级别以右下角低透明度图标水印区分,类别、状态与客户端字段用只读 chip 呈现,chip 图标按内容选择;切换「全部 / 错误 / 警告」筛选时列表回到顶部,不再出现卡片盖住列表上方按钮。
  • Material 3 规范:新增独立的成功/警告语义色,修复警告级日志显示为绿色的问题;六处手写对话框改用 M3 对话框,恢复平台宽度约束、返回键与输入法避让;形状、动效改用主题 token,触摸目标补足 48dp;接入窗口尺寸类别约束正文宽度。

验证范围

  • JVM 单元测试 146 项、Android Lint、调试与正式版构建通过。
  • 模拟器(Android 14,Shizuku 后端)前台验证首页布局、日志卡片与筛选切换、浅色/深色模式及 200% 字号。
  • Release(R8)装机验证:19/19 后端检测通过,Cloudflare 快速隧道连通并 PUBLIC_ORIGIN_VERIFIED。
  • 单架构包与 universal 包的安装行为、Root / Shizuku 偏差及厂商 ROM 的后台策略仍需在更多真机回归。

说明

Android 10 起,targetSdk ≥ 29 的应用不能执行自身可写目录中的文件。因此隧道二进制无法改为首次运行时下载,必须由系统解压到 nativeLibraryDir 后执行。已在应用进程内做过对照验证:同一文件在 nativeLibraryDir 可正常执行,移动到应用私有目录后返回 EACCES。

Virtual Screen 0.2.0

A UI rework and package-size release: the home screen uses two cards, the activity log is card-based and aligned with Material 3, and APKs are split per CPU architecture at about 20 MB each. Requires Android 13+ and an authorized Root or Shizuku / Stellar backend.

Highlights

  • Per-architecture APKs: the bundled tunnel binaries account for most of the download, so releases now ship separate arm64-v8a, armeabi-v7a, and x86_64 packages, plus a universal package when the architecture is unknown. A single-architecture APK is about 20 MB, down from 98.8 MB.
  • R8 and resource shrinking: release builds strip unused dependency code, dominated by the full Material icon set (11,100 classes shipped, 46 used).
  • Home screen: the large title and page-level scrolling are gone; only the card interior scrolls. Backend status moved to the top-left, and accessibility plus settings share one tonal icon-button treatment aligned with the card margins.
  • Activity log: entries are tonal cards. Severity is a low-opacity watermark in the bottom-right corner, and category, status, and client fields are read-only chips whose glyphs follow their content. Switching the All / Errors / Warnings filter resets the list to the top, so entries no longer draw over the buttons above.
  • Material 3: success and warning now have dedicated semantic colors, so warning entries no longer render green. Six hand-written dialogs moved to M3 dialogs, restoring the platform width limit, back handling, and IME insets. Shapes and motion use theme tokens, touch targets reach 48dp, and content width follows window size classes.

Validation

  • 146 JVM unit tests, Android Lint, and debug plus release builds pass.
  • Emulator foreground checks (Android 14, Shizuku backend): home layout, log cards and filter switching, light and dark themes, and 200% font scale.
  • Release (R8) on device: all 19 backend probe tools passed, and a Cloudflare quick tunnel connected with PUBLIC_ORIGIN_VERIFIED.
  • Install behavior of the split and universal APKs, Root / Shizuku differences, and vendor background policies still need regression coverage on more physical devices.

Note

Since Android 10, apps targeting API 29+ cannot execute files from their own writable directories. The tunnel binaries therefore cannot be downloaded on first run; they must be extracted to nativeLibraryDir by the system. Verified inside the app process: the same file executes from nativeLibraryDir but returns EACCES from app-private storage.

Close

Permissions

10 permissions requested

  • android.permission.INTERNET
  • android.permission.ACCESS_NETWORK_STATE
  • android.permission.POST_NOTIFICATIONS
  • android.permission.POST_PROMOTED_NOTIFICATIONS
  • android.permission.FOREGROUND_SERVICE
  • android.permission.FOREGROUND_SERVICE_SPECIAL_USE
  • android.permission.WAKE_LOCK
  • android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
  • io.github.lejw0925.virtualscreen.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION
  • moe.shizuku.manager.permission.API_V23
Close

Sources

4 sources

0.2.0 Universal GitHub · io.github.lejw0925.virtualscreen
Selected Download
0.2.0 arm64-v8a GitHub · io.github.lejw0925.virtualscreen
Download
0.2.0 armeabi-v7a GitHub · io.github.lejw0925.virtualscreen
Download
0.2.0 x86_64 GitHub · io.github.lejw0925.virtualscreen
Download