Android P图形架构之DisplayManagerService解析

2024-02-22 00:48

本文主要是介绍Android P图形架构之DisplayManagerService解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

顾名思义,DisplayManagerService是一个用于管理显示的服务。

源码:
\frameworks\base\services\java\com\android\server\SystemServer.java
\frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java
\frameworks\base\services\core\java\com\android\server\display\DisplayDevice.java
\frameworks\base\services\core\java\com\android\server\display\LogicalDisplay.java

作用:

  • 管理显示器的全局生命周期, 决定如何根据当前连接的物理显示设备配置逻辑显示,在状态更改时向系统和应用程序发送通知等
  • 显示管理服务依赖于DisplayAdapter(LocalDisplayAdapter,OverlayDisplayAdapter,WifiDisplayAdapter)用于发现和配置连接到系统的物理显示设备
  • 设备连接的方式都有单独的DisplayAdapter,一个本地显示器的适配器,用于模拟无头系统(不接显示器)的非功能显示;一个用于开发的模拟overlay显示器;一个用wifi显示器
  • 显示适配器仅与显示管理器服务弱耦合
  • 显示适配器通过显示管理器服务注册的DisplayAdapter.Listener异步地将显示设备状态的变化传送到显示管理器服务

启动过程:
DisplayManagerService是在SystemServer中启动的。
\frameworks\base\services\java\com\android\server\SystemServer.java

private void startBootstrapServices() {//...// Display manager is needed to provide display metrics before package manager// starts up.traceBeginAndSlog("StartDisplayManager");mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);traceEnd();//...
}

代码分析:

LocalDisplayAdapter

DisplayManagerService的onStart()中发送了消息MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS,去执行了registerDefaultDisplayAdapters(),初始化了主屏显示器适配器LocalDisplayAdapter

@Override
public void onStart() {// We need to pre-load the persistent data store so it's ready before the default display// adapter is up so that we have it's configuration. We could load it lazily, but since// we're going to have to read it in eventually we may as well do it here rather than after// we've waited for the display to register itself with us.
synchronized(mSyncRoot) {
mPersistentDataStore.loadIfNeeded();
loadStableDisplayValuesLocked();}mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),true /*allowIsolated*/);publishLocalService(DisplayManagerInternal.class, new LocalService());publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
}//加载LocalDisplayAdapter和getVirtualDisplayAdapter
private void registerDefaultDisplayAdapters() {// Register default display adapters.synchronized (mSyncRoot) {// main display adapterregisterDisplayAdapterLocked(new LocalDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayAdapterListener));// Standalone VR devices rely on a virtual display as their primary display for// 2D UI. We register virtual display adapter along side the main display adapter// here so that it is ready by the time the system sends the home Intent for// early apps like SetupWizard/Launcher. In particular, SUW is displayed using// the virtual display inside VR before any VR-specific apps even run.mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,mHandler, mDisplayAdapterListener);if (mVirtualDisplayAdapter != null) {registerDisplayAdapterLocked(mVirtualDisplayAdapter);}}
}

registerDisplayAdapterLocked把适配器放入了mDisplayAdapters中,并且执行了LocalDisplayAdapter的registerLocked();

// List of all currently registered display adapters.
private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();private void registerDisplayAdapterLocked(DisplayAdapter adapter) {mDisplayAdapters.add(adapter);adapter.registerLocked();
}

LocalDisplayAdapter中则去调用SurfaceFlinger获取物理显示屏的信息,并返回给DisplayManagerService,最终执行了handleDisplayDeviceAddedLocked(),来添加显示器设备。
\frameworks\base\services\core\java\com\android\server\display\LocalDisplayAdapter.java

@Override
public void registerLocked() {super.registerLocked();mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {tryConnectDisplayLocked(builtInDisplayId);}
}

添加显示器:

// List of all currently connected display devices.
private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();private void handleDisplayDeviceAddedLocked(DisplayDevice device) {DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();if (mDisplayDevices.contains(device)) {Slog.w(TAG, "Attempted to add already added display device: " + info);return;}Slog.i(TAG, "Display device added: " + info);device.mDebugLastLoggedDeviceInfo = info;mDisplayDevices.add(device);LogicalDisplay display = addLogicalDisplayLocked(device);Runnable work = updateDisplayStateLocked(device);if (work != null) {work.run();}scheduleTraversalLocked(false);
}

handleDisplayDeviceAddedLocked()会将显示器设备统一放到mDisplayDevices中,并且执行了addLogicalDisplayLocked(),作用是在一个显示设备中添加逻辑显示,assignDisplayIdLocked()分配一个displayId,并且放入mLogicalDisplays中。

// List of all logical displays indexed by logical display id.
private final SparseArray<LogicalDisplay> mLogicalDisplays = new SparseArray<LogicalDisplay>();// Adds a new logical display based on the given display device.
// Sends notifications if needed.
private LogicalDisplay addLogicalDisplayLocked(DisplayDevice device) {DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();boolean isDefault = (deviceInfo.flags& DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);isDefault = false;}if (!isDefault && mSingleDisplayDemoMode) {Slog.i(TAG, "Not creating a logical display for a secondary display "+ " because single display demo mode is enabled: " + deviceInfo);return null;}final int displayId = assignDisplayIdLocked(isDefault);final int layerStack = assignLayerStackLocked(displayId);LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);display.updateLocked(mDisplayDevices);if (!display.isValidLocked()) {// This should never happen currently.Slog.w(TAG, "Ignoring display device because the logical display "+ "created from it was not considered valid: " + deviceInfo);return null;}configureColorModeLocked(display, device);if (isDefault) {recordStableDisplayStatsIfNeededLocked(display);recordTopInsetLocked(display);}mLogicalDisplays.put(displayId, display);// Wake up waitForDefaultDisplay.if (isDefault) {mSyncRoot.notifyAll();}sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);return display;
}

OverlayDisplayAdapter、WifiDisplayAdapter

DisplayManagerService的systemReady()中,发送了MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS,并执行了registerAdditionalDisplayAdapters(),在registerAdditionalDisplayAdapters中完成了OverlayDisplayAdapter和WifiDisplayAdapter的注册。

/*** Called when the system is ready to go.*/
public void systemReady(boolean safeMode, boolean onlyCore) {synchronized (mSyncRoot) {mSafeMode = safeMode;mOnlyCore = onlyCore;mSystemReady = true;// Just in case the top inset changed before the system was ready. At this point, any// relevant configuration should be in place.recordTopInsetLocked(mLogicalDisplays.get(Display.DEFAULT_DISPLAY));}mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);mHandler.sendEmptyMessage(MSG_REGISTER_BRIGHTNESS_TRACKER);
}private void registerAdditionalDisplayAdapters() {synchronized (mSyncRoot) {if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {registerOverlayDisplayAdapterLocked();registerWifiDisplayAdapterLocked();}}
}

跟LocalDisplayAdapter流程类似:

private void registerOverlayDisplayAdapterLocked() {registerDisplayAdapterLocked(new OverlayDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
}private void registerWifiDisplayAdapterLocked() {if (mContext.getResources().getBoolean(com.android.internal.R.bool.config_enableWifiDisplay)|| SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {mWifiDisplayAdapter = new WifiDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayAdapterListener,mPersistentDataStore);registerDisplayAdapterLocked(mWifiDisplayAdapter);}
}

VirtualDisplayAdapter

在加载LocalDisplayAdapter的时候就加载了虚拟显示适配器,因为虚拟显示必须依赖于物理屏。
DisplayManagerService的onstart()中执行的,getVirtualDisplayAdapter(),加载虚拟屏。

private void registerDefaultDisplayAdapters() {// Register default display adapters.synchronized (mSyncRoot) {// main display adapterregisterDisplayAdapterLocked(new LocalDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayAdapterListener));// Standalone VR devices rely on a virtual display as their primary display for// 2D UI. We register virtual display adapter along side the main display adapter// here so that it is ready by the time the system sends the home Intent for// early apps like SetupWizard/Launcher. In particular, SUW is displayed using// the virtual display inside VR before any VR-specific apps even run.mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,mHandler, mDisplayAdapterListener);if (mVirtualDisplayAdapter != null) {registerDisplayAdapterLocked(mVirtualDisplayAdapter);}}
}@VisibleForTesting
static class Injector {VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,Handler handler, DisplayAdapter.Listener displayAdapterListener) {return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener);}long getDefaultDisplayDelayTimeout() {return WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;}
}

这篇关于Android P图形架构之DisplayManagerService解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/733617

相关文章

在Android平台上实现消息推送功能

《在Android平台上实现消息推送功能》随着移动互联网应用的飞速发展,消息推送已成为移动应用中不可或缺的功能,在Android平台上,实现消息推送涉及到服务端的消息发送、客户端的消息接收、通知渠道(... 目录一、项目概述二、相关知识介绍2.1 消息推送的基本原理2.2 Firebase Cloud Me

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

关于WebSocket协议状态码解析

《关于WebSocket协议状态码解析》:本文主要介绍关于WebSocket协议状态码的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录WebSocket协议状态码解析1. 引言2. WebSocket协议状态码概述3. WebSocket协议状态码详解3

CSS Padding 和 Margin 区别全解析

《CSSPadding和Margin区别全解析》CSS中的padding和margin是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍padding和... 目录css Padding 和 Margin 全解析1. Padding: 内边距2. Margin: 外边距3. Padd

Oracle数据库常见字段类型大全以及超详细解析

《Oracle数据库常见字段类型大全以及超详细解析》在Oracle数据库中查询特定表的字段个数通常需要使用SQL语句来完成,:本文主要介绍Oracle数据库常见字段类型大全以及超详细解析,文中通过... 目录前言一、字符类型(Character)1、CHAR:定长字符数据类型2、VARCHAR2:变长字符数

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.