Android Display 服务详解Android 的显示服务通常指DisplayManagerServiceDMS但它只是整条显示链路中的一个环节。下面按架构 → DMS 本身 → 周边服务 → 调用流程 → 应用 API → 调试的顺序展开。一、整体架构┌─────────────────────────────────────────────────────────┐ │ App 层 DisplayManager / Display / Presentation │ │ MediaProjection / SurfaceView / TextureView │ ├─────────────────────────────────────────────────────────┤ │ Framework DisplayManagerGlobal (客户端代理, 单例) │ │ ──────────────── Binder (IDisplayManager) ─────────── │ │ system_server: │ │ DisplayManagerService ── 管显示设备 │ │ WindowManagerService ── 管显示上的窗口 │ │ PowerManagerService / DisplayPowerController ── 管开关屏│ │ DisplayModeDirector ── 管刷新率/分辨率决策 │ ├─────────────────────────────────────────────────────────┤ │ Native SurfaceFlinger ── 图层合成、VSYNC、显示事件源 │ │ HWComposer (HWC2/HWC3 HAL) │ ├─────────────────────────────────────────────────────────┤ │ HAL/Kernel composer HAL → DPU/DSI/HDMI 驱动 → 屏幕面板 │ └─────────────────────────────────────────────────────────┘一个经典分工组件职责DisplayManagerService显示设备的增删、属性、模式、亮度、虚拟显示WindowManagerService窗口层级、焦点、动画、DisplayContentSurfaceFlinger图层合成、VSYNC、热插拔事件的源头DisplayPowerController屏幕电源状态ON/DOZE/OFF、超时熄屏DisplayModeDirector刷新率/分辨率投票决策二、DisplayManagerService2.1 启动与注册在SystemServer#startCoreServices()中启动mDisplayManagerServicemSystemServiceManager.startService(DisplayManagerService.class);onStart()里会做两件事publishBinderService(Context.DISPLAY_SERVICE,newBinderService());// 跨进程publishLocalService(DisplayManagerInternal.class,newLocalService());// system_server 内部Binder 服务名就是display应用getSystemService(DISPLAY_SERVICE)拿到的就是它。DisplayManagerInternal是 system_server 内部进程内接口WMS、PMS、StatusBar 等直接调用它避免走 Binder。2.2 核心数据结构类说明DisplayAdapter显示设备来源适配器负责发现设备LocalDisplayAdapter物理屏内屏/外屏/HDMI监听 SF 的 hotplug 事件VirtualDisplayAdapter应用创建的虚拟显示OverlayDisplayAdapter开发者选项里的模拟副屏WifiDisplayAdapterMiracast / Wi-Fi DisplayDisplayDevice一个物理/逻辑输出端点的抽象LogicalDisplay对应应用看到的displayId0 是默认屏LogicalDisplayMapperDisplayDevice → LogicalDisplay 的映射、displayId 分配DisplayDeviceConfig单块屏的配置亮度曲线、模式、刷新率档位来自display_*.xml/ config 资源DisplayDeviceInfo对外暴露的显示设备信息快照2.3 主要功能1显示设备生命周期管理通过DisplayAdapter接收 added/changed/removed 事件分配displayId维护DisplayInfo管理 Display Group默认组 扩展组2显示信息查询分辨率、密度 DPI、刷新率、支持的模式Display.Mode、HDR 能力、色彩模式、旋转、flagsSECURE / PRIVATE / PRESENTATION等。3模式与刷新率管理维护Display.getSupportedModes()结合DisplayModeDirector的投票应用请求、设置项、省电模式、温控、触控采样等选出最终模式下发给 SurfaceFlinger/HWC。4亮度管理较新版本Android 11/12 之后亮度策略逐步集中到 DMS手动/自动亮度、BrightnessTracker用户亮度习惯学习亮度映射曲线、阳光可读性HBM、HDR 亮度温控降亮度ThermalBrightnessThrottlingMapper通过SurfaceFlinger → HWC HAL (setDisplayBrightness)写入面板背光5虚拟显示createVirtualDisplay()屏幕录制、投屏、Presentation、多屏同显VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR/MIRROR/PRESENTATION/SECURE等。6Wi-Fi Display / Overlay Display无线投屏连接、重命名、扫描开发者模拟副屏。7色彩与 HDRrequestColorMode()如 NATIVE / sRGB / DCI_P3、HDR 类型HLG / HDR10 / DolbyVision与HdrConversionModeAndroid 12。三、对外接口3.1 Binder 接口IDisplayManager.aidl典型方法getDisplayInfo(displayId) getDisplayIds() getCompatibleDisplays(uniqueId) registerCallback(IDisplayManagerCallback) createVirtualDisplay(IVirtualDisplayCallback, ..., flags) resizeVirtualDisplay / setVirtualDisplaySurface / releaseVirtualDisplay setBrightness / setTemporaryAutoBrightnessAdjustment connectWifiDisplay / renameWifiDisplay / startWifiDisplayScan requestColorMode / getHdrConversionMode3.2DisplayManagerInternal进程内供 WMS、PowerManagerService 使用例如获取DisplayInfo、设置显示属性、在 WMS 遍历后同步显示状态performTraversal...等。3.3 回调链路SurfaceFlinger (hotplug/模式变化) → DisplayEventReceiver (NativeDisplayEventReceiver) → LocalDisplayAdapter.sendDisplayDeviceEventLocked() → LogicalDisplayMapper → DisplayManagerService 通知 IDisplayManagerCallback → DisplayManagerGlobal 更新缓存 → App 的 DisplayManager.DisplayListener onDisplayAdded / onDisplayRemoved / onDisplayChanged四、典型调用流程① 应用获取显示列表App: dm.getDisplays() → DisplayManagerGlobal.getDisplayInfo() (本地缓存未命中) → IDisplayManager.getDisplayInfo() (Binder) → DisplayManagerService.BinderService → LogicalDisplayMapper → DisplayInfoDisplayManagerGlobal会缓存DisplayInfo并只注册一次全局回调之后用版本号判断是否需要刷新减少 Binder 开销。② 外接屏热插拔HWC HAL 回调 → SurfaceFlinger 生成 hotplug 事件 →LocalDisplayAdapter收到 → DMS 创建LogicalDisplay→ WMS 创建对应DisplayContent布置窗口 → App 收到onDisplayAdded。③ 调亮度设置/快捷开关 → Settings.System.SCREEN_BRIGHTNESS → DisplayManagerService.setBrightness() → DisplayPowerController / BrightnessTracker 逻辑 → SurfaceFlinger → HWC HAL setDisplayBrightness → 背光寄存器应用侧一般用WindowManager.LayoutParams.screenBrightness只影响自己的窗口。④ 刷新率切换应用Surface.setFrameRate()或设置项产生投票 →DisplayModeDirector综合打分 → 选出目标 mode → DMS 下发 → SF 在 VSYNC 边界切换避免画面撕裂/闪烁。⑤ 创建虚拟显示dm.createVirtualDisplay(name, w, h, dpi, surface, flags) → IDisplayManager.createVirtualDisplay(IVirtualDisplayCallback, ...) → VirtualDisplayAdapter 创建 DisplayDevice → 分配 displayId可被 Presentation 或录制使用注意Android 14 对VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR收紧了权限普通应用需要通过MediaProjection授权才能做屏幕镜像录制。五、应用侧 API 示例valdmgetSystemService(Context.DISPLAY_SERVICE)asDisplayManager// 1. 列出所有显示设备dm.displays.forEach{d-Log.d(Display,id${d.displayId}name${d.name}${d.mode.physicalWidth}x${d.mode.physicalHeight}refresh${d.refreshRate}hdr${d.hdrCapabilities?.supportedHdrTypes?.toList()})}// 2. 只取可做 Presentation 的副屏valpresentsdm.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION)// 3. 监听显示变化dm.registerDisplayListener(object:DisplayManager.DisplayListener{overridefunonDisplayAdded(displayId:Int){}overridefunonDisplayRemoved(displayId:Int){}overridefunonDisplayChanged(displayId:Int){}},Handler(Looper.getMainLooper()))// 4. 虚拟显示录屏/自绘valvddm.createVirtualDisplay(my-vd,1080,1920,320,surface,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR)// 用完必须 release()vd.release()在副屏上弹 UIclassMyPresentation(context:Context,display:Display):Presentation(context,display){overridefunonCreate(savedInstanceState:Bundle?){setContentView(R.layout.presentation_layout)}}MyPresentation(this,presents[0]).show()六、调试与查看adb shell dumpsys display# 最常用DMS 全量状态adb shell dumpsys display|grep-A30DisplayModeDirectoradb shell dumpsys SurfaceFlinger# 图层、显示器、HWC 配置adb shell dumpsys window displays# WMS 侧的 DisplayContentadb shellservicelist|grepdisplay# 确认 display 服务已注册adb shell wm size# 分辨率adb shell wm density# 密度adb shell settings get system screen_brightness adb shell cmd display...# 较新版本提供的 shell 子命令亮度等dumpsys display一般包含DisplayManagerService 状态、各 DisplayAdapterLocal/Virtual/Overlay/Wifi、LogicalDisplay 列表、BrightnessTracker、DisplayModeDirector 的投票明细——排查刷新率不切换“副屏不识别”自动亮度异常都靠它。七、权限与注意事项普通应用读Display信息基本无需权限createVirtualDisplay做镜像需MediaProjection授权创建VIRTUAL_DISPLAY_FLAG_SECURE需要CAPTURE_SECURE_VIDEO_OUTPUT。系统 APIsetBrightness、requestColorMode、Wi-Fi Display 控制等是hide/SystemApi需要平台签名或WRITE_SECURE_SETTINGS、CONFIGURE_WIFI_DISPLAY等权限。displayId 语义Display.DEFAULT_DISPLAY 0是主屏副屏 id 由LogicalDisplayMapper分配不保证连续或稳定跨进程传屏建议用uniqueId。API 变更Activity.getWindowManager().getDefaultDisplay()在 API 30 起建议改用Context.getDisplay()各 Android 版本11/12/13/14在亮度管理归属、DisplayDeviceConfig、HDR 转换策略上有差异做兼容时要按目标版本核对。一句话总结DisplayManagerService是 system_server 里管理显示设备而非窗口的核心服务向上通过IDisplayManagerBinder 和DisplayManagerInternal提供设备查询、监听、亮度、模式、虚拟显示等能力向下经由DisplayAdapter与 SurfaceFlinger/HWC HAL 交互完成真正的硬件控制它与 WMS窗口、PMS/DPC电源、SurfaceFlinger合成共同构成 Android 的显示栈。