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

相关文章

C++ 右值引用(rvalue references)与移动语义(move semantics)深度解析

《C++右值引用(rvaluereferences)与移动语义(movesemantics)深度解析》文章主要介绍了C++右值引用和移动语义的设计动机、基本概念、实现方式以及在实际编程中的应用,... 目录一、右值引用(rvalue references)与移动语义(move semantics)设计动机1

MySQL 筛选条件放 ON后 vs 放 WHERE 后的区别解析

《MySQL筛选条件放ON后vs放WHERE后的区别解析》文章解释了在MySQL中,将筛选条件放在ON和WHERE中的区别,文章通过几个场景说明了ON和WHERE的区别,并总结了ON用于关... 今天我们来讲讲数据库筛选条件放 ON 后和放 WHERE 后的区别。ON 决定如何 "连接" 表,WHERE

Mybatis的mapper文件中#和$的区别示例解析

《Mybatis的mapper文件中#和$的区别示例解析》MyBatis的mapper文件中,#{}和${}是两种参数占位符,核心差异在于参数解析方式、SQL注入风险、适用场景,以下从底层原理、使用场... 目录MyBATis 中 mapper 文件里 #{} 与 ${} 的核心区别一、核心区别对比表二、底

Agent开发核心技术解析以及现代Agent架构设计

《Agent开发核心技术解析以及现代Agent架构设计》在人工智能领域,Agent并非一个全新的概念,但在大模型时代,它被赋予了全新的生命力,简单来说,Agent是一个能够自主感知环境、理解任务、制定... 目录一、回归本源:到底什么是Agent?二、核心链路拆解:Agent的"大脑"与"四肢"1. 规划模

MySQL字符串转数值的方法全解析

《MySQL字符串转数值的方法全解析》在MySQL开发中,字符串与数值的转换是高频操作,本文从隐式转换原理、显式转换方法、典型场景案例、风险防控四个维度系统梳理,助您精准掌握这一核心技能,需要的朋友可... 目录一、隐式转换:自动但需警惕的&ld编程quo;双刃剑”二、显式转换:三大核心方法详解三、典型场景

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求

SpringBoot实现图形验证码的示例代码

《SpringBoot实现图形验证码的示例代码》验证码的实现方式有很多,可以由前端实现,也可以由后端进行实现,也有很多的插件和工具包可以使用,在这里,我们使用Hutool提供的小工具实现,本文介绍Sp... 目录项目创建前端代码实现约定前后端交互接口需求分析接口定义Hutool工具实现服务器端代码引入依赖获

SQL 注入攻击(SQL Injection)原理、利用方式与防御策略深度解析

《SQL注入攻击(SQLInjection)原理、利用方式与防御策略深度解析》本文将从SQL注入的基本原理、攻击方式、常见利用手法,到企业级防御方案进行全面讲解,以帮助开发者和安全人员更系统地理解... 目录一、前言二、SQL 注入攻击的基本概念三、SQL 注入常见类型分析1. 基于错误回显的注入(Erro

Nginx概念、架构、配置与虚拟主机实战操作指南

《Nginx概念、架构、配置与虚拟主机实战操作指南》Nginx是一个高性能的HTTP服务器、反向代理服务器、负载均衡器和IMAP/POP3/SMTP代理服务器,它支持高并发连接,资源占用低,功能全面且... 目录Nginx 深度解析:概念、架构、配置与虚拟主机实战一、Nginx 的概念二、Nginx 的特点

2025最新版Android Studio安装及组件配置教程(SDK、JDK、Gradle)

《2025最新版AndroidStudio安装及组件配置教程(SDK、JDK、Gradle)》:本文主要介绍2025最新版AndroidStudio安装及组件配置(SDK、JDK、Gradle... 目录原生 android 简介Android Studio必备组件一、Android Studio安装二、A