一、DisplayManagerService功能说明(根据DisplayManagerService.java注释翻译)
DisplayManagerService 用来管理显示的生命周期,它决定如何根据当前连接的物理显示设备控制其逻辑显示,并且在状态更改时,向系统和应用程序发送通知,等等。
DisplayAdapter 是 DisplayManagerService 所依赖的集合组件,其为系统显示,收集并发现物理显示设备提供了适配器的作用。
目前有以下四种方式的适配器供使用
一、本地显示设备提供适配器。
二、无线连接显示适配器。
三、虚拟显示适配器。
四、开发者提供的模拟显示适配器。
DisplayAdapter 与 DisplayManagerService 是弱耦合关系。DisplayAdapter通过注册在 DisplayManagerService类中的 DisplayAdapter.Listener 实现异步通信。
这样做有两个原因
一、巧妙地封装了这两个类的职责,
DisplayAdapter :处理各个显示设备
DisplayManagerService:处理全局显示状态。
二、消除异步显示设备发现导致死锁的可能性
Synchronization(同步锁)
因为显示管理器可能被多个线程访问,所以同步锁就会变得有点复杂。 特别是当窗口管理器(window manager)在保持绘制事务的同时调用显示管理器(display manager),窗口管理器期望它可以立即应用并更改。 但不幸的是,显示管理器(display manager)不能异步地做所有事情。
为了解决这个问题,显示管理器的所有对象必须持有相同的锁。 我们将此锁称为同步锁,它具有唯一性。
二、DisplayManagerService类图关系
以系统built in display为例,整理类图关系。
三、DisplayManagerService启动流程
启动过程的主要工作是建立和Surfaceflinger的连接,获取build in display设备信息,创建虚拟显示设备,并通知启动模块,dms.onBootPhase检查到虚拟显示设备创建成功,就返回,系统继续其他服务。
//SystemServer.java
552 // Display manager is needed to provide display metrics before package manager
553 // starts up.
554 traceBeginAndSlog("StartDisplayManager");
555 //step1: 启动DisplayManagerService, 调用onStart方法
556 mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
557 traceEnd();
558
559 // We need the default display before we can initialize the package manager.
560 traceBeginAndSlog("WaitForDisplay");
561 //step2: 等待启动DisplayManagerService启动完成,调用dms.onBootPhase方法
562 mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
563 traceEnd();
//DisplayManagerService.java
256 DisplayManagerService(Context context, Injector injector) {
257 super(context);
258 mInjector = injector;
259 mContext = context;
260 //创建Handle,处理消息使用
261 mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
262 mUiHandler = UiThread.getHandler();
263 //创建AdpterListener, 简单显示设备增加/删除/改变
264 mDisplayAdapterListener = new DisplayAdapterListener();
265 mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
266 mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
267 com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);
268
269 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
270 mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
271
272 }
284 @Override
285 public void onStart() {
286 // We need to pre-load the persistent data store so it's ready before the default display
287 // adapter is up so that we have it's configuration. We could load it lazily, but since
288 // we're going to have to read it in eventually we may as well do it here rather than after
289 // we've waited for the diplay to register itself with us.
290 mPersistentDataStore.loadIfNeeded();
291 //异步注册adapter
292 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
293 //注册系统服务
294 publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
295 true /*allowIsolated*/);
296 //注册内部服务
297 publishLocalService(DisplayManagerInternal.class, new LocalService());
298 publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
299 }
300
301 @Override
302 public void onBootPhase(int phase) {
303 if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
304 synchronized (mSyncRoot) {
305 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
306 //循环检查逻辑屏幕是否存在
307 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
308 long delay = timeout - SystemClock.uptimeMillis();
309 if (delay <= 0) {
310 throw new RuntimeException("Timeout waiting for default display "
311 + "to be initialized.");
312 }
313 if (DEBUG) {
314 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
315 }
316 try {
317 mSyncRoot.wait(delay);
318 } catch (InterruptedException ex) {
319 }
320 }
321 }
322 }
323 }
四、Build In Display本地显示设备添加过程
启动的过程中,onStart方法会发一个MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER消息出来。
//DisplayManagerService.java
1230 private final class DisplayManagerHandler extends Handler {
1231 public DisplayManagerHandler(Looper looper) {
1232 super(looper, null, true /*async*/);
1233 }
1234
1235 @Override
1236 public void handleMessage(Message msg) {
1237 switch (msg.what) {
1238 //处理注册默认显示设备适配器
1239 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
1240 registerDefaultDisplayAdapter();
1241 break;
1242
1243 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
1244 registerAdditionalDisplayAdapters();
1245 break;
1246
1247 case MSG_DELIVER_DISPLAY_EVENT:
1248 deliverDisplayEvent(msg.arg1, msg.arg2);
1249 break;
1250
1251 case MSG_REQUEST_TRAVERSAL:
1252 mWindowManagerInternal.requestTraversalFromDisplayManager();
1253 break;
1254
1255 case MSG_UPDATE_VIEWPORT: {
1256 synchronized (mSyncRoot) {
1257 mTempDefaultViewport.copyFrom(mDefaultViewport);
1258 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
1259 if (!mTempVirtualTouchViewports.equals(mVirtualTouchViewports)) {
1260 mTempVirtualTouchViewports.clear();
1261 for (DisplayViewport d : mVirtualTouchViewports) {
1262 mTempVirtualTouchViewports.add(d.makeCopy());
1263 }
1264 }
1265 }
1266 mInputManagerInternal.setDisplayViewports(mTempDefaultViewport,
1267 mTempExternalTouchViewport, mTempVirtualTouchViewports);
1268 break;
1269 }
1270 }
1271 }
1272 }
693 private void registerDefaultDisplayAdapter() {
694 // Register default display adapter.
695 synchronized (mSyncRoot) {
696 // 创建LocalDisplayAdapter,并且调用registerLocked方法
697 registerDisplayAdapterLocked(new LocalDisplayAdapter(
698 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
699 }
700 }
744 private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
745 //添加到mDisplayAdapters列表中,
746 mDisplayAdapters.add(adapter);
747 //调用对应适配器的registerLocked方法
748 adapter.registerLocked();
749 }
//LocalDisplayAdapter.java
76 public void registerLocked() {
77 super.registerLocked();
78
79 //热插拔监听回调
80 mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
81
82 //默认屏幕 尝试和SurfaceFlingre建立连接
83 for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
84 tryConnectDisplayLocked(builtInDisplayId);
85 }
86 }
88 private void tryConnectDisplayLocked(int builtInDisplayId) {
89 //step1: 通过SurfaceControl和SurfaceFlinger打交道,或者client ibinder句柄
90 IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
91 if (displayToken != null) {
92 //step2: 获取display的硬件属性,新建LocalDisplayDevice
93 SurfaceControl.PhysicalDisplayInfo[] configs =
94 SurfaceControl.getDisplayConfigs(displayToken);
95 if (configs == null) {
96 // There are no valid configs for this device, so we can't use it
97 Slog.w(TAG, "No valid configs found for display device " +
98 builtInDisplayId);
99 return;
100 }
101 int activeConfig = SurfaceControl.getActiveConfig(displayToken);
102 if (activeConfig < 0) {
103 // There is no active config, and for now we don't have the
104 // policy to set one.
105 Slog.w(TAG, "No active config found for display device " +
106 builtInDisplayId);
107 return;
108 }
109 int activeColorMode = SurfaceControl.getActiveColorMode(displayToken);
110 if (activeColorMode < 0) {
111 // We failed to get the active color mode. We don't bail out here since on the next
112 // configuration pass we'll go ahead and set it to whatever it was set to last (or
113 // COLOR_MODE_NATIVE if this is the first configuration).
114 Slog.w(TAG, "Unable to get active color mode for display device " +
115 builtInDisplayId);
116 activeColorMode = Display.COLOR_MODE_INVALID;
117 }
118 int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
119 LocalDisplayDevice device = mDevices.get(builtInDisplayId);
120 if (device == null) {
121 // Display was added.
122 // 创建本地显示设备
123 device = new LocalDisplayDevice(displayToken, builtInDisplayId,
124 configs, activeConfig, colorModes, activeColorMode);
125 mDevices.put(builtInDisplayId, device);
126 //通知本地显示设备添加成功
127 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
128 } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
129 colorModes, activeColorMode)) {
130 // Display properties changed.
131 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
132 }
133 } else {
134 // The display is no longer available. Ignore the attempt to add it.
135 // If it was connected but has already been disconnected, we'll get a
136 // disconnect event that will remove it from mDevices.
137 }
138 }
139
//SurfaceControl.java,都是static,类函数通过id获取display token
public static IBinder getBuiltInDisplay(int builtInDisplayId) {
return nativeGetBuiltInDisplay(builtInDisplayId);
}
//通过display token,获取display硬件属性
public static boolean getDisplayInfo(IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo) {
if (displayToken == null) {
throw new IllegalArgumentException("displayToken must not be null");
}
if (outInfo == null) {
throw new IllegalArgumentException("outInfo must not be null");
}
return nativeGetDisplayInfo(displayToken, outInfo);
}
LocalDisplayAdapter构造函数的mHandler和mDisplayAdapterListener分别为DisplayManagerHandler和DisplayAdapterListener,进而会去调用回到DisplayManagerService处DISPLAY_DEVICE_EVENT_ADDED消息,
//DisplayManagerService.java
1276 private final class DisplayAdapterListener implements DisplayAdapter.Listener {
1277 @Override
1278 public void onDisplayDeviceEvent(DisplayDevice device, int event) {
1279 switch (event) {
1280 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
1281 handleDisplayDeviceAdded(device);
1282 break;
1283
1284 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
1285 handleDisplayDeviceChanged(device);
1286 break;
1287
1288 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
1289 handleDisplayDeviceRemoved(device);
1290 break;
1291 }
1292 }
744 private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
745 //添加到mDisplayAdapters列表中,
746 mDisplayAdapters.add(adapter);
747 //调用对应适配器的registerLocked方法
748 adapter.registerLocked();
749 }
750
751 private void handleDisplayDeviceAdded(DisplayDevice device) {
752 synchronized (mSyncRoot) {
753 handleDisplayDeviceAddedLocked(device);
754 }
755 }
756
757 private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
758 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
759 if (mDisplayDevices.contains(device)) {
760 Slog.w(TAG, "Attempted to add already added display device: " + info);
761 return;
762 }
763
764 Slog.i(TAG, "Display device added: " + info);
765 device.mDebugLastLoggedDeviceInfo = info;
766
767 //将LocalDisplayDevice添加到mDisplayDevices
768 mDisplayDevices.add(device);
769 //为一个物理display添加一个logical display
770 LogicalDisplay display = addLogicalDisplayLocked(device);
771 Runnable work = updateDisplayStateLocked(device);
772 if (work != null) {
773 work.run();
774 }
775 if (display != null && display.getPrimaryDisplayDeviceLocked() == device) {
776 int colorMode = mPersistentDataStore.getColorMode(device);
777 if (colorMode == Display.COLOR_MODE_INVALID) {
778 if ((device.getDisplayDeviceInfoLocked().flags
779 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
780 colorMode = mDefaultDisplayDefaultColorMode;
781 } else {
782 colorMode = Display.COLOR_MODE_DEFAULT;
783 }
784 }
785 display.setRequestedColorModeLocked(colorMode);
786 }
787 //刷新处理
788 scheduleTraversalLocked(false);
789 }
为物理屏幕创建一个logical display,至此DisplayManagerService启动就完成了,
863 // Adds a new logical display based on the given display device.
864 // Sends notifications if needed.
865 private LogicalDisplay addLogicalDisplayLocked(DisplayDevice device) {
866 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
867 //主屏,同时mLogicalDisplays包含了这个device
868 boolean isDefault = (deviceInfo.flags
869 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
870 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
871 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
872 isDefault = false;
873 }
874
875 //不是主屏,但是mSingleDisplayDemoMode为真,即设置了单屏模式
876 //这时候不会去为这个物理display创建新的logical display,如果
877 //有hdmi,这时候会mirror主屏的内容
878 //看来逻辑display就是和显示的内容有很大的关系
879 if (!isDefault && mSingleDisplayDemoMode) {
880 Slog.i(TAG, "Not creating a logical display for a secondary display "
881 + " because single display demo mode is enabled: " + deviceInfo);
882 return null;
883 }
884
885 //layerStack 就是displayId id,主屏0,hdmi 1
886 final int displayId = assignDisplayIdLocked(isDefault);
887 final int layerStack = assignLayerStackLocked(displayId);
888
889 //新建LogicalDisplay
890 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
891 display.updateLocked(mDisplayDevices);
892 if (!display.isValidLocked()) {
893 // This should never happen currently.
894 Slog.w(TAG, "Ignoring display device because the logical display "
895 + "created from it was not considered valid: " + deviceInfo);
896 return null;
897 }
898
899 mLogicalDisplays.put(displayId, display);
900
901 // Wake up waitForDefaultDisplay.
902 //如果添加的是built-in display,需要mSyncRoot.notifyAll()
903 //因为systemserver.java中调用了waitForDefaultDisplay,这时候systemserver可以继续运行了
904 if (isDefault) {
905 mSyncRoot.notifyAll();
906 }
907
908 //给mHandler发消息去处理
909 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
910 return display;
911 }
DMS启动完成,会通知其他服务注册了回调接口进程,通知显示设备以添加成功,回调接口就不继续分析,一般其他的模块通过aidl接口注册。
1134 // Runs on Handler thread.
1135 // Delivers display event notifications to callbacks.
1136 private void deliverDisplayEvent(int displayId, int event) {
1137 if (DEBUG) {
1138 Slog.d(TAG, "Delivering display event: displayId="
1139 + displayId + ", event=" + event);
1140 }
1141
1142 // Grab the lock and copy the callbacks.
1143 final int count;
1144 synchronized (mSyncRoot) {
1145 count = mCallbacks.size();
1146 mTempCallbacks.clear();
1147 for (int i = 0; i < count; i++) {
1148 mTempCallbacks.add(mCallbacks.valueAt(i));
1149 }
1150 }
1151
1152 // After releasing the lock, send the notifications out.
1153 for (int i = 0; i < count; i++) {
1154 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
1155 }
1156 mTempCallbacks.clear();
1157 }
五、 总结
DisplayManagerService只是对显示设备做简单管理,并不设计到太多东西,通过DisplayManager提供对外接口包括如下几个:(省略了wifi相关..)
1 、public Display getDisplay(int displayId)
根据displayId参数获得一个逻辑显示器的信息
2、 public Display[] getDisplays()
获得当前所有有效的逻辑显示器列表
3、public void registerDisplayListener(DisplayListener listener, Handler handler)
登记一个显示监听对象,用来监听显示器的新增、去除或改变通知事件。
4、public void unregisterDisplayListener(DisplayListener listener)
取消先前登记的一个显示监听对象
...
梳理DMS主要是这里面有DisplayViewport会传递给IMS模块,作为触摸输入区域会使用,这里简单记录下。
6、参考博客
android graphic(12)—display上层相关概念、关系
Android Framework 框架系列之 DisplayManagerService(一)
https://source.android.google.cn/devices/graphics?hl=zh_cn