一.DisplayManagerService
1.概述
DisplayManagerService是负责Display管理的系统服务之一,还有一些其他功能,包括屏幕亮度调节也涉及到DMS,其继承自SystemService,因此具有SystemService子类的共性:具有生命周期方法,由SystemServer启动、注册到系统服务中,通过Binder和其他组件进行交互等。
Display类型
1.LocalDisplay
2.OverlayDisplay
3.WifiDisplay
4.VirtualDisplay
DisplayAdapter类型
每个Display对应一个 DisplayAdapter:
1.LocalDisplayAdapter:本地已经存在的物理显示屏设备。
2.OverlayDisplayAdapter:模拟辅助显示设备,以类似浮动窗口的形式显示在主屏上,可以当第二个屏幕使用,默认也是镜像主屏。
3.WifiDisplayAdapter:WiFi Display
4.VirtualDisplayAdapter:显示一个虚拟屏幕
2.关系图
先将Display管理相关的类之间的关系图列出来,有个大概的了解:
![](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=file%3A%2F%2F%2FC%3A%2FUsers%2FAdministrator%2FDocuments%2FMy%20Knowledge%2Ftemp%2Fb735e5dd-ab1a-45d1-b630-48ef28546c9a%2F128%2Findex_files%2F0.5142094462703471.png&pos_id=mq1Rivve)
3.启动过程
和SystemService的其他子类一样,DMS由SystemServer通过反射的方式启动,看一下DMS的构造方法:
2.1.构造方法
构造方法内部逻辑比较简单,主要逻辑为:
1.创建了mHandler和mUiHandler用来自身和其他消息队列处理;
2.创建了DisplayDeviceRepository对象,接收设备事件变化;
3.获取系统服务PowerManger;
onStart()
在该方法中,发送了MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS消息注册DisplayAdapter
公共BinderSerive供其他进程进行调用,公开LocalService供本进程进行使用;
onBootPhase()
在onBootPhase内部,接收到phase为PHASE_WAIT_FOR_DEFAULT_DISPLAY时,
判断是否创建了Display.DEFAULT_DISPLAY对应的LogicalDisplay,
且是否创建了VirtualDisplayAdapter对象,如果不满足一个条件时,需要等待;
systemReady()
当systemReady时,发送MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS来注册其他的adapter;
二.创建DisplayDevice和LogicalDisplay
前面在onStart()中分析到,发送了MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS消息,跟随调用关系,会调用到registerDefaultDisplayAdapters()方法,一起看一下:
在该方法内部执行registerDisplayAdapterLocked(),会先创建LocalDisplayAdapter实例作为参数传入,
接下来创建了VirtualDisplayAdapter实例,然后执行registerDisplayAdapterLocked()进行注册。
先看一下registerDisplayAdapterLocked()实现:
先将adapter存入mDisplayAdapters进行管理,然后执行DisplayAdapter的registerLocked();
接下来看一下LocalDisplayAdapter类实现:
![](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=file%3A%2F%2F%2FC%3A%2FUsers%2FAdministrator%2FDocuments%2FMy%20Knowledge%2Ftemp%2Fb735e5dd-ab1a-45d1-b630-48ef28546c9a%2F128%2Findex_files%2Ff42abede-cb7b-4516-a9bd-0723d7643bfa.png&pos_id=FmVfzw9p)
LocalDisplayAdapter继承DisplayAdapter,在构造方法内部执行调用父类的构造方法,一起看一下:
进行一些赋值操作,后续相关逻辑会在父类里面进行调用处理;
接下来看一下registerLocked()方法:
当调用registerLocked()时,会遍历所有物理显示屏,执行tryConnectDisplayLocked():
该方法主要做了以下几件事:
1.根据PhysicalDisplayId通过SurfaceControlProxy的getPhysicalDisplayToke从SurfaceFlinger获取到对应的displayToken;
2.如果是合法的displayToken,则进行一系列获取设备信息操作,接下来创建对象时会用到;
3.从mDevices获取对应的LocalDisplayDevice,首次创建时不存在,会进行创建,然后加入mDevices进行管理;
4.执行sendDisplayDeviceEventLocked()进行通知设备创建;
先看一下LocalDisplayDevice类实现:
LocalDisplayDevice是LocalDisplayAdapter类的内部类,继承DisplayDevice,在构造方法内部,主要执行逻辑如下:
1.调用父类的构造方法,LocalDisplayDevice设备mUniqueId为:local:0、local:1等;
2.将上述获取的信息进行赋值,包括PhysicalDisplayInfo等;
3.创建BacklightAdapter,用来屏幕亮度调节;
4.调用display.updateLocked(mDisplayDevices),
将DisplayDevice对应的设备信息DisplayDeviceInfo封装为LogicalDisplay对应的设备信息DisplayInfo;
5.将创建的LogicalDisplay存入mLogicalDisplays进行管理;
6.执行mSyncRoot.notifyAll()进行唤醒操作;
7.执行sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED)来发送设备添加通知;
DISPLAY_ADDED通知
上面讲到,在创建完DisplayDevice后,先加入mDevices进行管理,然后执行sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED)来进行通知下一步操作:
最终会执行mListener的onDisplayDeviceEvent()方法。
前面讲到在DMS初始化时,创建LogicalDisplayMapper时,会传入DisplayDeviceRepository实例,
而DisplayDeviceRepository实现了DisplayAdapter内部的Listener接口:
LogicalDisplayMapper.java实现了这个Listener
创建逻辑显示屏的参数:
参数1:displayId
逻辑显示屏的displayId 获取如下:
mIdProducer.getId(/* isDefault= */ false)
通过assignLayerStackLocked()为displayId分配layerStack,跟displayId保持一致,layerStack与SurfaceFlinger里面屏幕内容显示是一一对应关系;
参数3:device
就是上面创建的LocalDisplayDevice
将displayId,layerStack,device作为参数来创建LogicalDisplay对象,创建的LocalDisplayDevice对象赋值为LogicalDisplay的mPrimaryDisplayDevice变量;
5.总结
1.在DMS的onStart()方法内部发送消息来创建LocalDisplayAdapter,然后执行registerDisplayAdapterLocked(),继而执行LocalDisplayAdapter的registerLocked()方法;
2.在LocakDisplayAdapter()内部执行tryConnectDisplayLocked()来创建物理Display对应的LocalDisplayDevice,最后发送DISPLAY_DEVICE_EVENT_ADDED事件通知;
3.DMS内部收到回调通知,执行handleDisplayDeviceAdded()来根据DisplayDevice创建对应的LogicalDisplay;
三.创建Display、ActivityDisplay和DisplayContent
前面讲到,在创建完LogicalDisplay时,会执行sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED)来发送设备添加通知来执行后续操作,跟随调用关系,一起看一下:
/frameworks/base/services/core/java/com/android/server/display/LogicalDisplayMapper.java
......
/frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
handleLogicalDisplayAddedLocked(display)
......
在该方法内部,会遍历mCallbacks来执行notifyDisplayEventAsync(),mCallbacks是CallbackRecord数组,通过registerCallback()来进行注册添加;
notifyDisplayEventAsync()
mCallback是IDisplayManagerCallback实现,具体实现是在DisplayManagerGlobal内部,调用其onDisplayEvent()方法:
/frameworks/base/core/java/android/hardware/display/DisplayManagerGlobal.java
/frameworks/base/core/java/android/hardware/display/DisplayManager.java
DisplayListener 接口如下:
在执行handleDisplayEvent()时,会遍历mDisplayListeners来执行sendDisplayEvent(),
mDisplayListeners是在registerDisplayEvent()内部进行注册的,
在执行sendDisplayEvent()时,通过DisplayListenerDelegate执行mListener.onDisplayAdded(msg.arg1),
mListener对应DisplayListener实例;
RootWindowContainer实现了DisplayListener接口,在setWindowManager()内部进行注册:
/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
在setWindowManager()内部进行注册监听
收到监听回调处理:
调用了getDisplayContentOrCreate
1.获取displayId对应的DIsplayContent,由于是初次创建,所以不会存在;
2.通过DisplayManager的getDisplay()来创建displayId对应的Display;
3.创建displayId对应的DisplayContent实例;
4.将新创建的displayContent添加到RootWindowContainer(窗口根容器)中;
接下来看一下通过mDisplayManager.getDisplay(displayId)来创建对应的Display;
/frameworks/base/core/java/android/hardware/display/DisplayManager.java
1.调用DisplayManagerGlobal的getCompatibleDisplay()来创建Display;
2.将创建的Display加入到mDisplays进行管理;
/frameworks/base/core/java/android/hardware/display/DisplayManagerGlobal.java
先通过getDisplayInfo()来获取displayId对应的DisplayInfo,然后创建Display实例;
通过IDisplayManager的getDisplayInfo()来获取DisplayInfo,
IDisplayManager.Stub实现是在DisplayManagerService内,最终调用方法为getDisplayInfoInternal():
可以看到,是通过displayId从mLogicalDisplayMapper内获取LogicalDisplay
然后在从内部获取到DisplayInfo,Display的内部跟LogicalDisplay是强相关的;
接着前面getActivityDisplayOrCreateLocked()分析,在创建完Display时,会通知WMS执行onDisplayAdded():
看下两个参数的获取:
/frameworks/base/services/core/java/com/android/server/display/LogicalDisplay.java
display.getFrameRateOverrides()
display.getDisplayInfoLocked()
回到getDisplayInfoForFrameRateOverride方法
/frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
此方法主要是对LogicalDisplay获取到的Displayinfo进行帧率覆盖。
以上介绍了DMS的启动流程、组成以及设备添加处理流程,
可以发现Android系统几大主要服务都是相辅相成的,系统的某一个服务单拎出来可能并不复杂,复杂的是和其他服务的关联,
WMS监听到Display的接入会创建一个DisplayContent,用于由于管理该Display所有WindowState;
AMS监听到Display接入会去创建ActivityDisplay,用于管理当前屏幕的所有ActivityRecord等;