观心静

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

版权声明

本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/17534995.html

本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。

前言

  此博客基于Android10版本,探索Activitiy的启动流程。Activitiy启动流程相当复杂,这里先看看简单概述的流程图:

  在说Activity启动流程时,我们一般会把这部分功能归于ActivityManagerService,但是系统进程中主要参与Activity的启动的是ActivityTaskManager,而ActivityTaskManager属于ActivityManagerService的一部分。 所以ActivityManagerService这个类只是一个Activity管理的笼统概念,有非常多与之配合的管理类才是真正实现这些功能的关键。

  此外请不要误解ActivityManagerService创建与显示了Activity,在Activity的启动流程中ActivityManagerService都未真正的去创建activity与显示Activity的内容(这部分还是会通过AIDL调用在应用层去实现)ActivityManagerService的主要工作还是记录Activity的堆栈、控制需要顶层显示的Activity、协调切换前后台的Activity流程,支配并且发布应用层activity的生命周期,控制Activity的生命周期全部流程。当然,我上面提了ActivityManagerService只是一个笼统概念,真正去实现这些功能的主要是以下几个类ActivityTaskManager、ActivityStarter、RootActivityContainer 、ActivityStackSupervisor、ActivityStack 。

启动Activity的流程图

启动Activity的流程详解 

第一步  调用Activity的startActivity方法。

注意,这个时候还是应用进程里。

第二步

第三步 调用mInstrumentation.execStartActivity方法

Instrumentation是Android用来自动化测试、性能分享、代码注入等等,用来辅助测试的类,说实话我也很纳闷为什么启动startActivity需要这个类参与,有点职责不清的感觉。

在下面代码中通过的ActivityTaskManager.getService() 获得的是IActivityTaskManager。你看到这个IActivityTaskManager就可以明白这是AIDL生成的接口类。然后通过IActivityTaskManager调用startActivity,通过AIDL将调用方法传递到系统进程,所以从这里继续下去就要跨进程了。

ActivityTaskManager.java

IActivityTaskManager.aidl

第四步 通过AIDL跨进程调用frameworek中ActivityTaskManagerService的startActivity方法

请注意,这一步已经是在系统进程里了

然后,我们看看startActivity方法

首先调用第1016行的startActivity,接下来会调用startActivityAsUser

startActivityAsUser方法

请注意,最后组装会执行execute方法

第五步 通过ActivityStarter活动启动,管理即将启动的Activity的堆栈与生命周期

  ActivityStarter的主要功能是解析和组装Intent、启动模式处理、权限和验证检查是否具有启动指定Activity的权限、是否满足Activity所需的最低API级别等、ActivityStarter会触发一系列系统回调方法,如onCreate()、onStart()、onResume()等,以便目标Activity能够进行必要的初始化和展示用户界面。它还会处理Activity的可见性和焦点事件的分发、ActivityStarter负责协调和监控Activity启动的整个过程。

首先通过ActivityStartController 活动启动控制器获得ActivityStarter

ActivityStarter的execute方法

ActivityStarter类

重载startActivity方法,主要是记录了马上要启动的Activity的启动原因、时间戳、启动结果。

ActivityStarter类

这是上面调用的startActivity方法,这个startActivity主要代码逻辑:

1.检查应用进程,如果进程不存在返回失败结果

2.拦截器这个需要启动的activity(应用退到后台或者用户锁屏了)

3.检查activity启动的权限

4.检查intent携带的flag,处理启动模式

5.创建ActivityRecord,记录信息

最后这个startActivity方法会调用这行代码继续执行:final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,         true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity); 

private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
        String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
        SafeActivityOptions options,
        boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
        TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
        PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
    mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
    int err = ActivityManager.START_SUCCESS;
    // Pull the optional Ephemeral Installer-only bundle out of the options early.
    final Bundle verificationBundle
            = options != null ? options.popAppVerificationBundle() : null;

    WindowProcessController callerApp = null;
    if (caller != null) {
        callerApp = mService.getProcessController(caller);
        if (callerApp != null) {
            callingPid = callerApp.getPid();
            callingUid = callerApp.mInfo.uid;
        } else {
            Slog.w(TAG, "Unable to find app for caller " + caller
                    + " (pid=" + callingPid + ") when starting: "
                    + intent.toString());
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }

    final int userId = aInfo != null && aInfo.applicationInfo != null
            ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;

    if (err == ActivityManager.START_SUCCESS) {
        Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
                + "} from uid " + callingUid);
    }

    ActivityRecord sourceRecord = null;
    ActivityRecord resultRecord = null;
    if (resultTo != null) {
        sourceRecord = mRootActivityContainer.isInAnyStack(resultTo);
        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                "Will send result to " + resultTo + " " + sourceRecord);
        if (sourceRecord != null) {
            if (requestCode >= 0 && !sourceRecord.finishing) {
                resultRecord = sourceRecord;
            }
        }
    }

    final int launchFlags = intent.getFlags();

    if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
        // Transfer the result target from the source activity to the new
        // one being started, including any failures.
        if (requestCode >= 0) {
            SafeActivityOptions.abort(options);
            return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
        }
        resultRecord = sourceRecord.resultTo;
        if (resultRecord != null && !resultRecord.isInStackLocked()) {
            resultRecord = null;
        }
        resultWho = sourceRecord.resultWho;
        requestCode = sourceRecord.requestCode;
        sourceRecord.resultTo = null;
        if (resultRecord != null) {
            resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
        }
        if (sourceRecord.launchedFromUid == callingUid) {
            // The new activity is being launched from the same uid as the previous
            // activity in the flow, and asking to forward its result back to the
            // previous.  In this case the activity is serving as a trampoline between
            // the two, so we also want to update its launchedFromPackage to be the
            // same as the previous activity.  Note that this is safe, since we know
            // these two packages come from the same uid; the caller could just as
            // well have supplied that same package name itself.  This specifially
            // deals with the case of an intent picker/chooser being launched in the app
            // flow to redirect to an activity picked by the user, where we want the final
            // activity to consider it to have been launched by the previous app activity.
            callingPackage = sourceRecord.launchedFromPackage;
        }
    }

    if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
        // We couldn't find a class that can handle the given Intent.
        // That's the end of that!
        err = ActivityManager.START_INTENT_NOT_RESOLVED;
    }

    if (err == ActivityManager.START_SUCCESS && aInfo == null) {
        // We couldn't find the specific class specified in the Intent.
        // Also the end of the line.
        err = ActivityManager.START_CLASS_NOT_FOUND;
    }

    if (err == ActivityManager.START_SUCCESS && sourceRecord != null
            && sourceRecord.getTaskRecord().voiceSession != null) {
        // If this activity is being launched as part of a voice session, we need
        // to ensure that it is safe to do so.  If the upcoming activity will also
        // be part of the voice session, we can only launch it if it has explicitly
        // said it supports the VOICE category, or it is a part of the calling app.
        if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
                && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
            try {
                intent.addCategory(Intent.CATEGORY_VOICE);
                if (!mService.getPackageManager().activitySupportsIntent(
                        intent.getComponent(), intent, resolvedType)) {
                    Slog.w(TAG,
                            "Activity being started in current voice task does not support voice: "
                                    + intent);
                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Failure checking voice capabilities", e);
                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
            }
        }
    }

    if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
        // If the caller is starting a new voice session, just make sure the target
        // is actually allowing it to run this way.
        try {
            if (!mService.getPackageManager().activitySupportsIntent(intent.getComponent(),
                    intent, resolvedType)) {
                Slog.w(TAG,
                        "Activity being started in new voice task does not support: "
                                + intent);
                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
            }
        } catch (RemoteException e) {
            Slog.w(TAG, "Failure checking voice capabilities", e);
            err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
        }
    }

    final ActivityStack resultStack = resultRecord == null
            ? null : resultRecord.getActivityStack();

    if (err != START_SUCCESS) {
        if (resultRecord != null) {
            resultStack.sendActivityResultLocked(
                    -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
        }
        SafeActivityOptions.abort(options);
        return err;
    }

    boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
            requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
            inTask != null, callerApp, resultRecord, resultStack);
    abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
            callingPid, resolvedType, aInfo.applicationInfo);
    abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
            callingPackage);

    boolean restrictedBgActivity = false;
    if (!abort) {
        try {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                    "shouldAbortBackgroundActivityStart");
            restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
                    callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
                    originatingPendingIntent, allowBackgroundActivityStart, intent);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
    }

    // Merge the two options bundles, while realCallerOptions takes precedence.
    ActivityOptions checkedOptions = options != null
            ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null;
    if (allowPendingRemoteAnimationRegistryLookup) {
        checkedOptions = mService.getActivityStartController()
                .getPendingRemoteAnimationRegistry()
                .overrideOptionsIfNeeded(callingPackage, checkedOptions);
    }
    if (mService.mController != null) {
        try {
            // The Intent we give to the watcher has the extra data
            // stripped off, since it can contain private information.
            Intent watchIntent = intent.cloneFilter();
            abort |= !mService.mController.activityStarting(watchIntent,
                    aInfo.applicationInfo.packageName);
        } catch (RemoteException e) {
            mService.mController = null;
        }
    }

    mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
    if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
            callingUid, checkedOptions)) {
        // activity start was intercepted, e.g. because the target user is currently in quiet
        // mode (turn off work) or the target application is suspended
        intent = mInterceptor.mIntent;
        rInfo = mInterceptor.mRInfo;
        aInfo = mInterceptor.mAInfo;
        resolvedType = mInterceptor.mResolvedType;
        inTask = mInterceptor.mInTask;
        callingPid = mInterceptor.mCallingPid;
        callingUid = mInterceptor.mCallingUid;
        checkedOptions = mInterceptor.mActivityOptions;
    }

    if (abort) {
        if (resultRecord != null) {
            resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
                    RESULT_CANCELED, null);
        }
        // We pretend to the caller that it was really started, but
        // they will just get a cancel result.
        ActivityOptions.abort(checkedOptions);
        return START_ABORTED;
    }

    // If permissions need a review before any of the app components can run, we
    // launch the review activity and pass a pending intent to start the activity
    // we are to launching now after the review is completed.
    if (aInfo != null) {
        if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                aInfo.packageName, userId)) {
            IIntentSender target = mService.getIntentSenderLocked(
                    ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
                    callingUid, userId, null, null, 0, new Intent[]{intent},
                    new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
                            | PendingIntent.FLAG_ONE_SHOT, null);

            Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);

            int flags = intent.getFlags();
            flags |= Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;

            /*
             * Prevent reuse of review activity: Each app needs their own review activity. By
             * default activities launched with NEW_TASK or NEW_DOCUMENT try to reuse activities
             * with the same launch parameters (extras are ignored). Hence to avoid possible
             * reuse force a new activity via the MULTIPLE_TASK flag.
             *
             * Activities that are not launched with NEW_TASK or NEW_DOCUMENT are not re-used,
             * hence no need to add the flag in this case.
             */
            if ((flags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT)) != 0) {
                flags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
            }
            newIntent.setFlags(flags);

            newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
            newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
            if (resultRecord != null) {
                newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
            }
            intent = newIntent;

            resolvedType = null;
            callingUid = realCallingUid;
            callingPid = realCallingPid;

            rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0,
                    computeResolveFilterUid(
                            callingUid, realCallingUid, mRequest.filterCallingUid));
            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
                    null /*profilerInfo*/);

            if (DEBUG_PERMISSIONS_REVIEW) {
                final ActivityStack focusedStack =
                        mRootActivityContainer.getTopDisplayFocusedStack();
                Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
                        true, false) + "} from uid " + callingUid + " on display "
                        + (focusedStack == null ? DEFAULT_DISPLAY : focusedStack.mDisplayId));
            }
        }
    }

    // If we have an ephemeral app, abort the process of launching the resolved intent.
    // Instead, launch the ephemeral installer. Once the installer is finished, it
    // starts either the intent we resolved here [on install error] or the ephemeral
    // app [on install success].
    if (rInfo != null && rInfo.auxiliaryInfo != null) {
        intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
                callingPackage, verificationBundle, resolvedType, userId);
        resolvedType = null;
        callingUid = realCallingUid;
        callingPid = realCallingPid;

        aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
    }

    ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
            callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
            resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
            mSupervisor, checkedOptions, sourceRecord);
    if (outActivity != null) {
        outActivity[0] = r;
    }

    if (r.appTimeTracker == null && sourceRecord != null) {
        // If the caller didn't specify an explicit time tracker, we want to continue
        // tracking under any it has.
        r.appTimeTracker = sourceRecord.appTimeTracker;
    }

    final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();

    // If we are starting an activity that is not from the same uid as the currently resumed
    // one, check whether app switches are allowed.
    if (voiceSession == null && (stack.getResumedActivity() == null
            || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
        if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                realCallingPid, realCallingUid, "Activity start")) {
            if (!(restrictedBgActivity && handleBackgroundActivityAbort(r))) {
                mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
                        sourceRecord, startFlags, stack, callerApp));
            }
            ActivityOptions.abort(checkedOptions);
            return ActivityManager.START_SWITCHES_CANCELED;
        }
    }

    mService.onStartActivitySetDidAppSwitch();
    mController.doPendingActivityLaunches(false);

    final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
            true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity);
    mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outActivity[0]);
    return res;
}

ActivityStarter类

这是上面调用的startActivity的方法代码

ActivityStarter类

这是上面代码调用的startActivityUnchecked方法,其中调用的resumeFocusedStacksTopActivities 方法是下一步的关键。 

// Note: This method should only be called from {@link startActivity}.
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();

    mSupervisor.getLaunchParamsController().calculate(
            reusedActivity != null ? reusedActivity.getTaskRecord() : mInTask,
            r.info.windowLayout, r, sourceRecord, options, PHASE_BOUNDS, mLaunchParams);
    mPreferredDisplayId =
            mLaunchParams.hasPreferredDisplay() ? mLaunchParams.mPreferredDisplayId
                    : DEFAULT_DISPLAY;

    // Do not start home activity if it cannot be launched on preferred display. We are not
    // doing this in ActivityStackSupervisor#canPlaceEntityOnDisplay because it might
    // fallback to launch on other displays.
    if (r.isActivityTypeHome() && !mRootActivityContainer.canStartHomeOnDisplay(r.info,
            mPreferredDisplayId, true /* allowInstrumenting */)) {
        Slog.w(TAG, "Cannot launch home on display " + mPreferredDisplayId);
        return START_CANCELED;
    }

    if (reusedActivity != null) {
        // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
        // still needs to be a lock task mode violation since the task gets cleared out and
        // the device would otherwise leave the locked task.
        if (mService.getLockTaskController().isLockTaskModeViolation(
                reusedActivity.getTaskRecord(),
                (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
            Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }

        // True if we are clearing top and resetting of a standard (default) launch mode
        // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
        final boolean clearTopAndResetStandardLaunchMode =
                (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
                        == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
                && mLaunchMode == LAUNCH_MULTIPLE;

        // If mStartActivity does not have a task associated with it, associate it with the
        // reused activity's task. Do not do so if we're clearing top and resetting for a
        // standard launchMode activity.
        if (mStartActivity.getTaskRecord() == null && !clearTopAndResetStandardLaunchMode) {
            mStartActivity.setTask(reusedActivity.getTaskRecord());
        }

        if (reusedActivity.getTaskRecord().intent == null) {
            // This task was started because of movement of the activity based on affinity...
            // Now that we are actually launching it, we can assign the base intent.
            reusedActivity.getTaskRecord().setIntent(mStartActivity);
        } else {
            final boolean taskOnHome =
                    (mStartActivity.intent.getFlags() & FLAG_ACTIVITY_TASK_ON_HOME) != 0;
            if (taskOnHome) {
                reusedActivity.getTaskRecord().intent.addFlags(FLAG_ACTIVITY_TASK_ON_HOME);
            } else {
                reusedActivity.getTaskRecord().intent.removeFlags(FLAG_ACTIVITY_TASK_ON_HOME);
            }
        }

        // This code path leads to delivering a new intent, we want to make sure we schedule it
        // as the first operation, in case the activity will be resumed as a result of later
        // operations.
        if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                || isDocumentLaunchesIntoExisting(mLaunchFlags)
                || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
            final TaskRecord task = reusedActivity.getTaskRecord();

            // In this situation we want to remove all activities from the task up to the one
            // being started. In most cases this means we are resetting the task to its initial
            // state.
            final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
                    mLaunchFlags);

            // The above code can remove {@code reusedActivity} from the task, leading to the
            // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
            // task reference is needed in the call below to
            // {@link setTargetStackAndMoveToFrontIfNeeded}.
            if (reusedActivity.getTaskRecord() == null) {
                reusedActivity.setTask(task);
            }

            if (top != null) {
                if (top.frontOfTask) {
                    // Activity aliases may mean we use different intents for the top activity,
                    // so make sure the task now has the identity of the new intent.
                    top.getTaskRecord().setIntent(mStartActivity);
                }
                deliverNewIntent(top);
            }
        }

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

        reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);

        final ActivityRecord outResult =
                outActivity != null && outActivity.length > 0 ? outActivity[0] : null;

        // When there is a reused activity and the current result is a trampoline activity,
        // set the reused activity as the result.
        if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
            outActivity[0] = reusedActivity;
        }

        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            // We don't need to start a new activity, and the client said not to do anything
            // if that is the case, so this is it!  And for paranoia, make sure we have
            // correctly resumed the top activity.
            resumeTargetStackIfNeeded();
            return START_RETURN_INTENT_TO_CALLER;
        }

        if (reusedActivity != null) {
            setTaskFromIntentActivity(reusedActivity);

            if (!mAddingToTask && mReuseTask == null) {
                // We didn't do anything...  but it was needed (a.k.a., client don't use that
                // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
                resumeTargetStackIfNeeded();
                if (outActivity != null && outActivity.length > 0) {
                    // The reusedActivity could be finishing, for example of starting an
                    // activity with FLAG_ACTIVITY_CLEAR_TOP flag. In that case, return the
                    // top running activity in the task instead.
                    outActivity[0] = reusedActivity.finishing
                            ? reusedActivity.getTaskRecord().getTopActivity() : reusedActivity;
                }

                return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
            }
        }
    }

    if (mStartActivity.packageName == null) {
        final ActivityStack sourceStack = mStartActivity.resultTo != null
                ? mStartActivity.resultTo.getActivityStack() : null;
        if (sourceStack != null) {
            sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
                    null /* data */);
        }
        ActivityOptions.abort(mOptions);
        return START_CLASS_NOT_FOUND;
    }

    // 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.
    final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack();
    final ActivityRecord topFocused = topStack.getTopActivity();
    final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
    final boolean dontStart = top != null && mStartActivity.resultTo == null
            && top.mActivityComponent.equals(mStartActivity.mActivityComponent)
            && top.mUserId == mStartActivity.mUserId
            && top.attachedToProcess()
            && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
            || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK))
            // This allows home activity to automatically launch on secondary display when
            // display added, if home was the top activity on default display, instead of
            // sending new intent to the home activity on default display.
            && (!top.isActivityTypeHome() || top.getDisplayId() == mPreferredDisplayId);
    if (dontStart) {
        // For paranoia, make sure we have correctly resumed the top activity.
        topStack.mLastPausedActivity = null;
        if (mDoResume) {
            mRootActivityContainer.resumeFocusedStacksTopActivities();
        }
        ActivityOptions.abort(mOptions);
        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            // We don't need to start a new activity, and the client said not to do
            // anything if that is the case, so this is it!
            return START_RETURN_INTENT_TO_CALLER;
        }

        deliverNewIntent(top);

        // Don't use mStartActivity.task to show the toast. We're not starting a new activity
        // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
        mSupervisor.handleNonResizableTaskIfNeeded(top.getTaskRecord(), preferredWindowingMode,
                mPreferredDisplayId, topStack);

        return START_DELIVERED_TO_TOP;
    }

    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;
    }

    mService.mUgmInternal.grantUriPermissionFromIntent(mCallingUid, mStartActivity.packageName,
            mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.mUserId);
    mService.getPackageManagerInternalLocked().grantEphemeralAccess(
            mStartActivity.mUserId, mIntent, UserHandle.getAppId(mStartActivity.appInfo.uid),
            UserHandle.getAppId(mCallingUid));
    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);

    mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
            mOptions);
    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;
}

第六步 调用RootActivityContainer类resumeFocusedStacksTopActivities 方法

RootActivityContainer 这个类是临时的(可能是从Android10版本后新增的),用于将一部分功能从ActivityStackSupervisor.java中分离出来,所以RootActivityContainer是ActivityStackSupervisor的部分功能的承接者,负责记录和管理活动的导航栈,也就是用户在应用程序中浏览活动的顺序和层次关系。它可以跟踪用户打开和关闭活动的操作,并确保正确的活动出现在屏幕上。

第七步 调用ActivityStack类的resumeTopActivityUncheckedLocked方法

这里介绍一下ActivityStack,ActivityStack是一个具体的活动栈实例,代表了一个任务(Task)中的一组活动。每个任务对应一个活动栈,其中包含了按照启动顺序排列的活动实例。ActivityStack的主要功能是管理和维护活动实例的生命周期,以及处理用户界面的导航和交互。内部有TaskRecord的集合mTaskHistory全局变量 与 ActivityRecord的集合mLRUActivities全局变量。mTaskHistory负责保存所有以前(可能仍在运行)活动的后台历史记录, mLRUActivities用来按最近的使用情况排序。

resumeTopActivityUncheckedLocked方法是ActivityStack类中的一个重要方法,用于恢复位于栈顶的Activity。

ActivityStack类resumeTopActivityInnerLocked方法

这里介绍下resumeTopActivityInnerLocked方法,此方法主要功能是在启动Activity的过程中将要启动的Activity设置为顶层可见。最后会调用mStackSupervisor.startSpecificActivityLocked(next, true, true); 跳转到下一个方法。 

@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    if (!mService.isBooting() && !mService.isBooted()) {
        // Not ready yet!
        return false;
    }

    //这行代码很关键!在这里会找到下一个需要顶层显示的Activity,也就是我们即将需要启动的Activity
    ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);

    //判断找到的下一个需要顶层显示的Activity是否存在
    final boolean hasRunningActivity = next != null;

    // TODO: Maybe this entire condition can get removed?
    if (hasRunningActivity && !isAttached()) {
        return false;
    }

    mRootActivityContainer.cancelInitializingActivities();

    // Remember how we'll process this pause/resume situation, and ensure
    // that the state is reset however we wind up proceeding.
    boolean userLeaving = mStackSupervisor.mUserLeaving;
    mStackSupervisor.mUserLeaving = false;

    if (!hasRunningActivity) {
        // There are no activities left in the stack, let's look somewhere else.
        return resumeNextFocusableActivityWhenStackIsEmpty(prev, options);
    }

    next.delayedResume = false;
    final ActivityDisplay display = getDisplay();

    // 判断现在顶层的Activity是否与下一个要启动的Activity是一样的,如果是一样的就不启动它了
    if (mResumedActivity == next && next.isState(RESUMED)
            && display.allResumedActivitiesComplete()) {
        // Make sure we have executed any pending transitions, since there
        // should be nothing left to do at this point.
        executeAppTransition(options);
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Top activity resumed " + next);
        return false;
    }
    //判断下一个要启动的Activity,是否可以恢复显示出来,这部分代码判断与窗口进程控制器有关
    if (!next.canResumeByCompat()) {
        return false;
    }

    //这里通过shouldSleepOrShutDownActivities判断设备是否在休眠(锁屏休眠),并且判断mLastPausedActivity暂停活动是否等于下一个要启动的活动。
    if (shouldSleepOrShutDownActivities()
            && mLastPausedActivity == next
            && mRootActivityContainer.allPausedActivitiesComplete()) {
        //如果下一个要启动的活动可能会遮挡锁屏页面,但是遮挡状态没有设置,则在检查一下要启动的活动是否能显示。简单的说就是这个Activity牛,可以在锁屏上显示
        boolean nothingToResume = true;
        if (!mService.mShuttingDown) {
            final boolean canShowWhenLocked = !mTopActivityOccludesKeyguard
                    && next.canShowWhenLocked();
            final boolean mayDismissKeyguard = mTopDismissingKeyguardActivity != next
                    && next.mAppWindowToken != null
                    && next.mAppWindowToken.containsDismissKeyguardWindow();

            if (canShowWhenLocked || mayDismissKeyguard) {
                ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
                        !PRESERVE_WINDOWS);
                nothingToResume = shouldSleepActivities();
            }
        }
        //如果是true表示无需恢复下一个要启动的activity,因为设备已经锁屏睡眠了
        if (nothingToResume) {
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            executeAppTransition(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Going to sleep and all paused");
            return false;
        }
    }

    // 判断下一个要启动Activity的设备用户是否已经启动了,如果用户已经被切换到其他用户了,这个Activity就不启动了
    if (!mService.mAmInternal.hasStartedUserState(next.mUserId)) {
        Slog.w(TAG, "Skipping resume of top activity " + next
                + ": user " + next.mUserId + " is stopped");
        return false;
    }

    //下一个要启动Activity,因为马上要启动了,将它从stop状态的堆栈里移除
    mStackSupervisor.mStoppingActivities.remove(next);
    //下一个要启动Activity,因为马上要启动了,将它从休眠状态堆栈里移除
    mStackSupervisor.mGoingToSleepActivities.remove(next);
    //将休眠状态设置为false
    next.sleeping = false;

    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

    //判断让要暂停的Activity先暂停
    if (!mRootActivityContainer.allPausedActivitiesComplete()) {
        if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                "resumeTopActivityLocked: Skip resume: some activity pausing.");

        return false;
    }

    mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);

    //下面的这段代码是检查最后一个焦点堆栈中的Activity是否可以进入画中画模式,这里的单词Pip是画中画的意思。
    boolean lastResumedCanPip = false;
    ActivityRecord lastResumed = null;
    final ActivityStack lastFocusedStack = display.getLastFocusedStack();
    if (lastFocusedStack != null && lastFocusedStack != this) {
        // So, why aren't we using prev here??? See the param comment on the method. prev doesn't
        // represent the last resumed activity. However, the last focus stack does if it isn't null.
        lastResumed = lastFocusedStack.mResumedActivity;
        if (userLeaving && inMultiWindowMode() && lastFocusedStack.shouldBeVisible(next)) {
            // The user isn't leaving if this stack is the multi-window mode and the last
            // focused stack should still be visible.
            if(DEBUG_USER_LEAVING) Slog.i(TAG_USER_LEAVING, "Overriding userLeaving to false"
                    + " next=" + next + " lastResumed=" + lastResumed);
            userLeaving = false;
        }
        lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
                "resumeTopActivity", userLeaving /* beforeStopping */);
    }
    // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
    // to be paused, while at the same time resuming the new resume activity only if the
    // previous activity can't go into Pip since we want to give Pip activities a chance to
    // enter Pip before resuming the next activity.
    final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
            && !lastResumedCanPip;

    /// M: onBeforeActivitySwitch @{
    ActivityRecord lastResumedBeforeActivitySwitch
        = lastResumed != null ? lastResumed : mResumedActivity;
    /// M: onBeforeActivitySwitch @}

    boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
    if (mResumedActivity != null) {
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Pausing " + mResumedActivity);
        pausing |= startPausingLocked(userLeaving, false, next, false);
    }

    /// M: onBeforeActivitySwitch @{
    mService.mAmsExt.onBeforeActivitySwitch(
        lastResumedBeforeActivitySwitch, next, pausing,
        next.getActivityType());
    /// M: onBeforeActivitySwitch @}

    if (pausing && !resumeWhilePausing) {
        if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
                "resumeTopActivityLocked: Skip resume: need to start pausing");
        // At this point we want to put the upcoming activity's process
        // at the top of the LRU list, since we know we will be needing it
        // very soon and it would be a waste to let it get killed if it
        // happens to be sitting towards the end.
        if (next.attachedToProcess()) {
            next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
                    true /* activityChange */, false /* updateOomAdj */);
        }
        if (lastResumed != null) {
            lastResumed.setWillCloseOrEnterPip(true);
        }
        return true;
    } else if (mResumedActivity == next && next.isState(RESUMED)
            && display.allResumedActivitiesComplete()) {
        // It is possible for the activity to be resumed when we paused back stacks above if the
        // next activity doesn't have to wait for pause to complete.
        // So, nothing else to-do except:
        // Make sure we have executed any pending transitions, since there
        // should be nothing left to do at this point.
        executeAppTransition(options);
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
        return true;
    }

    // If the most recent activity was noHistory but was only stopped rather
    // than stopped+finished because the device went to sleep, we need to make
    // sure to finish it as we're making a new activity topmost.
    if (shouldSleepActivities() && mLastNoHistoryActivity != null &&
            !mLastNoHistoryActivity.finishing) {
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "no-history finish of " + mLastNoHistoryActivity + " on new resume");
        requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
                null, "resume-no-history", false);
        mLastNoHistoryActivity = null;
    }
    //执行到这里已经,要启动的Activity已经显示了,现在这边判断将prev上一个Ativity尽快隐藏。
    if (prev != null && prev != next && next.nowVisible) {

        // The next activity is already visible, so hide the previous
        // activity's windows right now so we can show the new one ASAP.
        // We only do this if the previous is finishing, which should mean
        // it is on top of the one being resumed so hiding it quickly
        // is good.  Otherwise, we want to do the normal route of allowing
        // the resumed activity to be shown so we can decide if the
        // previous should actually be hidden depending on whether the
        // new one is found to be full-screen or not.
        if (prev.finishing) {
            //这里判断上一个Activity是否finish,并且将可见度设置为false
            prev.setVisibility(false);
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                    "Not waiting for visible to hide: " + prev
                    + ", nowVisible=" + next.nowVisible);
        } else {
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                    "Previous already visible but still waiting to hide: " + prev
                    + ", nowVisible=" + next.nowVisible);
        }

    }

    //启动此应用程序的Activity时,请确保不再认为该应用程序已停止。
    //这里通过AppGlobals对要启动的Activity的应用程序进行设置,防止Activity启动的同时应用程序被停止了。
    try {
        AppGlobals.getPackageManager().setPackageStoppedState(
                next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */
    } catch (RemoteException e1) {
    } catch (IllegalArgumentException e) {
        Slog.w(TAG, "Failed trying to unstop package "
                + next.packageName + ": " + e);
    }

    //这里马上要启动下一个Activity了,这里通知DisplayContent内容显示执行前后Activity的切换,包括是否执行切换Activity时的动画。
    boolean anim = true;
    final DisplayContent dc = getDisplay().mDisplayContent;
    if (prev != null) {
        if (prev.finishing) {
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare close transition: prev=" + prev);
            if (mStackSupervisor.mNoAnimActivities.contains(prev)) {
                anim = false;
                dc.prepareAppTransition(TRANSIT_NONE, false);
            } else {
                dc.prepareAppTransition(
                        prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_CLOSE
                                : TRANSIT_TASK_CLOSE, false);
            }
            prev.setVisibility(false);
        } else {
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare open transition: prev=" + prev);
            if (mStackSupervisor.mNoAnimActivities.contains(next)) {
                anim = false;
                dc.prepareAppTransition(TRANSIT_NONE, false);
            } else {
                dc.prepareAppTransition(
                        prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_OPEN
                                : next.mLaunchTaskBehind ? TRANSIT_TASK_OPEN_BEHIND
                                        : TRANSIT_TASK_OPEN, false);
            }
        }
    } else {
        if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
        if (mStackSupervisor.mNoAnimActivities.contains(next)) {
            anim = false;
            dc.prepareAppTransition(TRANSIT_NONE, false);
        } else {
            dc.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
        }
    }

    if (anim) {
        next.applyOptionsLocked();
    } else {
        next.clearOptionsLocked();
    }

    mStackSupervisor.mNoAnimActivities.clear();
    //判断要启动的Activity有没有属于它的进程(就是应用程序的进程有没有启动)
    if (next.attachedToProcess()) {
        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
                + " stopped=" + next.stopped + " visible=" + next.visible);

        // If the previous activity is translucent, force a visibility update of
        // the next activity, so that it's added to WM's opening app list, and
        // transition animation can be set up properly.
        // For example, pressing Home button with a translucent activity in focus.
        // Launcher is already visible in this case. If we don't add it to opening
        // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
        // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
        final boolean lastActivityTranslucent = lastFocusedStack != null
                && (lastFocusedStack.inMultiWindowMode()
                || (lastFocusedStack.mLastPausedActivity != null
                && !lastFocusedStack.mLastPausedActivity.fullscreen));

        // 将要启动的Activity设置为可见
        if (!next.visible || next.stopped || lastActivityTranslucent) {
            next.setVisibility(true);
        }

        //这里会安排启动时间以收集有关慢速应用程序的信息。记录应用的启动速度
        next.startLaunchTickingLocked();

        ActivityRecord lastResumedActivity =
                lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity;
        final ActivityState lastState = next.getState();
        //更新CPU的状态
        mService.updateCpuStats();

        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
                + " (in existing)");
        //更新启动Activity的生命周期为onResumed生命周期
        next.setState(RESUMED, "resumeTopActivityInnerLocked");
        //这个是MTK联发科的系统服务工厂功能,这里我也不知道联发科要这个已经启动的Activity干什么..
        /// M: onAfterActivityResumed @{
        mService.mAmsExt.onAfterActivityResumed(next);
        /// M: onAfterActivityResumed @}
        //更新应用的进程信息,activity发生了变化,   
        next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
                true /* activityChange */, true /* updateOomAdj */);
        updateLRUListLocked(next);

        // Have the window manager re-evaluate the orientation of
        // the screen based on the new activity order.
        boolean notUpdated = true;

        // Activity should also be visible if set mLaunchTaskBehind to true (see
        // ActivityRecord#shouldBeVisibleIgnoringKeyguard()).
        if (shouldBeVisible(next)) {
            // We have special rotation behavior when here is some active activity that
            // requests specific orientation or Keyguard is locked. Make sure all activity
            // visibilities are set correctly as well as the transition is updated if needed
            // to get the correct rotation behavior. Otherwise the following call to update
            // the orientation may cause incorrect configurations delivered to client as a
            // result of invisible window resize.
            // TODO: Remove this once visibilities are set correctly immediately when
            // starting an activity.
            notUpdated = !mRootActivityContainer.ensureVisibilityAndConfig(next, mDisplayId,
                    true /* markFrozenIfConfigChanged */, false /* deferResume */);
        }

        if (notUpdated) {
            // The configuration update wasn't able to keep the existing
            // instance of the activity, and instead started a new one.
            // We should be all done, but let's just make sure our activity
            // is still at the top and schedule another run if something
            // weird happened.
            ActivityRecord nextNext = topRunningActivityLocked();
            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
                    "Activity config changed during resume: " + next
                            + ", new next: " + nextNext);
            if (nextNext != next) {
                // Do over!
                mStackSupervisor.scheduleResumeTopActivities();
            }
            if (!next.visible || next.stopped) {
                next.setVisibility(true);
            }
            next.completeResumeLocked();
            return true;
        }

        try {
            final ClientTransaction transaction =
                    ClientTransaction.obtain(next.app.getThread(), next.appToken);
            // Deliver all pending results.
            ArrayList<ResultInfo> a = next.results;
            if (a != null) {
                final int N = a.size();
                if (!next.finishing && N > 0) {
                    if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                            "Delivering results to " + next + ": " + a);
                    transaction.addCallback(ActivityResultItem.obtain(a));
                }
            }

            if (next.newIntents != null) {
                transaction.addCallback(
                        NewIntentItem.obtain(next.newIntents, true /* resume */));
            }

            // Well the app will no longer be stopped.
            // Clear app token stopped state in window manager if needed.
            next.notifyAppResumed(next.stopped);

            EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.mUserId,
                    System.identityHashCode(next), next.getTaskRecord().taskId,
                    next.shortComponentName);

            next.sleeping = false;
            mService.getAppWarningsLocked().onResumeActivity(next);
            next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState);
            next.clearOptionsLocked();
            transaction.setLifecycleStateRequest(
                    ResumeActivityItem.obtain(next.app.getReportedProcState(),
                            getDisplay().mDisplayContent.isNextTransitionForward()));
            mService.getLifecycleManager().scheduleTransaction(transaction);

            if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
                    + next);
        } catch (Exception e) {
            // Whoops, need to restart this activity!
            if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
                    + lastState + ": " + next);
            next.setState(lastState, "resumeTopActivityInnerLocked");

            // lastResumedActivity being non-null implies there is a lastStack present.
            if (lastResumedActivity != null) {
                lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
            }

            Slog.i(TAG, "Restarting because process died: " + next);
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else  if (SHOW_APP_STARTING_PREVIEW && lastFocusedStack != null
                    && lastFocusedStack.isTopStackOnDisplay()) {
                next.showStartingWindow(null /* prev */, false /* newTask */,
                        false /* taskSwitch */);
            }
            mStackSupervisor.startSpecificActivityLocked(next, true, false);
            return true;
        }

        // From this point on, if something goes wrong there is no way
        // to recover the activity.
        try {
            next.completeResumeLocked();
        } catch (Exception e) {
            // If any exception gets thrown, toss away this
            // activity and try the next one.
            Slog.w(TAG, "Exception thrown during resume of " + next, e);
            requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
                    "resume-exception", true);
            return true;
        }
    } 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);
    }

    return true;
}

下面图片中调用了ActivityStackSupervisor类realStartActivityLocked方法,去执行下一步。

ActivityStackSupervisor是一个活动堆栈的全局的管理者,负责协调和管理整个应用程序中的所有活动栈。它是ActivityManagerService中的一部分,负责跟踪和管理不同任务的活动栈,并处理活动的启动、切换和销毁。

ActivityStackSupervisor通过创建和管理多个ActivityStack实例来实现对整个应用程序的活动栈的管理(所以ActivityStackSupervisor是作为ActivityStack管理者)。它通过ActivityStack的方法来操作和管理ActivityStack中的活动实例。ActivityStackSupervisor可以通过跟踪活动栈的状态和任务之间的关系,进行任务的切换和活动的启动。

在realStartActivityLocked方法中

这里创建了ClientTransaction类它客户端事务类,它会携带一些应用进程信息、Activity生命周期信息、ActivityToken。它是需要被传递到应用层的关键信息。提供应用层创建Activity的进程信息与Activity的生命周期信息。

第八步 通过ClientLifecycleManager进行AIDL跨进程

下面会调用ClientLifecycleManager类scheduleTransaction方法。

ClientTransaction类是客户端事务类在上面被创建后传递到这里,它会携带一些应用进程信息、Activity生命周期信息、ActivityToken。它是需要被传递到应用层的关键信息。提供应用层创建Activity的进程信息与Activity的生命周期信息。

通过ClientTransaction类的schedule方法。在这里会通过mClient(这是IApplicationThread的实例)调用scheduleTransaction方法将ClientTransaction自己传递到应用层,最终通过AIDL这个调用会被应用层的ActivityThread.ApplicationThread中的scheduleTransaction方法接收。 

第九步 回调到应用进程中

在ActivityThread的scheduleTransaction会接收消息,从

第十步 发送Handler消息

在上面我们可以看到ActivityThread的scheduleTransaction里又自己调用了scheduleTransaction方法,所以这里的关键是ActivityThread继承的ClientTransactionHandler类,看看它实现的scheduleTransaction方法做了什么。在下面的图片中我们可以看到它发送了一个Handler消息。 这个sendMessage是抽象方法,它的具体实现要回到ActivityThread类中查看。

这里补充一下上面发送sendMessage的ActivityThread的Handler,这很关键,因为大部分工作都通过了ActivityThread的内部类H(H类继承了Handler类),通过这个H类异步调度大量工作,包括了绑定应用、申请退出应用、广播、启动服务、停止服务、绑定服务、解绑服务、创建Activity等等。

在ActivityThread类中的H内部类里,处理发送过来的消息

第十一步 执行启动activity

TransactionExecutor类的execute方法

TransactionExecutor类的executeCallbacks方法

LaunchActivityItem类的execute方法

ActivityThread类的handlerLaunchActivity方法

最后一步,创建新的Activity

ActivityThread类的performLaunchActivity方法

下图最终new了一个activity

end

posted on 2023-07-08 11:55  观心静  阅读(494)  评论(0编辑  收藏  举报