Android Display管理服务

一.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等;

 

  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weijaky

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值