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

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

mybatis的整体架构

mybatis的整体架构分为三层: 1.基础支持层 该层包括:数据源模块、事务管理模块、缓存模块、Binding模块、反射模块、类型转换模块、日志模块、资源加载模块、解析器模块 2.核心处理层 该层包括:配置解析、参数映射、SQL解析、SQL执行、结果集映射、插件 3.接口层 该层包括:SqlSession 基础支持层 该层保护mybatis的基础模块,它们为核心处理层提供了良好的支撑。

百度/小米/滴滴/京东,中台架构比较

小米中台建设实践 01 小米的三大中台建设:业务+数据+技术 业务中台--从业务说起 在中台建设中,需要规范化的服务接口、一致整合化的数据、容器化的技术组件以及弹性的基础设施。并结合业务情况,判定是否真的需要中台。 小米参考了业界优秀的案例包括移动中台、数据中台、业务中台、技术中台等,再结合其业务发展历程及业务现状,整理了中台架构的核心方法论,一是企业如何共享服务,二是如何为业务提供便利。

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

OWASP十大安全漏洞解析

OWASP(开放式Web应用程序安全项目)发布的“十大安全漏洞”列表是Web应用程序安全领域的权威指南,它总结了Web应用程序中最常见、最危险的安全隐患。以下是对OWASP十大安全漏洞的详细解析: 1. 注入漏洞(Injection) 描述:攻击者通过在应用程序的输入数据中插入恶意代码,从而控制应用程序的行为。常见的注入类型包括SQL注入、OS命令注入、LDAP注入等。 影响:可能导致数据泄

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动