「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」。
今天是2022年1月31日,农历除夕夜,祝福各位程序员兄弟姐妹们,虎年吉祥,虎虎生威,事事顺心,来年好运连连!!!
系统启动后的Launcher应用启动流程分析
在系统启动过程中,通过zygote进程fork了一个SystemServer进程,而在这个进程中,启动了系统所必须的各种核心服务,其中AMS就是其中的重要的一个。 AMS在启动SystemServer进程启动结束后,在会调用一个systemReady函数来完成当系统启动完成后的一些操作,其中就有Launcher应用的启动过程,而代码如下:
ActivityManagerService.java
// bootingSystemUser参数表明当前登录的用户是否为系统用户
if (bootingSystemUser) {
// mAtmInternal参数通过LocalServices的getService函数获取
// 而LocalServiecs中当ActivityTaskManagerService初始化的时候,会通过addService函数注册这个对象
// 因此此处返回的mAtmInternal参数其实是一个ActivityTaskManagerService.LocalService对象
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
}
如上备注解析可知,此处会调用ActivityTaskManagerService.LocalService.startHomeOnAllDisplays函数,因此
ActivityTaskManagerService.java
public boolean startHomeOnAllDisplays(int userId, String reason) {
// mGlobalLock参数锁,其实是WindowManagerGlobalLock对象,在其他服务中也会通过这个锁来锁定同步操作
synchronized (mGlobalLock) {
// 此处会调用mRootWindowContainer对象的startHomeOnAllDisplays函数
// 这边的mRootWindowContainer参数的值是从WindowManagerService中的mRoot参数对应的对象
// mRootWindowContainer参数是通过AMS的setWindowManager函数调用,进而调用ATMS.LocalServices的setWindowManager函数得到的
// 因此,此处需要注意的是RootWindowContainer对象的mWmService参数对应的是WindowManagerService对象
// mService参数对应的ActivityTaskManagerService对象
return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
}
}
上述的RootWindowContainer类图关系如下:
classDiagram
WindowContainer <|-- RootWindowContainer
ActivityTaskManagerService -- RootWindowContainer : mStackSupervisor
Handler <|-- MyHandler
RootWindowContainer <-- MyHandler : mHandler
ActivityStackSupervisor <-- RootWindowContainer : mRootWindowContainer
MyHandler --* RootWindowContainer
class ActivityTaskManagerService {
#mStackSupervisor : ActivityStackSupervisor
}
class RootWindowContainer {
#mService : ActivityTaskManagerService
-mHandler : Handler
#mStackSupervisor : ActivityStackSupervisor
+setWindowManager(WindowManagerService)
}
class WindowContainer {
#mWmService : WindowManagerService
}
class ActivityStackSupervisor {
#mRootWindowContainer : RootWindowContainer
}
根据前述的代码,此处会调用是RootWindowContainer对象的startHomeOnAllDisplays函数
RootWindowContainer.java
// 此处传入参数,userId = UserHandle.USER_SYSTEM, reason = "systemReady"
boolean startHomeOnAllDisplays(int userId, String reason) {
boolean homeStarted = false;
// getChildCount获取显示设备数目,这个主要从mChildren参数中获取对应的数量
// mChildren是一个WindowList的一个对象,其包含的数据是在setWindowManager函数被调用时,
// 从DisplayManagerService中获取到的Display的数目,
// 其实DisplayManagerService加载默认显示设备一文已经描述,此处不作详细分析
for (int i = getChildCount() - 1; i >= 0; i--) {
// 获取到对应新建的DisplayContent的displayId
final int displayId = getChildAt(i).mDisplayId;
// 调用startHomeOnDisplay函数
homeStarted |= startHomeOnDisplay(userId, reason, displayId);
}
return homeStarted;
}
从代码中可以看到,此处会针对于多显示设备的情况,启动多个Launcher主界面,当然在这边,我们只分析默认显示设备的情况,因此
RootWindowContainer.java
boolean startHomeOnDisplay(int userId, String reason, int displayId) {
return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */, false /* fromHomeKey */);
}
boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey) {
// Fallback to top focused display or default display if the displayId is invalid.
// 由于DisplayManagerService中获取到的displayId部位INVALID_DISPLAY,因此此处判断条件不满足
if (displayId == INVALID_DISPLAY) {
final ActivityStack stack = getTopDisplayFocusedStack();
displayId = stack != null ? stack.getDisplayId() : DEFAULT_DISPLAY;
}
final DisplayContent display = getDisplayContent(displayId);
boolean result = false;
for (int tcNdx = display.getTaskDisplayAreaCount() - 1; tcNdx >= 0; --tcNdx) {
final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tcNdx);
// 最终会调用startHomeOnTaskDisplayArea函数
result |= startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
allowInstrumenting, fromHomeKey);
}
return result;
}
boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
boolean allowInstrumenting, boolean fromHomeKey) {
// ...... 功能呢无关代码,此处省略
if (taskDisplayArea == getDefaultTaskDisplayArea()) {
// 1. 通过ATMS的getHomeIntent函数,获取一个Intent对象
// 这个Intent对象
// homeIntent.action = Intent.ACTION_MAIN
// homeIntent的flags包含Intent.FLAG_DEBUG_TRIAGED_MISSING
// homeIntent的category包含Intent.CATEGORY_HOME
homeIntent = mService.getHomeIntent();
// 2. 获取包含启动信息的一个ActivityInfo对象
aInfo = resolveHomeActivity(userId, homeIntent);
}
// ...... 功能呢无关代码,此处省略
// Updates the home component of the intent.
homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
// ...... 条件判断无法满足,代码省略
// Update the reason for ANR debugging to verify if the user activity is the one that
// actually launched.
final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
aInfo.applicationInfo.uid) + ":" + taskDisplayArea.getDisplayId();
// 3. 通过ActivityStartController对象的startHomeActivity函数
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
taskDisplayArea);
return true;
}
从上述这段代码可以看到,这边主要是依次做了三件事情
- 通过ATMS的getHomeIntent函数,获取启动Activity的一个Intent对象
- 通过resolveHomeActivity函数获取启动界面的ActivityInfo对象
- 通过ActivityStartController对象的startHomeActivity函数来启动对应的Activity
因此,接下来我们一一来分析一下
获取启动Activity的一个Intent对象
Intent getHomeIntent() {
// 初始化一个Intent对象,其action对应的值为Intent.ACTION_MAIN
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
// 设置对应的Component,此处为null
intent.setComponent(mTopComponent);
// 添加flags,
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
// 添加category
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
可以看到,这边的代码相对比较简单,就是初始化一个Intent,并设置其对应的参数
获取启动界面的ActivityInfo对象
RootWindowContainer.java
ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
final int flags = ActivityManagerService.STOCK_PM_FLAGS;
final ComponentName comp = homeIntent.getComponent(); // null
ActivityInfo aInfo = null;
try {
if (comp != null) {
// ...... 条件无法满足,代码省略
} else {
// 获取Intent的content type数据,此处为null
final String resolvedType =
homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
// AppGlobals.getPackageManager()函数返回一个PackageManagerService对象
// 这个函数会遍历系统中所有满足条件的应用信息,然后获取对应的最满足条件的ResolveInfo对象
final ResolveInfo info = AppGlobals.getPackageManager()
.resolveIntent(homeIntent, resolvedType, flags, userId);
// 此处aInfo对应ResolveInfo对象的ActivityInfo对象
if (info != null) {
aInfo = info.activityInfo;
}
}
}
// ...... 捕捉异常,代码省略
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId);
return aInfo;
}
最终会返回一个对应的最满足条件的包含所有应用信息的ActivityInfo对象
启动对应的Activity
// ATMS的getActivityStartController函数会返回一个ActivityStartController对象
// 这个对象在ATMS的initialize函数中初始化完成
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, taskDisplayArea);
如下为ActivityStartController类图
classDiagram
ActivityStarter *-- DefaultFactory
ActivityStarter *-- Factory
ActivityStartController <-- DefaultFactory : mFactory
ActivityStartController <-- ActivityTaskManagerService : mService
ActivityStartController <-- ActivityStackSupervisor : mSupervisor
ActivityStartController <-- StartHandler : mHandler
Handler <|-- StartHandler
Factory <|-- DefaultFactory
ActivityStartController *--StartHandler
ActivityStartController --> DefaultFactory : mController
ActivityTaskManagerService --> DefaultFactory : mService
ActivityStackSupervisor --> DefaultFactory : mSupervisor
<<interface>> Factory
ActivityTaskManagerService <-- ActivityStackSupervisor : mSupervisor
class ActivityTaskManagerService {
+getActivityStartController()
}
有类图可知,此处会调用ActivityStartController对象的startHomeActivity函数
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,
TaskDisplayArea taskDisplayArea) {
final ActivityOptions options = ActivityOptions.makeBasic();
// 设置模式为全屏模式
options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
if (!ActivityRecord.isResolverActivity(aInfo.name)) {
// The resolver activity shouldn't be put in home stack because when the foreground is
// standard type activity, the resolver activity should be put on the top of current
// foreground instead of bring home stack to front.
options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
}
final int displayId = taskDisplayArea.getDisplayId();
options.setLaunchDisplayId(displayId);
options.setLaunchTaskDisplayArea(taskDisplayArea.mRemoteToken
.toWindowContainerToken());
// The home activity will be started later, defer resuming to avoid unneccerary operations
// (e.g. start home recursively) when creating home stack.
mSupervisor.beginDeferResume();
final ActivityStack homeStack;
try {
// 创建一个ActivityStack对象
// Make sure home stack exists on display area.
homeStack = taskDisplayArea.getOrCreateRootHomeTask(ON_TOP);
} finally {
mSupervisor.endDeferResume();
}
// obtainStarter函数初始化一个ActivityStarter对象,并且设置其Intent和reason参数
// 在ActivityStarter对象初始化的时候,会初始化一个Request对象,而此处的设置函数,均在设置Request的参数
// 最后通过execute函数来运行这个Request
mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
.setOutActivity(tmpOutRecord)
.setCallingUid(0)
.setActivityInfo(aInfo)
.setActivityOptions(options.toBundle())
.execute();
mLastHomeActivityStartRecord = tmpOutRecord[0];
// ......
}
ActivityStarter.java
int execute() {
try {
// ...... 功能无关代码,此处省略
int res;
synchronized (mService.mGlobalLock) {
final boolean globalConfigWillChange = mRequest.globalConfig != null
&& mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;
final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
if (stack != null) {
stack.mConfigWillChange = globalConfigWillChange;
}
// ...... 日志打印,功能无关代码,此处省略
// 调用executeRequest函数来运行这个Request
res = executeRequest(mRequest);
// ...... 功能无关代码,此处省略
// Notify ActivityMetricsLogger that the activity has launched.
// ActivityMetricsLogger will then wait for the windows to be drawn and populate
// WaitResult.
// 通知Activity启动
mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
mLastStartActivityRecord);
return getExternalResult(mRequest.waitResult == null ? res
: waitForResult(res, mLastStartActivityRecord));
}
} finally {
// 运行完成
onExecutionComplete();
}
}
如上代码,最终会调用executeRequest函数来继续运行
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);
mLastStartActivityRecord = r;
// ......
final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
// ......
mService.onStartActivitySetDidAppSwitch();
mController.doPendingActivityLaunches(false);
// startActivityUnchecked
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
restrictedBgActivity, intentGrants);
// ......
return mLastStartActivityResult;
}
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
// ......
// 调用startActivityInner函数
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
// ......
return result;
}
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
// ......
mTargetStack.startActivityLocked(mStartActivity,
topStack != null ? topStack.getTopNonFinishingActivity() : null, newTask,
mKeepCurTransition, mOptions);
// ......
mRootWindowContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
// Update the recent tasks list immediately when the activity starts
mSupervisor.mRecentTasks.add(mStartActivity.getTask());
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetStack);
return START_SUCCESS;
}
通过startActivityInner函数,最终会启动Launcher应用(通过ActivityInfo对象包含的数据信息),至于具体如何启动的流程,待下篇再做详细分析
总结
此处我们先来总结一下当前启动Launcher应用流程
- 在SystemServer的startOtherServices函数中,通过调用ActivityManagerService的systemReady函数来通知系统启动完成的消息
- 在AMS.systemReady函数中调用ATMS服务的startHomeOnAllDisplays函数,来启动Launcher的加载和启动流程
- 调用RootWindowContainer对象的startHomeOnAllDisplays函数,在这个函数中,通过DisplayManagerService服务获取到对应的需要显示的显示设备ID,即displayId,然后获取需要显示的区域,最终通过RootWindowContainner的startHomeOnTaskDisplayArea函数继续整个启动流程
- 在RootWindowContainner的startHomeOnTaskDisplayArea函数中,通过ATMS获取到ActivityStartController对象,并调用其startHomeActivity函数,同时在这个函数中,通过Launcher应用特定的Intent属性(Action = Intent.ACTION_MAIN和包含category为Intent.CATEGORY_HOME对应的Intent意图)找到系统中对应的所有满足条件的Launcher对应的ActivityInfo
- 基于上述对应的ActiivtyInfo对象,在ActivityStarterController对象的startHomeActivity函数中启动Launcher应用
对应上述流程的时序图如下: