Android11 以Window的视角来看FallbackHome的启动

2024-06-17 15:04

本文主要是介绍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的启动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1069769

相关文章

Redis在windows环境下如何启动

《Redis在windows环境下如何启动》:本文主要介绍Redis在windows环境下如何启动的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Redis在Windows环境下启动1.在redis的安装目录下2.输入·redis-server.exe

解决SpringBoot启动报错:Failed to load property source from location 'classpath:/application.yml'

《解决SpringBoot启动报错:Failedtoloadpropertysourcefromlocationclasspath:/application.yml问题》这篇文章主要介绍... 目录在启动SpringBoot项目时报如下错误原因可能是1.yml中语法错误2.yml文件格式是GBK总结在启动S

SpringBoot启动报错的11个高频问题排查与解决终极指南

《SpringBoot启动报错的11个高频问题排查与解决终极指南》这篇文章主要为大家详细介绍了SpringBoot启动报错的11个高频问题的排查与解决,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一... 目录1. 依赖冲突:NoSuchMethodError 的终极解法2. Bean注入失败:No qu

一文带你了解SpringBoot中启动参数的各种用法

《一文带你了解SpringBoot中启动参数的各种用法》在使用SpringBoot开发应用时,我们通常需要根据不同的环境或特定需求调整启动参数,那么,SpringBoot提供了哪些方式来配置这些启动参... 目录一、启动参数的常见传递方式二、通过命令行参数传递启动参数三、使用 application.pro

SpringBoot项目启动报错"找不到或无法加载主类"的解决方法

《SpringBoot项目启动报错找不到或无法加载主类的解决方法》在使用IntelliJIDEA开发基于SpringBoot框架的Java程序时,可能会出现找不到或无法加载主类com.example.... 目录一、问题描述二、排查过程三、解决方案一、问题描述在使用 IntelliJ IDEA 开发基于

如何使用Python实现一个简单的window任务管理器

《如何使用Python实现一个简单的window任务管理器》这篇文章主要为大家详细介绍了如何使用Python实现一个简单的window任务管理器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 任务管理器效果图完整代码import tkinter as tkfrom tkinter i

SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法

《SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法》本文主要介绍了SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法,具有一定的参考价值,感兴趣的可以了解一下... 目录方法1:更改IDE配置方法2:在Eclipse中清理项目方法3:使用Maven命令行在开发Sprin

Nginx启动失败:端口80被占用问题的解决方案

《Nginx启动失败:端口80被占用问题的解决方案》在Linux服务器上部署Nginx时,可能会遇到Nginx启动失败的情况,尤其是错误提示bind()to0.0.0.0:80failed,这种问题通... 目录引言问题描述问题分析解决方案1. 检查占用端口 80 的进程使用 netstat 命令使用 ss

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

Windows设置nginx启动端口的方法

《Windows设置nginx启动端口的方法》在服务器配置与开发过程中,nginx作为一款高效的HTTP和反向代理服务器,被广泛应用,而在Windows系统中,合理设置nginx的启动端口,是确保其正... 目录一、为什么要设置 nginx 启动端口二、设置步骤三、常见问题及解决一、为什么要设置 nginx