Overview
Android's support for external displays spans a variety of connection protocols, from wired solutions like HDMI and DisplayPort (DP) over USB-C to wireless solutions like Miracast. Managing these displays requires coordination between the kernel DRM (Direct Rendering Manager) drivers, the Hardware Composer (HWC), SurfaceFlinger, and system services.
HDMI Display Connection Flow
When an HDMI display is plugged into an Android device, a sequence of events propagates from the hardware to the application layer.
- Kernel Layer: The DRM driver detects the hot-plug event (HPD: Hot Plug Detect). It reads the EDID (Extended Display Identification Data) from the monitor to determine supported resolutions, refresh rates, and color formats.
- Hardware Composer (HWC): The HWC HAL receives the hot-plug notification from the DRM driver.
- SurfaceFlinger: HWC notifies SurfaceFlinger via the
onHotplugcallback. SurfaceFlinger queries HWC for display attributes and allocates anIBindertoken representing the physical display. - DisplayManagerService (DMS): SurfaceFlinger notifies DMS via
ISurfaceComposerClient.LocalDisplayAdapterin DMS creates aPhysicalDisplayDeviceand maps it to aLogicalDisplay. - WindowManagerService (WMS): WMS is notified by DMS, creating a
DisplayContentstructure, allowing activities to be placed on the new display.
Diagnosing HDMI Connections
To view the raw EDID and connected display ports at the kernel level, you can use the dumpsys command targeting SurfaceFlinger:
adb shell dumpsys SurfaceFlinger --display
This output provides low-level details about active display tokens, active configurations, and color modes.
Miracast/WFD (WiFi Display)
Miracast (WiFi Display) allows mirroring or extending the Android UI over a Wi-Fi Direct connection. Unlike wired displays managed by HWC, Miracast heavily relies on the media framework and virtual displays.
- Connection: The
WifiDisplayControllermanages the P2P connection to the sink (receiver). - Virtual Display: Once connected, the framework creates a
VirtualDisplay. - Encoding Pipeline: SurfaceFlinger composites the UI for this virtual display into a
Surface. This Surface acts as an input toMediaCodec, which encodes the frames into an H.264/HEVC stream. - Transport: The encoded stream is sent over RTP/UDP to the Miracast sink.
Because this goes through the video encoder rather than direct hardware display planes, latency is naturally higher than wired connections.
DisplayPort over USB-C
Modern Android devices support DisplayPort Alternate Mode over USB-C. The stack is very similar to HDMI, but the physical connection negotiation differs.
- USB Power Delivery (PD) Controller: The USB-C port negotiates the "Alternate Mode" via the PD protocol.
- Mux Switching: Once DP Alt Mode is negotiated, a hardware mux routes the DisplayPort signals from the SoC's display controller directly to the USB-C pins.
- HWC Integration: From the perspective of the Display Controller and HWC, this looks identical to a native DisplayPort or HDMI connection. The DRM driver handles it as a standard external connector.
Hot-Plug Detection Architecture
Hot-plug detection (HPD) is critical for a seamless user experience. SurfaceFlinger manages HPD events through a dedicated thread to avoid blocking composition.
Native Code Snippet: HPD Event Handling
In the Android source, HWC reports events to SurfaceFlinger. Here is a simplified view of how SurfaceFlinger processes an HWC hot-plug event:
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::processDisplayHotplugEventsLocked() {
for (const auto& event : mPendingHotplugEvents) {
std::optional<DisplayId> displayId = event.hwcDisplayId;
if (event.connection == hal::Connection::CONNECTED) {
// Retrieve display information from HWC
auto info = getHwComposer().getDisplayInfo(*displayId);
// Create a physical display device
setupNewDisplayDeviceInternalLocked(token, std::move(info), ...);
} else {
// Handle disconnection, destroy DisplayDevice
processDisplayRemoved(token);
}
}
}
This asynchronous handling ensures that the primary UI on the built-in display does not freeze while the system queries the external display's capabilities and configures the composition layers.