AMS知识点——Activity的启动流程

        AMS这个东西可能是现在Android开发面试时面试官比较常问的一个问题点了。但是很多朋友每次都和我一样,一问就懵逼,于是回来发誓要学好弄懂,去看几篇博客,半懂不懂的就以为自己弄懂了。然后下次再面试依旧面临尴尬的局面。于是不禁怀疑自己是否不适合开发这一行了(怀疑人生了)。但是这里我想结合自身的情况说一句:我们并不是不适合做开发,而是我们没有学会如何去学习一个自己不懂得知识点,找不到学习得切入点。所以就出现了上面说的那样,找几篇博客看一看就自以为懂了,这个过程中甚至连源码都不带看一眼的。这样即使你看再多遍博客,我敢说你都不可能会弄懂这个知识点(因为我就是这样,看了无数遍还是不会)。真正的学习方式是找到学习的切入点。就拿AMS来说,它的切入点当然是Activity的启动流程啊。如果你连Activity的启动流程都不知道,一个版本的源码都没跟过,怎么敢说自己学会了AMS这个知识点了呢?本篇我们就已Activity的启动流程为切入点,初窥一下AMS是个什么东西,以及它都干了什么。

一、AMS服务是啥

        前面我们在讲Binder知识的时候已经对AMS有过了解了。AMS是一个运行在SystemServer进程中的服务(全名:ActivityManagerService),主要功能就是帮助我们管理应用Activity相关的一个系统服务,而SystemServer进程又是我们的Android系统启动后由Zygote进程孵化的一个子进程这个子进程与Zygote进程之间的通信方式是通过Socket来进行的(我们APP应用与SystemServer进程通信是通过Binder)。我们的每个应用进程同样也是由Zygote进程孵化出来的一个子进程,不过区别就是SystemServer是系统启动后就被孵化出来,而应用进程是我们点击应用启动才被孵化出来。这里我们只需要知道这中间是这么个关系就行了,没必要深入的研究。但是我们需要清楚应用启动过程中这几个进程之间的一个调用关系,如下图:

 

 

二、startActivity后都经过了哪些流程

        要弄懂这个流程,这一块的Android源码是必须扣至少一遍才能继续走下去的,这里我整理了份Android10源码的startActivity整个流程时序图,看懂了这张图也就离明白Activity的启动流程不远了。个人建议看图的时候跟着阅读源码,这样或许效果更好些。(因为在看源码的时候我自己是来来回回看了好几遍才理清楚整个流程的)。

 

下面我们就跟着这张图来讲讲Activity启动的整个流程。

1、Activity启动的发起

我们知道,要启动一个Activity,常见的有两种方式

  • 调用Activity.startActivity
  • 调用Context.startActivity

(1)Activity.startActivity

@Override
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        // Note we want to go through this call for compatibility with
        // applications that may have overridden the method.
        startActivityForResult(intent, -1);
    }
}

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            // ...
            mStartedActivity = true;
        }

        cancelInputsAndStartExitTransition(options);
        // TODO Consider clearing/flushing other event sources and events for child windows.
    } else {
        // ... 最终也是调用到Instrumentation.execStartActivity
    }
}

 可见最终调用到了 Instrumentation.execStartActivity 方法。

(2)Context.startActivity

public void startActivity(Intent intent, Bundle options) {
    warnIfCallingFromSystemProcess();

    // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
    // generally not allowed, except if the caller specifies the task id the activity should
    // be launched in. A bug was existed between N and O-MR1 which allowed this to work. We
    // maintain this for backwards compatibility.
    final int targetSdkVersion = getApplicationInfo().targetSdkVersion;

    if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
            && (targetSdkVersion < Build.VERSION_CODES.N
                    || targetSdkVersion >= Build.VERSION_CODES.P)
            && (options == null
                    || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
        throw new AndroidRuntimeException(
                "Calling startActivity() from outside of an Activity "
                        + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                        + " Is this really what you want?");
    }
    mMainThread.getInstrumentation().execStartActivity(
            getOuterContext(), mMainThread.getApplicationThread(), null,
            (Activity) null, intent, -1, options);
}

可见最终也是调用到 Instrumentation.execStartActivity 方法。于是进入第二阶段

2、与AMS通信的节点

通过上面的源码我们发现不管是Activity还是Context的startActivity最终都走到Instrumentation.execStartActivity 方法。

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    // ...
    try {
        // ...
        int result = ActivityTaskManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    }
    // ...
}

可以看到,这边调用了 ActivityTaskManager.getService().startActivity 方法

这个ActivityTaskManager.getService()取到的是个啥呢?

public static IActivityTaskManager getService() {
        return IActivityTaskManagerSingleton.get();
}

@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
        new Singleton<IActivityTaskManager>() {
            @Override
            protected IActivityTaskManager create() {
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                return IActivityTaskManager.Stub.asInterface(b);
            }
        };

 通过看源码我们发现这里getService方法,拿到的就是一个IActivityTaskManager对象,这个IActivityTaskManager.Stub.asInterface(b)很熟悉,是AIDL的写法,这就涉及到了Binder通信,是不是想到了上面流程图中应用与AMS通信方式就是通过Binder。没错这里就是调用AMS服务ActivityManagerService。但是在Android10源码中最终调用的是ActivityTaskManagerService,于是转入第三阶段

3、Activity启动管理

查看ActivityTaskManagerService的代码,发现startActivity最终调用是来到了startActivityAsUser方法.

int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
        boolean validateIncomingUser) {
    enforceNotIsolatedCaller("startActivityAsUser");

    userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

    // TODO: Switch to user app stacks here.
    return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setResolvedType(resolvedType)
            .setResultTo(resultTo)
            .setResultWho(resultWho)
            .setRequestCode(requestCode)
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(bOptions)
            .setMayWait(userId)
            .execute();

}

 getActivityStartController().obtainStarter这边是用了工厂模式,最终是获取一个ActivityStarter,顾名思义,这个ActivityStarter就是用来执行startActivity操作的

(1)ActivityStarter的启动操作

int execute() {
    try {
        // TODO(b/64750076): Look into passing request directly to these methods to allow
        // for transactional diffs and preprocessing.
        if (mRequest.mayWait) {
            return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                    mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid,
                    mRequest.intent, mRequest.resolvedType,
                    mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                    mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                    mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                    mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                    mRequest.inTask, mRequest.reason,
                    mRequest.allowPendingRemoteAnimationRegistryLookup,
                    mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
        } else {
            return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                    mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                    mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                    mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                    mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                    mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                    mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                    mRequest.outActivity, mRequest.inTask, mRequest.reason,
                    mRequest.allowPendingRemoteAnimationRegistryLookup,
                    mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
        }
    } finally {
        onExecutionComplete();
    }
}

 上面我们看到,Stater的setMaywait被调用了,因此mayWait为true,所以就会走到startActivityMayWait中。

private int startActivityMayWait(IApplicationThread caller, int callingUid,
        String callingPackage, int requestRealCallingPid, int requestRealCallingUid,
        Intent intent, String resolvedType, IVoiceInteractionSession voiceSession,
        IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, WaitResult outResult,
        Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
        int userId, TaskRecord inTask, String reason,
        boolean allowPendingRemoteAnimationRegistryLookup,
        PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
    // Refuse possible leaked file descriptors
    if (intent != null && intent.hasFileDescriptors()) {
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }
    
    // .. Calling pid uid 设置 省略

    // Save a copy in case ephemeral needs it
    final Intent ephemeralIntent = new Intent(intent);
    // Don't modify the client's object!
    intent = new Intent(intent);
    if (componentSpecified
            && !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
            && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
            && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
            && mService.getPackageManagerInternalLocked()
                    .isInstantAppInstallerComponent(intent.getComponent())) {
        // intercept intents targeted directly to the ephemeral installer the
        // ephemeral installer should never be started with a raw Intent; instead
        // adjust the intent so it looks like a "normal" instant app launch
        intent.setComponent(null /*component*/);
        componentSpecified = false;
    }

    ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
            0 /* matchFlags */,
                    computeResolveFilterUid(
                            callingUid, realCallingUid, mRequest.filterCallingUid));
    if (rInfo == null) {
        UserInfo userInfo = mSupervisor.getUserInfo(userId);
        if (userInfo != null && userInfo.isManagedProfile()) {
            // Special case for managed profiles, if attempting to launch non-cryto aware
            // app in a locked managed profile from an unlocked parent allow it to resolve
            // as user will be sent via confirm credentials to unlock the profile.

            // ...
        }
    }
    // Collect information about the target of the Intent.
    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

    synchronized (mService.mGlobalLock) {
        final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
        stack.mConfigWillChange = globalConfig != null
                && mService.getGlobalConfiguration().diff(globalConfig) != 0;
        if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                "Starting activity when config will change = " + stack.mConfigWillChange);

        final long origId = Binder.clearCallingIdentity();

        if (aInfo != null &&
                (aInfo.applicationInfo.privateFlags
                        & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 &&
                mService.mHasHeavyWeightFeature) {
            // This may be a heavy-weight process!  Check to see if we already
            // have another, different heavy-weight process running.

            // ... 省略
        }

        final ActivityRecord[] outRecord = new ActivityRecord[1];
        int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent,
                allowBackgroundActivityStart);

        Binder.restoreCallingIdentity(origId);

        if (stack.mConfigWillChange) {
            // If the caller also wants to switch to a new configuration,
            // do so now.  This allows a clean switch, as we are waiting
            // for the current activity to pause (so we will not destroy
            // it), and have not yet started the next activity.
            mService.mAmInternal.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
                    "updateConfiguration()");
            stack.mConfigWillChange = false;
            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                    "Updating to new configuration after starting activity.");
            mService.updateConfigurationLocked(globalConfig, null, false);
        }

        // Notify ActivityMetricsLogger that the activity has launched. ActivityMetricsLogger
        // will then wait for the windows to be drawn and populate WaitResult.
        // ... 省略

        return res;
    }
}

这个方法很长,做了一些特殊情况的处理,最终是调用到了 startActivity 方法。

接下来是一系列检查,例如能否切换app等等,然后走到了startActivityUnchecked方法。

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity, boolean restrictedBgActivity) {
    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor, restrictedBgActivity);

    final int preferredWindowingMode = mLaunchParams.mWindowingMode;

    computeLaunchingTaskFlags();

    computeSourceStack();

    mIntent.setFlags(mLaunchFlags);

    ActivityRecord reusedActivity = getReusableIntentActivity();

    // ... Reused 逻辑,也就是说启动了一个已存在的Activity,这部分先不考虑

    // 错误处理...

    // If the activity being launched is the same as the one currently at the top, then
    // we need to check if it should only be launched once.
    // 刚好启动了当前Activity,省略

    boolean newTask = false;
    final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
            ? mSourceRecord.getTaskRecord() : null;

    // Should this be considered a new task?
    int result = START_SUCCESS;
    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;
        result = setTaskFromReuseOrCreateNewTask(taskToAffiliate);
    } else if (mSourceRecord != null) {
        result = setTaskFromSourceRecord();
    } else if (mInTask != null) {
        result = setTaskFromInTask();
    } else {
        // This not being started from an existing activity, and not part of a new task...
        // just put it in the top task, though these days this case should never happen.
        result = setTaskToCurrentTopOrCreateNewTask();
    }
    if (result != START_SUCCESS) {
        return result;
    }

    // ...
    if (newTask) {
        EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.mUserId,
                mStartActivity.getTaskRecord().taskId);
    }
    ActivityStack.logStartActivity(
            EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTaskRecord());
    mTargetStack.mLastPausedActivity = null;

    mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
            false /* forceSend */, mStartActivity);

    // 通知Stack
    mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
            mOptions);
    // Resume 逻辑
    if (mDoResume) {
        final ActivityRecord topTaskActivity =
                mStartActivity.getTaskRecord().topRunningActivityLocked();
        if (!mTargetStack.isFocusable()
                || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                && mStartActivity != topTaskActivity)) {
            // If the activity is not focusable, we can't resume it, but still would like to
            // make sure it becomes visible as it starts (this will also trigger entry
            // animation). An example of this are PIP activities.
            // Also, we don't want to resume activities in a task that currently has an overlay
            // as the starting activity just needs to be in the visible paused state until the
            // over is removed.
            mTargetStack.ensureActivitiesVisibleLocked(mStartActivity, 0, !PRESERVE_WINDOWS);
            // Go ahead and tell window manager to execute app transition for this activity
            // since the app transition will not be triggered through the resume channel.
            mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
        } else {
            // If the target stack was not previously focusable (previous top running activity
            // on that stack was not visible) then any prior calls to move the stack to the
            // will not update the focused stack.  If starting the new activity now allows the
            // task stack to be focusable, then ensure that we now update the focused stack
            // accordingly.
            if (mTargetStack.isFocusable()
                    && !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) {
                mTargetStack.moveToFront("startActivityUnchecked");
            }
            mRootActivityContainer.resumeFocusedStacksTopActivities(
                    mTargetStack, mStartActivity, mOptions);
        }
    } else if (mStartActivity != null) {
        mSupervisor.mRecentTasks.add(mStartActivity.getTaskRecord());
    }
    mRootActivityContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);

    mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTaskRecord(),
            preferredWindowingMode, mPreferredDisplayId, mTargetStack);

    return START_SUCCESS;
}

 这个方法主要就是处理Activity重用的逻辑,以及确定要启动Activity的Task,启动模式相关的问题都可以在这里找到答案,此处我们先略过。

看代码,一开始以为下一步是在 mTargetStack.startActivityLocked 里面,但是跟了几遍查代码之后发现整个流程走不通,并不是这样,于是回过头来继续往下看,跟踪mRootActivityContainer.resumeFocusedStacksTopActivities 方法,发现调用路径如下:

mRootActivityContainer.resumeFocusedStacksTopActivities -> ActivityStack.resumeTopActivityUncheckedLocked -> ActivityStack.resumeTopActivityInnerLocked

这才是整个启动流程真实入口,希望大家看源码的时候能少走一点弯路。最终走到ActivityStack.resumeTopActivityInnerLocked方法,这里只贴出关键代码

if (next.attachedToProcess()) {
    // 省略,我们跟踪的是一个全新的App启动,所以此时进程还没起来
} else {
    // Whoops, need to restart this activity!
    if (!next.hasBeenLaunched) {
        next.hasBeenLaunched = true;
    } else {
        if (SHOW_APP_STARTING_PREVIEW) {
            next.showStartingWindow(null /* prev */, false /* newTask */,
                    false /* taskSwich */);
        }
        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
    }
    if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
    mStackSupervisor.startSpecificActivityLocked(next, true, true);
}

 可以发现,走到了StackSupervisor.startSpecificActivityLocked方法。走到这里我们的第三阶段就走完了一大半了。进入第四阶段

4、分岔路口

首先我们来看一下startSpecificActivityLocked的源码

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    final WindowProcessController wpc =
            mService.getProcessController(r.processName, r.info.applicationInfo.uid);

    boolean knownToBeDead = false;
    // 1. 如果有进程了,则走到realStartActivityLocked方法
    if (wpc != null && wpc.hasThread()) {
        try {
            realStartActivityLocked(r, wpc, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }

        // If a dead object exception was thrown -- fall through to
        // restart the application.
        knownToBeDead = true;
    }

    // Suppress transition until the new activity becomes ready, otherwise the keyguard can
    // appear for a short amount of time before the new process with the new activity had the
    // ability to set its showWhenLocked flags.
    if (getKeyguardController().isKeyguardLocked()) {
        r.notifyUnknownVisibilityLaunched();
    }

    try {
        if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
                    + r.processName);
        }
        // Post message to start process to avoid possible deadlock of calling into AMS with the
        // ATMS lock held.
        // 2、没有进程,启动进程
        final Message msg = PooledLambda.obtainMessage(
                ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
                r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
        mService.mH.sendMessage(msg);
    } finally {
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
}

 这里会有一个是否已经有应用进程的判断(也就是这个应用有没有被启动),如果有应用进程则直接到我们的第六阶段,也就是真实启动Activity阶段,如果没有进程则进入我们的第五阶段,创建应用进程阶段。

5、创建应用进程,启动应用

由于是启动一个未启动的App,所以需要先为其分配应用进程,可以发现本质上是走到了ActivityManagerInternal::startProcess方法。

那么这个ActivityManagerInternal又是何方神圣呢,我们发现,它是一个abstract的类,而子类则是ActivityManagerService.LocalService(这里确实让我找了挺久的,看源码就恶心在这里,根本找不到源头),因此我们转移到LocalService的startProcess方法,实际上是调用到了ActivityManagerService的startProcessLocked方法:

final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        HostingRecord hostingRecord, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
            hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
            null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
            null /* crashHandler */);
}

 由此可见,ActivityManagerInternal本质上是ActivityManagerService的一个封装,看LocalLocalService这个名字也就知道它仅用于system_server进程内部使用,方便其他的系统服务调用AMS。

顺藤摸瓜,ProcessList.startProcessLocked 最终的调用如下:

ProcessList.startProcessLocked -> ProcessList.startProcessLocked(重载方法) -> startProcessLocked(重载方法2,这里面进行了一系列启动前检查) ->startProcessLocked(重载方法3) ->ProcessList.startProcess

private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
        ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
        String seInfo, String requiredAbi, String instructionSet, String invokeWith,
        long startTime) {
    try {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                app.processName);
        checkSlow(startTime, "startProcess: asking zygote to start proc");
        final Process.ProcessStartResult startResult;
        if (hostingRecord.usesWebviewZygote()) {
            startResult = startWebView(entryPoint,
                    app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, null, app.info.packageName,
                    new String[] {PROC_START_SEQ_IDENT + app.startSeq});
        } else if (hostingRecord.usesAppZygote()) {
            final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);

            startResult = appZygote.getProcess().start(entryPoint,
                    app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, null, app.info.packageName,
                    /*useUsapPool=*/ false,
                    new String[] {PROC_START_SEQ_IDENT + app.startSeq});
        } else {
            startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, invokeWith, app.info.packageName,
                    new String[] {PROC_START_SEQ_IDENT + app.startSeq});
        }
        checkSlow(startTime, "startProcess: returned from zygote!");
        return startResult;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}

 这边其实是调用到了Process.start方法。这里就是启动一个进程的开始啦。Process启动过程比较复杂,后续再分析,此处可以简单总结一下调用流程:Process.start -> ZYGOTE_PROCESS.start -> ZygoteProcess.startViaZygote -> ZygoteProcess.zygoteSendArgsAndGetResult(此处发送启动命令到Zygote进程,通过LocalSocket方式实现进程通信,即前面我们流程图提到的AMS与Zygote进程是通过Sokect进程通信的)

Zygote进程接收命令后,通过fork操作,复制出一个新进程,然后进入新进程执行(fork操作调用一次,在新旧进程分别返回不同的resultCode,从而可以在新旧进程中执行不同的逻辑),这部分逻辑如下:ZygoteServer.runSelectLoop -> ZygoteConnection.processOneCommand

pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
            parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
            parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
            parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);

    try {
        if (pid == 0) {
            // in child
            zygoteServer.setForkChild();

            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;

            return handleChildProc(parsedArgs, descriptors, childPipeFd,
                    parsedArgs.mStartChildZygote);
        } else {
            // In the parent. A pid < 0 indicates a failure and will be handled in
            // handleParentProc.
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            handleParentProc(pid, descriptors, serverPipeFd);
            return null;
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }

 此处便是fork的逻辑,可以看到,返回值pid可能为0,也可能不为0,这就是fork执行一次,返回两次的奥秘,对于新fork出来的子进程,pid == 0,于是便进入了 handleChildProc 方法。在handleChildProc中,又调用了 ZygoteInit.childZygoteInit 方法,这里面就是去查找进程的main方法了。我们知道,Android App的main方法,就是ActivityThread.main方法,于是来到了ActivityThread.main,main方法中,又调用了ActivityThread.attach方法,然后调用到了IActivityManager.attachApplication方法,这时候又回到了AMS中。那么我们接着来看看ActivityManagerService.attachApplication

public final void attachApplication(IApplicationThread thread, long startSeq) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}

 attachApplication 又会调用attachApplicationLocked,在attachApplicationLocked中,首先会调用ActivityThread.bindApplication(IPC,运行在app进程),bindApplication后继续调用ActivityTaskManagerService.attachApplication。这两次调用都是在ActivityManagerService中依次执行的异步任务

 if (app.isolatedEntryPoint != null) {
        // This is an isolated process which should just call an entry point instead of
        // being bound to an application.
        thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
    } else if (instr2 != null) {
        thread.bindApplication(processName, appInfo, providers,
                instr2.mClass,
                profilerInfo, instr2.mArguments,
                instr2.mWatcher,
                instr2.mUiAutomationConnection, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.compat, getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions);
    } else {
        thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                null, null, null, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.compat, getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions);
    }
} catch (Exception e) {
    // 省略
}
   // 省略
if (normalMode) {
    try {
//这里的mAtmInternal是ActivityTaskManagerService的代理接口
        didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
    } catch (Exception e) {
        Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
        badApp = true;
    }
}

 而ActivityTaskManagerService.attachApplication又会调用RootActivityContainer.attachApplication

boolean attachApplication(WindowProcessController app) throws RemoteException {
    final String processName = app.mName;
    boolean didSomething = false;
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
        final ActivityDisplay display = mActivityDisplays.get(displayNdx);
        final ActivityStack stack = display.getFocusedStack();
        if (stack != null) {
            stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
            final ActivityRecord top = stack.topRunningActivityLocked();
            final int size = mTmpActivityList.size();
            for (int i = 0; i < size; i++) {
                final ActivityRecord activity = mTmpActivityList.get(i);
                if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
                        && processName.equals(activity.processName)) {
                    try {
                        if (mStackSupervisor.realStartActivityLocked(activity, app,
                                top == activity /* andResume */, true /* checkConfig */)) {
                            didSomething = true;
                        }
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Exception in new application when starting activity "
                                + top.intent.getComponent().flattenToShortString(), e);
                        throw e;
                    }
                }
            }
        }
    }
    if (!didSomething) {
        ensureActivitiesVisible(null, 0, false /* preserve_windows */);
    }
    return didSomething;
}

 这个方法的核心逻辑就是把待启动的Activity取出来,调用StackSupervisor.realStartActivityLocked方法。于是正式进入我们的第六阶段,启动Activity。

6、启动Activity

StackSupervisor.realStartActivityLocked方法是不是很熟悉,这就是上面第四步判断如果应用已经启动直接执行的方法。绕了一大圈,多了整个第五阶段就是为了创建应用进程启动我们的应用。看方法名也能猜出来,这里就是我们真正启动我们的Activity的地方了。我们只贴一下核心的逻辑代码

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
        boolean andResume, boolean checkConfig) throws RemoteException {
//省略
// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(
        proc.getThread(), r.appToken);

final DisplayContent dc = r.getDisplay().mDisplayContent;
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
        System.identityHashCode(r), r.info,
        // TODO: Have this take the merged configuration instead of separate global
        // and override configs.
        mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(), r.compat,
        r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
        r.icicle, r.persistentState, results, newIntents,
        dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
                r.assistToken));

// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
    lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
    lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);

// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
//省略
}

通过代码调用流程发现最终调用的是就是clientTransaction.addCallback时创建的LaunchActivityItem实列的execute方法。具体流程请跟着流程图跟踪源码。

public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
            mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
            mPendingResults, mPendingNewIntents, mIsForward,
            mProfilerInfo, client, mAssistToken);
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

 可以发现是调用了client.handleLaunchActivity方法。这个client为何物呢?这是一个ClientTransactionHandler,通过分析我们发现这个ClientTransactionHandler的实现类就是ActivityThread,也就是说,最终走到了ActivityThread.handleLaunchActivity,这也就是回到了app进程,进入执行阶段。

public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    // 省略

    // Initialize before creating the activity
    if (!ThreadedRenderer.sRendererDisabled
            && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
        HardwareRenderer.preload();
    }
    WindowManagerGlobal.initialize();

    // Hint the GraphicsEnvironment that an activity is launching on the process.
    GraphicsEnvironment.hintActivityLaunch();

    final Activity a = performLaunchActivity(r, customIntent);

    // 省略
}

 走进了performLaunchActivity方法

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 准备工作

    // 1、首先创建和Activity绑定的Context对象,这也就解释了为什么我们Activity的Context实列是ContextImpl 了
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
     //2、创建Activity   
     activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        // ...
    }

    try {
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

        // ...

        if (activity != null) {
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);
            if (r.overrideConfig != null) {
                config.updateFrom(r.overrideConfig);
            }
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                    + r.activityInfo.name + " with config " + config);
            Window window = null;
            if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                window = r.mPendingRemoveWindow;
                r.mPendingRemoveWindow = null;
                r.mPendingRemoveWindowManager = null;
            }
            appContext.setOuterContext(activity);
            // 3、Attach,一些组件的赋值
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback,
                    r.assistToken);

            if (customIntent != null) {
                activity.mIntent = customIntent;
            }
            r.lastNonConfigurationInstances = null;
            checkAndBlockForNetworkAccess();
            activity.mStartedActivity = false;
            int theme = r.activityInfo.getThemeResource();
            if (theme != 0) {
                activity.setTheme(theme);
            }

            activity.mCalled = false;
            // 4、调用Activity.onCreate方法
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            if (!activity.mCalled) {
                throw new SuperNotCalledException(
                    "Activity " + r.intent.getComponent().toShortString() +
                    " did not call through to super.onCreate()");
            }
            r.activity = activity;
        }
        r.setState(ON_CREATE);

        // updatePendingActivityConfiguration() reads from mActivities to update
        // ActivityClientRecord which runs in a different thread. Protect modifications to
        // mActivities to avoid race.
        synchronized (mResourcesManager) {
            mActivities.put(r.token, r);
        }

    } catch (SuperNotCalledException e) {
        throw e;

    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to start activity " + component
                + ": " + e.toString(), e);
        }
    }

    return activity;
}

 从注释 Core implementation of activity launch. 就可以看出来,这是Activity启动的核心逻辑。

最终,走到了mInstrumentation.callActivityOnCreate,顾名思义,这里面就会调用到Activity.onCreate方法,也就到了我们熟悉的Activity的第一个生命周期方法了。这里就不贴代码解释了。这样我们Activity启动的整个流程就结束了。

三、总结

由以上分析可以看出,启动一个Activity,过程十分复杂,主要分为如下部分

  1. Activity启动的发起:这部分主要是调用进程中执行,较简单
  2. 与AMS建立通信节点:这部分是发起的延续,主要是获取AMS的Binder代理,准备通信。
  3. AMS的Activity启动管理:这部分主要在system_server进程中执行,是最复杂的部分,包含了各种情况的处理,主要分为应用未启动还应用已启动两种情况。
  4. 创建应用进程:这部分是针对应用未启动的情况的,这个过程中涉及到AMS与Zygote进程的通信,请求Zygote进程为应用分配进程,以及Zygote分配进程后启动应用进程,应用进程再回到AMS,再到AMS与应用进程通信,启动Activity的流程,非常复杂。
  5. 启动Activity:这一部分是核心,不管应用是否启动最终都会走到这一步

本文只是对Activity启动流程做了一个粗浅的分析,其中还有非常多的细节是被略过的,建议亲自阅读源码,而这篇文章可以作为一个指路者,亲自阅读才能更深刻地理解其中的原理。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值