当前位置: 首页 > news >正文

WindowContainerTransaction类详解(一)

1、WindowContainerTransaction是什么:

windowContainerTransaction类的对象是用来存储对windowContainer的修改的一个集合,windowContainer。因为应用侧是无法直接操作windowContainer的,如果应用侧需要修改windowContainer的话,需要通过系统侧对windowContainer进行修改,这就涉及了信息的跨进程传输了。所以首先,WindowContainerTransaction类应该是一个磕跨进程传输的类。看到定义:
public final class WindowContainerTransaction implements Parcelable
也证实了这个猜测,其实现了Parcelable接口。然后就是另一个问题,应用通过系统侧修改WindowContainer的话,必定会告诉他修改窗口的什么属性,然后进去这个类找找代码:

 * Sets whether a container or its children should be hidden. When {@code false}, the existing* visibility of the container applies, but when {@code true} the container will be forced* to be hidden.*/
@NonNull
public WindowContainerTransaction setHidden(@NonNull WindowContainerToken container, boolean hidden) {Change chg = getOrCreateChange(container.asBinder());chg.mHidden = hidden;chg.mChangeMask |= Change.CHANGE_HIDDEN;return this;
}

这里可以看到一个设置窗口及其子窗口是否被隐藏的接口,暂时不详细叙述这个方法的实现。这里可以看到修改这个hidden属性是通过一个Change类的对象实现的,Change类是WindowContainerTransaction的内部类,也是实现了Parcelable接口的。而且WindowContainerTransaction类内部也维护了一个包含Change类的Map:
private final ArrayMap<IBinder, Change> mChanges = new ArrayMap<>();
所以可以大概知道,对窗口的修改应该是通过Change类的对象去描述的。

所以目前可以得知WindowContainerTransaction类的作用,他的对象就是应用侧需要对窗口进行的修改的集合。而这个修改,则是通过Change类的对象描述的。
这里通过一个例子来展示下WindowContainerTransaction类的使用(例子引用自博客https://blog.csdn.net/ukynho/article/details/126747771):

public boolean splitPrimaryTask() {......final WindowContainerTransaction wct = new WindowContainerTransaction();// Clear out current windowing mode before reparenting to split task.wct.setWindowingMode(topRunningTask.token, WINDOWING_MODE_UNDEFINED);wct.reparent(topRunningTask.token, mSplits.mPrimary.token, true /* onTop */);mWindowManagerProxy.applySyncTransaction(wct);return true;
}

由上述示例可见这个WindowContainerTransaction类的使用过程为:1.创建一个WindowContainerTransaction对象;2.通过该对象设置你需要修改的属性;3.提交步骤2设置的修改。

2、如何通过WindowContainerTransaction修改窗口属性:

前面已经讲到了WindowContainerTransaction中的setHidden方法,那就继续分析这个方法:
public WindowContainerTransaction setHidden(@NonNull WindowContainerToken container, boolean hidden) {Change chg = getOrCreateChange(container.asBinder());chg.mHidden = hidden;chg.mChangeMask |= Change.CHANGE_HIDDEN;return this;
}

1)、看参数列表:

参数列表第一个是一个WindowContainerToken对象,看一下定义,这个类是什么含义:

public final class WindowContainerToken implements Parcelable {private final IWindowContainerToken mRealToken;/** @hide */public WindowContainerToken(IWindowContainerToken realToken) {mRealToken = realToken;}private WindowContainerToken(Parcel in) {mRealToken = IWindowContainerToken.Stub.asInterface(in.readStrongBinder());}/** @hide */public IBinder asBinder() {return mRealToken.asBinder();}…………………………………
}

从代码上看,这个类也是实现了Parcelable,然后主要是包装了一个IWindowContainerToken类型的对象。因为系统侧的WMS里要管理所有的WindowContainer,那么WMS中该如何区分每一个WindowContainer呢?那就得用唯一的身份标识,即这个IWindowContainerToken,通过这个Token,WMS可以区分不同的WindowContainer,可以简单理解成,我们每个人其实在国家的户籍管理的制度里,就是用一个身份证号进行辨识的,在人口管理的系统中,我们是以身份证号进行区分的,所以身份证号就是这个Token。而WMS也可以通过WindowContainerToken的asBinder()方法访问到对应WindowContainer的方法。
而我们怎么获取到这个WindowContainerToken方法呢?从示例代码中可见:
wct.setWindowingMode(topRunningTask.token, WINDOWING_MODE_UNDEFINED);
可以通过TaskInfo类的token属性获取。看到TaskInfo类的token属性,正是WindowContainerToken类型的对象。那问题又来了,我们的这个token属性是在什么时候进行的赋值操作的呢?
这里得找到Task.java中的fillTaskInfo()方法了,这里可见info.token的赋值:

void fillTaskInfo(TaskInfo info, boolean stripExtras, @Nullable TaskDisplayArea tda) {
………………………………………………………………info.token = mRemoteToken.toWindowContainerToken();
………………………………………………………………}

这里再提一个小小的疑问:mRemoteToken又是什么?看到Task类中没有定义,于是找到其父类中,最后在WindowContainer类中发现如下定义:
首先他实现了一个aidl接口的Stub类,所以其实RemoteToken就是一个binder的server端的抽象类Stub的子类的实现 。他包含了对WindowContainer的引用和WindowContainerToken。

static class RemoteToken extends IWindowContainerToken.Stub {final WeakReference<WindowContainer> mWeakRef;private WindowContainerToken mWindowContainerToken;RemoteToken(WindowContainer container) {mWeakRef = new WeakReference<>(container);}@NullableWindowContainer getContainer() {return mWeakRef.get();}static RemoteToken fromBinder(IBinder binder) {return (RemoteToken) binder;}WindowContainerToken toWindowContainerToken() {if (mWindowContainerToken == null) {mWindowContainerToken = new WindowContainerToken(this);}return mWindowContainerToken;}@Overridepublic String toString() {StringBuilder sb = new StringBuilder(128);sb.append("RemoteToken{");sb.append(Integer.toHexString(System.identityHashCode(this)));sb.append(' ');sb.append(mWeakRef.get());sb.append('}');return sb.toString();}
}

而且在WindowContainerToken中的mRealToken其实就是IWindowContainerToken的对象,也就是说,mRealToken其实就是一个RemoteToken类型的对象,他才是能够通过弱引用真正的指向WindowContainer,同时还包含WindowContainerToken属性。这里再多说一个点,就是WindowContainerToken,只有Task和DisplayArea才会有。

然后第二个参数就是需要设置的属性了,就不再多说;

2)、setHidden方法的实现:

public WindowContainerTransaction setHidden(@NonNull WindowContainerToken container, boolean hidden) {Change chg = getOrCreateChange(container.asBinder());chg.mHidden = hidden;chg.mChangeMask |= Change.CHANGE_HIDDEN;return this;
}

该方法第一步,定义一个Change对象chg,定义后通过getOrCreateChange方法对chg进行赋值。继续查看该方法的实现。

private Change getOrCreateChange(IBinder token) {Change out = mChanges.get(token);if (out == null) {out = new Change();mChanges.put(token, out);}return out;
}

定义一个Change类型的对象out,然后在mChanges中去get一个Change,看下mChanges的定义发现,这是一个ArrayMap。Key是IBinder(这个IBinder的对象就是一个WindowContainerToken的对象,对应唯一的WindowContainer),value是Change。
private final ArrayMap<IBinder, Change> mChanges = new ArrayMap<>();
那就知道了,肯定有有地方会把这个键值对IBinder和Change组成的键值对放进mChanges中。这里如果是刚初始化的WindowContainerTransaction对象,mChanges肯定是空的,所以out == null,则会将token和out放进mChanges,并返回out。注意这里out只是一个默认的Change()方法构造出来的对象。

public static class Change implements Parcelable {public static final int CHANGE_FOCUSABLE = 1;public static final int CHANGE_BOUNDS_TRANSACTION = 1 << 1;public static final int CHANGE_PIP_CALLBACK = 1 << 2;public static final int CHANGE_HIDDEN = 1 << 3;public static final int CHANGE_BOUNDS_TRANSACTION_RECT = 1 << 4;public static final int CHANGE_IGNORE_ORIENTATION_REQUEST = 1 << 5;public static final int CHANGE_FORCE_NO_PIP = 1 << 6;public static final int CHANGE_FORCE_TRANSLUCENT = 1 << 7;public static final int CHANGE_DRAG_RESIZING = 1 << 8;private final Configuration mConfiguration = new Configuration();private boolean mFocusable = true;private boolean mHidden = false;private boolean mIgnoreOrientationRequest = false;private boolean mForceTranslucent = false;private boolean mDragResizing = false;private int mChangeMask = 0;private @ActivityInfo.Config int mConfigSetMask = 0;private @WindowConfiguration.WindowConfig int mWindowSetMask = 0;private Rect mPinnedBounds = null;private SurfaceControl.Transaction mBoundsChangeTransaction = null;private Rect mBoundsChangeSurfaceBounds = null;private int mActivityWindowingMode = -1;private int mWindowingMode = -1;public Change() {}
…………………………………………………………………………………………………
}

所以Out的属性都是默认值,接下来就是对这个Change进行赋值了,我们看的是setHidden方法,所以需要修改Hidden相关的属性。首先是修改chg.mHidden属性,然后修改chg.mChangeMask。
mHidden属性就可以简单的认为是否需要隐藏,下面的mChangeMask就是一个标志位,通过这个属性能得知提交的WindowContainerTransaction进行了哪些属性的修改。
通过Change的初始值可知,mChangeMask = 0;是int类型。CHANGE_HIDDEN = 1<<3; 通过将二者进行异或运算,就能将标志着HIDDEN属性变化的第三位设置为1.

于是,在系统侧应用WindowContainerTransaction的时候,可以看到,这里就会通过mChangeMask属性与标志位的结果进行判断后,再对修改进行应用。

private int applyTaskChanges(Task tr, WindowContainerTransaction.Change c) {int effects = applyChanges(tr, c, null /* errorCallbackToken */);final SurfaceControl.Transaction t = c.getBoundsChangeTransaction();if ((c.getChangeMask() & WindowContainerTransaction.Change.CHANGE_HIDDEN) != 0) {if (tr.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, c.getHidden())) {effects = TRANSACT_EFFECTS_LIFECYCLE;}}if ((c.getChangeMask()& WindowContainerTransaction.Change.CHANGE_FORCE_TRANSLUCENT) != 0) {tr.setForceTranslucent(c.getForceTranslucent());effects = TRANSACT_EFFECTS_LIFECYCLE;}
…………………………………………………………………………………………
}

3)reparent方法的实现:

public WindowContainerTransaction reparent(@NonNull WindowContainerToken child,@Nullable WindowContainerToken parent, boolean onTop) {mHierarchyOps.add(HierarchyOp.createForReparent(child.asBinder(),parent == null ? null : parent.asBinder(),onTop));return this;
}

这里不是通过Change保存reparent操作,而是通过mHierarchyOps来保存修改的。看下定义,mHierarchyOps 是一个ArrayList类型的对象。里面存储的是HierarchyOp类型的变量。

private final ArrayList<HierarchyOp> mHierarchyOps = new ArrayList<>();

然后再看到HierarchyOp的构造方法,这里container就是需要重新设置parent的WindowContainer,然后reparent就是新的parent,toTop代表reparent操作后是否需要将子WindowContainer移动到父

WindowContainerToppublic static HierarchyOp createForReparent(@NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) {return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REPARENT).setContainer(container).setReparentContainer(reparent).setToTop(toTop).build();
}

相关文章:

WindowContainerTransaction类详解(一)

1、WindowContainerTransaction是什么&#xff1a; windowContainerTransaction类的对象是用来存储对windowContainer的修改的一个集合&#xff0c;windowContainer。因为应用侧是无法直接操作windowContainer的&#xff0c;如果应用侧需要修改windowContainer的话&#xff0c…...

安装NFS扩展

#添加helm源 helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner #创建个namespace(可选,主要是为了查看资源方便) kubectl create ns nfs-sc-default #使用helm安装(10.1.129.86为NFS地址,/home/data/nfs…...

计算机网络——运输层(进程之间的通信、运输层端口,UDP与TCP、TCP详解)

运输层协议概述 进程之间的通信 运输层向它上面的应用层提供通信服务。 当网络边缘部分的两台主机使用网络核心部分的功能进行端到端的通信时&#xff0c;都要使用协议栈中的运输层&#xff1b;而网络核心部分中的路由器在转发分组时只用到下三层的功能。 Q1&#xff1a;我们…...

代码随想录算法训练营第一天 | 二分查找

文章目录 Leetcode704 二分查找二分法的使用前提:区间选择其他注意事项 Leetcode27 移除元素解题思路:优化思路 Leetcode704 二分查找 链接&#xff1a;https://leetcode.cn/problems/binary-search/ 代码随想录: https://programmercarl.com/ 时间复杂度: O(logN) 空间复杂度:…...

python相关知识

1、注释 共有三种&#xff1a;#、 、””” ””” 2、数据类型 整数、浮点、字符串、布尔、列表、元组、集合、字典 num1 666、num2 3.14、t1 True、t2 False、 列表&#xff1a;list [1,2,3,4] 元组&#xff1a;tuple (11,aaa,ddd,3) 字典&#xff1a;dict {li…...

Visual Studio 2022 LNK2001无法解析的外部符号 _wcscat_s 问题记录

ANSI C程序中&#xff0c;用到了wcsrchr、wcsncpy_s、wcscat_s、wcscpy_s等几个字符串函数&#xff0c;但是编译时提示&#xff1a; 错误 LNK2001 无法解析的外部符号 _wcscat_s 查了挺多帖子&#xff0c;没有解决。 https://bbs.csdn.net/topics/250012844 解决VS编译…...

Java高并发处理机制

高并发处理的思路&#xff1a; 扩容&#xff1a;水平扩容、垂直扩容缓存&#xff1a;将基础的数据放入缓存进行处理使用SpringCloud的注册中心&#xff0c;分服务注册到同一个注册中心&#xff0c;服务器检测使用Spring的熔断操作&#xff0c;检测服务器的心跳那个正常随机跳转…...

7 数据存储单位,整型、浮点型、字符型、布尔型数据类型,sizeof 运算符

目录 1 数据类型的分类 2 数据存储单位 2.1 位 2.2 字节 2.3 其余单位 3 整数类型 3.1 基本介绍 3.2 整型的类型 3.2.1 整数类型多样性的原因 3.2.2 整型类型之间的相对大小关系 3.3 整型注意事项 3.4 字面量后缀 3.5 格式占位符 3.6 案例&#xff1a;声明并输出…...

导游职业资格考试真题题库

导游职业资格考试真题题库 80.重庆有"雾都"之称。壁山区的()全年雾日多204天&#xff0c;堪称"世界之最"。 A.枇杷山 B.雾灵山 C.云雾山 D.四姑娘山 答案&#xff1a;C 81.我国最具热带海洋气候特色的地方为&#xff08;&#xff09;。 A.广西壮族…...

【Rust】使用开源项目搭建瓦片地图服务

本文通过获取在线和离线地图数据&#xff0c;使用开源Rust项目搭建瓦片地图服务&#xff0c;并使用DevExpress的MapControl控件使用自建地图服务 获取地图数据 获取地图数据有很多种方式&#xff0c;这里分别用在线和离线地图数据举例说明 在线下载瓦片地图 打开在线瓦片地…...

【面试宝典】mysql常见面试题总结(上)

一、MySQL 中有哪几种锁&#xff1f; MySQL中的锁机制是数据库并发控制的重要组成部分&#xff0c;它用于管理多个用户对数据库资源的访问&#xff0c;确保数据的一致性和完整性。MySQL中的锁可以根据不同的分类标准进行分类&#xff0c;以下是一些常见的分类方式及对应的锁类…...

第1章 初识C语言

第1章 初识C语言 1.1 C语言概述 1.1.1 C语言的发展历史 C语言的原型为ALGOL 60语言&#xff08;也称A语言&#xff09;。 1963年 剑桥大学将ALGOL 60语言发展成为GPL语言。 1967年 剑桥大学的Matin Richards简化GPL&#xff0c;产生了BGPL语言。 1970年 美国贝尔实验室的Ken…...

【考研数学】定积分应用——旋转体体积的计算(一文以蔽之)

目录 一、如何计算旋转体体积&#xff1f;思考一个小例子 二、旋转体体积的二重积分表达式 三、用真题&#xff0c;小试牛刀 定积分的应用中&#xff0c;有一类题是求解旋转体的体积问题。 相较于记忆体积计算公式&#xff0c;有一种通法求解体积更不容易出错&#xff1a;二重…...

PHP移动端商城分销全平台全端同步使用

&#x1f4f1;【掌中购物新纪元&#xff1a;探索移动端购物商城系统的无限魅力】&#x1f6cd;️ &#x1f680; 随时随地&#xff0c;购物自由新体验 在这个快节奏的时代&#xff0c;移动端购物商城系统彻底颠覆了传统购物方式&#xff0c;让消费者享受到了前所未有的便捷与…...

TLE8386-2EL:汽车级DC-DC转换器中文资料书

描述 TLE8386-2EL是一款具有内置保护功能的低端感应升压控制器。该器件的主要功能是将输入电压升高&#xff08;升压&#xff09;到更大的输出电压。开关频率可从100kHz调整至700kHz&#xff0c;并可与外部时钟源同步。 TLE8386-2EL的独特功能可将关断电流消耗降至 <2μA。该…...

EasyRecovery17中文mac苹果电脑版数据恢复软件 永久免费破解版下载

&#x1f389; 数据丢失不再是噩梦&#xff01;EasyRecovery17中文版来拯救你的硬盘啦&#xff01; 各位小伙伴们&#xff0c;有没有遇到过重要文件一不小心就消失无踪的尴尬情况&#xff1f;别担心&#xff0c;今天就给大家种草一款神奇的工具——EasyRecovery17中文版&#x…...

Ubuntu 22.04 安装 VirtualBox7

Ubuntu默认库为VirtualBox-6版本 # 安装 VirtualBox-6 sudo apt update sudo apt install virtualbox# 卸载 VirtualBox-6 sudo apt remove --purge --auto-remove virtualbox virtualbox-6.1 1. 安装 VirtualBox-7 # 导入软件包密钥 curl https://www.virtualbox.org/downl…...

NPM使用教程:从入门到精通

NPM使用教程&#xff1a;从入门到精通&#xff0c;掌握Node.js包管理神器 引言 随着Node.js的流行&#xff0c;JavaScript已经成为服务器端开发的主力军。NPM&#xff08;Node Package Manager&#xff09;作为Node.js的官方包管理工具&#xff0c;为开发者提供了一个庞大的代…...

模电实验3 - 单电源集成运放交流耦合放大器

实验目标 学习集成运放的单电源使用。掌握交流耦合单电源集成运放放大器的测试方法。了解交流耦合单电源集成运放放大器的特点。 实验器材 ADALM2000 1kΩ 电阻 (1/4 W) x 1 10 kΩ 电阻 (1/4 W) x 1 100kΩ 电阻 (1/4 W) x 3 0.1μF电容 x 1 1μF电容 …...

海对外经贸大学学报

《上海对外经贸大学学报》创刊于1994年&#xff0c;原名为《世界贸易组织动态与研究》(上海对外贸易学院学报)&#xff0c;随原上海对外贸易学院更名为上海对外经贸大学&#xff0c;自2014年起更为现名&#xff0c;现为综合性社科类双月刊&#xff0c;为中文社会科学引文检索&a…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

Axure 下拉框联动

实现选省、选完省之后选对应省份下的市区...