Android DMS

一.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管理相关的类之间的关系图列出来,有个大概的了解:








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类实现:




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)



参数2:layerStack


通过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)


......





deliverDisplayEvent()



在该方法内部,会遍历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等;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容