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

相关文章

Ubuntu 24.04启用root图形登录的操作流程

《Ubuntu24.04启用root图形登录的操作流程》Ubuntu默认禁用root账户的图形与SSH登录,这是为了安全,但在某些场景你可能需要直接用root登录GNOME桌面,本文以Ubuntu2... 目录一、前言二、准备工作三、设置 root 密码四、启用图形界面 root 登录1. 修改 GDM 配

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应

MyBatis中$与#的区别解析

《MyBatis中$与#的区别解析》文章浏览阅读314次,点赞4次,收藏6次。MyBatis使用#{}作为参数占位符时,会创建预处理语句(PreparedStatement),并将参数值作为预处理语句... 目录一、介绍二、sql注入风险实例一、介绍#(井号):MyBATis使用#{}作为参数占位符时,会

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.