Activity 启动流程分析(一)一天搞懂所有疑难杂问

前言

Activity启动操作在Android开发过程中非常常见,但大多时候我们并未认真思考过其背后的具体流程。在启动某个Activity时,会先启动Activity所在的应用,并启动一个以应用包名为进程名的进程,该进程有一个主线程,叫ActivityThread,也叫做UI线程。

本文将结合源码,详细分析Activity的启动流程。希望帮助大家理解与掌握。同时若文中存在错误,或有不易理解的地方,也请大家帮忙指正,一起学习,共同涨薪。

一、开始调用

入口函数ContextWrapper.startActivity

启动Activity的时候,首先我们会调用到Activity的startActivity()方法 点进去一看实际上调用的是ContextWrapper的startActivity()方法,看一下这个方法:

 @Override
    public void startActivity(Intent intent) {
        mBase.startActivity(intent);
    } 

这里并没有具体实现,而是调用mBase的startActivity方法,而这个mBase其实是传入的一个ContextImpl实例

ContextImpl.startActivity

 // /frameworks/base/core/java/android/app/ContextImpl.java
    @Override
    public void startActivity(Intent intent) {
        warnIfCallingFromSystemProcess();
        startActivity(intent, null);
    }

    /** @hide */
    @Override
    public void startActivityAsUser(Intent intent, UserHandle user) {
        startActivityAsUser(intent, null, user);
    }

    @Override
    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);
    } 

这里又调用了execStartActivity方法继续看源码,可以找到,该方法是ActivityThread中的实例对象Instrumentation的方法,找到这个java文件,进去看一下方法实现

Instrumentation.execStartActivity

 // /frameworks/base/core/java/android/app/Instrumentation.java
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        result = am.onStartActivity(intent);
                    }
                    if (result != null) {
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    } 

可以看到,实际上通过ActivityManager去调用的ActivityManagerService的startActivity方法

二、ActivityManagerService.startActivity

关于ActivityManagerService的其它功能这里暂不分析,只关注启动流程这一块,其它的后续会继续出文章来描述

 @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);
    }

    public final 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("startActivity");

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

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

    } 

看下这里都做了什么,首先是检测程序是不是强制执行,将会抛出一个SecurityException 然后是获取到调用者的用户id 最后调用ActivityStartController.obtainStarter,设置所有启动参数,返回一个ActivityStarter对象,同时执行execute方法

ActivityStarter.execute

 // /frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
    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.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);
            } 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);
            }
        } finally {
            onExecutionComplete();
        }
    } 

这里有两个方法,因为上面调用了setMayWait(userId)方法,所以这里会走到startActivityMayWait中,接着看下该方法的实现

ActivityStarter.startActivityMayWait

 // /frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
    private int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, 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) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors()) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }
        mSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
        //查找PMS中的注册表
        boolean componentSpecified = intent.getComponent() != null;
        //得到调用的Pid和Uid
        final int realCallingPid = Binder.getCallingPid();
        final int realCallingUid = Binder.getCallingUid();

        int callingPid;
        if (callingUid >= 0) {
            callingPid = -1;
        } else if (caller == null) {
            callingPid = realCallingPid;
            callingUid = realCallingUid;
        } else {
            callingPid = callingUid = -1;
        }

        // Save a copy in case ephemeral needs it
        //拷贝两个Intent,一个临时使用,一个防止修改后无法复原
        final Intent ephemeralIntent = new Intent(intent);
        // Don't modify the client's object!
        intent = new Intent(intent);
        //当有对应的组件,并且传递的数据不为null,并且action指定了Intent.ACTION_VIEW,同时满足是安装程序对应的Activity
        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;
        }

        //通过PMS解析满足Intent等参数要求的信息,内部包含了四大组件的清单文件中声明的信息
        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
                0 /* matchFlags */,
                        computeResolveFilterUid(
                                callingUid, realCallingUid, mRequest.filterCallingUid));
        //当rInfo为null的处理
        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.
                UserManager userManager = UserManager.get(mService.mContext);
                boolean profileLockedAndParentUnlockingOrUnlocked = false;
                long token = Binder.clearCallingIdentity();
                try {
                    UserInfo parent = userManager.getProfileParent(userId);
                    profileLockedAndParentUnlockingOrUnlocked = (parent != null)
                            && userManager.isUserUnlockingOrUnlocked(parent.id)
                            && !userManager.isUserUnlockingOrUnlocked(userId);
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
                if (profileLockedAndParentUnlockingOrUnlocked) {
                    rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
                            PackageManager.MATCH_DIRECT_BOOT_AWARE
                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                            computeResolveFilterUid(
                                    callingUid, realCallingUid, mRequest.filterCallingUid));
                }
            }
        }
        // Collect information about the target of the Intent.
        //通过resolveActivity得到目标Activity的信息
        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
        //获取到AMS锁时的操作
        synchronized (mService) {
            //得到当前栈
            final ActivityStack stack = mSupervisor.mFocusedStack;
            stack.mConfigWillChange = globalConfig != null
                    && mService.getGlobalConfiguration().diff(globalConfig) != 0;
            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                    "Starting activity when config will change = " + stack.mConfigWillChange);
            //清除Pid和Uid用于安全检查
            final long origId = Binder.clearCallingIdentity();
            //若ActivityInfo不为null,并且有PRIVATE_FLAG_CANT_SAVE_STATE标记,意味着调用则为heavy-weight process
            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.
                //进程名为Application中的包名
                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
                    //得到当前运行的重量级进程的记录
                    final ProcessRecord heavy = mService.mHeavyWeightProcess;
                    //当前运行的重量级进程与要启动的不符
                    if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
                            || !heavy.processName.equals(aInfo.processName))) {
                        int appCallingUid = callingUid;
                        if (caller != null) {
                            //得到调用者进程记录
                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
                            if (callerApp != null) {
                                appCallingUid = callerApp.info.uid;
                            } else {
                                Slog.w(TAG, "Unable to find app for caller " + caller
                                        + " (pid=" + callingPid + ") when starting: "
                                        + intent.toString());
                                SafeActivityOptions.abort(options);
                                return ActivityManager.START_PERMISSION_DENIED;
                            }
                        }

                        IIntentSender target = mService.getIntentSenderLocked(
                                ActivityManager.INTENT_SENDER_ACTIVITY, "android",
                                appCallingUid, userId, null, null, 0, new Intent[] { intent },
                                new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
                                        | PendingIntent.FLAG_ONE_SHOT, null);
                        //新的Intent
                        Intent newIntent = new Intent();
                        if (requestCode >= 0) {
                            // Caller is requesting a result.
                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
                        }
                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
                                new IntentSender(target));
                        //当当前重量级进程的ActivityRecord数大于0时
                        if (heavy.activities.size() > 0) {
                            //得到第一个Activity,并将名字和栈set进新的Intent中
                            ActivityRecord hist = heavy.activities.get(0);
                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
                                    hist.packageName);
                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
                                    hist.getTask().taskId);
                        }
                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
                                aInfo.packageName);
                        newIntent.setFlags(intent.getFlags());
                        newIntent.setClassName("android",
                                HeavyWeightSwitcherActivity.class.getName());
                        intent = newIntent;
                        resolvedType = null;
                        caller = null;
                        callingUid = Binder.getCallingUid();
                        callingPid = Binder.getCallingPid();
                        componentSpecified = true;
                        rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId,
                                0 /* matchFlags */, computeResolveFilterUid(
                                        callingUid, realCallingUid, mRequest.filterCallingUid));
                        aInfo = rInfo != null ? rInfo.activityInfo : null;
                        if (aInfo != null) {
                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
                        }
                    }
                }
            }
            //创建新的ActivityRecord
            final ActivityRecord[] outRecord = new ActivityRecord[1];
            //执行startActivity
            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);

            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.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);
            }
            //当结果不为null
            if (outResult != null) {
                outResult.result = res;

                final ActivityRecord r = outRecord[0];
                判断启动状态
                switch(res) {
                    case START_SUCCESS: {
                        //目标Activiy要运行在一个新的应用进程中,因此需要等待应用程序正常启动,并处理相关请求
                        mSupervisor.mWaitingActivityLaunched.add(outResult);
                        do {
                            try {
                                //一直等待,直到outResult显示Activity对应的Task成为Front task
                                mService.wait();
                            } catch (InterruptedException e) {
                            }
                        } while (outResult.result != START_TASK_TO_FRONT
                                && !outResult.timeout && outResult.who == null);
                        if (outResult.result == START_TASK_TO_FRONT) {
                            res = START_TASK_TO_FRONT;
                        }
                        break;
                    }
                    case START_DELIVERED_TO_TOP: {
                        outResult.timeout = false;
                        outResult.who = r.realActivity;
                        outResult.totalTime = 0;
                        outResult.thisTime = 0;
                        break;
                    }
                    case START_TASK_TO_FRONT: {
                        // ActivityRecord may represent a different activity, but it should not be
                        // in the resumed state.
                        if (r.nowVisible && r.isState(RESUMED)) {
                            outResult.timeout = false;
                            outResult.who = r.realActivity;
                            outResult.totalTime = 0;
                            outResult.thisTime = 0;
                        } else {
                            outResult.thisTime = SystemClock.uptimeMillis();
                            //Activity对应的task拉到后台后,一直要等待该界面被加载
                            mSupervisor.waitActivityVisible(r.realActivity, outResult);
                            // Note: the timeout variable is not currently not ever set.
                            do {
                                try {
                                    mService.wait();
                                } catch (InterruptedException e) {
                                }
                            } while (!outResult.timeout && outResult.who == null);
                        }
                        break;
                    }
                }
            }

            mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]);
            return res;
        }
    } 

这里面代码比较多,为了便于理解,我把注释都加在代码里面了 小结一下: 解析出与Intent对应的ActivityInfo 获取到启动该Activity的前台Task 通过startActivity启动Activity 对启动结果进行处理 接着继续往下,上面调用到了startActivity方法,该方法会调用到比较重要的方法startActivityUnchecked,看一下源码

三、启动模式等相关处理

ActivityStarter.startActivityUnchecked

 // /frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {

        //初始化环境和LauncherModeFlags
        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor);
        //计算关于task的启动参数
        computeLaunchingTaskFlags();
        //计算SourceStack,也就是调用者所在的Stack
        computeSourceStack();

        mIntent.setFlags(mLaunchFlags);

        //复用ActivityRecord
        ActivityRecord reusedActivity = getReusableIntentActivity();

        int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
        int preferredLaunchDisplayId = DEFAULT_DISPLAY;
        if (mOptions != null) {
            preferredWindowingMode = mOptions.getLaunchWindowingMode();
            preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
        }

        // windowing mode and preferred launch display values from {@link LaunchParams} take
        // priority over those specified in {@link ActivityOptions}.
        if (!mLaunchParams.isEmpty()) {
            if (mLaunchParams.hasPreferredDisplay()) {
                preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId;
            }

            if (mLaunchParams.hasWindowingMode()) {
                preferredWindowingMode = mLaunchParams.mWindowingMode;
            }
        }

        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.getTask(),
                    (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.getTask() == null && !clearTopAndResetStandardLaunchMode) {
                mStartActivity.setTask(reusedActivity.getTask());
            }

            if (reusedActivity.getTask().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.getTask().setIntent(mStartActivity);
            }

            // 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.getTask();

                // 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.getTask() == 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.getTask().setIntent(mStartActivity);
                    }
                    deliverNewIntent(top);
                }
            }

            mSupervisor.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) {
                        outActivity[0] = reusedActivity;
                    }

                    return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
                }
            }
        }

        if (mStartActivity.packageName == null) {
            final ActivityStack sourceStack = mStartActivity.resultTo != null
                    ? mStartActivity.resultTo.getStack() : 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;
        }

        //SingleTop或则SingleInstance的处理
        // 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 = mSupervisor.mFocusedStack;
        final ActivityRecord topFocused = topStack.getTopActivity();
        final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
        final boolean dontStart = top != null && mStartActivity.resultTo == null
                && top.realActivity.equals(mStartActivity.realActivity)
                && top.userId == mStartActivity.userId
                && top.app != null && top.app.thread != null
                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
        if (dontStart) {
            // For paranoia, make sure we have correctly resumed the top activity.
            topStack.mLastPausedActivity = null;
            if (mDoResume) {
                mSupervisor.resumeFocusedStackTopActivityLocked();
            }
            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.getTask(), preferredWindowingMode,
                    preferredLaunchDisplayId, topStack);

            return START_DELIVERED_TO_TOP;
        }

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

        // Should this be considered a new task?
        int result = START_SUCCESS;
        //设置对应的task并带到前台
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
        } 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.
            setTaskToCurrentTopOrCreateNewTask();
        }
        if (result != START_SUCCESS) {
            return result;
        }

        mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
                mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
        mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
                mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
        if (newTask) {
            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
                    mStartActivity.getTask().taskId);
        }
        ActivityStack.logStartActivity(
                EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
        mTargetStack.mLastPausedActivity = null;

        mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
        //启动Activity
        mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
                mOptions);
        //使Activity可见
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().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(null, 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.
                mService.mWindowManager.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() && !mSupervisor.isFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else if (mStartActivity != null) {
            mSupervisor.mRecentTasks.add(mStartActivity.getTask());
        }
        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

        mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
                preferredLaunchDisplayId, mTargetStack);

        return START_SUCCESS;
    } 

这里的整体流程主要是对Activity启动模式的处理:

  • 计算启动的dlag
  • 对于找到task的过程,还有一些特殊的activity模式和标志的处理,以及对activity的复用,包含以下几种情况: LaunchSingleInstance LaunchSingleTask SingleTop && Activity已经在栈顶 对于已经在栈顶的情况,如果指定FLAG_ACTIVITY_NEW_TASK标志,或则要启动的Activity模式为SingleInstance和SingleTask,又或则mOption.getLaunchTaskId()指定了taskid
  • 计算在那个task中启动 新建task启动(指定了FLAG_ACTIVITY_NEW_TASK,没有找到复用的Activity) 在SourceRecord(也就是调用startActivity的Activity),没有指定FLAG_ACTIVITY_NEW_TASK标志,并且SourceRecord不为Null 在指定的task中启动,一半用于恢复task 在当前焦点stack中的task中启动(既没有FLAG_ACTIVITY_NEW_TASK也没有SourceRecord)
  • 设置对应的task并带到前台之后,开始启动对应的Activity(mTargetStack.startActivityLocked)
  • 调用mSupervisor.resumeFocusedStackTopActivityLocked 使Activity可见

然后再接着看启动Activity的startActivityLocked方法,该方法在ActivityStack中,看一下都做了啥

四、Task和Activity的进栈等相关处理

ActivityStack.startActivityLocked

 // /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
    void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
            boolean newTask, boolean keepCurTransition, ActivityOptions options) {
        TaskRecord rTask = r.getTask();
        final int taskId = rTask.taskId;
        // mLaunchTaskBehind tasks get placed at the back of the task stack.
        if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
            // Last activity in task had been removed or ActivityManagerService is reusing task.
            // Insert or replace.
            // Might not even be in.
            insertTaskAtTop(rTask, r);
        }
        TaskRecord task = null;
        if (!newTask) {
            // If starting in an existing task, find where that is...
            boolean startIt = true;
            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
                task = mTaskHistory.get(taskNdx);
                if (task.getTopActivity() == null) {
                    // All activities in task are finishing.
                    continue;
                }
                if (task == rTask) {
                    // Here it is!  Now, if this is not yet visible to the
                    // user, then just add it without starting; it will
                    // get started when the user navigates back to it.
                    if (!startIt) {
                        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
                                + task, new RuntimeException("here").fillInStackTrace());
                        r.createWindowContainer();
                        ActivityOptions.abort(options);
                        return;
                    }
                    break;
                } else if (task.numFullscreen > 0) {
                    startIt = false;
                }
            }
        }

        //将一个新活动放在堆栈顶部,这样它就可以与用户进行交互
        // Place a new activity at top of stack, so it is next to interact with the user.

        // If we are not placing the new activity frontmost, we do not want to deliver the
        // onUserLeaving callback to the actual frontmost activity
        final TaskRecord activityTask = r.getTask();
        if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
            mStackSupervisor.mUserLeaving = false;
            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                    "startActivity() behind front, mUserLeaving=false");
        }

        task = activityTask;

        // Slot the activity into the history stack and proceed
        //将活动放入历史堆栈并继续
        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
                new RuntimeException("here").fillInStackTrace());
        // TODO: Need to investigate if it is okay for the controller to already be created by the
        // time we get to this point. I think it is, but need to double check.
        // Use test in b/34179495 to trace the call path.

        if (r.getWindowContainerController() == null) {
            r.createWindowContainer();
        }
        //设置栈为前台栈
        task.setFrontOfTask();

        //判断是否为第一个activity
        if (!isHomeOrRecentsStack() || numActivities() > 0) {
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare open transition: starting " + r);
            //是否需要动画
            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
                mStackSupervisor.mNoAnimActivities.add(r);
            } else {
                int transit = TRANSIT_ACTIVITY_OPEN;
                if (newTask) {
                    if (r.mLaunchTaskBehind) {
                        transit = TRANSIT_TASK_OPEN_BEHIND;
                    } else {
                        // If a new task is being launched, then mark the existing top activity as
                        // supporting picture-in-picture while pausing only if the starting activity
                        // would not be considered an overlay on top of the current activity
                        // (eg. not fullscreen, or the assistant)
                        if (canEnterPipOnTaskSwitch(focusedTopActivity,
                                null /* toFrontTask */, r, options)) {
                            focusedTopActivity.supportsEnterPipOnTaskSwitch = true;
                        }
                        transit = TRANSIT_TASK_OPEN;
                    }
                }
                //准备应用程序转换
                mWindowManager.prepareAppTransition(transit, keepCurTransition);
                mStackSupervisor.mNoAnimActivities.remove(r);
            }
            //是否显示启动窗口
            boolean doShow = true;
            if (newTask) {
                //如果一个Activity被设置了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                //并且是在一个新的task中启动,那么这个Activity就会被当作task的首个Activity来启动,即可能显示启动窗口
                // Even though this activity is starting fresh, we still need
                // to reset it to make sure we apply affinities to move any
                // existing activities from other tasks in to it.
                // If the caller has requested that the target task be
                // reset, then do so.
                if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                    resetTaskIfNeededLocked(r, r);
                    doShow = topRunningNonDelayedActivityLocked(null) == r;
                }
            } else if (options != null && options.getAnimationType()
                    == ActivityOptions.ANIM_SCENE_TRANSITION) {
                doShow = false;
            }
            if (r.mLaunchTaskBehind) {
                // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
                // tell WindowManager that r is visible even though it is at the back of the stack.
                r.setVisibility(true);
                ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
            } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
                //此方法是寻找当前task中设置了STARTING_WINDOW_SHOWN
                //并且不是正在finishing中,并且可以显示的activity,STARTING_WINDOW_SHOWN
                //是在下面的showStartingWindow方法中设置的,也就是获取task中已添加了启动窗口的那个activity,
                //所以第一个启动的应用,他的task中没有设置STARTING_WINDOW_SHOWN的activity
                //最终prev为null
                // Figure out if we are transitioning from another activity that is
                // "has the same starting icon" as the next one.  This allows the
                // window manager to keep the previous window it had previously
                // created, if it still had one.
                TaskRecord prevTask = r.getTask();
                ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked();
                //如果prev不为Null说明此Activity在task中已经有了
                //其它Activity添加过了启动窗口
                if (prev != null) {
                    // We don't want to reuse the previous starting preview if:
                    // (1) The current activity is in a different task.
                    //如果当前正在启动的activity和已经添加了启动窗口的activity不属于同一个tsak,则让prev为Null
                    if (prev.getTask() != prevTask) {
                        prev = null;
                    }
                    // (2) The current activity is already displayed.
                    //当前正在启动的activity的nowVisible为true,则置空prev
                    else if (prev.nowVisible) {
                        prev = null;
                    }
                }
                //isTaskSwitch 方法判断(r, focusedTopActivity)是否在同一个task
                //focusedTopActivity当前系统最顶层的activity
                r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity));
            }
        } else {
            //第一个activity不需要任何花里胡哨的动画
            // If this is the first activity, don't do any fancy animations,
            // because there is nothing for it to animate on top of.
            ActivityOptions.abort(options);
        }
    } 

这个方法的主要作用是Task和Activity的进栈处理,为新开启的Activity创建Task,并将Task保存在ActivityRecord

  1. 根据newtask判断是否为新创建的task,否则从历史栈中获取到task

  2. 将该栈设置为前台栈

  3. 判断是否需要动画,并准备应用程序转换

  4. 设置启动窗口

接着回来继续看mSupervisor.resumeFocusedStackTopActivityLocked

ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

 // /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

        if (!readyToResume()) {
            return false;
        }
        //判断targetStack(也就是我们要启动的activity)不为null,并且是否处于焦点,是则进一步处理
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }

        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || !r.isState(RESUMED)) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.isState(RESUMED)) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }

        return false;
    } 

这个方法主要是对Activity栈的焦点检查,然后便调用targetStack.resumeTopActivityUncheckedLocked继续处理

ActivityStack.resumeTopActivityUncheckedLocked

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n57" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
 @GuardedBy("mService")
 boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
 if (mStackSupervisor.inResumeTopActivity) {
 // Don't even start recursing.
 return false;
 }

 boolean result = false;
 try {
 // Protect against recursion.
 mStackSupervisor.inResumeTopActivity = true;
 //Activity启动的核心方法
 result = resumeTopActivityInnerLocked(prev, options);

 // When resuming the top activity, it may be necessary to pause the top activity (for
 // example, returning to the lock screen. We suppress the normal pause logic in
 // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
 // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
 // to ensure any necessary pause logic occurs. In the case where the Activity will be
 // shown regardless of the lock screen, the call to
 // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
 final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
 if (next == null || !next.canTurnScreenOn()) {
 checkReadyForSleep();
 }
 } finally {
 mStackSupervisor.inResumeTopActivity = false;
 }

 return result;
 } </pre>

这个地方去调用了resumeTopActivityInnerLocked方法,这里分成几部分来看,首先是暂停当前正在运行的Activity

五、暂停操作(Pause)

ActivityStack.resumeTopActivityInnerLocked(上半部分 Pause Activity 入口)

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n62" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
 @GuardedBy("mService")
 private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
 if (!mService.mBooting && !mService.mBooted) {
 // Not ready yet!
 return false;
 }

 // Find the next top-most activity to resume in this stack that is not finishing and is
 // focusable. If it is not focusable, we will fall into the case below to resume the
 // top activity in the next focusable task.
 //将要显示的目标activity
 final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);

 final boolean hasRunningActivity = next != null;

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

 //非顶部处于INITIALIZING状态的活动清理
 mStackSupervisor.cancelInitializingActivities();

 // Remember how we'll process this pause/resume situation, and ensure
 // that the state is reset however we wind up proceeding.
 //标记是否调用Activity的performUserLeaving回调方法
 boolean userLeaving = mStackSupervisor.mUserLeaving;
 mStackSupervisor.mUserLeaving = false;

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

 //标记是否延迟显示
 next.delayedResume = false;

 // If the top activity is the resumed one, nothing to do.
 //如果最重要的activity是恢复的activity,则无需执行任何操作
 if (mResumedActivity == next && next.isState(RESUMED)
 && mStackSupervisor.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);
 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
 return false;
 }

 // If we are sleeping, and there is no resumed activity, and the top
 // activity is paused, well that is the state we want.
 //如果activity sleep或则已暂停,则是我们需要的状态,不需要再处理
 if (shouldSleepOrShutDownActivities()
 && mLastPausedActivity == next
 && mStackSupervisor.allPausedActivitiesComplete()) {
 // 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");
 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
 return false;
 }

 // Make sure that the user who owns this activity is started.  If not,
 // we will just leave it as is because someone should be bringing
 // another user's activities to the top of the stack.
 //确保负责此activity的用户已启动。如果不是,
 //我们将保持原样,因为应该有人带来
 //将另一个用户的活动添加到堆栈顶部。
 if (!mService.mUserController.hasStartedUserState(next.userId)) {
 Slog.w(TAG, "Skipping resume of top activity " + next
 + ": user " + next.userId + " is stopped");
 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
 return false;
 }

 // The activity may be waiting for stop, but that is no longer
 // appropriate for it.
 //如果该activity正在等待或则停止,则移除
 mStackSupervisor.mStoppingActivities.remove(next);
 mStackSupervisor.mGoingToSleepActivities.remove(next);
 next.sleeping = false;
 mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);

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

 // If we are currently pausing an activity, then don't do anything until that is done.
 //判断当前是否存在暂停未完成的activity
 if (!mStackSupervisor.allPausedActivitiesComplete()) {
 if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
 "resumeTopActivityLocked: Skip resume: some activity pausing.");
 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
 return false;
 }

 //设置wake lock关联的Source,用于应用耗电统计
 mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);

 //画中画判断
 boolean lastResumedCanPip = false;
 ActivityRecord lastResumed = null;
 final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
 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;
 //pausing标记是否有执行pause操作
 boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
 //mResumedActivity表示正在显示的activity,若不为null,则暂停它startPausingLocked
 if (mResumedActivity != null) {
 if (DEBUG_STATES) Slog.d(TAG_STATES,
 "resumeTopActivityLocked: Pausing " + mResumedActivity);
 pausing |= startPausingLocked(userLeaving, false, next, false);
 }
 //省略
 ...
 } </pre>

ActivityStack.startPausingLocked

Activity的生命周期我们应该很了解了吧,这里startPausingLocked将会去暂停当前运行的Activity,下面进入这个方法看一下

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n65" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
 final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
 ActivityRecord resuming, boolean pauseImmediately) {
 //mPausingActivity表示当前正在pause中的activity,若存在则先处理pause的善后操作
 if (mPausingActivity != null) {
 Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
 + " state=" + mPausingActivity.getState());
 if (!shouldSleepActivities()) {
 // Avoid recursion among check for sleep and complete pause during sleeping.
 // Because activity will be paused immediately after resume, just let pause
 // be completed by the order of activity paused from clients.
 completePauseLocked(false, resuming);
 }
 }
 //检查prev
 ActivityRecord prev = mResumedActivity;

 if (prev == null) {
 if (resuming == null) {
 Slog.wtf(TAG, "Trying to pause when nothing is resumed");
 mStackSupervisor.resumeFocusedStackTopActivityLocked();
 }
 return false;
 }

 if (prev == resuming) {
 Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
 return false;
 }

 //prev赋值给mPausingActivity,此时的mPausingActivity持有了当前显示activity的引用
 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
 else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
 mPausingActivity = prev;
 mLastPausedActivity = prev;
 mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
 || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
 //设置prev的状态为PAUSING,此时会将mResumedActivity置为null
 prev.setState(PAUSING, "startPausingLocked");
 //更新prev的task的最后活动时间
 prev.getTask().touchActiveTime();
 //超时设置
 clearLaunchTime(prev);

 mStackSupervisor.getLaunchTimeTracker().stopFullyDrawnTraceIfNeeded(getWindowingMode());

 mService.updateCpuStats();

 //判断prev的applicationThread是否为空,需要通过它向对应进程通信
 if (prev.app != null && prev.app.thread != null) {
 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
 try {
 EventLogTags.writeAmPauseActivity(prev.userId, System.identityHashCode(prev),
 prev.shortComponentName, "userLeaving=" + userLeaving);
 mService.updateUsageStats(prev, false);
 //通知目标应用进程执行对应Activity的生命调度
 mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
 PauseActivityItem.obtain(prev.finishing, userLeaving,
 prev.configChangeFlags, pauseImmediately));
 } catch (Exception e) {
 // Ignore exception, if process died other code will cleanup.
 Slog.w(TAG, "Exception thrown during pause", e);
 mPausingActivity = null;
 mLastPausedActivity = null;
 mLastNoHistoryActivity = null;
 }
 } else {
 mPausingActivity = null;
 mLastPausedActivity = null;
 mLastNoHistoryActivity = null;
 }

 // If we are not going to sleep, we want to ensure the device is
 // awake until the next activity is started.
 if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
 mStackSupervisor.acquireLaunchWakelock();
 }

 //正常情况下mPausingActivity持有的引用还在
 if (mPausingActivity != null) {
 // Have the window manager pause its key dispatching until the new
 // activity has started.  If we're pausing the activity just because
 // the screen is being turned off and the UI is sleeping, don't interrupt
 // key dispatch; the same activity will pick it up again on wakeup.
 if (!uiSleeping) {
 //暂停事件分发
 prev.pauseKeyDispatchingLocked();
 } else if (DEBUG_PAUSE) {
 Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
 }

 if (pauseImmediately) {
 // If the caller said they don't want to wait for the pause, then complete
 // the pause now.
 completePauseLocked(false, resuming);
 return false;

 } else {
 schedulePauseTimeout(prev);
 return true;
 }

 } else {
 // This activity failed to schedule the
 // pause, so just treat it as being paused now.
 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
 //resuming默认持有下一个要显示的activityRecord
 if (resuming == null) {
 mStackSupervisor.resumeFocusedStackTopActivityLocked();
 }
 return false;
 }
 } </pre>

此方法将mResumedActivity赋值给了mPausingActivity,并将状态设置为PAUSING,再将mResumedActivity置空 并通过IApplicationThread通知对应的App执行pause操作 接下来继续看scheduleTransaction方法

ClientLifecycleManager.scheduleTransaction

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n68" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/services/core/java/com/android/server/am/ClientLifecycleManager.java
 void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
 @NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
 //创建ClientTransaction,保存client,token,stateRequest参数
 final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
 stateRequest);
 scheduleTransaction(clientTransaction);
 } </pre>

ClientTransaction事务对象,用于封装命令和参数,发送到APP进程处理。ClientTransaction的schedule方法中 又调用IApplicationThread的scheduleTransaction方法,并将ClientTransaction实例自身作为入参调用 接着继续看scheduleTransaction,AMS通过IApplicationThread调用到APP进程,scheduleTransaction会触发 ApplicationThread.scheduleTransaction方法,该方法中又调用ActivityThread的父类 ClientTransactionHandler的scheduleTransaction方法

ClientTransactionHandler.scheduleTransaction

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n71" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/core/java/android/app/ClientTransactionHandler.java
 void scheduleTransaction(ClientTransaction transaction) {
 transaction.preExecute(this);
 sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
 } </pre>

抽象方法sendMessage的实现在ActivityThread中

ActivityThread.sendMessage

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n74" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/core/java/android/app/ActivityThread.java
 private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
 if (DEBUG_MESSAGES) Slog.v(
 TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
 + ": " + arg1 + " / " + obj);
 Message msg = Message.obtain();
 msg.what = what;
 msg.obj = obj;
 msg.arg1 = arg1;
 msg.arg2 = arg2;
 if (async) {
 msg.setAsynchronous(true);
 }
 mH.sendMessage(msg);
 }

 省略...
 case EXECUTE_TRANSACTION:
 final ClientTransaction transaction = (ClientTransaction) msg.obj;
 mTransactionExecutor.execute(transaction);
 if (isSystem()) {
 // Client transactions inside system process are recycled on the client side
 // instead of ClientLifecycleManager to avoid being cleared before this
 // message is handled.
 transaction.recycle();
 }
 // TODO(lifecycler): Recycle locally scheduled transactions.
 break; </pre>

该方法中利用mH从binder线程切换到主线程来处理这个事务。在mH的handleMessage方法中的对应case EXECUTE_TRANSACTION中, 又通过TransactionExecutor的execute方法来执行ClientTransaction事务消息。

TransactionExecutor.execute

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n77" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
 public void execute(ClientTransaction transaction) {
 final IBinder token = transaction.getActivityToken();
 log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
 //遍历调用ClientTransaction中的mActivityCallbacks
 executeCallbacks(transaction);
 //调用ClientTransaction中的的mLidecycleStateRequest成员,即在Ams中设置的PauseActivityItem
 executeLifecycleState(transaction);
 mPendingActions.clear();
 log("End resolving transaction");
 }

 @VisibleForTesting
 public void executeCallbacks(ClientTransaction transaction) {
 final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
 if (callbacks == null) {
 // No callbacks to execute, return early.
 return;
 }
 log("Resolving callbacks");

 final IBinder token = transaction.getActivityToken();
 ActivityClientRecord r = mTransactionHandler.getActivityClient(token);

 // In case when post-execution state of the last callback matches the final state requested
 // for the activity in this transaction, we won't do the last transition here and do it when
 // moving to final state instead (because it may contain additional parameters from server).
 final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
 final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState()
 : UNDEFINED;
 // Index of the last callback that requests some post-execution state.
 final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);

 final int size = callbacks.size();
 for (int i = 0; i < size; ++i) {
 final ClientTransactionItem item = callbacks.get(i);
 log("Resolving callback: " + item);
 final int postExecutionState = item.getPostExecutionState();
 final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
 item.getPostExecutionState());
 if (closestPreExecutionState != UNDEFINED) {
 cycleToPath(r, closestPreExecutionState);
 }

 item.execute(mTransactionHandler, token, mPendingActions);
 item.postExecute(mTransactionHandler, token, mPendingActions);
 if (r == null) {
 // Launch activity request will create an activity record.
 r = mTransactionHandler.getActivityClient(token);
 }

 if (postExecutionState != UNDEFINED && r != null) {
 // Skip the very last transition and perform it by explicit state request instead.
 final boolean shouldExcludeLastTransition =
 i == lastCallbackRequestingState && finalState == postExecutionState;
 cycleToPath(r, postExecutionState, shouldExcludeLastTransition);
 }
 }
 }

 /** Transition to the final state if requested by the transaction. */
 private void executeLifecycleState(ClientTransaction transaction) {
 final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
 if (lifecycleItem == null) {
 // No lifecycle request, return early.
 return;
 }
 log("Resolving lifecycle state: " + lifecycleItem);

 final IBinder token = transaction.getActivityToken();
 final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);

 if (r == null) {
 // Ignore requests for non-existent client records for now.
 return;
 }

 // Cycle to the state right before the final requested state.
 //该方法会按生命周期顺序补充执行对应生命周期阶段的方法
 cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);

 // Execute the final transition with proper parameters.
 lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
 lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
 } </pre>

在executeLifecycleState中,会先后调用PauseActivityItem的execute和postExecute方法。其中execute会调用ClientTransactionHandler.handlePauseActivity方法, PauseActivityItem.execute

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n79" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/core/java/android/app/servertransaction/PauseActivityItem.java
 @Override
 public void execute(ClientTransactionHandler client, IBinder token,
 PendingTransactionActions pendingActions) {
 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
 client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
 "PAUSE_ACTIVITY_ITEM");
 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
 } </pre>

handlePauseActivity由ActivityThread实现

ActivityThread.handlePauseActivity

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n82" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/core/java/android/app/ActivityThread.java
 @Override
 public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
 int configChanges, PendingTransactionActions pendingActions, String reason) {
 ActivityClientRecord r = mActivities.get(token);
 if (r != null) {
 if (userLeaving) {
 performUserLeavingActivity(r);
 }

 r.activity.mConfigChangeFlags |= configChanges;
 //执行pause PauseActivity的操作
 performPauseActivity(r, finished, reason, pendingActions);

 // Make sure any pending writes are now committed.
 if (r.isPreHoneycomb()) {
 QueuedWork.waitToFinish();
 }
 mSomeActivitiesChanged = true;
 }
 }

 private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
 PendingTransactionActions pendingActions) {
 if (r.paused) {
 if (r.activity.mFinished) {
 // If we are finishing, we won't call onResume() in certain cases.
 // So here we likewise don't want to call onPause() if the activity
 // isn't resumed.
 return null;
 }
 RuntimeException e = new RuntimeException(
 "Performing pause of activity that is not resumed: "
 + r.intent.getComponent().toShortString());
 Slog.e(TAG, e.getMessage(), e);
 }
 if (finished) {
 r.activity.mFinished = true;
 }

 // Pre-Honeycomb apps always save their state before pausing
 final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb();
 if (shouldSaveState) {
 callActivityOnSaveInstanceState(r);
 }

 performPauseActivityIfNeeded(r, reason);

 // Notify any outstanding on paused listeners
 ArrayList<OnActivityPausedListener> listeners;
 synchronized (mOnPauseListeners) {
 listeners = mOnPauseListeners.remove(r.activity);
 }
 int size = (listeners != null ? listeners.size() : 0);
 for (int i = 0; i < size; i++) {
 listeners.get(i).onPaused(r.activity);
 }

 final Bundle oldState = pendingActions != null ? pendingActions.getOldState() : null;
 if (oldState != null) {
 // We need to keep around the original state, in case we need to be created again.
 // But we only do this for pre-Honeycomb apps, which always save their state when
 // pausing, so we can not have them save their state when restarting from a paused
 // state. For HC and later, we want to (and can) let the state be saved as the
 // normal part of stopping the activity.
 if (r.isPreHoneycomb()) {
 r.state = oldState;
 }
 }

 return shouldSaveState ? r.state : null;
 }

 private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
 if (r.paused) {
 // You are already paused silly...
 return;
 }

 try {
 r.activity.mCalled = false;
 mInstrumentation.callActivityOnPause(r.activity);
 if (!r.activity.mCalled) {
 throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
 + " did not call through to super.onPause()");
 }
 } catch (SuperNotCalledException e) {
 throw e;
 } catch (Exception e) {
 if (!mInstrumentation.onException(r.activity, e)) {
 throw new RuntimeException("Unable to pause activity "
 + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
 }
 }
 r.setState(ON_PAUSE);
 } </pre>

performPauseActivity方法中会对ActivityClientRecord中保存的状态进行检查,并视情况调用onSaveInstanceState(), 之后又调用performPauseActivityIfNeeded方法,在该方法中通过Instrumentation最终触发了Activity的onPause生命周期回调方法。

当完成了这些操作后,接着将执行PauseActivityItem的postExecute方法

PauseActivityItem.postExecute

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n86" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/core/java/android/app/servertransaction/PauseActivityItem.java
 @Override
 public void postExecute(ClientTransactionHandler client, IBinder token,
 PendingTransactionActions pendingActions) {
 if (mDontReport) {
 return;
 }
 try {
 // TODO(lifecycler): Use interface callback instead of AMS.
 ActivityManager.getService().activityPaused(token);
 } catch (RemoteException ex) {
 throw ex.rethrowFromSystemServer();
 }
 } </pre>

然后调用AMS的activityPaused,通知Activity pause完成

ActivityManagerService.activityPaused

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n89" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
 @Override
 public final void activityPaused(IBinder token) {
 final long origId = Binder.clearCallingIdentity();
 synchronized(this) {
 ActivityStack stack = ActivityRecord.getStackLocked(token);
 if (stack != null) {
 stack.activityPausedLocked(token, false);
 }
 }
 Binder.restoreCallingIdentity(origId);
 } </pre>

这里面调用了ActivityStack的activityPausedLocked方法

ActivityStack.activityPausedLocked

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n92" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
 final void activityPausedLocked(IBinder token, boolean timeout) {
 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
 "Activity paused: token=" + token + ", timeout=" + timeout);

 final ActivityRecord r = isInStackLocked(token);
 if (r != null) {
 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
 if (mPausingActivity == r) {
 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
 + (timeout ? " (due to timeout)" : " (pause complete)"));
 mService.mWindowManager.deferSurfaceLayout();
 try {
 completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
 } finally {
 mService.mWindowManager.continueSurfaceLayout();
 }
 return;
 } else {
 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
 r.userId, System.identityHashCode(r), r.shortComponentName,
 mPausingActivity != null
 ? mPausingActivity.shortComponentName : "(none)");
 if (r.isState(PAUSING)) {
 r.setState(PAUSED, "activityPausedLocked");
 if (r.finishing) {
 if (DEBUG_PAUSE) Slog.v(TAG,
 "Executing finish of failed to pause activity: " + r);
 finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false,
 "activityPausedLocked");
 }
 }
 }
 }
 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
 } </pre>

这里面又会去调用completePauseLocked方法

ActivityStack.completePauseLocked(Pasue Activity 完成)

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n95" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> // /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
 private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
 将之前AMS保存的进程PauseActivity赋值给prev
 ActivityRecord prev = mPausingActivity;
 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);

 if (prev != null) {
 prev.setWillCloseOrEnterPip(false);
 final boolean wasStopping = prev.isState(STOPPING);
 prev.setState(PAUSED, "completePausedLocked");
 if (prev.finishing) {
 //finish Activity操作
 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,
 "completedPausedLocked");
 } else if (prev.app != null) {
 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
 + " wasStopping=" + wasStopping + " visible=" + prev.visible);
 if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(prev)) {
 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,
 "Complete pause, no longer waiting: " + prev);
 }
 if (prev.deferRelaunchUntilPaused) {
 // Complete the deferred relaunch that was waiting for pause to complete.
 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
 prev.relaunchActivityLocked(false /* andResume */,
 prev.preserveWindowOnDeferredRelaunch);
 } else if (wasStopping) {
 // We are also stopping, the stop request must have gone soon after the pause.
 // We can't clobber it, because the stop confirmation will not be handled.
 // We don't need to schedule another stop, we only need to let it happen.
 prev.setState(STOPPING, "completePausedLocked");
 } else if (!prev.visible || shouldSleepOrShutDownActivities()) {
 // Clear out any deferred client hide we might currently have.
 prev.setDeferHidingClient(false);
 // If we were visible then resumeTopActivities will release resources before
 // stopping.
 //等待后续继续执行stop操作
 addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */);
 }
 } else {
 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);
 prev = null;
 }
 // It is possible the activity was freezing the screen before it was paused.
 // In that case go ahead and remove the freeze this activity has on the screen
 // since it is no longer visible.
 if (prev != null) {
 //停止屏幕冻结
 prev.stopFreezingScreenLocked(true /*force*/);
 }
 mPausingActivity = null;
 }

 //表示需要调度resume下一个Activity
 if (resumeNext) {
 final ActivityStack topStack = mStackSupervisor.getFocusedStack();
 if (!topStack.shouldSleepOrShutDownActivities()) {
 mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
 } else {
 checkReadyForSleep();
 ActivityRecord top = topStack.topRunningActivityLocked();
 if (top == null || (prev != null && top != prev)) {
 // If there are no more activities available to run, do resume anyway to start
 // something. Also if the top activity on the stack is not the just paused
 // activity, we need to go ahead and resume it to ensure we complete an
 // in-flight app switch.
 mStackSupervisor.resumeFocusedStackTopActivityLocked();
 }
 }
 }

 if (prev != null) {
 prev.resumeKeyDispatchingLocked();

 if (prev.app != null && prev.cpuTimeAtResume > 0
 && mService.mBatteryStatsService.isOnBattery()) {
 long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
 - prev.cpuTimeAtResume;
 if (diff > 0) {
 BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
 synchronized (bsi) {
 BatteryStatsImpl.Uid.Proc ps =
 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
 prev.info.packageName);
 if (ps != null) {
 ps.addForegroundTimeLocked(diff);
 }
 }
 }
 }
 prev.cpuTimeAtResume = 0; // reset it
 }

 // Notify when the task stack has changed, but only if visibilities changed (not just
 // focus). Also if there is an active pinned stack - we always want to notify it about
 // task stack changes, because its positioning may depend on it.
 if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause
 || getDisplay().hasPinnedStack()) {
 mService.mTaskChangeNotificationController.notifyTaskStackChanged();
 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
 }

 mStackSupervisor.ensureActivitiesVisibleLocked(resuming, 0, !PRESERVE_WINDOWS);
 } </pre>

completePauseLocked方法中会将这次pause的ActivityRecord存入ActivityStackSupervisor的mStoppingActivities成员(ArrayList)中, 用于后续再对其执行stop和finish操作。之后将mPausingActivity赋值为null,表示当前没有正在pause的Activity。接着便又调用了 resumeFocusedStackTopActivityLocked方法,再次进行resume Activity。


...
因篇幅原因,本章节将分为两篇文章进行讲解,之后更新Activity启动流程(二),其他Android开发中高级知识点也在持续更新中~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容