WindowManager相关容器类

窗口中容器类介绍:
本节内容较多,建议结合前面的内容一起阅读:
1、addWindow的宏观概念
2、WindowManager#addView_1
3、WindowManager#addView_2

1)、WindowContainer:

class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>{
……………………
}

WindowContainer的定义如上,可见其是一个容器,容器内的元素是自己或自己的子类(如:RootWindowContainer、DisplayContent、DisplayArea、DisplayArea.Tokens、TaskDisplayArea、Task、ActivityRecord、WindowToken、WindowState),而WindowContainer类继承自ConfigurationContainer类,该类也是一个容器类,其元素为自己或自己的子类。
其中有一些属性比较重要:mParent和mChildren,分别代表父节点和子节点。其中子节点是WindowList类型的,其排列顺序是依据其在z轴上的高度排列的,尾部的节点在z轴上最高最容易被用户看到。

2)、RootWindowContainer:

class RootWindowContainer extends WindowContainer<DisplayContent>implements DisplayManager.DisplayListener {

WindowContainer的根容器,可通过该节点遍历到窗口树上的任意窗口。他的mChildren继承自WindowContainer,所以该List的元素为DisplayContent。
在这里插入图片描述

3)、DisplayContent:

class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.DisplayContentInfo {

对应显示屏幕的概念,一个屏幕对应一个DisplayContent。一般情况下都是只有一个。在同一个DisplayContent中的窗口都会显示在同一个屏幕内。

4)、WindowToken:

class WindowToken extends WindowContainer<WindowState> {

WindowToken类是WindowState的容器,WindowState之前说过,在WMS中代表了一个窗口。
在这里插入图片描述

5)、ActivityRecord:

final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {

该类继承自WindowToken,所以也是WindowState类的容器。
在这里插入图片描述

6)、WindowState:

class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState,InsetsControlTarget, InputTarget {

其实WindowState也可以作为其他WindowState的容器;
在这里插入图片描述

7)、WallpaperWindowToken:

class WallpaperWindowToken extends WindowToken {

该类同样继承自WindowToken;
对以上4)-7)进行统一分析,所有的窗口分三大类:系统窗口、应用窗口、其他窗口;其中系统窗口在最上层,应用窗口次之,而系统窗口的容器则为WindowToken,应用窗口为ActivityRecord。而App以下的窗口,父容器就为WallpaperWindowToken。

8)、DisplayArea.Tokens:

是WindowToken的父容器,同时会在其中对WindowToken进行排序;
在这里插入图片描述

public static class Tokens extends DisplayArea<WindowToken> {
private final Comparator<WindowToken> mWindowComparator =Comparator.comparingInt(WindowToken::getWindowLayerFromType);//这就是排序算法的核心。
}

排序算法触发的前提就是addChild函数,和前一节说的一样,找到addChild函数:

void addChild(WindowToken token) {addChild(token, mWindowComparator);
}

这里可以看到在addChild的时候,通过mWindowComparator为WindowToken确认顺序,而mWindowComparator的初始化是通过WindowToken.java中的getWindowLayerFromType方法作为比较器的。最后的方法实现在WindowManagerPolicy.java中的getWindowLayerFromTypeLw()方法。这里在addWindow的宏观概念一文中有讲到,主要就是对比了窗口的类型,如果是应用窗口则直接返回2,如果是wallpaper窗口,直接返回1(在最底层);然后再根据窗口的类型返回其排序的权重,根据权重再决定该窗口在子窗口中该插入到哪个位置。其中这里的type是在WindowToken中的一个属性:从注释看就是WindowManager类中的LayoutParams属性,这个属性会在窗口初始化时确定。

/** The type of window this token is for, as per {@link WindowManager.LayoutParams} */
final int windowType;

9)、Task:

ActivityRecord的容器,作为应用窗口的容器,ActivityRecord也是需要容器的。
在这里插入图片描述

class Task extends TaskFragment {

从定义可见Task是继承自TaskFragment的一个类。而TaskFragment则也是继承自WindowContainer的类。
class TaskFragment extends WindowContainer {
Task可以是Task的容器,也可以是ActivityRecord的容器,最形象的理解就是多任务界面的一个窗口就是一个Task。TaskFragment这个类型我了解不多,只知道和平行视界相关。平行视界中两个Activity需要同时显示,Task实现不了这个功能,所以再Task和ActivityRecord之间加入了TaskFragment。而一般情况下因为TaskFragment是Task的父类,所以大家都会通过TaskFragment创建对象,但是最终创建的还是Task类型的对象
这里的排序的话比较简单:老规矩找到addchild方法。

void addChild(WindowContainer child, int index) {index = getAdjustedChildPosition(child, index);super.addChild(child, index);ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);// A rootable task that is now being added to be the child of an organized task. Making// sure the root task references is keep updated.if (mTaskOrganizer != null && mCreatedByOrganizer && child.asTask() != null) {getDisplayArea().addRootTaskReferenceIfNeeded((Task) child);}// Make sure the list of display UID allowlists is updated// now that this record is in a new task.mRootWindowContainer.updateUIDsPresentOnDisplay();// Only pass minimum dimensions for pure TaskFragment. Task's minimum dimensions must be// passed from Task constructor.下面应该就是平行视界这类相关的操作了final TaskFragment childTaskFrag = child.asTaskFragment();if (childTaskFrag != null && childTaskFrag.asTask() == null) {childTaskFrag.setMinDimensions(mMinWidth, mMinHeight);// The starting window should keep covering its task when a pure TaskFragment is added// because its bounds may not fill the task.final ActivityRecord top = getTopMostActivity();if (top != null) {top.associateStartingWindowWithTaskIfNeeded();}}
}

这个方法比较直接,直接通过index指定了位置。虽然指定了位置,但是程序中还是要对其进行调整的。

private int getAdjustedChildPosition(WindowContainer wc, int suggestedPosition) {final boolean canShowChild = wc.showToCurrentUser();final int size = mChildren.size();// Figure-out min/max possible position depending on if child can show for current user.int minPosition = (canShowChild) ? computeMinUserPosition(0, size) : 0;int maxPosition = minPosition;if (size > 0) {maxPosition = (canShowChild) ? size - 1 : computeMaxUserPosition(size - 1);}// Factor in always-on-top children in max possible position.if (!wc.isAlwaysOnTop()) {// We want to place all non-always-on-top containers below always-on-top ones.while (maxPosition > minPosition) {if (!mChildren.get(maxPosition).isAlwaysOnTop()) break;--maxPosition;}}// preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.if (suggestedPosition == POSITION_BOTTOM && minPosition == 0) {return POSITION_BOTTOM;} else if (suggestedPosition == POSITION_TOP && maxPosition >= (size - 1)) {return POSITION_TOP;}// Increase the maxPosition because children size will grow once wc is added.if (!hasChild(wc)) {++maxPosition;}// Reset position based on minimum/maximum possible positions.return Math.min(Math.max(suggestedPosition, minPosition), maxPosition);
}

这里其实就是根据最大最小值和指定的值进行对比然后修正一下。

不过还有另一个形式的addChild算法:

void addChild(WindowContainer child, final boolean toTop, boolean showForAllUsers) {Task task = child.asTask();//这里如果child是task则返回一个值,否则返回null。try {if (task != null) {task.setForceShowForAllUsers(showForAllUsers);}// We only want to move the parents to the parents if we are creating this task at the// top of its root task.addChild(child, toTop ? MAX_VALUE : 0, toTop /*moveParents*/);} finally {if (task != null) {task.setForceShowForAllUsers(false);}}
}

这个算法参数都不同了,有三个参数,这里第一步直接判断子元素是不是task类型。如果是的话,就执行setForceShowForAllUsers该方法,但是这里也没啥,就是对mForceShowForAllUsers进行赋值,然后就是对其进行比较器为null的排序,这里就不重复讲了,比较的过程在WindowContainer.java中的protected void addChild(E child, Comparator comparator) 该方法中。

10)、TaskDisplayArea:

Task或者TaskDisplayArea的容器。继承自DisplayArea类。代表的是屏幕上一块专门用来存放app窗口的区域。其父容器是DisplayContent。

在这里插入图片描述

final class TaskDisplayArea extends DisplayArea<WindowContainer> {
这个类对其中元素排序的方法依然可以通过addChild方法去查看,
void addChild(WindowContainer child, int position) {if (child.asTaskDisplayArea() != null) {if (DEBUG_ROOT_TASK) {Slog.d(TAG_WM, "Set TaskDisplayArea=" + child + " on taskDisplayArea=" + this);}super.addChild(child, position);} else if (child.asTask() != null) {addChildTask(child.asTask(), position);} else {throw new IllegalArgumentException("TaskDisplayArea can only add Task and TaskDisplayArea, but found "+ child);}
}

其对于两个子类的元素有着不同的排序方法。第一种就是直接调用WindowContainer.java中的addChild(E child, int index)方法,直接在指定位置添加。
第二个的话就是如果元素是task类的话其实和上面也差不多,就是通过当前已有的一些子类对指定的位置进行一些修正。

11)、DisplayArea:

该类用于将WindowContainer分组到DisplayContent下方的容器。DisplayArea是被DisplayAreaPolicy管理的,能够复写Configuration和被绑定到leash上,并且可以嵌套DisplayArea,该类有三种风格:
BELOW_TASKS:只能包含位于任务下方的BELLOW_TASK显示区域和WindowToken。
ABOVE_TASKS:只能包含位于任务上方的ABOVE_TASK显示区域和WindowToken。
ANY:可以包含任何类型的DisplayArea,以及任何类型的WindowToken或Task容器。

12)、RootDisplayArea:

DisplayArea的根节点。根据注释来看:从等级制度上是DisplayArea的根节点。同时也可以是 逻辑屏幕上DisplayContent的根节点,或者逻辑屏幕上一个群组DisplayAreaGroup的根节点。

/*** Root of a {@link DisplayArea} hierarchy. It can be either the {@link DisplayContent} as the root* of the whole logical display, or a {@link DisplayAreaGroup} as the root of a partition of the* logical display.*/
class RootDisplayArea extends DisplayArea.Dimmable {

所以这里将屏幕上的窗口分为两个逻辑,一个是等级制度,一个是物理屏幕。
在这里插入图片描述

13)、DisplayAreaGroup:

继承自RootDisplayArea,可以理解为一个集群,一个DisplayArea和DisplayContent之间的一个集群。 DisplayContent是整个屏幕上DisplayArea的根节点,但是一部分DisplayArea也可以挂载在DisplayAreaGroup上 。

/** The root of a partition of the logical display. */
class DisplayAreaGroup extends RootDisplayArea {

14)、另外还有一个容器ImeContainer:

这是输入法相关的,我暂时没了解,看定义大概能知道也是一类WindowToken的容器。

private static class ImeContainer extends DisplayArea.Tokens {

综上最后得到一个关系图:其中我将一个层级的都用同一个颜色标注出来。
请添加图片描述

然后再通过类图对其中涉及到的类进行归类。
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/20063.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法(一)递归

文章目录 递归的概念递归三要素递归demo打印100次“hello word”斐波那契数列 递归的概念 递归算法是一种直接或者间接调用自身函数或者方法的算法。 递归三要素 递归条件结束 因为递归是循环调用自身&#xff0c;因此就必须要有结束条件&#xff0c;或者就会OOM。 函数的功…

低代码开发系统是什么?它有那些部分组成?

低代码开发系统是什么&#xff1f;它有那些部分组成&#xff1f; 一、引言 在当今快速变化的商业环境中&#xff0c;企业对于快速响应市场需求、降低开发成本和提高开发效率的需求日益增强。低代码开发系统&#xff08;Low-Code Development Platform&#xff09;应运而生&am…

安卓启动 性能提升 20-30% ,基准配置 入门教程

1.先从官方下载demohttps://github.com/android/codelab-android-performance/archive/refs/heads/main.zip 2.先用Android studio打开里面的baseline-profiles项目 3.运行一遍app&#xff0c;这里建议用模拟器&#xff0c;&#xff08;Pixel 6 API 34&#xff09;设备运行&a…

思科防火墙 网线连接的端口还是down 已配置 端口还是down

环境&#xff1a; 思科防火墙fpr-2100 isco Firepower 2100 系列防火墙是思科系统&#xff08;Cisco Systems&#xff09;推出的一款中端网络安全和防火墙设备。这一系列的产品主要针对中到大型企业的需求&#xff0c;提供高性能的威胁防护和网络流量管理功能。 问题描述&am…

Java微服务智慧工地可视化SaaS云解决方案源码

智慧工地是指运用信息化手段&#xff0c;围绕施工过程管理&#xff0c;建立互联协同、智能生产、科学管理的施工项目信息化生态圈&#xff0c;并将此数据在虚拟现实环境下与物联网采集到的工程信息进行数据挖掘分析&#xff0c;提供过程趋势预测及专家预案&#xff0c;实现工程…

排序算法之直接选择排序【图文详解】

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;LiUEEEEE                        …

基于tensorflow和NasNet的皮肤癌分类项目

数据来源 https://challenge.isic-archive.com/data/#2019 数据划分 写了个脚本划分 for line in open(ISIC/labels.csv).readlines()[1:]:split_line line.split(,)img_file split_line[0]benign_malign split_line[1]# 0.8 for train, 0.1 for test, 0.1 for validati…

快蜗牛OZON数据分析,OZON快蜗牛数据

在当今电商行业蓬勃发展的背景下&#xff0c;OZON作为俄罗斯及东欧市场的重要电商平台&#xff0c;其数据背后蕴藏着巨大的商业价值。快蜗牛&#xff0c;作为专注于OZON平台的数据分析工具&#xff0c;为卖家提供了深入的市场洞察和策略指导。接下来看看快蜗牛OZON数据分析&…

线上 | OpenSergo - [规范]

INDEX 1 参考资料2 OpenSergo 与 Sentinel 关系3 规范体系3.1 服务元数据ReportMetadataRequest 信息![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/ffba569841ae4668b4cff74e4d41d21f.png)##### ReportMetadataReply 信息![在这里插入图片描述](https://img-blog…

BurpSuite2024.5

1 工具介绍 本版本更新介绍 此版本引入了Burp Scanner对WebSockets的支持、对记录登录编辑器的改进、WebSocket 匹配和替换规则以及许多性能改进。 Burp Scanner 支持 WebSockets 我们已更新内部代理的配置以允许 WebSocket 流量。这使 Burp Scanner 现在可以抓取依赖 WebSo…

基于大模型的智慧零售教育科研平台——技术方案

一、概述 1.1背景 随着数字经济的快速发展和全社会数字化水平的升级&#xff0c;人工智能的积极作用越来越凸显&#xff0c;人工智能与各个行业的深度融合已成为促进传统产业转型升级的重要方式之一。ChatGPT的出现掀起了又一波人工智能发展热潮&#xff0c;人工智能行业发展势…

Linux sudo用户权限管理小实验001

Linux sudo用户权限管理和审计-初步 1、设置历史指令的保存数量 默认history指令可以查看当前用户执行的1000条历史命令的条目 2、使用export指令设置HISTSIZE环境变量的数量为999999条。 3、基于date指令&#xff0c;输出日期和时间 4、设置linux系统history相关变量&…

预编码算法(个人总结)

引言 预编码算法是现代无线通信系统中的关键技术&#xff0c;特别是在多输入多输出&#xff08;MIMO&#xff09;系统中。它们通过在发送端对信号进行处理&#xff0c;减少干扰并提高信道容量。这种技术广泛应用于5G、Wi-Fi和卫星通信系统中。本教程将详细介绍预编码算法的背景…

FV悬浮球,安卓真正小而美的神器,满足你的一切需求。

如果你问安卓最强软件有哪些&#xff0c;不同的人可能会有不同的答案&#xff0c;但如果是问我&#xff0c;那我的答案中一定会有他。 FV悬浮球 他是ES文件浏览器&#xff0c;原作者的新作品&#xff0c;经过几年的开发&#xff0c;拥有了超过400项功能&#xff0c;但大小只有…

如何在 llama.cpp 服务器中实现用户登录功能的优化方案?(语言-c++)

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

HCIP-Datacom-ARST自选题库__BGP/MPLS IP VPN判断【10道题】

1.部署BGP/MPLSIP VPN时,当两个VPN有共同的站点,则该共同站点一定不能与两个VPN其他站点使用重叠的地址空间。 2.如图所示&#xff0c;运营商BGP/MPLSIP VPN骨干网通过LDP构建LSP&#xff0c;若想实现用户X两个站点之间通过BGP/MPLSIP VPN网络互通&#xff0c;则PE1和PE2之间必…

ZL-LGF-2离体心脏灌流系统适用于离体哺乳动物心脏灌流和离体心脏冠脉流量的测定

单介绍&#xff1a; 离体心脏灌流系统适用于离体哺乳动物心脏灌流&#xff08;langendorff氏法&#xff09;和离体心脏冠脉流量的测定&#xff0e;可直接进行恒压灌流&#xff0c;加上蠕动泵可进行恒流灌流&#xff0e; 详情介绍&#xff1a; 1、灌流数量&#xff1a;2个心脏…

10款实用软件工具推荐,从绘图到系统优化一应俱全!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/ 1.绘图软件——Adobe Fresco Adobe Fresco是由Adobe公司推出的一款绘图软件&#xff0c;适用于Windows平台。Adobe Fresco是一款功能强大的绘…

tinyrenderer-切线空间法线贴图

法线贴图 法线贴图分两种&#xff0c;一种是模型空间中的&#xff0c;一种是切线空间中的 模型空间中的法线贴图的rgb代表着每个渲染像素法线的xyz&#xff0c;与顶点坐标处于一个空间&#xff0c;图片是五颜六色的。 切线空间中的法线贴图的rgb同样对应xyz&#xff0c;是切线…