Android11 以Window的视角来看FallbackHome的启动
在WMS中,使用WindowState代表着一个Window并维护着一个Window的"层级树",每个Window需要按照"层级"的规则进行排列。对于FallbackHome,其Window是挂载在home task上,而home task挂载在DefaultTaskDisplayArea这个叶子节点下,其父子关系如下:

1,home Task
home Task 在 SystemServer启动的时候,就会创建
//frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {//省略t.traceBegin("SetWindowManagerService");mActivityManagerService.setWindowManager(wm);t.traceEnd();//省略
}
AMS.setWindowManager
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void setWindowManager(WindowManagerService wm) {synchronized (this) {mWindowManager = wm;mWmInternal = LocalServices.getService(WindowManagerInternal.class);mActivityTaskManager.setWindowManager(wm);}
}
ATMS.setWindowManager
public void setWindowManager(WindowManagerService wm) {synchronized (mGlobalLock) {//省略mRootWindowContainer.setWindowManager(wm);}}
RootWindowContainer.setWindowManager
//frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
void setWindowManager(WindowManagerService wm) {//省略final TaskDisplayArea defaultTaskDisplayArea = getDefaultTaskDisplayArea();defaultTaskDisplayArea.getOrCreateRootHomeTask(ON_TOP);//省略}
先获取defaultTaskDisplayArea ,然后调用其getOrCreateRootHomeTask去创建home Task
//frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java
ActivityStack getOrCreateRootHomeTask(boolean onTop) {ActivityStack homeTask = getRootHomeTask();if (homeTask == null && mDisplayContent.supportsSystemDecorations()) {homeTask = createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, onTop);}return homeTask;}
如果home Task没有创建过的话,就调用createStack去创建,传入的参数中,type为ACTIVITY_TYPE_HOME。在createStack方法中,继续调用createStackUnchecked
//frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java
ActivityStack createStackUnchecked(int windowingMode, int activityType, int stackId,boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer) {final ActivityStack stack = new ActivityStack(mAtmService, stackId, activityType,info, intent, createdByOrganizer);//1if (launchRootTask != null) {//省略} else {addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);//2stack.setWindowingMode(windowingMode, true /* creating */);}return stack;}
注释1处,创建ActivityStack 对象,ActivityStack 继承自Task,注释2处将该ActivityStack设置为当前对象即defaultTaskDisplayArea的孩子。所以经过以上的调用流程,创建了一个home Task,其实home Task就是ActivityStack对象,然后挂载到DefaultTaskDisplayArea下。
2,FallbackHome Task
FallbackHome 是在 ActivityManagerService的 systemReady 中,调用startHomeOnAllDisplays 启动的,startHomeOnAllDisplays 会调用的ActivityStarter的executeRequest方法,从这个方法开始分析
//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int executeRequest(Request request) {//省略final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,callingPackage, callingFeatureId, intent, resolvedType, aInfo,mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode,request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions,sourceRecord);//创建 ActivityRecord ,继承WindowToken//省略mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,restrictedBgActivity, intentGrants);
}
先创建一个ActivityRecord 对象,然后调用startActivityUnchecked继续处理。该方法最后调用setNewTask来创建Task
//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private void setNewTask(Task taskToAffiliate) {final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;final Task task = mTargetStack.reuseOrCreateTask(mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);//1addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");//2//省略}
注释1处创建FallbackHome Task,mTargetStack为前面创建的home Task。注释2处,将前面创建的ActivityRecord设置为FallbackHome Task的孩子。
//frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
Task reuseOrCreateTask(ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor, boolean toTop, ActivityRecord activity,ActivityRecord source, ActivityOptions options) {Task task;if (DisplayContent.alwaysCreateStack(getWindowingMode(), getActivityType())) {//省略} else {//省略task = new ActivityStack(mAtmService, taskId, info, intent, voiceSession,voiceInteractor, null /* taskDescription */, this);//新建task // add the task to stack first, mTaskPositioner might need the stack associationaddChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);//添加为home Task的孩子}//省略return task;}
可以看出,FallbackHome Task也是一个ActivityStack对象,FallbackHome Task的父亲为home Task
3,ActivityRecord
前面提到过,在executeRequest方法中创建ActivityRecord,最后调用到addOrReparentStartingActivity方法
//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.javaprivate void addOrReparentStartingActivity(Task parent, String reason) {if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {parent.addChild(mStartActivity);//1} else {mStartActivity.reparent(parent, parent.getChildCount() /* top */, reason);}}
注释1处,parent为前面创建的FallbackHome Task,mStartActivity为前面创建的ActivityRecord,将ActivityRecord设置为FallbackHome Task的孩子
4,WindowState
在FallbackHome 的resume流程中,会调用ViewRootImpl的setView方法,最终调用到WMS的addWindow
//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int addWindow(/*省略*/) {//省略final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], seq, attrs, viewVisibility, session.mUid, userId,session.mCanAddInternalSystemWindow);//创建WindowState//省略win.mToken.addWindow(win);//省略
}
这里的win.mToken就是前面创建的ActivityRecord对象
//frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
@Overridevoid addWindow(WindowState w) {super.addWindow(w);//删除}
调用其父类也就是WindowToken的addWindow方法
void addWindow(final WindowState win) {//省略if (!mChildren.contains(win)) {addChild(win, mWindowComparator);mWmService.mWindowsChanged = true;}}
也是通过addChild将该WindowState设置为ActivityRecord的孩子
总结
本文以Window的视角来分析了一下FallbackHome的显示流程。我们知道了在WMS中,使用WindowState来代表一个窗口。WindowState的父亲是ActivityRecord,也就是说在WMS的层级树中,FallbackHome对应的WindowState挂载在ActivityRecord下。ActivityRecord挂载在FallbackHome Task(ActivityStack)下,FallbackHome Task又挂载在home Task(ActivityStack)下。而home Task的父亲是DefaultTaskDisplayArea
相关文章:
Android11 以Window的视角来看FallbackHome的启动
在WMS中,使用WindowState代表着一个Window并维护着一个Window的"层级树",每个Window需要按照"层级"的规则进行排列。对于FallbackHome,其Window是挂载在home task上,而home task挂载在DefaultTaskDisplayArea…...
9 RestClient客户端操作文档
1. match_all GetMapping("matchAll")public void matchAll() throws IOException {//1. 准备requestSearchRequest request new SearchRequest("hotel");//2. 组织DSL参数request.source().query(QueryBuilders.matchAllQuery());SearchResponse respon…...
『Z-Weekly Feed 08』加密资产观 | FHE应用前景 | OPAL协议
一位机构投资者的加密资产观 作者:Hongbo 01 💡TL;DR 在加密投资领域如何找到真正的“价值”:Crypto 作为一种新兴资产,应该找到一种区别于传统公司股票资产的估值方法,本文重点阐述了加密货币作为新的资产类型与传统资…...
酒店预定系统
酒店预定系统本身设计过程中会遇到售卖系统两个常见问题,第一个同一个房间同一日期被多个订单预定,或者预定和库存数据不一致,这些都会涉及到金钱,需要在系统涉及是被重点考虑。 问题1:同一个房间同一个日期被多个订单预定 酒店…...
Redis的实战常用一、验证码登录(解决session共享问题)(思路、意识)
一、基于session实现登录功能 第一步:发送验证码: 用户在提交手机号后,会校验手机号是否合法: 如果不合法,则要求用户重新输入手机号如果手机号合法,后台此时生成对应的验证码,同时将验证码进行…...
基于Spring Boot的智能分析平台
项目介绍: 智能分析平台实现了用户导入需要分析的原始数据集后,利用AI自动生成可视化图表和分析结论,改善了传统BI系统需要用户具备相关数据分析技能的问题。该项目使用到的技术是SSMSpring Boot、redis、rabbitMq、mysql等。在项目中&#…...
HTML(13)——显示模式
目录 显示模式 块级元素 行内元素 行内块元素 转换显示模式 显示模式:标签的显示方式 作用:布局网页时,根据标签的显示模式选择合适的标签摆放内容 显示模式 块级元素 独占一行宽度默认为父级的100%添加宽高属性生效 行内元素 …...
【Spring】Spring Boot 快速入门
📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更…...
Go自定义数据的序列化流程
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...
贪心算法练习题(2024/6/18)
什么是贪心 贪心的本质是选择每一阶段的局部最优,从而达到全局最优。 贪心算法一般分为如下四步: 将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解 1分发饼干 假设你是一位很棒的家长,…...
4.1 四个子空间的正交性
一、四个子空间的正交性 如果两个向量的点积为零,则两个向量正交: v ⋅ w v T w 0 \boldsymbol v\cdot\boldsymbol w\boldsymbol v^T\boldsymbol w0 v⋅wvTw0。本章着眼于正交子空间、正交基和正交矩阵。两个子空间的中的向量,一组基中的向…...
RabbitMQ实践——使用WebFlux响应式方式实时返回队列中消息
大纲 Pom.xml监听队列实时返回消息测试完整代码工程代码 在之前的案例中,我们在管理后台收发消息都是通过短连接的形式。本文我们将探索对队列中消息的实时读取,并通过流式数据返回给客户端。 webflux是反应式Web框架,客户端可以通过一个长连…...
SpringBoot前后端传递数据时常用的JSON格式数据是什么?【讲解JSON概念、语法、以及Java对象互转】
SpringBoot前后端传递数据时常用的JSON格式数据是什么? JSON概念JSON语法JSON的两种结构:JSON字符串和Java对象互转:objectMapper.writeValueAsString(person);objectMapper.readValue(jsonStr,Person.class); 在SpringMVC框架中,…...
mysql学习——SQL中的DQL和DCL
SQL中的DQL和DCL DQL基本查询条件查询聚合函数分组查询排序查询分页查询 DCL管理用户权限控制 学习黑马MySQL课程,记录笔记,用于复习。 DQL DQL英文全称是Data Query Language(数据查询语言),数据查询语言,用来查询数据库中表的记…...
windows系统上nginx搭建文件共享
1、下载windows版nginx 下载地址 2、配置nginx 编辑nginx.conf配置文件 在http模块下添加这个参数 underscores_in_headers on;#修改location内容,共享哪个文件夹,就写哪个文件夹,最后一定要跟上/,否则无法访问 location / {…...
星闪指向遥控,做家电交互的破壁人
“面壁者罗辑,我是你的破壁人。” 科幻小说《三体》中,当人类的基础科学被三体人封锁,变得停步不前,人类启动了自救的面壁计划,通过一次又一次破壁,找到战胜三体人的办法。 现实中,有一点已经成…...
SpringBoot使用AutoConfigure实现依赖库自动导入配置
我们知道导入配置有两种,一种是Value,一种是ConfigurationProperties,将对应的类标记为Component即可导入。但是被注解标识的类创建Bean有一个前提,只对启动类所在的包路径下的所有带有Component等注解的类才会创建Bean。如果我们…...
QT中利用动画弄一个侧边栏窗口,以及贴条效果
1、效果 2、关键代码 void Widget::on_sliderBtn_clicked() {m_sliderWidget->show();QPropertyAnimation* animation = new QPropertyAnimation(m...
win10免安装配置MySQL8.4.0
注:此教程基于win10 22H2 版本 1、下载最新版本MySQL压缩包 下载链接:MySQL官网下载地址 点击第二行的 ZIP Archive 后面的Download(当前时间2024-06-19最新版本是8.4.0) 2、解压并添加配置文件 下载完毕后,解压缩…...
VS Code安装及环境配置(超详细)
VS Code简介 Visual Studio Code(简称 VS Code )是 Microsoft 于2015年4月发布的一款代码编辑器,以界面简洁、轻量著称。 它是一款免费开源的现代化轻量级代码编辑器,支持几乎所有主流开发语言的语法高亮、智能代码补全、自定义…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...
若依登录用户名和密码加密
/*** 获取公钥:前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...
Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...
