一、DisplayManagerService 核心职责
1. 系统服务定位
frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
- 核心功能:
- 监控显示设备(主屏/副屏/HDMI)的 热插拔事件
- 维护
DisplayDevice
列表(设备创建/销毁) - 提供
DisplayManager
API 给 App 使用 - 管理显示模式(HDR/刷新率/DPI)
2. 启动流程概览
public class SystemServer {
private void startOtherServices() {
mSystemServiceManager.startService(DisplayManagerService.class);
ServiceManager.addService(Context.DISPLAY_SERVICE, service);
sendBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
}
}
二、DisplayDevice 生命周期全解析
1. 设备类型分类
类型 | 来源 | 示例 |
---|
Internal | 系统内置 | 手机主屏 |
External | 热插拔 | HDMI/Virtual Display |
Wifi | Miracast 投屏 | 无线显示设备 |
2. 生命周期阶段详解
(1) 设备添加阶段
void SurfaceFlinger::onHotplugReceived(int dispId, bool connected) {
mEventControlThread->post([this, dispId, connected] {
mDisplayEventReceiver.sendDisplayEvent(dispId, connected ?
DisplayEventReceiver::DISPLAY_CONNECTED :
DisplayEventReceiver::DISPLAY_DISCONNECTED);
});
}
private final class DisplayEventReceiver extends Handler {
@Override
public void onMessageReceived(Message msg) {
switch (msg.what) {
case MSG_HANDLE_DISPLAY_EVENT:
if (connected) {
createDisplayDeviceLocked(displayId);
} else {
removeDisplayDeviceLocked(displayId);
}
}
}
}
(2) DisplayDevice 初始化
public DisplayDevice(...) {
mInfo = new DisplayDeviceInfo();
configureDisplayLocked();
registerDisplayListener();
}
public final class DisplayDeviceInfo implements Parcelable {
public int width;
public int height;
public float refreshRate;
public int densityDpi;
public boolean secure;
}
(3) 显示模式变更
WindowManager.LayoutParams params = getWindow().getAttributes();
params.preferredDisplayModeId = getMatchingDisplayModeId(90);
getWindow().setAttributes(params);
(4) 设备移除清理
private void removeDisplayDeviceLocked(int displayId) {
for (DisplayDevice device : mDevices) {
device.mCallback.onDisplayDeviceRemoved(device);
}
releaseResourcesLocked(displayId);
sendDisplayRemovedBroadcast(displayId);
}
三、关键协作组件
1. DisplayAdapter
- 职责:适配不同显示类型的协议(如 LocalDisplayAdapter 处理主屏)
protected void processDisplayDeviceInfoLocked(DisplayDeviceInfo info) {
DisplayDevice device = new DisplayDevice(this, info, false);
mGlobal.registerDisplayDeviceLocked(device);
}
2. DisplayPowerController
- 职能:管理屏幕亮灭状态(与 PowerManager 协作)
private void updateDisplayPowerStateLocked() {
if (mDisplayReadyCondition != Display.STATE_ON) {
mDisplayPowerController.setScreenState(Display.STATE_OFF);
}
}
四、实战调试技巧
1. ADB 命令监控
adb shell dumpsys display
adb shell setprop debug.sf.use_phase_clock 1
adb shell sendevent /dev/input/eventX 1 330 1
adb shell sendevent /dev/input/eventX 1 330 0
2. 日志分析
adb logcat -s DisplayManagerService
adb shell dumpsys SurfaceFlinger --latency
3. 开发者选项调试
- 强制 GPU 渲染:
开发者选项 → GPU 渲染模式分析
- 窗口动画缩放:
设置 → 开发者选项 → 动画持续时间调整
五、典型问题排查案例
场景:副屏连接后黑屏
排查路径:
- 检查 DMS 是否收到连接事件:
adb logcat -s DisplayManagerService | grep "Display connected"
- 查看 SF 是否创建 Layer:
adb shell dumpsys SurfaceFlinger | grep "Layer name=.*display"
- 检查 DisplayDevice 参数:
adb shell dumpsys display | grep "DisplayDeviceInfo"
修复方向:
- 若
secure=true
导致无法渲染,检查 DRM 权限配置 - 若
width/height=0
,需修复厂商驱动返回的显示参数
六、推荐动手实验
实验1:监听显示设备变化
DisplayManager dm = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
dm.registerDisplayListener(new DisplayManager.DisplayListener() {
@Override
public void onDisplayAdded(int displayId) {
Log.d("Display", "新增设备 ID:" + displayId);
}
@Override
public void onDisplayRemoved(int displayId) {
Log.d("Display", "移除设备 ID:" + displayId);
}
@Override
public void onDisplayChanged(int displayId) {
Log.d("Display", "设备变更 ID:" + displayId);
}
}, null);
实验2:创建虚拟显示器
DisplayManager dm = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
VirtualDisplay vd = dm.createVirtualDisplay(...);
Surface surface = new Surface.Builder(vd.getDisplay())
.setFormat(PixelFormat.RGBA_8888)
.build();
camera.setPreviewDisplay(surface);