Overview
Virtual Displays provide a mechanism to render Android UI into a memory buffer instead of directly outputting to physical hardware. This powerful concept underpins screen recording, screen casting, Android Auto, and secure secondary workspaces.
Rather than sending composed frames to the Hardware Composer (HWC), SurfaceFlinger renders the output of a Virtual Display into an Android Surface, which is backed by a BufferQueue.
Creating Virtual Displays via DisplayManager
The DisplayManager API provides the createVirtualDisplay method to construct a virtual display. The core requirement is providing a target Surface where the frames will be produced.
Basic Creation Flow
- Allocate a Surface: An application creates a
Surface. This typically comes from aSurfaceView, anImageReader, or aMediaCodecinput surface. - Invoke DisplayManager: The app calls
DisplayManager.createVirtualDisplay(), passing the target Surface, dimensions, density, and flags. - Display Adapter:
VirtualDisplayAdapterinside theDisplayManagerServicehandles the request and creates aLogicalDisplay. - Composition: SurfaceFlinger creates a virtual display token. During composition, it renders the layers assigned to this display into the provided Surface.
Java API Example
DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
// Suppose we have an ImageReader to capture frames
ImageReader imageReader = ImageReader.newInstance(1920, 1080, PixelFormat.RGBA_8888, 2);
Surface targetSurface = imageReader.getSurface();
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC |
DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
VirtualDisplay virtualDisplay = displayManager.createVirtualDisplay(
"MyVirtualDisplay",
1920, 1080, 320, // width, height, densityDpi
targetSurface,
flags
);
// The virtualDisplay object now represents a new display.
// Activities can be launched on it using ActivityOptions.
Use Cases: Recording, Casting, Secondary UIs
Virtual displays are highly versatile due to their configurable flags:
- Screen Recording & Casting: Using the
MediaProjectionAPI, an app can capture the contents of the primary display. The framework creates a virtual display that mirrors the main display, outputting frames to aMediaCodecSurface for video encoding. - Android Auto (Projection): The smartphone renders the automotive UI onto a virtual display. The resulting frames are encoded and streamed over USB or Wi-Fi to the car's head unit.
- Presentation Mode: Apps like presentation software can project a specialized UI onto a virtual display (which might be routed to a Miracast dongle) while keeping speaker notes on the phone's primary screen.
VirtualDisplay and MediaProjection API
The MediaProjection API is a specialized, secure wrapper around virtual displays specifically designed for screen capturing. Because capturing the user's screen has severe privacy implications, MediaProjection requires explicit user consent via a system dialog.
The MediaProjection Architecture
- Consent Request: The app launches the
MediaProjectionManager.createScreenCaptureIntent(). - System UI: System UI displays a permission dialog asking the user to grant screen recording rights.
- Token Generation: If granted, the system returns an
Intentcontaining a secure token. - Projection Start: The app retrieves a
MediaProjectionobject using the token. - Virtual Display Creation: The app uses
MediaProjection.createVirtualDisplay(). UnlikeDisplayManager.createVirtualDisplay, this method automatically configures the display to mirror the main screen and bypasses standard permission checks, relying instead on the user's explicit consent token.
Security and DRM
Virtual displays respect DRM protections. If a user is screen-recording, any SurfaceView configured with SurfaceView.setSecure(true) (often used for Widevine L1 protected video) will be blacked out in the virtual display output. SurfaceFlinger strictly enforces this rule during the composition phase, ensuring that protected content cannot be extracted via virtual displays.
To inspect active virtual displays, you can query SurfaceFlinger:
adb shell dumpsys SurfaceFlinger | grep -i "Virtual Display"