基于10.0的activity分析(一)

1.從launcher恢復(fù)activity
2.從當(dāng)前activity打開(kāi)另一個(gè)acivity
3.從當(dāng)前activity打開(kāi)另一個(gè)acivity驹饺,并在當(dāng)前activity設(shè)置了newTask標(biāo)記

本系列將分3篇文章厂画,講述不同情況下activity的啟動(dòng)情況
本文就先分析最簡(jiǎn)單的情況,也就是第一種情況

下文出現(xiàn)的MainActivity指的是我們自己的應(yīng)用也就是從LoadingActivity-MainActivity
LaunchActivity指的是回到桌面時(shí)候所展現(xiàn)的頁(yè)面

1.在ams里獲取到要啟動(dòng)的activity的activityinfo對(duì)象

 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

這個(gè) intent是launcher打開(kāi)activity的默認(rèn)是new_task和clear_flags
startFlags和profilerInfo都是0,不用管
接下來(lái)會(huì)調(diào)用

    final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();

這里是獲取當(dāng)前正在顯示的activityStack(也就是最上層的activitstack)
然后進(jìn)入以下代碼乍桂,有些參數(shù)是通過(guò)mRequest通過(guò)建造者模式傳過(guò)來(lái)的
也就是新建了一個(gè)activityStarter

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

下面說(shuō)下這幾個(gè)參數(shù)的作用

ApplicationThread caller

也就說(shuō)是調(diào)用者的一個(gè)binderproxy對(duì)象耿币,用來(lái)回調(diào)調(diào)用者的回調(diào)方法
這個(gè)參數(shù)是application級(jí)別的翠胰,也就是和進(jìn)程有關(guān)的,一個(gè)進(jìn)程就會(huì)創(chuàng)建一個(gè)對(duì)象

private class ApplicationThread extends IApplicationThread.Stub {
        private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";

        public final void scheduleSleeping(IBinder token, boolean sleeping) {
            sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
        }
Intent intent

調(diào)用者設(shè)置的intent對(duì)象在此處是(表示要打開(kāi)的activity的intent)

Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.badtokendemo/.LoadingActivity bnds=[41,258][290,586] }

Intent ephemeralIntent

intent的賦值對(duì)象(沒(méi)多大意義)

String resolvedType
 intent.resolveTypeIfNeeded(who.getContentResolver()),

來(lái)源于此值乎完,現(xiàn)在沒(méi)啥作用

ActivityInfo aInfo

存放著啟動(dòng)的activity的info值(包括了此activity在xml里的各種屬性)

ResolveInfo rInfo

包含了activityInfo對(duì)象熏兄,并有些其他的屬性

IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor

默認(rèn)都是為null

IBinder resultTo

這個(gè)屬性很重要,是activityRecord里的一個(gè)內(nèi)部類树姨,用來(lái)找到對(duì)應(yīng)的actiivtyRecord(這里的值是launcher的activityrecord)

resultWho

這里默認(rèn)為null

requestCode

默認(rèn)也為0

callingPid callingUid

這里傳過(guò)來(lái)的是都是0摩桶,后面會(huì)取launcher的realCallingPid 和realCallingUid

SafeActivityOptions options

這里是打開(kāi)activity時(shí)傳的activityoptions的封裝的形式,這里由于是launcher開(kāi)啟的帽揪,所以會(huì)傳過(guò)來(lái)一些參數(shù)
下面幾個(gè)都是默認(rèn)的值

boolean ignoreTargetSecurity

為false

boolean componentSpecified

為true

boolean allowPendingRemoteAnimationRegistryLookup

為true

boolean allowBackgroundActivityStart

為false

PendingIntentRecord originatingPendingIntent

為null

boolean ignoreTargetSecurity

為false

ActivityRecord[] outActivity

要打開(kāi)activity對(duì)應(yīng)的activityRecord

TaskRecord inTask

這里為null
接下來(lái)會(huì)調(diào)用

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

這里獲取launcher的WindowProcess硝清,然后獲得callingPid和callingUid
接下來(lái)是根據(jù)IBinder對(duì)象獲取ActivityRecord

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

顯然這里sourceRecord是launcher activity對(duì)應(yīng)的record
接下來(lái)(launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0這個(gè)暫且跳過(guò)
launchFlags就是newTask和if need屬性
接下來(lái)的代碼都是判斷activity的啟動(dòng)權(quán)限是否是后臺(tái)啟動(dòng)的攔截等,這里不做多講
然后就是新建打開(kāi)頁(yè)面的activityRecord了

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

這里說(shuō)下activityRecord的具體參數(shù)吧
appToken 包含了當(dāng)前的activityrecord和intent

appToken = new Token(this, _intent);

這個(gè)intent是傳過(guò)來(lái)的intent转晰,this就是當(dāng)前的要打開(kāi)的activityRecord
也就是說(shuō)通過(guò)token就能找到對(duì)應(yīng)的activity
比如a打開(kāi)b頁(yè)面芦拿,通常要傳遞a頁(yè)面的token,是因?yàn)檫@樣才能找到a的activityRecord查邢,從而來(lái)確定b是依附于哪個(gè)activityRecord上(標(biāo)準(zhǔn)情況下)
frontOfTask 是否是task的第一個(gè)蔗崎,默認(rèn)是false
ActivityState mState 是ActivityRecord的一個(gè)成員變量,通過(guò)不斷的賦值不同的狀態(tài)來(lái)回調(diào)

final TaskRecord parent = getTaskRecord();

        if (parent != null) {
            parent.onActivityStateChanged(this, state, reason);
        }

當(dāng)然現(xiàn)在的activity對(duì)應(yīng)的taskrecord還是null扰藕,不會(huì)空時(shí)會(huì)調(diào)用onActivityStateChanged方法
stopped = false;判斷棧有沒(méi)有被終止
delayedResume=false 有沒(méi)有可見(jiàn)缓苛,默認(rèn)是false
finishing = false;
mActivityComponent 對(duì)象代表著包名和類名,就是新的activityRecord存放著intent的componentName

if (aInfo.targetActivity == null
                || (aInfo.targetActivity.equals(_intent.getComponent().getClassName())
                && (aInfo.launchMode == LAUNCH_MULTIPLE
                || aInfo.launchMode == LAUNCH_SINGLE_TOP))) {
            mActivityComponent = _intent.getComponent();
        } else {
            mActivityComponent = new ComponentName(aInfo.packageName, aInfo.targetActivity);
        }

intent 取的是launch傳過(guò)來(lái)的值邓深,當(dāng)然如果
taskAffinity 讀取的是xml寫(xiě)的值未桥,還有一些processName,theme芥备,logolaunchMode等
resultTo 參數(shù)冬耿,這個(gè)參數(shù)后面會(huì)用到,來(lái)源在于

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

當(dāng)然現(xiàn)在默認(rèn)是null的萌壳,和上面IBinder傳過(guò)來(lái)的result不同亦镶,那個(gè)是找到sourceRecord的

注意:logolaunchMode是存在activityRecord里的日月,但是flages沒(méi)存,存的是launch的intent
在賦值完activityRecord以后
繼續(xù)調(diào)用startActivity方法

 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity, boolean restrictedBgActivity) {
        int result = START_CANCELED;
        final ActivityStack startedActivityStack;
        try {
            mService.mWindowManager.deferSurfaceLayout();
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
        }

這里主要是調(diào)用startActivityUnchecked核心方法染乌,也是邏輯非常繞的一段
先來(lái)說(shuō)下他幾個(gè)參數(shù)
第一個(gè)r是將要打開(kāi)的LoadingActivity的activityRecord山孔,注意,此時(shí)還沒(méi)被添加到activityTask里和activityStack里
sourceRecord是launcher的啟動(dòng)的activityRecord
doResume 參數(shù)這里傳過(guò)來(lái)的是true
outActivity 數(shù)組里第一個(gè)就是LoadingActivity的activityRecord
inTask 參數(shù)為null 表示有沒(méi)有指定放入的task
首先會(huì)調(diào)用setInitialState方法荷憋,可以看到,主要是一個(gè)賦值的操作

 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
            boolean doResume, int startFlags, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            boolean restrictedBgActivity) {
        reset(false /* clearRequest */);

可以看到的是一個(gè)activityRecord對(duì)應(yīng)一個(gè)activityStater
activityStater里的mStartActivity對(duì)應(yīng)的就是要打開(kāi)的activity
mIntent就是launcher的intent
mCallingUid就是launcher的uid
mLaunchMode 就是xml設(shè)置的mode

 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
                r, LAUNCH_SINGLE_INSTANCE == mLaunchMode,
                LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());

這里的mLaunchFlags就是intent的launch就是0x10200000
由于是根據(jù)DocumentMode調(diào)整的褐望,我們這里暫且不論
接下來(lái)調(diào)用

 private void sendNewTaskResultRequestIfNeeded() {
        final ActivityStack sourceStack = mStartActivity.resultTo != null
                ? mStartActivity.resultTo.getActivityStack() : null;
        if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            // For whatever reason this activity is being launched into a new task...
            // yet the caller has requested a result back.  Well, that is pretty messed up,
            // so instead immediately send back a cancel and let the new task continue launched
            // as normal without a dependency on its originator.
            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
            sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
                    null /* data */);
            mStartActivity.resultTo = null;
        }
    }

由于我們的resultTo為null勒庄,上文說(shuō)過(guò),所以暫且不論
mDoResume就是一開(kāi)始賦的值瘫里,這里為true
mNotTop 字段

mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? sourceRecord : null;

和FLAG_ACTIVITY_PREVIOUS_IS_TOP有關(guān)实蔽,這里為null
inTask對(duì)應(yīng)的taskRecord這里由于沒(méi)制定也是null
這里第一步是分析完了,主要是給activityStarter賦值谨读,并且修正一些值
現(xiàn)階段還沒(méi)有修正過(guò)哪個(gè)值
接下來(lái)調(diào)用computeLaunchingTaskFlags
簡(jiǎn)單來(lái)說(shuō)就是修正一些flag

 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
                // The original activity who is starting us is running as a single
                // instance...  this new activity it is starting must go on its
                // own task.
                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
            } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
                // The activity being started is a single instance...  it always
                // gets launched into its own task.
                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
            }

由于我們有sourcerecord所以只可能會(huì)走這里局装,如果sourcerecord是singleInstance,則給新的activityStater添加FLAG_ACTIVITY_NEW_TASK
如果是singleTask或者singleInstance的話劳殖,就添加newTask
很顯然我們的mLunchFlag是包含了newTask
所以都不會(huì)走
3.接下來(lái)給當(dāng)前activityRecord賦值mSourceStack
很顯然取得也是mSourceRecord的stack

private void computeSourceStack() {
        if (mSourceRecord == null) {
            mSourceStack = null;
            return;
        }
        if (!mSourceRecord.finishing) {
            mSourceStack = mSourceRecord.getActivityStack();
            return;
        }

4.給intent設(shè)置調(diào)整后的flags

 mIntent.setFlags(mLaunchFlags);

由于沒(méi)調(diào)整過(guò)铐尚,所以不用處理
5.尋找可重用的activityRecord,這個(gè)很重要

  private ActivityRecord getReusableIntentActivity() {
        // We may want to try to place the new activity in to an existing task.  We always
        // do this if the target activity is singleTask or singleInstance; we will also do
        // this if NEW_TASK has been requested, and there is not an additional qualifier telling
        // us to still place it in a new task: multi task, always doc mode, or being asked to
        // launch this as a new task behind the current one.
        boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
                (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK);
        // If bring to front is requested, and no result is requested and we have not been given
        // an explicit task to launch in to, and we can find a task that was started with this
        // same component, then instead of launching bring that one to the front.
        putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
        ActivityRecord intentActivity = null;
        if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
            final TaskRecord task = mRootActivityContainer.anyTaskForId(mOptions.getLaunchTaskId());
            intentActivity = task != null ? task.getTopActivity() : null;
        } else if (putIntoExistingTask) {
            if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
                // There can be one and only one instance of single instance activity in the
                // history, and it is always in its own unique task, so we do a special search.
               intentActivity = mRootActivityContainer.findActivity(mIntent, mStartActivity.info,
                       mStartActivity.isActivityTypeHome());
            } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
                // For the launch adjacent case we only want to put the activity in an existing
                // task if the activity already exists in the history.
                intentActivity = mRootActivityContainer.findActivity(mIntent, mStartActivity.info,
                        !(LAUNCH_SINGLE_TASK == mLaunchMode));
            } else {
                // Otherwise find the best task to put the activity in.
                intentActivity =
                        mRootActivityContainer.findTask(mStartActivity, mPreferredDisplayId);
            }
        }

        if (intentActivity != null
                && (mStartActivity.isActivityTypeHome() || intentActivity.isActivityTypeHome())
                && intentActivity.getDisplayId() != mPreferredDisplayId) {
            // Do not reuse home activity on other displays.
            intentActivity = null;
        }

        return intentActivity;
    }

先判斷是否放入現(xiàn)有的任務(wù)中
mStartActivity.resultTo這里對(duì)應(yīng)的就是上文的resultRecord,當(dāng)然這里為null
這里主要調(diào)用findTask方法

  intentActivity =
                        mRootActivityContainer.findTask(mStartActivity, mPreferredDisplayId);

核心調(diào)用的方法是

void findTaskLocked(ActivityRecord target, FindTaskResult result) {
        Intent intent = target.intent;
        ActivityInfo info = target.info;
        ComponentName cls = intent.getComponent();
        if (info.targetActivity != null) {
            cls = new ComponentName(info.packageName, info.targetActivity);
        }
        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
        boolean isDocument = intent != null & intent.isDocument();
        // If documentData is non-null then it must match the existing task data.
        Uri documentData = isDocument ? intent.getData() : null;

        if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this);
        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
            final TaskRecord task = mTaskHistory.get(taskNdx);
            if (task.voiceSession != null) {
                // We never match voice sessions; those always run independently.
                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
                continue;
            }
            if (task.userId != userId) {
                // Looking for a different task.
                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
                continue;
            }

            // Overlays should not be considered as the task's logical top activity.
            final ActivityRecord r = task.getTopActivity(false /* includeOverlays */);
            if (r == null || r.finishing || r.mUserId != userId ||
                    r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
                continue;
            }
            if (!r.hasCompatibleActivityType(target)) {
                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type");
                continue;
            }

            final Intent taskIntent = task.intent;
            final Intent affinityIntent = task.affinityIntent;
            final boolean taskIsDocument;
            final Uri taskDocumentData;
            if (taskIntent != null && taskIntent.isDocument()) {
                taskIsDocument = true;
                taskDocumentData = taskIntent.getData();
            } else if (affinityIntent != null && affinityIntent.isDocument()) {
                taskIsDocument = true;
                taskDocumentData = affinityIntent.getData();
            } else {
                taskIsDocument = false;
                taskDocumentData = null;
            }

            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
                    + (task.realActivity != null ? task.realActivity.flattenToShortString() : "")
                    + "/aff=" + r.getTaskRecord().rootAffinity + " to new cls="
                    + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
            // TODO Refactor to remove duplications. Check if logic can be simplified.
            if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
                    && Objects.equals(documentData, taskDocumentData)) {
                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
                //dump();
                if (DEBUG_TASKS) Slog.d(TAG_TASKS,
                        "For Intent " + intent + " bringing to top: " + r.intent);
                result.mRecord = r;
                result.mIdealMatch = true;
                break;
            } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
                    affinityIntent.getComponent().compareTo(cls) == 0 &&
                    Objects.equals(documentData, taskDocumentData)) {
                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
                //dump();
                if (DEBUG_TASKS) Slog.d(TAG_TASKS,
                        "For Intent " + intent + " bringing to top: " + r.intent);
                result.mRecord = r;
                result.mIdealMatch = true;
                break;
            } else if (!isDocument && !taskIsDocument
                    && result.mRecord == null && task.rootAffinity != null) {
                if (task.rootAffinity.equals(target.taskAffinity)) {
                    if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
                    // It is possible for multiple tasks to have the same root affinity especially
                    // if they are in separate stacks. We save off this candidate, but keep looking
                    // to see if there is a better candidate.
                    result.mRecord = r;
                    result.mIdealMatch = false;
                }
            } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
        }
    }

這里會(huì)遍歷activityStack哆姻,當(dāng)然現(xiàn)在lunancher對(duì)應(yīng)activityStack先被遍歷到宣增,傳過(guò)去的參數(shù)是要打開(kāi)的activityRecord
簡(jiǎn)單來(lái)說(shuō)就是從每個(gè)activityStack里去尋找匹配的activityRecord
這里先拿到要打開(kāi)activity的ComponentName,然后去遍歷activityStater中的taskRecord去拿到最上面的activityRecord矛缨,如果是singleInstance的話就跳過(guò)(8.0以后基本上一個(gè)activityStack對(duì)應(yīng)了一個(gè)taskRecord)
這里要說(shuō)明的是不但activityRecord屬性爹脾,taskRecord也有此屬性
最后來(lái)匹配創(chuàng)建taskRecord的傳過(guò)來(lái)的ComponentName和當(dāng)前的activityRecord的ComponentName做比較
很明顯由于是打開(kāi)過(guò)的taskRecord,所以第二個(gè)taskRecord的realactivity符合
所以會(huì)走到這里面箕昭,所以返回的 result.mRecord也就是taskRecord

 result.mRecord = r;
 result.mIdealMatch = true;

也就是原來(lái)的mainActivity對(duì)應(yīng)的activityRecord

6.當(dāng)reusedActivity不為null時(shí)灵妨,也是最重要的邏輯
6.1

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

這里clearTopAndResetStandardLaunchMode為false
會(huì)走到setTask里,也就是給activity放到taskRecord里

void setTask(TaskRecord task, boolean reparenting) {
        // Do nothing if the {@link TaskRecord} is the same as the current {@link getTaskRecord}.
        if (task != null && task == getTaskRecord()) {
            return;
        }

        final ActivityStack oldStack = getActivityStack();
        final ActivityStack newStack = task != null ? task.getStack() : null;

        // Inform old stack (if present) of activity removal and new stack (if set) of activity
        // addition.
        if (oldStack != newStack) {
            if (!reparenting && oldStack != null) {
                oldStack.onActivityRemovedFromStack(this);
            }

            if (newStack != null) {
                newStack.onActivityAddedToStack(this);
            }
        }

        this.task = task;

        if (!reparenting) {
            onParentChanged();
        }
    }

這里由于不是resume的狀態(tài)落竹,所以onActivityAddedToStack沒(méi)啥用泌霍,簡(jiǎn)單來(lái)說(shuō)就是把taskRecord賦值到了這個(gè)activityRecord里
接下來(lái)是針對(duì)singletask的一個(gè)條件語(yǔ)句

  if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                    || isDocumentLaunchesIntoExisting(mLaunchFlags)
                    || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {

這里我們暫時(shí)不分析,下文會(huì)分析筋量,重點(diǎn)看下這方法

reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);

從名字上來(lái)說(shuō)是把這個(gè)acivityRecord對(duì)應(yīng)的activityStack移到第一個(gè)烹吵,來(lái)看看具體的操作

private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
        mTargetStack = intentActivity.getActivityStack();
        mTargetStack.mLastPausedActivity = null;
        // If the target task is not in the front, then we need to bring it to the front...
        // except...  well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
        // the same behavior as if a new instance was being started, which means not bringing it
        // to the front if the caller is not itself in the front.
        final boolean differentTopTask;
        if (mPreferredDisplayId == mTargetStack.mDisplayId) {
            final ActivityStack focusStack = mTargetStack.getDisplay().getFocusedStack();
            final ActivityRecord curTop = (focusStack == null)
                    ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
            final TaskRecord topTask = curTop != null ? curTop.getTaskRecord() : null;
            differentTopTask = topTask != intentActivity.getTaskRecord()
                    || (focusStack != null && topTask != focusStack.topTask());
        } else {
            // The existing task should always be different from those in other displays.
            differentTopTask = true;
        }
      ....

這里mTargetStack就是我們的loadingActivity對(duì)應(yīng)的ActivityStack就是targetStack,把這個(gè)mLastPausedActivity設(shè)為null,而focusStack肯定就是launcher對(duì)應(yīng)的ActivityRecord 接下來(lái)去尋找當(dāng)前activitystack對(duì)應(yīng)的可見(jiàn)的ActivityRecord

 ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
            final TaskRecord task = mTaskHistory.get(taskNdx);
            final ArrayList<ActivityRecord> activities = task.mActivities;
            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                ActivityRecord r = activities.get(activityNdx);
                if (!r.finishing && !r.delayedResume && r != notTop && r.okToShowLocked()) {
                    return r;
                }
            }
        }
        return null;
    }

可以看到取到的就是lunchActivity
然后判斷

 differentTopTask = topTask != intentActivity.getTaskRecord()
                    || (focusStack != null && topTask != focusStack.topTask());

MainActivity對(duì)應(yīng)taskRecord是否是launcher的taskRecord一樣,很顯然是不一樣的
所以走了如下的邏輯

 if (differentTopTask && !mAvoidMoveToFront) {
            mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
            if (mSourceRecord == null || (mSourceStack.getTopActivity() != null &&
                    mSourceStack.getTopActivity().getTaskRecord()
                            == mSourceRecord.getTaskRecord())) {
                // We really do want to push this one into the user's face, right now.
                if (mLaunchTaskBehind && mSourceRecord != null) {
                    intentActivity.setTaskToAffiliateWith(mSourceRecord.getTaskRecord());
                }

這里給MainActivity對(duì)應(yīng)的activityRecord設(shè)置flag桨武,這個(gè)flag也就是launcher啟動(dòng)的標(biāo)志
然后判斷mSourceStack也就是activityStack的taskrecord的topActivity如果是sourceRecord對(duì)應(yīng)的taskrecord肋拔,顯然這里是符合的
但是mLaunchTaskBehind是false所以不走以下邏輯

final boolean willClearTask =
                        (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
                if (!willClearTask) {
                    final ActivityStack launchStack = getLaunchStack(
                            mStartActivity, mLaunchFlags, mStartActivity.getTaskRecord(), mOptions);
                    final TaskRecord intentTask = intentActivity.getTaskRecord();
                    if (launchStack == null || launchStack == mTargetStack) {
                        // We only want to move to the front, if we aren't going to launch on a
                        // different stack. If we launch on a different stack, we will put the
                        // task on top there.
                        mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
                                mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
                        mMovedToFront = true;
                    } else if (launchStack.inSplitScreenWindowingMode()) {
                        if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
                            // If we want to launch adjacent and mTargetStack is not the computed
                            // launch stack - move task to top of computed stack.
                            intentTask.reparent(launchStack, ON_TOP,
                                    REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
                                    "launchToSide");
                        } else {
                            // TODO: This should be reevaluated in MW v2.
                            // We choose to move task to front instead of launching it adjacent
                            // when specific stack was requested explicitly and it appeared to be
                            // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
                            mTargetStack.moveTaskToFrontLocked(intentTask,
                                    mNoAnimation, mOptions, mStartActivity.appTimeTracker,
                                    "bringToFrontInsteadOfAdjacentLaunch");
                        }
                        mMovedToFront = launchStack != launchStack.getDisplay()
                                .getTopStackInWindowingMode(launchStack.getWindowingMode());
                    } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
                        // Target and computed stacks are on different displays and we've
                        // found a matching task - move the existing instance to that display and
                        // move it to front.
                        intentActivity.getTaskRecord().reparent(launchStack, ON_TOP,
                                REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
                                "reparentToDisplay");
                        mMovedToFront = true;
                    } else if (launchStack.isActivityTypeHome()
                            && !mTargetStack.isActivityTypeHome()) {
                        // It is possible for the home activity to be in another stack initially.
                        // For example, the activity may have been initially started with an intent
                        // which placed it in the fullscreen stack. To ensure the proper handling of
                        // the activity based on home stack assumptions, we must move it over.
                        intentActivity.getTaskRecord().reparent(launchStack, ON_TOP,
                                REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
                                "reparentingHome");
                        mMovedToFront = true;
                    }
                    mOptions = null;

                    // We are moving a task to the front, use starting window to hide initial drawn
                    // delay.
                    intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
                            true /* taskSwitch */);
                }

重點(diǎn)看下這個(gè)邏輯
先獲得getLaunchStack,
最終會(huì)走到

if (r.getDisplayId() == displayId && r.getTaskRecord() == candidateTask) {
            return candidateTask.getStack();
        }

這個(gè)r是mStartActivity呀酸,因?yàn)橹耙呀?jīng)賦值過(guò)taskRecord凉蜂,所以是返回taskRecord對(duì)應(yīng)的activityStack
然后走到關(guān)鍵的地方

 
 if (!willClearTask) {
                    final ActivityStack launchStack = getLaunchStack(
                            mStartActivity, mLaunchFlags, mStartActivity.getTaskRecord(), mOptions);
                    final TaskRecord intentTask = intentActivity.getTaskRecord();
                    if (launchStack == null || launchStack == mTargetStack) {
                        // We only want to move to the front, if we aren't going to launch on a
                        // different stack. If we launch on a different stack, we will put the
                        // task on top there.
                        mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
                                mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
                        mMovedToFront = true;
                    } 

由于launchStack等于mTargetStack(就是loadingActivity對(duì)應(yīng)的activityStack)
回調(diào)用此activityStack的moveTaskToFrontLocked方法
里面獲取到LoadingActivity的activityRecord以后

 final ActivityRecord r = topRunningActivityLocked();
            if (r != null) {
                r.moveFocusableActivityToTop(reason);
            }

重點(diǎn)調(diào)用了如下方法

/** Move activity with its stack to front and make the stack focused. */
    boolean moveFocusableActivityToTop(String reason) {
        if (!isFocusable()) {
            if (DEBUG_FOCUS) {
                Slog.d(TAG_FOCUS, "moveActivityStackToFront: unfocusable activity=" + this);
            }
            return false;
        }

        final TaskRecord task = getTaskRecord();
        final ActivityStack stack = getActivityStack();
        if (stack == null) {
            Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: activity="
                    + this + " task=" + task);
            return false;
        }

        if (mRootActivityContainer.getTopResumedActivity() == this) {
            if (DEBUG_FOCUS) {
                Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
            }
            return false;
        }

        if (DEBUG_FOCUS) {
            Slog.d(TAG_FOCUS, "moveActivityStackToFront: activity=" + this);
        }

        stack.moveToFront(reason, task);
        // Report top activity change to tracking services and WM
        if (mRootActivityContainer.getTopResumedActivity() == this) {
            // TODO(b/111361570): Support multiple focused apps in WM
            mAtmService.setResumedActivityUncheckLocked(this, reason);
        }
        return true;
    }

重點(diǎn)在于moveTofront方法會(huì)調(diào)用此方法來(lái)排序displayContent中的activityStack的顯示順序

 display.positionChildAtTop(this, !movingTask /* includingParents */, reason);

這個(gè)方法用來(lái)排序把loadingactivity對(duì)應(yīng)的activityStack排序到前面去
然后

if (mRootActivityContainer.getTopResumedActivity() == this) {
            // TODO(b/111361570): Support multiple focused apps in WM
            mAtmService.setResumedActivityUncheckLocked(this, reason);
        }

此時(shí)ams里最上面的activityrecord就是此,然后把a(bǔ)ms的lastResumeActivity設(shè)置成MainActivity

setResumedActivityUncheckLocked() 方法
  if (mLastResumedActivity != null && r.mUserId != mLastResumedActivity.mUserId) {
            mAmInternal.sendForegroundProfileChanged(r.mUserId);
        }
        updateResumedAppTrace(r);
        mLastResumedActivity = r;

        r.getDisplay().setFocusedApp(r, true);

        applyUpdateLockStateLocked(r);
        applyUpdateVrModeLocked(r);

在設(shè)置完成之后
ams會(huì)調(diào)用一個(gè)最重要的方法resumeFocusedStacksTopActivities,此時(shí)要打開(kāi)的activity的棧已經(jīng)被移到前面了

  boolean resumeFocusedStacksTopActivities() {
        return resumeFocusedStacksTopActivities(null, null, null);
    }

三個(gè)參數(shù)都是null

 boolean resumeFocusedStacksTopActivities(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

        if (!mStackSupervisor.readyToResume()) {
            return false;
        }

        boolean result = false;
        if (targetStack != null && (targetStack.isTopStackOnDisplay()
                || getTopDisplayFocusedStack() == targetStack)) {
            result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }

        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            boolean resumedOnDisplay = false;
            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = display.getChildAt(stackNdx);
                final ActivityRecord topRunningActivity = stack.topRunningActivityLocked();
                if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
                    continue;
                }
                if (stack == targetStack) {
                    // Simply update the result for targetStack because the targetStack had
                    // already resumed in above. We don't want to resume it again, especially in
                    // some cases, it would cause a second launch failure if app process was dead.
                    resumedOnDisplay |= result;
                    continue;
                }
                if (display.isTopStack(stack) && topRunningActivity.isState(RESUMED)) {
                    // Kick off any lingering app transitions form the MoveTaskToFront operation,
                    // but only consider the top task and stack on that display.
                    stack.executeAppTransition(targetOptions);
                } else {
                    resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
                }
            }

這里由于runnActivity(就是mainActivity)最終會(huì)調(diào)用makeActiveIfNeeded方法

 @GuardedBy("mService")
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mInResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mInResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options);

間接調(diào)用resumeTopActivityInnerLocked注意這兩個(gè)參數(shù)都是null,并且設(shè)置了loadactivity對(duì)應(yīng)的activityStack的mInResumeTopActivity值為true
從而調(diào)用mainactivity對(duì)應(yīng)的activityStack的resumeTopActivityInnerLocked
方法窿吩,也就是在這方法里MainActivity來(lái)resume的
這里看判斷這個(gè)activitystack里mPausingActivity的對(duì)應(yīng)的activityrecord是否是null

 // If we are currently pausing an activity, then don't do anything until that is done.
        if (!mRootActivityContainer.allPausedActivitiesComplete()) {
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                    "resumeTopActivityLocked: Skip resume: some activity pausing.");

            return false;
        }

如果此activityRecord在pause就返回true
接下來(lái)就調(diào)用pauseBackStacks用來(lái)讓launch onpause;

boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);

這方法判斷activitystack對(duì)應(yīng)的resumeActivity屬性收否是null,并且不是fosucable

boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
        boolean someActivityPaused = false;
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = mStacks.get(stackNdx);
            final ActivityRecord resumedActivity = stack.getResumedActivity();
            if (resumedActivity != null
                    && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
                        || !stack.isFocusable())) {
                if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
                        " mResumedActivity=" + resumedActivity);
                someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
                        dontWait);
            }
        }
        return someActivityPaused;
    }

會(huì)調(diào)用activityStack(此時(shí)是launcherActivity)的startPausingLocked方法

 final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean pauseImmediately) {
        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);
            }
        }
        ActivityRecord prev = mResumedActivity;

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

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

        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.setState(PAUSING, "startPausingLocked");
        prev.getTaskRecord().touchActiveTime();
        clearLaunchTime(prev);

        mService.updateCpuStats();

        if (prev.attachedToProcess()) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev),
                        prev.shortComponentName, "userLeaving=" + userLeaving);

                mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
                        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();
        }

        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.");
            if (resuming == null) {
                mRootActivityContainer.resumeFocusedStacksTopActivities();
            }
            return false;
        }
    }

由于這里是launcherActivity的activityStack,所以他的mPauseing為null
而正在mResumedActivity就是launcheractivity了茎杂,然后把mPausingActivity和
mLastPausedActivity賦值為launcheractivity
然后這里

 prev.setState(PAUSING, "startPausingLocked");

把a(bǔ)ctivityrecord的狀態(tài)設(shè)置成pausing

 void setState(ActivityState state, String reason) {
        if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState()
                        + " to:" + state + " reason:" + reason);

        if (state == mState) {
            // No need to do anything if state doesn't change.
            if (DEBUG_STATES) Slog.v(TAG_STATES, "State unchanged from:" + state);
            return;
        }

        mState = state;

        final TaskRecord parent = getTaskRecord();

        if (parent != null) {
            parent.onActivityStateChanged(this, state, reason);
        }

會(huì)間接調(diào)用onActivityStateChanged方法

  void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
        if (record == mResumedActivity && state != RESUMED) {
            setResumedActivity(null, reason + " - onActivityStateChanged");
        }

        if (state == RESUMED) {
            if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:"
                    + reason);
            setResumedActivity(record, reason + " - onActivityStateChanged");
            if (record == mRootActivityContainer.getTopResumedActivity()) {
                // TODO(b/111361570): Support multiple focused apps in WM
                mService.setResumedActivityUncheckLocked(record, reason);
            }
            mStackSupervisor.mRecentTasks.add(record.getTaskRecord());
        }
    }

這里由于狀態(tài)是onpause所以不走如下邏輯,但是把這個(gè)activitystask的resume狀態(tài)取消了

接下來(lái)判斷進(jìn)程是否存在

if (prev.attachedToProcess()) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev),
                        prev.shortComponentName, "userLeaving=" + userLeaving);

                mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
                        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;
        }

這里當(dāng)有activityrecord所在進(jìn)程存在的情況下會(huì)讓此activity進(jìn)行onpause的操作

if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }
        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;
        }

這里回到了Mainactivity的activityrecord里,由于mResumedActivity還沒(méi)有賦值纫雁,mResumedActivity還是原來(lái)的activitystack里煌往,雖然已經(jīng)執(zhí)行了onpause操作
這里返回的pausing就是mPausingActivity正在pause的標(biāo)示符,
這里是返回的true.然后更新process的優(yōu)先級(jí)

 if (next.attachedToProcess()) {
                next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
                        true /* activityChange */, false /* updateOomAdj */);
            }

這里的next指的就是mainActivity的record
這里總結(jié)一下:
1.先循環(huán)找到最頂層的activityStack對(duì)應(yīng)的activityRecord轧邪,然后調(diào)用其makeActiveIfNeeded方法
判斷是focusable但不是resume狀態(tài)的
2.然后根據(jù)mResume的狀態(tài)去pause activityStack是resume但不是在最上層的activityStack對(duì)應(yīng)的activityRecord
至此moveTaskToFrontLocked算是走完了刽脖,可見(jiàn)非常的繞,當(dāng)然這只是一種case
最后走到了

if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
            return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
        }

由于從launcher啟動(dòng)會(huì)帶上這個(gè)參數(shù)忌愚,來(lái)看下這個(gè)參數(shù)實(shí)際的含義
這里這個(gè)屬性其實(shí)和這三個(gè)設(shè)置的有關(guān)曲管,由于默認(rèn)沒(méi)設(shè)置,就沒(méi)有

 final int flags = target.info.flags;
            final boolean finishOnTaskLaunch =
                    (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
            final boolean allowTaskReparenting =
                    (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
            final boolean clearWhenTaskReset =
                    (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;

再來(lái)看下setTaskFromIntentActivity方法硕糊,傳過(guò)來(lái)的是MainActivity

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

這個(gè)方法主要對(duì)singleTask和FLAG_ACTIVITY_SINGLE_TOP做的處理

最后如果此mStartActivity沒(méi)有被加到task中

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

這里會(huì)間接調(diào)用resumeFocusedStacksTopActivities方法院水,上文已經(jīng)調(diào)用過(guò)了,但是參數(shù)mTargetStack代表了MainActivity

 boolean resumeFocusedStacksTopActivities(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

        if (!mStackSupervisor.readyToResume()) {
            return false;
        }

        boolean result = false;
        if (targetStack != null && (targetStack.isTopStackOnDisplay()
                || getTopDisplayFocusedStack() == targetStack)) {
            result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
     ....

這里targetStack很明顯就是我們MainActivity對(duì)應(yīng)的task
此時(shí)看到了又循環(huán)了此方法简十,但是由于我們的pausing標(biāo)記

   if (!mRootActivityContainer.allPausedActivitiesComplete()) {
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                    "resumeTopActivityLocked: Skip resume: some activity pausing.");

            return false;
        }

這里很明顯會(huì)走到這個(gè)if里面檬某,返回false,也就是不會(huì)在走進(jìn)去了
當(dāng)然后面由于狀態(tài)是pausing的狀態(tài)勺远,所以是返回false
當(dāng)然后面的makeActiveIfNeeded也是因?yàn)槭莗ause狀態(tài)所以沒(méi)有執(zhí)行resumeTopActivityUncheckedLocked方法

boolean makeActiveIfNeeded(ActivityRecord activeActivity) {
        if (shouldResumeActivity(activeActivity)) {
            if (DEBUG_VISIBILITY) {
                Slog.v("TAG_VISIBILITY", "Resume visible activity, " + this);
            }
            return getActivityStack().resumeTopActivityUncheckedLocked(activeActivity /* prev */,
                    null /* options */);
        } 

顯然過(guò)程已經(jīng)執(zhí)行完了橙喘,接下來(lái)執(zhí)行

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

還記得上文么,outActivity是startActivity也就是LoadingActivityRecord
胶逢,現(xiàn)在變成了我們?cè)瓉?lái)的的MainActivity
好吧厅瞎,我們的startactivityunchecked方法終于執(zhí)行完了

try {
            mService.mWindowManager.deferSurfaceLayout();
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
        } finally {
            final ActivityStack currentStack = r.getActivityStack();
            startedActivityStack = currentStack != null ? currentStack : mTargetStack;

            if (ActivityManager.isStartResultSuccessful(result)) {
                if (startedActivityStack != null) {
                    // If there is no state change (e.g. a resumed activity is reparented to
                    // top of another display) to trigger a visibility/configuration checking,
                    // we have to update the configuration for changing to different display.
                    final ActivityRecord currentTop =
                            startedActivityStack.topRunningActivityLocked();
                    if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) {
                        mRootActivityContainer.ensureVisibilityAndConfig(
                                currentTop, currentTop.getDisplayId(),
                                true /* markFrozenIfConfigChanged */, false /* deferResume */);
                    }
                }
            } else {
                // If we are not able to proceed, disassociate the activity from the task.
                // Leaving an activity in an incomplete state can lead to issues, such as
                // performing operations without a window container.
                final ActivityStack stack = mStartActivity.getActivityStack();
                if (stack != null) {
                    stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
                            null /* intentResultData */, "startActivity", true /* oomAdj */);
                }

                // Stack should also be detached from display and be removed if it's empty.
                if (startedActivityStack != null && startedActivityStack.isAttached()
                        && startedActivityStack.numActivities() == 0
                        && !startedActivityStack.isActivityTypeHome()) {
                    startedActivityStack.remove();
                }
            }
            mService.mWindowManager.continueSurfaceLayout();
        }

        postStartActivityProcessing(r, result, startedActivityStack);

        return result;
    }

接下來(lái)看下后續(xù)的流程
這里currentTop很明顯不為null的,然后后面的邏輯是分屏的邏輯初坠,這里暫且不論
然后通知wms去刷新屏幕的操作

 mService.mWindowManager.continueSurfaceLayout();

wms去刷新SurfaceLayout();本文也不做多的詳細(xì)解釋
然后回到最初的地方也就是startActivityMayWait方法
會(huì)調(diào)用日志打印的地方來(lái)打印日志

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

最后通過(guò)activityStater來(lái)重新更新mLastStarter的操作
分析了一圈我們只分析出來(lái)了會(huì)調(diào)用我們onPause方法和簸,那此時(shí)界面根本沒(méi)顯示,啥時(shí)候調(diào)用onResume方法呢碟刺?
其實(shí)在我們客戶端調(diào)用完onPause之后

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

    @Override
    public int getTargetState() {
        return ON_PAUSE;
    }

    @Override
    public void postExecute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        if (mDontReport) {
            return;
        }
        try {
            // TODO(lifecycler): Use interface callback instead of AMS.
            ActivityTaskManager.getService().activityPaused(token);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

會(huì)調(diào)用postExecute锁保,也就是執(zhí)行完onPause的操作,可以看到會(huì)調(diào)用activityPaused方法
這里說(shuō)下ams的處理超時(shí)的機(jī)制半沽,如果從ams端到客戶端onPause的時(shí)間大于500毫秒爽柒,注意,這里就只有ipc通訊的時(shí)間者填,并不包括你客戶端執(zhí)行onPause時(shí)間(因?yàn)榭蛻舳耸峭ㄟ^(guò)handler調(diào)用你自己的onpause方法的)
這段代碼在activityStack里面浩村,這個(gè)代碼和正常返回的代碼是競(jìng)爭(zhēng)同一把鎖的,這里要注意下

/**
     * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because
     * this directly impacts the responsiveness seen by the user.
     */
    private void schedulePauseTimeout(ActivityRecord r) {
        final Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
        msg.obj = r;
        r.pauseTime = SystemClock.uptimeMillis();
        mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
    }

那來(lái)看下activityPaused方法

    @Override
    public final void activityPaused(IBinder token) {
        final long origId = Binder.clearCallingIdentity();
        synchronized (mGlobalLock) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                stack.activityPausedLocked(token, false);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }

這里根據(jù)token來(lái)找到activityRecord占哟,然后找到activityStack
然后進(jìn)入到activityPausedLocked方法里

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.mUserId, 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");
                    }
                }
            }
        }
        mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
    }

也就是launcheractivity的activitystack方法心墅,這里前面說(shuō)過(guò)
lunaunch的stack的mPausingActivity就已經(jīng)被賦值過(guò)了酿矢,所以是等于的,會(huì)進(jìn)入completePauseLocked里面

private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
        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) {
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,
                        "completePausedLocked");
            } else if (prev.hasProcess()) {
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
                        + " wasStopping=" + wasStopping + " visible=" + prev.visible);
                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.
                    addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */,
                            "completePauseLocked");
                }
            } 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;
        }

        if (resumeNext) {
            final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack();
            if (!topStack.shouldSleepOrShutDownActivities()) {
                mRootActivityContainer.resumeFocusedStacksTopActivities(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.
                    mRootActivityContainer.resumeFocusedStacksTopActivities();
                }
            }
        }

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

            if (prev.hasProcess() && prev.cpuTimeAtResume > 0) {
                final long diff = prev.app.getCpuTime() - prev.cpuTimeAtResume;
                if (diff > 0) {
                    final Runnable r = PooledLambda.obtainRunnable(
                            ActivityManagerInternal::updateForegroundTimeIfOnBattery,
                            mService.mAmInternal, prev.info.packageName,
                            prev.info.applicationInfo.uid,
                            diff);
                    mService.mH.post(r);
                }
            }
            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() != null && getDisplay().hasPinnedStack())) {
            mService.getTaskChangeNotificationController().notifyTaskStackChanged();
            mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
        }

        mRootActivityContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
    }

這里分為兩部分怎燥,一開(kāi)始是把launch的activity的狀態(tài)設(shè)置成paused的狀態(tài)瘫筐,然后判斷有沒(méi)有重啟的標(biāo)志
是的話就重啟,這應(yīng)該和屏幕旋轉(zhuǎn)有關(guān),以后有時(shí)間在分析

else if (prev.hasProcess()) {
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
                        + " wasStopping=" + wasStopping + " visible=" + prev.visible);
                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);

也就是relaunchActivityLocked方法
第二部分有調(diào)用了resumeFocusedStacksTopActivities方法铐姚,可見(jiàn)這是一個(gè)核心方法
很明顯

   if (!mRootActivityContainer.allPausedActivitiesComplete()) {
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                    "resumeTopActivityLocked: Skip resume: some activity pausing.");

            return false;
        }

由于剛剛的狀態(tài)改了策肝,把pausing狀態(tài)改成了paused了,當(dāng)然不走這里了谦屑,然后進(jìn)行到第二部分

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 */);
        }

這里是拿到上一個(gè)有焦點(diǎn)的activitystack驳糯,然后判斷是否等于現(xiàn)在的
activityStack,這里很明顯不是氢橙,當(dāng)然由于此前,resume狀態(tài)被重置過(guò)了恬偷,所以lastResumed也為null
接下來(lái)pause的判斷

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

由于mResumeActivity都為null
所以也不會(huì)走到onpause里面悍手,然后就開(kāi)始更改Mainactivity的狀態(tài)了

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

            // This activity is now becoming visible.
            if (!next.visible || next.stopped || lastActivityTranslucent) {
                next.setVisibility(true);
            }

            // schedule launch ticks to collect information about slow apps.
            next.startLaunchTickingLocked();

            ActivityRecord lastResumedActivity =
                    lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity;
            final ActivityState lastState = next.getState();

            mService.updateCpuStats();

            if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
                    + " (in existing)");

            next.setState(RESUMED, "resumeTopActivityInnerLocked");

也就是說(shuō)從這里開(kāi)始activityStack對(duì)應(yīng)的mResumedActivity是MainActivity,然后會(huì)間接調(diào)用到onActivityStateChanged方法里

void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
        if (record == mResumedActivity && state != RESUMED) {
            setResumedActivity(null, reason + " - onActivityStateChanged");
        }

        if (state == RESUMED) {
            if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:"
                    + reason);
            setResumedActivity(record, reason + " - onActivityStateChanged");
            if (record == mRootActivityContainer.getTopResumedActivity()) {
                // TODO(b/111361570): Support multiple focused apps in WM
                mService.setResumedActivityUncheckLocked(record, reason);
            }
            mStackSupervisor.mRecentTasks.add(record.getTaskRecord());
        }
    }

這里主要作用是增加Recentask的taskRecord,然后把a(bǔ)ms里的mLastResumedActivity設(shè)置為mainactivity對(duì)應(yīng)的record
然后會(huì)調(diào)用遠(yuǎn)端的onResume方法

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

然后會(huì)調(diào)用ams這里的activityResumed方法,也就差不多了袍患,最后還有一個(gè)疑問(wèn)就是onStop方法在哪里調(diào)用的
其實(shí)在客戶端也就是actiivtyThread中
在處理onResume之后

 r.nextIdle = mNewActivities;
        mNewActivities = r;
        if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
        Looper.myQueue().addIdleHandler(new Idler());
    }

會(huì)有一個(gè)idler的handler坦康,從而調(diào)用遠(yuǎn)程的activityIdle方法

if (a.activity != null && !a.activity.mFinished) {
                        try {
                            am.activityIdle(a.token, a.createdConfig, stopProfiling);
                            a.createdConfig = null;
                        } catch (RemoteException ex) {
                            throw ex.rethrowFromSystemServer();
                        }
                    }

最終會(huì)調(diào)用到launcher對(duì)應(yīng)的activityStack的stopActivityLocked方法,來(lái)進(jìn)行stop操作

final void stopActivityLocked(ActivityRecord r) {
        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + r);
        if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
            if (!r.finishing) {
                if (!shouldSleepActivities()) {
                    if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r);
                    if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
                            "stop-no-history", false)) {
                        // If {@link requestFinishActivityLocked} returns {@code true},
                        // {@link adjustFocusedActivityStack} would have been already called.
                        r.resumeKeyDispatchingLocked();
                        return;
                    }
                } else {
                    if (DEBUG_STATES) Slog.d(TAG_STATES, "Not finishing noHistory " + r
                            + " on stop because we're just sleeping");
                }
            }
        }

        if (r.attachedToProcess()) {
            adjustFocusedActivityStack(r, "stopActivity");
            r.resumeKeyDispatchingLocked();
            try {
                r.stopped = false;
                if (DEBUG_STATES) Slog.v(TAG_STATES,
                        "Moving to STOPPING: " + r + " (stop requested)");
                r.setState(STOPPING, "stopActivityLocked");
                if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
                        "Stopping visible=" + r.visible + " for " + r);
                if (!r.visible) {
                    r.setVisible(false);
                }
                EventLogTags.writeAmStopActivity(
                        r.mUserId, System.identityHashCode(r), r.shortComponentName);
                mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), r.appToken,
                        StopActivityItem.obtain(r.visible, r.configChangeFlags));
                if (shouldSleepOrShutDownActivities()) {
                    r.setSleeping(true);
                }
                Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
                mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
            } catch (Exception e) {
                // Maybe just ignore exceptions here...  if the process
                // has crashed, our death notification will clean things
                // up.
                Slog.w(TAG, "Exception thrown during pause", e);
                // Just in case, assume it to be stopped.
                r.stopped = true;
                if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + r);
                r.setState(STOPPED, "stopActivityLocked");
                if (r.deferRelaunchUntilPaused) {
                    destroyActivityLocked(r, true, "stop-except");
                }
            }
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末诡延,一起剝皮案震驚了整個(gè)濱河市滞欠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌肆良,老刑警劉巖筛璧,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異惹恃,居然都是意外死亡夭谤,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)巫糙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)朗儒,“玉大人,你說(shuō)我怎么就攤上這事参淹∽沓” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵浙值,是天一觀的道長(zhǎng)恳不。 經(jīng)常有香客問(wèn)我,道長(zhǎng)亥鸠,這世上最難降的妖魔是什么妆够? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任识啦,我火速辦了婚禮,結(jié)果婚禮上神妹,老公的妹妹穿的比我還像新娘颓哮。我一直安慰自己,他們只是感情好鸵荠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布冕茅。 她就那樣靜靜地躺著,像睡著了一般蛹找。 火紅的嫁衣襯著肌膚如雪姨伤。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天庸疾,我揣著相機(jī)與錄音乍楚,去河邊找鬼。 笑死届慈,一個(gè)胖子當(dāng)著我的面吹牛徒溪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播金顿,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼臊泌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了揍拆?” 一聲冷哼從身側(cè)響起渠概,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嫂拴,沒(méi)想到半個(gè)月后播揪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顷牌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年剪芍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窟蓝。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡罪裹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出运挫,到底是詐尸還是另有隱情状共,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布谁帕,位于F島的核電站峡继,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏匈挖。R本人自食惡果不足惜碾牌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一康愤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧舶吗,春花似錦征冷、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至腹侣,卻和暖如春叔收,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背傲隶。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工饺律, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人跺株。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓蓝晒,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親帖鸦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容