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

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

1,home Task

home Task 在 SystemServer启动的时候,就会创建

c 复制代码
//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

c 复制代码
//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

c 复制代码
public void setWindowManager(WindowManagerService wm) {
        synchronized (mGlobalLock) {
            //省略
            mRootWindowContainer.setWindowManager(wm);
        }
    }

RootWindowContainer.setWindowManager

c 复制代码
//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

c 复制代码
//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

c 复制代码
//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);//1
        if (launchRootTask != null) {
           //省略
        } else {
            addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);//2
            stack.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方法,从这个方法开始分析

c 复制代码
//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

c 复制代码
//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);//1
        addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");//2

       //省略
    }

注释1处创建FallbackHome Task,mTargetStack为前面创建的home Task。注释2处,将前面创建的ActivityRecord设置为FallbackHome Task的孩子。

c 复制代码
//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 association
            addChild(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方法

c 复制代码
//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
 private 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

c 复制代码
//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对象

c 复制代码
//frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
@Override
    void addWindow(WindowState w) {
        super.addWindow(w);
		//删除
    }

调用其父类也就是WindowToken的addWindow方法

c 复制代码
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

相关推荐
拭心1 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王4 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡4 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道4 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库5 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道6 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe6 小时前
Android Hook - 动态加载so库
android
居居飒7 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He10 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗10 小时前
Android笔试面试题AI答之Android基础(1)
android