系统启动流程分析之系统启动后的Launcher应用启动流程分析(上)

1,121 阅读7分钟

「这是我参与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;
}

从上述这段代码可以看到,这边主要是依次做了三件事情

  1. 通过ATMS的getHomeIntent函数,获取启动Activity的一个Intent对象
  2. 通过resolveHomeActivity函数获取启动界面的ActivityInfo对象
  3. 通过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应用流程

  1. 在SystemServer的startOtherServices函数中,通过调用ActivityManagerService的systemReady函数来通知系统启动完成的消息
  2. 在AMS.systemReady函数中调用ATMS服务的startHomeOnAllDisplays函数,来启动Launcher的加载和启动流程
  3. 调用RootWindowContainer对象的startHomeOnAllDisplays函数,在这个函数中,通过DisplayManagerService服务获取到对应的需要显示的显示设备ID,即displayId,然后获取需要显示的区域,最终通过RootWindowContainner的startHomeOnTaskDisplayArea函数继续整个启动流程
  4. 在RootWindowContainner的startHomeOnTaskDisplayArea函数中,通过ATMS获取到ActivityStartController对象,并调用其startHomeActivity函数,同时在这个函数中,通过Launcher应用特定的Intent属性(Action = Intent.ACTION_MAIN和包含category为Intent.CATEGORY_HOME对应的Intent意图)找到系统中对应的所有满足条件的Launcher对应的ActivityInfo
  5. 基于上述对应的ActiivtyInfo对象,在ActivityStarterController对象的startHomeActivity函数中启动Launcher应用

对应上述流程的时序图如下: 图片.png