In modern multi-device ecosystems, cross-device integration has evolved far beyond basic screen mirroring. With the introduction of the Virtual Device Manager (VDM) framework in Android 13 and expanded in Android 14 and 15, Android smartphones can stream individual application windows directly to companion displays—such as ChromeOS Chromebooks, Windows PCs running Microsoft Phone Link, automotive infotainment screens, and standalone virtual reality headsets. Rather than mirroring the entire device interface, VDM creates isolated, synthetic virtual displays, routes dedicated touch and keyboard input streams, and redirects audio output independently of the physical smartphone screen.
When cross-device app streaming freezes, virtual keyboards fail to transmit keystrokes, or multi-display permissions block apps from launching on external screens, developers and system engineers can query internal subsystem state using Android Debug Bridge (ADB). The dumpsys virtualdevice command provides full observability into active virtual device instances, assigned virtual display IDs, client owner packages, and input device mappings. This guide covers how the Virtual Device Manager operates, how to inspect streaming sessions, and how to troubleshoot virtual display errors.
Understanding the Virtual Device Manager (VDM) Architecture
Operating inside the Android system server, the Virtual Device Manager (VirtualDeviceManagerService) manages synthetic hardware instances on behalf of privileged companion applications (such as Google Cross-Device Services or Microsoft Link to Windows):
- Synthetic Virtual Device Abstraction: Each connected external companion is represented as a distinct virtual device entity carrying a unique device ID, client owner UID, and custom device policy flags.
- Virtual Display Allocation: VDM coordinates with SurfaceFlinger and the Display Manager to provision headless virtual displays (e.g.,
Display ID: 2). These displays render application surfaces into hardware video encoding pipes (such as WebRTC or H.264 streams) sent over local Wi-Fi or USB. - Isolated Input Injection: Rather than injecting global touch events, VDM registers synthetic touchscreens, virtual mice, and virtual keyboards bound strictly to the specific virtual display ID. Keystrokes typed on a PC keyboard land solely inside the streamed app without affecting physical phone inputs.
- Audio and Sensor Redirection: Audio flinger output generated by streamed apps can be routed directly to the companion device speakers while the primary phone continues playing notifications through its internal speaker.
Dumping Virtual Device Manager State via ADB
To inspect the status of active virtual devices and app streaming sessions, connect your Android device with USB debugging enabled and open a terminal console. Query the service using dumpsys virtualdevice:
# Dump complete virtual device manager diagnostic state
adb shell dumpsys virtualdevice
The console output produces structured diagnostic logs detailing registered virtual devices, client owner packages, virtual display bindings, and synthetic input devices:
VirtualDeviceManagerService:
============================
Virtual Devices Count: 1
Virtual Device ID: 1
Owner Package: com.google.android.apps.bettertogether.setup (Cross-Device Services)
Owner UID: 10145
Name: "Pixel-Chromebook-Stream"
Created Timestamp: 2026-11-08 04:15:10.420
Virtual Displays:
Display ID: 3 (Flags: FLAG_PRIVATE | FLAG_PRESENTATION)
Resolution: 1920x1080 @ 60Hz (DPI: 320)
Surface: Surface(name=VirtualDevice_Surface_1)/@0x45a810
Virtual Input Devices:
Touchscreen ID: 14 (Mapped to Display ID: 3)
Keyboard ID: 15 (Mapped to Display ID: 3)
Mouse ID: 16 (Mapped to Display ID: 3)
Device Policies:
POLICY_TYPE_RECENTS: VIRTUAL
POLICY_TYPE_ACTIVITY: VIRTUAL
POLICY_TYPE_CLIPBOARD: SHARED
Inspecting Active Virtual Displays and Dimensions
Under the active virtual device section, review the Virtual Displays block. Key indicators to check include:
- Display ID: The integer identifier assigned by the Display Manager. The primary smartphone display is always
Display ID: 0; streaming displays typically receive dynamic IDs like2or3. - Resolution and DPI: Displays the canvas width, height, refresh rate, and pixel density negotiated with the companion client. Mismatched DPI can cause streamed apps to render oversized tablet UI or tiny unreadable phone layouts.
- Surface: Confirms whether the underlying graphics pipeline has bound an active hardware composition surface to the virtual display buffer.
To verify the display orientation and active tasks running on that virtual display, cross-reference with the activity manager:
# Inspect activities and stack tasks running on Display ID 3
adb shell dumpsys activity displays | grep -A 10 "Display #3"
Auditing Synthetic Virtual Input Devices
When typing or clicking inside a streamed application on a PC fails to register, inspect the Virtual Input Devices section of the dump:
# Filter output to inspect virtual input mappings
adb shell dumpsys virtualdevice | grep -A 8 "Virtual Input Devices:"
Verify that:
- Every virtual input controller (Touchscreen, Keyboard, Mouse) is correctly mapped to the target
Display ID. If an input controller is mapped toDisplay ID: 0instead of the virtual screen, touch gestures will erroneously trigger on the physical phone screen. - The synthetic input drivers match the companion hardware capabilities.
Inspecting Device Policies and Cross-Device Permissions
The Device Policies section dictates how the virtual device interacts with system-wide features:
POLICY_TYPE_RECENTS: Governs whether apps launched on the virtual display appear in the main phone’s recent apps switcher or remain isolated to the companion device.POLICY_TYPE_CLIPBOARD: Indicates whether copy-paste buffers are shared seamlessly between the streamed app and the physical phone.POLICY_TYPE_ACTIVITY: Controls whether non-resizable or orientation-locked apps are permitted to launch on the external virtual canvas.
Testing App Launches on Virtual Displays via ADB
You can test whether a specific application supports multi-display streaming by manually launching an activity onto the virtual display ID:
# Force launch an application onto virtual Display ID 3
adb shell am start -n com.example.app/.MainActivity --display 3
If the application immediately crashes or bounces back to the primary display, inspect logcat for SecurityException: Activity not permitted on display. This indicates that the app declared android:resizeableActivity="false" or lacks multi-display compatibility flags.
Troubleshooting Common Virtual Device and Streaming Issues
When diagnosing cross-device streaming failures, watch out for these common bottlenecks:
- Black Screen on Companion Client: If the streaming window opens on the PC or Chromebook but displays a completely black screen, verify whether the app is playing DRM-protected media or has enabled
FLAG_SECURE(preventing screenshots and external display captures). DRM and banking apps cannot be streamed over standard virtual displays. - Stale Virtual Device Handles: If an external connection drops abruptly without deregistering, orphan virtual displays may persist in memory. Disconnect the companion app or force-stop the owner package to clear stale virtual devices:
# Force-stop Cross-Device Services to clear zombie virtual displays adb shell am force-stop com.google.android.apps.bettertogether.setup - SurfaceFlinger Encoding Glitches: If streamed video stutters or drops frames, inspect
adb shell dumpsys SurfaceFlinger --latencyto evaluate hardware video encoder queue latencies.
By regularly inspecting dumpsys virtualdevice, developers and engineers can diagnose multi-display rendering pipelines, ensure robust input injection, and optimize modern cross-device app streaming architectures.