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

Android14 WMS-窗口绘制之relayoutWindow流程(一)-Client端

Android14 WMS-窗口添加流程(一)-Client端-CSDN博客

Android14 WMS-窗口添加流程(二)-Server端-CSDN博客

经过上述两个流程后,窗口的信息都已经传入了WMS端。

f57b6efae369489bbf40634cccb43bf0.jpg

 

1. ViewRootImpl#setView

在窗口添加流程(一)中,有这个方法:

http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/view/ViewRootImpl.java#1314

    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,int userId) {
...// Schedule the first layout -before- adding to the window// manager, to make sure we do the relayout before receiving// any other events from the system.requestLayout();
...}

2. ViewRootImpl#requestLayout

requestLayout中的scheduleTraversals是一个异步方法

    @Overridepublic void requestLayout() {if (!mHandlingLayoutInLayoutRequest) {checkThread();mLayoutRequested = true;
//异步方法scheduleTraversals();}}

3. ViewRootImpl#scheduleTraversals

scheduleTraversals中有一个Runnable方法

关于Choreographer编舞者,这里也不重点介绍。

    final class TraversalRunnable implements Runnable {@Overridepublic void run() {
//执行view遍历操作,进行measure,layout,draw操作doTraversal();}}final TraversalRunnable mTraversalRunnable = new TraversalRunnable();@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)void scheduleTraversals() {if (!mTraversalScheduled) {mTraversalScheduled = true;mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
//Choreographer Posts a callback to run on the next frame.
// The callback runs once then is automatically removed.mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);notifyRendererOfFramePending();pokeDrawLockIfNeeded();}}

4. ViewRootImpl#doTraversal

来看看Runnable中的方法

void doTraversal() {if (mTraversalScheduled) {mTraversalScheduled = false;mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
...
//要执行到了真正的遍历操作,这就要对view执行measure,layout, draw流程了performTraversals();
...}}

5. ViewRootImpl#performTraversals

    private void performTraversals() {
...// cache mView since it is used so much below...
//这个mView是通过setView方法传进来的,也就是Activity的根布局DecorView,使用final修饰,以防在遍历过程中被修改final View host = mView;
...
//mAdded指DecorView是否被成功加入到window中,在setView()中被赋值为trueif (host == null || !mAdded) {mLastPerformTraversalsSkipDrawReason = host == null ? "no_host" : "not_added";return;}
...mIsInTraversal = true;//是否正在遍历mWillDrawSoon = true;//是否需要马上绘制boolean cancelDraw = false;String cancelReason = null;boolean isSyncRequest = false;boolean windowSizeMayChange = false;WindowManager.LayoutParams lp = mWindowAttributes;
//顶层视图DecorView窗口的期望宽高int desiredWindowWidth;int desiredWindowHeight;
//DecorView是否可见final int viewVisibility = getHostVisibility();
//视图可见性改变final boolean viewVisibilityChanged = !mFirst&& (mViewVisibility != viewVisibility || mNewSurfaceNeeded// Also check for possible double visibility update, which will make current// viewVisibility value equal to mViewVisibility and we may miss it.|| mAppVisibilityChanged);
...WindowManager.LayoutParams params = null;
...boolean windowShouldResize = layoutRequested && windowSizeMayChange&& ((mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight())|| (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT &&frame.width() < desiredWindowWidth && frame.width() != mWidth)|| (lp.height == ViewGroup.LayoutParams.WRAP_CONTENT &&frame.height() < desiredWindowHeight && frame.height() != mHeight));windowShouldResize |= mDragResizing && mPendingDragResizing;
...
//第一次执行测量布局绘制操作||Activity窗口大小需要改变||View的可见性发生了变化||窗口属性发生了变化||ViewRootHandler接收到消息MSG_RESIZED_REPORT,即size改变了if (mFirst || windowShouldResize || viewVisibilityChanged || params != null|| mForceNextWindowRelayout) {
...
//如果此窗口为窗口管理器提供内部insets,那么我们首先要在布局期间使提供的insets保持不变。
//这样可以避免它短暂地导致其他窗口根据窗口的原始框架调整大小/移动,
//等到我们完成此窗口的布局并返回窗口管理器,并最终计算出插图。insetsPending = computesInternalInsets;
...
//判断是否有surfaceboolean hadSurface = mSurface.isValid();try {
...if (mFirst || viewVisibilityChanged) {mViewFrameInfo.flags |= FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED;}
//params,窗口属性变化内容
//请求WMS计算Activity窗口大小及边衬区域大小relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
...// Ask host how big it wants to be//绘制三部曲之measureperformMeasure(childWidthMeasureSpec, childHeightMeasureSpec);...//绘制三部曲之layoutperformLayout(lp, mWidth, mHeight);...//绘制三部曲之drawperformDraw();
...

6. ViewRootImpl#relayoutWindow

我们主要是来看看ViewRootImpl如何向WMS申请布局的

    private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,boolean insetsPending) throws RemoteException {
...
//window申请的宽final int requestedWidth = (int) (measuredWidth * appScale + 0.5f);
//window申请的高final int requestedHeight = (int) (measuredHeight * appScale + 0.5f);int relayoutResult = 0;mRelayoutSeq++;if (relayoutAsync) {mWindowSession.relayoutAsync(mWindow, params,requestedWidth, requestedHeight, viewVisibility,insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mRelayoutSeq,mLastSyncSeqId);} else {
//请求重新布局relayoutResult = mWindowSession.relayout(mWindow, params,requestedWidth, requestedHeight, viewVisibility,insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mRelayoutSeq,mLastSyncSeqId, mTmpFrames, mPendingMergedConfiguration, mSurfaceControl,mTempInsets, mTempControls, mRelayoutBundle);
...

这里就又用到了AIDL,WindowSession,WindowSession是APP和WMS沟通的桥梁

   final IWindowSession mWindowSession;

可以看下这篇文章加强理解

Android14 WMS-IWindowSession介绍-CSDN博客

7. Session #relayout

 

//Session继承了IWindowSession.Stub
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
...@Overridepublic int relayout(IWindow window, WindowManager.LayoutParams attrs,int requestedWidth, int requestedHeight, int viewFlags, int flags, int seq,int lastSyncSeqId, ClientWindowFrames outFrames,MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl,InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls,Bundle outSyncSeqIdBundle) {if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "+ Binder.getCallingPid());Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
//调用到了Server端int res = mService.relayoutWindow(this, window, attrs,requestedWidth, requestedHeight, viewFlags, flags, seq,lastSyncSeqId, outFrames, mergedConfiguration, outSurfaceControl, outInsetsState,outActiveControls, outSyncSeqIdBundle);Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "+ Binder.getCallingPid());return res;}

8. WindowManagerService #relayoutWindow

Server端流程太多了,另起一篇文章分析。

 

 

相关文章:

Android14 WMS-窗口绘制之relayoutWindow流程(一)-Client端

Android14 WMS-窗口添加流程(一)-Client端-CSDN博客 Android14 WMS-窗口添加流程(二)-Server端-CSDN博客 经过上述两个流程后&#xff0c;窗口的信息都已经传入了WMS端。 1. ViewRootImpl#setView 在窗口添加流程(一)中&#xff0c;有这个方法&#xff1a; http://aospxref…...

JVM学习-Jprofiler

JProfiler 基本概述 特点 使用方便&#xff0c;界面操作友好对被分析的应用影响小(提供模板)CPU&#xff0c;Tread&#xff0c;Memory分析功能尤其强大支持对jdbc,noSql,jsp,servlet,socket进行分析支持多种模式(离线、在线)的分析支持监控本地、远程JVM跨平台&#xff0c;拥…...

Skins

本主题解释如何将DevExpress主题/皮肤应用到应用程序中&#xff0c;如何允许用户在运行时在主题之间切换&#xff0c;如何自定义现有皮肤或创建自己的皮肤&#xff0c;等等。 WinForms订阅包括许多基本控件&#xff1a;按钮、复选框、表单、消息框、对话框、对话框等。 我们实现…...

【Meetup】探索Apache SeaTunnel的二次开发与实战案例

在数据科技快速演进的今天&#xff0c;业务场景的复杂化和数据量的激增&#xff0c;推动了大数据技术的迅速发展&#xff0c;在众多开源大数据处理工具中&#xff0c;Apache SeaTunnel以其强大的数据集成能力&#xff0c;成为众多企业的首选。 但随着应用深入&#xff0c;企业面…...

嵌入式Linux系统中RTC应用的操作详解

第一:RTC的作用以及时间简介 “RTC”的英文全称是Reul-Time Clock,翻译过来是实时时钟芯片.实时时钟芯片是日常生活中应用最为广泛的电子器件之一,它为人们或者电子系统提供精确的实时时间,实时时钟芯片通过引脚对外提供时间读写接口,通常内部带有电池,保证在外部系统关…...

Edge 工作区是什么?它都有哪些作用?

什么是工作区 Edge 工作区是什么&#xff1f;它是微软 Edge 浏览器中的一个功能&#xff0c;在帮助用户更好地组织和管理他们的浏览会话。通过工作区&#xff0c;用户可以创建多个独立的浏览环境&#xff0c;每个工作区内包含一组相关的标签页和浏览器设置。这使得用户能够根据…...

Docker|了解容器镜像层(1)

引言 容器非常神奇。它们允许简单的进程表现得像虚拟机。在这种优雅的底层是一组模式和实践&#xff0c;最终使一切运作起来。在设计的根本是层。层是存储和分发容器化文件系统内容的基本方式。这种设计既出人意料地简单&#xff0c;同时又非常强大。在今天的帖子[1]中&#xf…...

vue3设置全局变量并获取 全局响应式变量 窗口大小

设置 js文件统一管理全局变量 方法1 app provide() 全局提供变量 通过inject()使用 方法2 app实例配置全局变量 获取 通过 getCurrentInstance.appContext.config.globalProperties.$innerWidth访问到 code import { ref } from vue export const useGlobalState () > {c…...

Java——面向对象进阶(一)

前言 面向对象进阶(一)&#xff1a;static&#xff0c;继承&#xff0c;this和super关键字 文章目录 一、static1.1 静态变量1.2 静态方法1.3 静态变量和静态方法在内存中 二、继承2.1 概念2.2 继承的特点和能继承什么2.3 继承中的重写2.4 this和super关键字 一、static 在 Jav…...

JDBC是什么?它如何工作?

一、JDBC概述 JDBC&#xff08;Java Database Connectivity&#xff09;是Java语言与数据库之间进行交互的API。它允许Java程序通过SQL&#xff08;结构化查询语言&#xff09;来执行各种数据库操作&#xff0c;如查询、更新、删除等。JDBC是Java应用程序访问数据库的标准方式…...

Qt:QDialogButtonBox的使用

QDialogButtonBox是Qt自带的按钮箱&#xff0c;通过枚举QDialogButtonBox::ButtonRole可以添加Qt定义按钮&#xff0c;或者通过方法QDialogButtonBox::addButton添加自定义的按钮。 // 自定义按钮。 button_box_ new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonB…...

38页 | 工商银行大数据平台助力全行数字化转型之路(免费下载)

【1】关注本公众号&#xff0c;转发当前文章到微信朋友圈 【2】私信发送 工商银行大数据平台 【3】获取本方案PDF下载链接&#xff0c;直接下载即可。 如需下载本方案PPT/WORD原格式&#xff0c;请加入微信扫描以下方案驿站知识星球&#xff0c;获取上万份PPT/WORD解决方案&a…...

【Git】如何不管本地文件,强制git pull

要在 Git 中强制执行 git pull 操作&#xff0c;忽略本地文件的更改&#xff0c;可以按照以下步骤操作&#xff1a; 保存当前工作状态&#xff1a;如果你有未提交的更改&#xff0c;可以使用 git stash 将这些更改存储起来。 git stash强制拉取最新代码&#xff1a;使用 git re…...

MySQL 高级 - 第十一章 | 索引优化与查询优化

目录 第十一章 索引优化与查询优化11.1 数据准备11.2 索引失效案例11.2.1 全值匹配10.2.2 最佳左前缀法则10.2.3 主键插入顺序10.2.4 计算、函数、类型转换&#xff08;自动或手动&#xff09;导致索引失效10.2.5 范围条件右边的列索引失效10.2.6 不等于&#xff08;! 或者 <…...

工厂模式——工厂方法模式+注册表

工厂方法模式的瑕疵 在前一篇笔记中我们介绍了工厂方法模式&#xff0c;示例的类图如下&#xff1a; 考虑一种情况&#xff1a;现在要在程序运行时&#xff0c;根据外部资源&#xff0c;动态的实例化对象。也就是说在编译期我们无法知道要实例化的对象的类型。因此在实例化的过…...

实验一、网络传输介质————双绞线 《计算机网络》

蝙蝠身上长鸡毛&#xff0c;忘了自己是什么鸟。 目录 一、实验目的 二、实验内容 1.双绞线的原理以及分类 2.了解双绞线的性质、结构与特性 3.掌握双绞线的制作方法 4.了解双绞线的材质 5.了解双绞线的发展趋势 三、实验小结 一、实验目的 1.双绞线的原理以及分类 2.了…...

在Linux/Ubuntu/Debian中使用lshw查看系统信息

在Linux/Ubuntu/Debian中使用lshw查看系统信息 lshw 是一个用于显示硬件配置的命令&#xff0c;可以提供系统硬件的详细信息&#xff0c;包括 CPU、内存、硬盘、主板等。该命令需要超级用户权限来获取详细信息。 常见用法&#xff1a; 显示所有硬件信息&#xff1a; sudo l…...

提高篇(八):扩展Processing功能:从库使用到跨平台应用

提高篇(八):扩展Processing功能:从库使用到跨平台应用 引言 Processing是一款强大的创意编程工具,广泛应用于艺术、设计和教育等领域。但其真正的魅力在于其可扩展性:你可以通过使用各种扩展库、结合其他编程语言、在不同硬件平台上应用,甚至创建自己的扩展库来丰富Pro…...

ubuntu18.04环境下,arduino ide在打开串口监视器时报错

ubuntu18.04环境下&#xff0c;arduino ide在打开串口监视器时报错 Exception in thread “AWT-EventQueue-0” java.lang.UnsatisfiedLinkError: /home/lzx/.jssc/linux/libjSSC-2.8_x86_64.so: /home/lzx/.jssc/linux/libjSSC-2.8_x86_64.so: file too short 这个错误表明 li…...

码蹄集部分题目(2024OJ赛18期;并查集+ST表+贪心)

1&#x1f40b;&#x1f40b;史莱姆融合&#xff08;钻石&#xff1b;并查集&#xff09; 时间限制&#xff1a;1秒 占用内存&#xff1a;128M &#x1f41f;题目描述 &#x1f41f;题目思路 这道题目使用并查集&#xff0c;同一集合的所有元素的最顶上的祖父节点是统一的。…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...