Activity启动模式源码剖析

前言:之前我们分析过Activity在AMS中的启动流程,当时也简单的说了下Activity的启动模式,现在我们更详细,更全面的解析一下它;

启动Activity的时候,Activity.startActivity()方法会将启动流程交给AMS,AMS又将启动交给ActivityStarter处理,关于Activity的启动模式,就在ActivityStarter.startActivityUnchecked()方法里;

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

    //代码1
    //初始化属性
    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor);

    //代码2
    //将启动模式SingleInstance或者SingleTask转化成FLAG_ACTIVITY_NEW_TASK标签,保存在mLaunchFlags
    computeLaunchingTaskFlags();

    //代码3
    //初始化获取当前的ActivityStack,ActivityStack是用来管理栈的
    computeSourceStack();

    //将收集到的flags设置给Intent
    mIntent.setFlags(mLaunchFlags);

    //代码4
    //找到可以复用的栈或者Activity
    ActivityRecord reusedActivity = getReusableIntentActivity();

    final int preferredLaunchStackId =
            (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
    final int preferredLaunchDisplayId =
            (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;

    if (reusedActivity != null) {//成立,此时reusedActivity不为null,有可复用的Activity或者栈
        if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
                (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
            mSupervisor.showLockTaskToast();
            Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }

        //给Settings分配栈;
        //将:要启动的Activity绑定到已经找到的可复用的栈中,这样,它们就在同一个栈中了
        if (mStartActivity.getTask() == null) {
            mStartActivity.setTask(reusedActivity.getTask());
        }

        //设置栈的intent和taskAffinity和rootAffinity;
        //我们可以发现,第一个被加入到栈的Activity,它的intent就是栈的intent,它的taskAffinity就是栈的affinity和rootAffinity;
        if (reusedActivity.getTask().intent == null) {
            reusedActivity.getTask().setIntent(mStartActivity);
        }

        //当intent中有FLAG_ACTIVITY_CLEAR_TOP标签,或者启动模式为SingleInstance,SingleTask时;
        //也就是说,启动模式为SingleInstance,SingleTask时,就默认为有FLAG_ACTIVITY_CLEAR_TOP标签
        if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                || isDocumentLaunchesIntoExisting(mLaunchFlags)
                || mLaunchSingleInstance || mLaunchSingleTask) {
            //找到的可复用栈
            final TaskRecord task = reusedActivity.getTask();

            //代码5
            //查找栈中是否存在与mStartActivity相同的Activity,假设存在这个Activity,那就finish并且删除掉栈中所有位于这个Activity前面的Activity
            final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
                    mLaunchFlags);

            //上面的代码有可能把reusedActivity也从栈中给删除了,但是reusedActivity在后面的setTargetStackAndMoveToFrontIfNeeded()方法中会被用到,
            //所以得给reusedActivity重新设置task
            if (reusedActivity.getTask() == null) {
                reusedActivity.setTask(task);
            }

            if (top != null) {//top != null,意味着栈中存在与mStartActivity相同的Activity
                if (top.frontOfTask) {//位于栈底的Activity才有资格成为frontOfTask,此时的top,不一定位于栈底
                    top.getTask().setIntent(mStartActivity);
                }
                //调用mStartActivity的onNewIntet()方法
                deliverNewIntent(top);
            }
        }

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

        //代码6
        //(1)mStartActivity的启动,将目标ActivityStack放到前台;
        //(2)也有可能会导致从栈A跳转到栈B,那我们现在就要把栈B放到前台,以后的操作都是操作栈B的;
        reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
        
        final ActivityRecord outResult =
                outActivity != null && outActivity.length > 0 ? outActivity[0] : null;

        if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
            outActivity[0] = reusedActivity;
        }

        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            resumeTargetStackIfNeeded();
            return START_RETURN_INTENT_TO_CALLER;
        }

        //代码7
        //处理一些特殊标签,判断新启动的Activity是否被添加进已经存在的栈
        setTaskFromIntentActivity(reusedActivity);
        
        //举个例子,这个例子会使下面的判断成立;
        //栈中有A,B,C,D 4个Activity,现在再次启动B,启动模式为singleTask;
        //这样,下面的判断就成立了,函数直接返回,不再往下执行
        if (!mAddingToTask && mReuseTask == null) {
            resumeTargetStackIfNeeded();
            if (outActivity != null && outActivity.length > 0) {
                outActivity[0] = reusedActivity;
            }

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

    final ActivityStack topStack = mSupervisor.mFocusedStack;
    final ActivityRecord topFocused = topStack.topActivity();
    final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);

    //代码8
    //接下来处理SingleTop启动模式,要想SingleTop起作用,那要启动的Activity必须已经位于栈顶
    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
            || mLaunchSingleTop || mLaunchSingleTask);
    if (dontStart) {//当启动模式为SINGLE_TOP时,并且要启动的Activity已经位于栈顶,那就执行onNewIntent()方法
        topStack.mLastPausedActivity = null;
        if (mDoResume) {
            mSupervisor.resumeFocusedStackTopActivityLocked();
        }
        ActivityOptions.abort(mOptions);
        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            return START_RETURN_INTENT_TO_CALLER;
        }

        //执行onNewIntent()方法
        deliverNewIntent(top);

        mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
                preferredLaunchDisplayId, topStack.mStackId);

        return START_DELIVERED_TO_TOP;
    }

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

    int result = START_SUCCESS;
    //接下来就开始创建栈或者绑定栈了
    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;
        String packageName= mService.mContext.getPackageName();
        if (mPerf != null) {
            mStartActivity.perfActivityBoostHandler =
                mPerf.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, packageName, -1, BoostFramework.Launch.BOOST_V1);
        }
        //代码9
        //先是处理FLAG_ACTIVITY_NEW_TASK标签,含有此标签,表示可能会需要创建一个新栈
        result = setTaskFromReuseOrCreateNewTask(
                taskToAffiliate, preferredLaunchStackId, topStack);
    } else if (mSourceRecord != null) {
        //代码10
        //正常绑定
        //一般情况下,mSourceRecord就是调用者,如本例中的Launcher;
        //但也有特殊情况,举个例子,如果启动模式为singleTask,栈中又不存在相同的Activity时,mSourceRecord就是栈顶的Activity,
        result = setTaskFromSourceRecord();
    } else if (mInTask != null) {
        result = setTaskFromInTask();
    } else {
        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 (mSourceRecord != null) {
        mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
    }
    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;

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

    //启动
    mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
            mOptions);
    if (mDoResume) {
        final ActivityRecord topTaskActivity =
                mStartActivity.getTask().topRunningActivityLocked();
        if (!mTargetStack.isFocusable()
                || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                && mStartActivity != topTaskActivity)) {         
            mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
            mWindowManager.executeAppTransition();
        } else {
            if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                mTargetStack.moveToFront("startActivityUnchecked");
            }
            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                    mOptions);
        }
    } else {
        mTargetStack.addRecentActivityLocked(mStartActivity);
    }
    mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

    mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
            preferredLaunchDisplayId, mTargetStack.mStackId);

    return START_SUCCESS;
}

先把ActivityStarter.startActivityUnchecked()函数的代码贴出来,然后慢慢分析,假设我们要从Launcher中启动Settings:
(1)setInitialState():

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

    //要启动的Activity的ActivityRecord,即Settings
    mStartActivity = r;
    
    //Settings的intent
    mIntent = r.intent;
    
    //Activity启动动画,可以忽略
    mOptions = options;
    mCallingUid = r.launchedFromUid;
    
    //调用者的ActivityRecord,也就是Launcher
    mSourceRecord = sourceRecord;
    
    //下面4个属性可以忽略
    mVoiceSession = voiceSession;
    mVoiceInteractor = voiceInteractor;
    mSourceDisplayId = getSourceDisplayId(mSourceRecord, mStartActivity);
    mLaunchBounds = getOverrideBounds(r, options, inTask);

    //启动模式:single_top
    mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;

    //启动模式:single_instance
    mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;

    //启动模式:single_task
    mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;

    //调整mLaunchFlags;
    //(1)如果此时的启动模式是single_instance或者是single_task,Intent.FLAG_ACTIVITY_NEW_DOCUMENT和FLAG_ACTIVITY_MULTIPLE_TASK标签无效
    //(2)将documentLaunchMode转化成intent中相应的flag
    mLaunchFlags = adjustLaunchFlagsToDocumentMode(
            r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());

    mLaunchTaskBehind = r.mLaunchTaskBehind
            && !mLaunchSingleTask && !mLaunchSingleInstance
            && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;

    sendNewTaskResultRequestIfNeeded();

    if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {//忽略
        mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
    }

    if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {//忽略
        if (mLaunchTaskBehind
                || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
            mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
        }
    }

    //如果设置了这个标志,可以在避免用户离开当前Activity时回调onUserLeaveHint()
    mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;

    mDoResume = doResume;//mDoResume为true
    if (!doResume || !r.okToShowLocked()) {//不成立
        r.delayedResume = true;
        mDoResume = false;
    }

    //动画参数,忽略
    if (mOptions != null && mOptions.getLaunchTaskId() != -1
            && mOptions.getTaskOverlay()) {
       ............
    }

    //使用这个标记启动的Activity会被自己立即终止。
    mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;

    mInTask = inTask;//mInTask为null
 
    if (inTask != null && !inTask.inRecents) {//不成立
        mInTask = null;
    }

    mStartFlags = startFlags;

    if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {//不成立
        ............
    }

    //Activity启动的时候不执行动画
    mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
}

点评:setInitialState()方法初始化了一些属性,重要的属性有:
mStartActivity:            即Settings的ActivityRecord;
mSourceRecord:          Launcher的ActivityRecord;
mLaunchSingleTop:       是否是singleTop启动模式;
mLaunchSingleInstance:  singleInstance启动模式;
mLaunchSingleTask:      singleTask启动模式;

(2)computeLaunchingTaskFlags():

private void computeLaunchingTaskFlags() {
    if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {//不成立
        ............
    } else {
        mInTask = null;
        if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
                && mSourceRecord.isFreeform())  {
            mAddingToTask = true;
        }
    }

    if (mInTask == null) {
        if (mSourceRecord == null) {//不成立
            if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
            }
        } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
        } else if (mLaunchSingleInstance || mLaunchSingleTask) {
            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
        }
    }
}


点评:将启动模式SingleInstance或者SingleTask转化成FLAG_ACTIVITY_NEW_TASK标签,保存在mLaunchFlags;

(3)computeSourceStack():

private void computeSourceStack() {
    if (mSourceRecord == null) {
        mSourceStack = null;
        return;
    }
    if (!mSourceRecord.finishing) {//成立
        mSourceStack = mSourceRecord.getStack();
        return;
    }
    .........
}

点评:初始化了mSourceStack;

(4)ActivityRecord reusedActivity = getReusableIntentActivity();

private ActivityRecord getReusableIntentActivity() {
    //如果要让putIntoExistingTask为true,那么下面三种情况可满足这个条件:
    //(1)当启动模式为SingleInstance;
    //(2)当启动模式为singleTask;
    //(3)使用了Intent.FLAG_ACTIVITY_NEW_TASK标签,并且没有使用FLAG_ACTIVITY_MULTIPLE_TASK标签
    boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
            (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)//成立
            || mLaunchSingleInstance || mLaunchSingleTask;
    putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;//成立
    ActivityRecord intentActivity = null;
    if (mOptions != null && mOptions.getLaunchTaskId() != -1) {//不成立
        final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
        intentActivity = task != null ? task.getTopActivity() : null;
    } else if (putIntoExistingTask) {
        if (mLaunchSingleInstance) {//启动模式为SingleInstance
           //找到与mIntent相同ComponentName的Activity;
           intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
                   mStartActivity.isHomeActivity());
        } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {//忽略
            intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
                    !mLaunchSingleTask);
        } else {//启动模式为singleTask或者使用了Intent.FLAG_ACTIVITY_NEW_TASK标签
            //遍历所有的栈,找到rootAffinity与Settings的taskAffinity相同的栈,返回的intentActivity是栈中的第一个Activity
            intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
        }
    }
    return intentActivity;
}

点评:当启动模式为SingleInstance时:
调用mSupervisor.findActivityLocked():

ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
                                  boolean compareIntentFilters) {
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
        final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
        //遍历所有的ActivityStack
        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
            //到ActivityStack中去寻找匹配的ActivityRecord
            final ActivityRecord ar = stacks.get(stackNdx)
                    .findActivityLocked(intent, info, compareIntentFilters);
            if (ar != null) {
                return ar;
            }
        }
    }
    return null;
}

看下ActivityStack是怎么寻找的:

ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
                                  boolean compareIntentFilters) {
    ComponentName cls = intent.getComponent();
    if (info.targetActivity != null) {//当匹配该intent的Activity不止一个的时候,可以指定targetActivity
        cls = new ComponentName(info.packageName, info.targetActivity);
    }
    final int userId = UserHandle.getUserId(info.applicationInfo.uid);

    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.okToShowLocked()) {
                continue;
            }
            if (!r.finishing && r.userId == userId) {
                if (compareIntentFilters) {
                    if (r.intent.filterEquals(intent)) {
                        return r;
                    }
                } else {
                    //找到class一样的Activity
                    if (r.intent.getComponent().equals(cls)) {
                        return r;
                    }
                }
            }
        }
    }

    return null;
}

对于启动模式为SingleInstance的Activity来说,找到Intent中相同的Component才算是找到可以复用的Activity;

当启动模式为singleTask或者同时使用了Intent.FLAG_ACTIVITY_NEW_TASK时,调用mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId):

ActivityRecord findTaskLocked(ActivityRecord r, int displayId) {
    mTmpFindTaskResult.r = null;
    mTmpFindTaskResult.matchedByRootAffinity = false;
    ActivityRecord affinityMatch = null;
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
        final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
        //遍历所有的ActivityStack
        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = stacks.get(stackNdx);
            if (!checkActivityBelongsInStack(r, stack)) {
                continue;
            }
            //由ActivityStack去寻找合适的Task,并将结果保存在mTmpFindTaskResult中
            stack.findTaskLocked(r, mTmpFindTaskResult);
            //mTmpFindTaskResult.r != null,表示已经查找到了可以复用的ActivityStack
            if (mTmpFindTaskResult.r != null) {
                if (!mTmpFindTaskResult.matchedByRootAffinity) {//不成立
                    ............
                } else if (mTmpFindTaskResult.r.getDisplayId() == displayId) {//成立
                    //返回满足条件的ActivityRecord,作为可以复用的Activity或者栈
                    affinityMatch = mTmpFindTaskResult.r;
                }
            }
        }
    }
    .........
    return affinityMatch;
}

看下ActivityStack的查找:

void findTaskLocked(ActivityRecord target, FindTaskResult result) {
    Intent intent = target.intent;
    ActivityInfo info = target.info;
    ComponentName cls = intent.getComponent();
    if (info.targetActivity != null) {//如果有targetActivity
        cls = new ComponentName(info.packageName, info.targetActivity);
    }
    final int userId = UserHandle.getUserId(info.applicationInfo.uid);
    boolean isDocument = intent != null & intent.isDocument();

    Uri documentData = isDocument ? intent.getData() : null;

    //遍历所有的栈
    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) {
            continue;
        }

        //得到栈中第一个没有被正在finish的ActivityRecord
        final ActivityRecord r = task.getTopActivity(false /* includeOverlays */);
        if (r == null || r.finishing || r.userId != userId ||
                r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
            continue;
        }

        //Activity的类型必须得一致
        if (r.mActivityType != target.mActivityType) {
            continue;
        }

        //taskIntent为task的intent
        final Intent taskIntent = task.intent;
        //affinityIntent为task的affinityIntent
        final Intent affinityIntent = task.affinityIntent;
        .........
        if (taskIntent != null && taskIntent.getComponent() != null &&
                taskIntent.getComponent().compareTo(cls) == 0 &&
                Objects.equals(documentData, taskDocumentData)) {
            .........
        } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
                affinityIntent.getComponent().compareTo(cls) == 0 &&
                Objects.equals(documentData, taskDocumentData)) {
            .........
        } else if (!isDocument && !taskIsDocument
                && result.r == null && task.rootAffinity != null) {//看这个判断
            //栈名一致, 满足
            if (task.rootAffinity.equals(target.taskAffinity)) {
                result.r = r;
                result.matchedByRootAffinity = true;
            }
        }
    }
}

从上面的代码可以看出,可以被复用的栈必须满足以下条件:
(1)栈中有一个没有被finish的Activity;
(2)栈中第一个没有被正在finish的Activity与要启动的Activity的type必须一样;
(3)该栈的栈名必须与要启动的Activity的栈名一致;
总结:当启动模式为SingleInstance或者singleTask,又或者使用了Intent.FLAG_ACTIVITY_NEW_TASK标签时才会去寻找可以复用的Actiivty或者栈;
启动模式为SingleInstance:在所有的Activity中寻找与Intent相同Component的Activity,找到了才算是找到可以复用的Activity;
当启动模式为SingleTask,或者使用了Intent.FLAG_ACTIVITY_NEW_TASK标签:在所有的栈中寻找rootAffinity与Settings的taskAffinity相同的栈,一旦找到,就返回栈顶的Activity;
也就是,一个是找Activity,一个是找栈;

(5)接下来就是处理FLAG_ACTIVITY_CLEAR_TOP标签了:
注意:当启动模式为SingleInstance或者SingleTask时,就默认为有FLAG_ACTIVITY_CLEAR_TOP标签,也就是说,光有Intent.FLAG_ACTIVITY_NEW_TASK标签而没有FLAG_ACTIVITY_CLEAR_TOP标签,是没有cleanTop功能的;
来看下是怎么cleanTop的:

final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,mLaunchFlags);
ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
    mReuseTask = true;
    final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
    mReuseTask = false;
    return result;
}

final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
    int numActivities = mActivities.size();
    for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
        ActivityRecord r = mActivities.get(activityNdx);
        if (r.finishing) {
            continue;
        }
        //如果Settings之前已经就存在于栈中了,那就finish掉栈中位于Settings前面的Acvitivty
        if (r.realActivity.equals(newR.realActivity)) {
            final ActivityRecord ret = r;

            for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
                r = mActivities.get(activityNdx);
                if (r.finishing) {
                    continue;
                }
                ActivityOptions opts = r.takeOptionsLocked();
                if (opts != null) {
                    ret.updateOptionsLocked(opts);
                }
                if (mStack != null && mStack.finishActivityLocked(
                        r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
                    --activityNdx;
                    --numActivities;
                }
            }

            //ActivityInfo.LAUNCH_MULTIPLE表示启动模式为标准模式;
            //下面的判断如果成立,那就表示一个正常启动的Activity如果含有FLAG_ACTIVITY_CLEAR_TOP标签,那它会将自己以及位于它前面的Activity全部给finish掉
            if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
                    && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
                    && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
                if (!ret.finishing) {
                    if (mStack != null) {
                        mStack.finishActivityLocked(
                                ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
                    }
                    return null;
                }
            }

            return ret;
        }
    }

    return null;
}

(6)再接下来,就是将目标ActivityStack和Task移动到前台:
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);

private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
    mTargetStack = intentActivity.getStack();
    mTargetStack.mLastPausedActivity = null;
    final ActivityStack focusStack = mSupervisor.getFocusedStack();
    //获取最近使用的Activity,也就是Launcher
    ActivityRecord curTop = (focusStack == null)
            ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);

    //获取Launcher所在的栈
    final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
    //Settings所在栈和Launcher所在栈不同,所以下面的判断是成立的
    if (topTask != null
            && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
            && !mAvoidMoveToFront) {//成立
        //给Settings添加Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT标签
        mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
        if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
                mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {//成立
            if (mLaunchTaskBehind && mSourceRecord != null) {
                intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
            }
            mMovedOtherTask = true;

            //如果一个Activity既存在FLAG_ACTIVITY_NEW_TASK标签又存在FLAG_ACTIVITY_CLEAR_TASK标签,那就表示它要将栈中的元素全部清楚,那也就是说,
            //不需要将该Activity的所在栈移动到前台了
            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.getTask(), mOptions);
                //intentTask是之前找到的可复用的栈
                final TaskRecord intentTask = intentActivity.getTask();
                if (launchStack == null || launchStack == mTargetStack) {//成立
                    //通过insertTaskAtTop()将目标栈移动到前台
                    mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
                            mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
                    mMovedToFront = true;
                } else if (launchStack.mStackId == DOCKED_STACK_ID
                        || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
                    if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
                        intentTask.reparent(launchStack.mStackId, ON_TOP,
                                REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
                                "launchToSide");
                    } else {
                        mTargetStack.moveTaskToFrontLocked(intentTask,
                                mNoAnimation, mOptions, mStartActivity.appTimeTracker,
                                "bringToFrontInsteadOfAdjacentLaunch");
                    }
                    mMovedToFront = true;
                } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
                    intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
                            REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
                            "reparentToDisplay");
                    mMovedToFront = true;
                } else if (launchStack.getStackId() == StackId.HOME_STACK_ID
                    && mTargetStack.getStackId() != StackId.HOME_STACK_ID) {
                    intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
                            REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
                            "reparentingHome");
                    mMovedToFront = true;
                }
                mOptions = null;
                intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
                        true /* taskSwitch */);
            }
            updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
        }
    }
    if (!mMovedToFront && mDoResume) {//成立
        //将目标ActivityStack移动前台
        mTargetStack.moveToFront("intentActivityFound");
    }

    mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
            DEFAULT_DISPLAY, mTargetStack.mStackId);

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

可以看到,setTargetStackAndMoveToFrontIfNeeded()函数的作用,就是将Settings所在的ActivityStack移动到前台,并且将Settings所在栈移动到ActivityStack的顶部;
(7)处理一些特殊的标签,判断是否要将Activity添加进栈中;
setTaskFromIntentActivity(reusedActivity):

private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
    if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {//如果含有NEW_TASK和CLEAR_TASK标签
        final TaskRecord task = intentActivity.getTask();
        //清除栈中所有的Activity
        task.performClearTaskLocked();
        mReuseTask = task;
        mReuseTask.setIntent(mStartActivity);

        mMovedOtherTask = true;
    } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
            || mLaunchSingleInstance || mLaunchSingleTask) {//如果含CLEAR_TOP标签,或者启动模式为singleTask或者singleInstance
        //将栈中位于mStartActivity前面的Activity全部清除
        ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
                mLaunchFlags);
        if (top == null) {//如果top == null,那就表示栈中之前不存在mStartActivity,也就是Settings之前没有启动过
            //要将Settings添加进栈中
            mAddingToTask = true;

            //不再将Settings放在我们以前认为的栈中
            mStartActivity.setTask(null);

            //现在假设Settings是由其栈的顶部启动的,那mSourceRecord就等于初始化栈中(未清除)的栈顶Activity;
            //比如,刚开始的时候,栈P中的Activity从下往上排列依次有A,B,C,D;现在要启动B,B的启动模式为SingleTask,那么此时栈P中只存在A和B;
            //intentActivity就是我们之前在可复用栈,也就是栈P的栈顶Activity D,所以,mSourceRecord为D;
            mSourceRecord = intentActivity;
            final TaskRecord task = mSourceRecord.getTask();
            if (task != null && task.getStack() == null) {
                mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
                        null /* bounds */, mLaunchFlags, mOptions);
                mTargetStack.addTask(task,
                        !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
            }
        }
    } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
        //上面这个判断表示,要启动的Activity已经位于栈底;
        //如果我们使用的是singleTask或者singleInstance,那此时栈中只有一个元素,就是mStartActivity自己;
        //如果我们使用的是NEW_TASK标签,那此时栈中还有其他元素
        if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
                && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
            //上面这个判断表示,如果启动模式为SingleTop,并且要启动的Activity已经位于栈顶
            if (intentActivity.frontOfTask) {
                intentActivity.getTask().setIntent(mStartActivity);
            }
            //那就不重新启动Activity了,直接调用onNewIntent
            deliverNewIntent(intentActivity);
        } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
            mAddingToTask = true;
            mSourceRecord = intentActivity;
        }
    } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
        mAddingToTask = true;
        mSourceRecord = intentActivity;
    } else if (!intentActivity.getTask().rootWasReset) {
        intentActivity.getTask().setIntent(mStartActivity);
    }
}

(8)接下来就是处理SingleTop启动模式,要想SingleTop起作用,那要启动的Activity必须已经位于栈顶;
当启动模式为SingleTop,或者SingleTask,或者含有SINGLE_TOP标签,并且要启动的Activity又已经位于栈顶时,那就执行onNewIntent()方法;
(9)再接着,就是要开始创建栈或者绑定栈了;
先处理FLAG_ACTIVITY_NEW_TASK标签,含有此标签,表示可能会需要创建一个新栈;

result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, preferredLaunchStackId, topStack):

private int setTaskFromReuseOrCreateNewTask(
        TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
    mTargetStack = computeStackFocus(
            mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);

    if (mReuseTask == null) {//如果不含有FLAG_ACTIVITY_CLEAR_TASK标签,那么mReuseTask == null
        //创建一个栈TaskRecord,并把该TaskRecord加入到ActivityStack的顶部
        final TaskRecord task = mTargetStack.createTaskRecord(
                mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
                mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
                mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
        //task是一个新栈
        addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
        if (mLaunchBounds != null) {
            final int stackId = mTargetStack.mStackId;
            if (StackId.resizeStackWithLaunchBounds(stackId)) {
                mService.resizeStack(
                        stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
            } else {
                mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
            }
        }
    } else {//mReuseTask != null,意味着含有FLAG_ACTIVITY_CLEAR_TASK标签,
        // 那就表示此时的mReuseTask栈已经被清除干净了,直接将Settings加入到mReuseTask栈中;
        //此后,mReuseTask中只有一个元素,就是mStartActivity,也就是Settings
        addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
    }

    if (taskToAffiliate != null) {
        mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
    }

    if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
        return START_RETURN_LOCK_TASK_MODE_VIOLATION;
    }

    if (!mMovedOtherTask) {
        updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
                preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
    }
    if (mDoResume) {
        mTargetStack.moveToFront("reuseOrNewTask");
    }
    return START_SUCCESS;
}
private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
    if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
        //如果即将启动的Settings没有栈,或者Settings的栈就是新栈,那就将Settings加入到新栈的栈顶
        parent.addActivityToTop(mStartActivity);
    } else {
        //如果即将启动的Settings已经被绑定了栈,之前的栈和新栈不同,那就得将Settings从旧栈中移除,并移动到新栈;
        //举个例子:栈A中有a,b,c三个Activity,这3个Activity从上到下依次排列,a在栈顶,他们的taskAffinity是"a";
        //在Activity a中再次启动Activity b,启动模式为singleTask,不过给b指定了taskAffinity为"b",此时会出现什么情况呢?
        //由于Activity b先前在栈a中,也就是与栈a进行了绑定了,现在要先将Activity b从栈a中移除,然后再将它添加到栈b中
        mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
    }
}

(10)来看下正常情况下的绑定:
result = setTaskFromSourceRecord();
 

private int setTaskFromSourceRecord() {
    if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
        Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
        return START_RETURN_LOCK_TASK_MODE_VIOLATION;
    }
    String packageName = mService.mContext.getPackageName();
    if (mPerf != null) {
        mStartActivity.perfActivityBoostHandler =
            mPerf.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, packageName, -1, BoostFramework.Launch.BOOST_V1);
    }
    final TaskRecord sourceTask = mSourceRecord.getTask();
    final ActivityStack sourceStack = mSourceRecord.getStack();
    // We only want to allow changing stack in two cases:
    // 1. If the target task is not the top one. Otherwise we would move the launching task to
    //    the other side, rather than show two side by side.
    // 2. If activity is not allowed on target display.
    final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
            : sourceStack.mDisplayId;
    //我们在前面已经将要启动的Activity所在栈移动到前台了,所以,sourceStack.topTask()就是要启动的Activity所在栈;
    //正常情况下,sourceTask就是调用者,如本例中的Launcher,所以,sourceStack.topTask() != sourceTask;
    //但也有特殊情况,如果启动模式为singleTask,栈中又不存在相同的Activity时,mSourceRecord就是栈顶的Activity,sourceStack.topTask() == sourceTask
    final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
            || !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
    if (moveStackAllowed) {
        mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
                mOptions);
        // If target stack is not found now - we can't just rely on the source stack, as it may
        // be not suitable. Let's check other displays.
        if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
            // Can't use target display, lets find a stack on the source display.
            mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
                    sourceStack.mDisplayId, mStartActivity);
        }
        if (mTargetStack == null) {
            // There are no suitable stacks on the target and source display(s). Look on all
            // displays.
            mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
                    mStartActivity, -1 /* currentFocus */);
        }
    }

    if (mTargetStack == null) {//不成立
        mTargetStack = sourceStack;
    } else if (mTargetStack != sourceStack) {//也不成立
        sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
                !ANIMATE, DEFER_RESUME, "launchToSide");
    }

    final TaskRecord topTask = mTargetStack.topTask();
    //两个栈不同,得把相应的栈移动到前台
    if (topTask != sourceTask && !mAvoidMoveToFront) {
        mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
                mStartActivity.appTimeTracker, "sourceTaskToFront");
    } else if (mDoResume) {
        mTargetStack.moveToFront("sourceStackToFront");
    }

    //处理FLAG_ACTIVITY_CLEAR_TOP标签
    if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
        // In this case, we are adding the activity to an existing task, but the caller has
        // asked to clear that task if the activity is already running.
        ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
        mKeepCurTransition = true;
        if (top != null) {
            ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
            deliverNewIntent(top);
            // For paranoia, make sure we have correctly resumed the top activity.
            mTargetStack.mLastPausedActivity = null;
            if (mDoResume) {
                mSupervisor.resumeFocusedStackTopActivityLocked();
            }
            ActivityOptions.abort(mOptions);
            return START_DELIVERED_TO_TOP;
        }
    } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
        // In this case, we are launching an activity in our own task that may already be
        // running somewhere in the history, and we want to shuffle it to the front of the
        // stack if so.
        final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
        if (top != null) {
            final TaskRecord task = top.getTask();
            task.moveActivityToFrontLocked(top);
            top.updateOptionsLocked(mOptions);
            ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
            deliverNewIntent(top);
            mTargetStack.mLastPausedActivity = null;
            if (mDoResume) {
                mSupervisor.resumeFocusedStackTopActivityLocked();
            }
            return START_DELIVERED_TO_TOP;
        }
    }

    // An existing activity is starting this new activity, so we want to keep the new one in
    // the same task as the one that is starting it.
    //将Activity添加到相应的Task
    addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
    if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
            + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
    return START_SUCCESS;
}

 

总结:今天是过年放假前的最后一天工作日,实在是没有心情写了,下午还得解一个bug;

关于AMS中的启动模式分析,断断续续的写了一周左右,暂时就先分析到这里了,后面会结合实际情况,再来个大的总结;

完结,撒花!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

renshuguo123723

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值