深入AMS源碼(二)—— ActivityManagerService對Activity的調度管理

1、概述

在上一篇深入AMS源碼(一)——ActivityManagerService的基礎知識文章介紹了AMS的基礎信息,主要包括AMS中主要的數據結構、主要功能類和屬性以及AMS中對生命週期的調度方式,本篇主要從源碼的角度分析下AMS對Activity的調度邏輯,這也是AMS的主要功能;

2、源碼分析

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
        boolean validateIncomingUser) {
    userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
    return mActivityStartController.obtainStarter(intent, "startActivityAsUser”)  // 創建ActivityStarter對象
            .setCaller(caller) // 設置回調的Application對象
            .setCallingPackage(callingPackage) // 設置發起請求的包名
            .setResolvedType(resolvedType)
            .setResultTo(resultTo) // 設置setResult返回數據的Record對象,即調用startActivityForResult()的活動
            .setResultWho(resultWho) 
            .setRequestCode(requestCode) // 設置請求碼
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(bOptions)
            .setMayWait(userId) // 所屬用戶ID
            .execute(); // 執行execute()
}

最終在startActivityAsUser()方法中,執行mActivityStartController.obtainStarter()創建ActivityStarter對象並初始化數據,調用execute()程序進入ActivityStarter類中

int execute() {
    try {
        if (mRequest.mayWait) {  //首次進入執行mayWait()
            return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                  …….
            mRequest.allowPendingRemoteAnimationRegistryLookup);
        } else {
            return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                  …….
            mRequest.allowPendingRemoteAnimationRegistryLookup);
        }
    } 
}

在設置userId是已經將mayWait設置爲true了,所以execute()中會執行startActivityMayWait()方法

 final int startActivityMayWait(){
boolean componentSpecified = intent.getComponent() != null; // 1、
 
final int realCallingPid = Binder.getCallingPid(); // 獲取當前進程的Uid
final int realCallingUid = Binder.getCallingUid();
final Intent ephemeralIntent = new Intent(intent); // 創建備份的Intent
intent = new Intent(intent); // 創建新的intent

 //(2)
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
        0 /* matchFlags */,computeResolveFilterUid(callingUid, realCallingUid, mRequest.filterCallingUid));
        
//(3)
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
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);

在startActivityMayWait()中主要執行四個操作

  1. 判斷當前Intent中是否含有數據,並創建新的Intent對象封裝數據
  2. 校驗PMS中掃描到的mActivities集合中能處理Intent的ResolveInfo,查詢不到則失敗;
  3. 查找啓動的目標活動對應的ActivityInfo
  4. 調用startActivity()執行Activity啓動
  • mSupervisor.resolveIntent()
mService.getPackageManagerInternalLocked().resolveIntent( 
        intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
PackageManagerInternal getPackageManagerInternalLocked() {
    if (mPackageManagerInt == null) {
        mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class); // 獲取PackageManagerInternalImpl()
    }
    return mPackageManagerInt;
}

在PMS啓動完成後,會使用LocalService註冊PackageManagerInternalImpl()對象,它是PMS的內部類;

LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());

通過LocalServices對象調用的實際是PackageManagerInternalImpl.resolveIntent()中的方法,resolveIntent()中又調用resolveIntentInternal()方法

private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
        int flags, int userId, boolean resolveForStart, int filterCallingUid) {
    try {
        if (!sUserManager.exists(userId)) return null; // 1、檢查程序的userId
        final int callingUid = Binder.getCallingUid();
        flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart);//2、更新Flag
        mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
       //3、從PMS遍歷後保存的Intent-filter結合中查詢能處理Intent的ResolveInfo的集合
        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
                flags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/); 
      
        final ResolveInfo bestChoice =
                chooseBestActivity(intent, resolvedType, flags, query, userId);//4、匹配最好的ResolveInfo
        return bestChoice; // 返回ResolveInfo
    } 
}

在resolveIntentInternal()中回調用queryIntentActivitiesInternal()查詢匹配的集合,這裏實際是通過PMS中完成的,PMS中會遍歷保存的四大組件信息的集合匹配能處理的信息對象,具體匹配細節見另一篇問文章深入PMS源碼(三)—— PMS中intent-filter的匹配架構,在匹配成功後返回一個符合條件的集合,然後調用chooseBestActivity選擇並返回最合適的ResolveInfo對象,之後繼續執行下面的resolveActivity()

  • mSupervisor.resolveActivity()
ActivityInfo resolveActivity(Intent intent, ResolveInfo rInfo, int startFlags,
        ProfilerInfo profilerInfo) {
    final ActivityInfo aInfo = rInfo != null ? rInfo.activityInfo : null; // 1、獲取其中的ActivityInfo對象
    if (aInfo != null) {
        intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));//2、設置Component對象
        final String intentLaunchToken = intent.getLaunchToken();
        if (aInfo.launchToken == null && intentLaunchToken != null) {
            aInfo.launchToken = intentLaunchToken;
        }
    }
    return aInfo; // 返回aInfo對象
}

resolveActivity()中邏輯很簡單,根據查詢獲取到的ResolveInfo獲取其中的ActivityInfo對象,並將信息封裝在Component對象中,最後賦值給Intent對象,此時Component中就包含着要啓動的真正對象;

  • startActivity()
ProcessRecord callerApp =  mService.getRecordForAppLocked(caller); // 1、

ActivityRecord sourceRecord = null; // 保存請求啓動的父Activity
ActivityRecord resultRecord = null; // 保存結果返回的resultCode
if (resultTo != null) { // 處理resultTo回傳數據
    sourceRecord = mSupervisor.isInAnyStackLocked(resultTo); //  2、
    if (sourceRecord != null) {
        if (requestCode >= 0 && !sourceRecord.finishing) {
            resultRecord = sourceRecord; // 默認賦值resultRecord爲啓動者所在的棧
        }
    }
}
 int launchFlags = intent.getFlags(); // 3、
 //Intent.FLAG_ACTIVITY_FORWARD_RESULT:處理跨Activity回傳結果問題,這裏主要針對在第一個Activity啓動但需要在第三個activity返回數據
if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
 ……….
}
//初始化ActivityStack,默認使用resultRecord中TaskStack所屬的管理類
final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho, // 4、
        requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
        inTask != null, callerApp, resultRecord, resultStack); 
if (mService.mController != null){// 5、
Intent watchIntent = intent.cloneFilter();
abort |= !mService.mController.activityStarting(watchIntent,aInfo.applicationInfo.packageName);
}  
mInterceptor.intercept(..) // 執行攔截器的intercept()
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,  //6、
        callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
        resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
        mSupervisor, checkedOptions, sourceRecord);
final ActivityStack stack = mSupervisor.mFocusedStack; // 獲取當前交互的ActivityStack
// 7、
If(!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start”) ){
   mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
        sourceRecord, startFlags, stack, callerApp));
}
mController.doPendingActivityLaunchesLocked(false); // 8、
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
        true /* doResume */, checkedOptions, inTask, outActivity); // 9、

在startActivity()中執行了許多主要的功能,具體如下:

  1. 根據調用傳入的IApplication對象,從AMS的mLruProcesses集合中獲取當前進程信息;
  2. 根據保存的resultTo取出要回傳數據的Record,即發起啓動的Activity,主要針對setActivityForRequest()方法
  3. 獲取設置的Flag信息,處理跨Activity回傳信息標識
  4. 初始化ActivityStack對象,執行檢查權限信息
  5. 執行AMS中的IActivityController對象,主要用於監聽AMS啓動過程
  6. 創建臨時的ActivityRecord信息保存所有的請求信息
  7. 檢驗是否允許切換活動,如果當前進程暫停切換,則創建延遲意圖PendingIntent保存啓動信息,添加到mPendingActivityLaunches集合中;
  8. 判斷mPendingActivityLaunches是否有任務,優先執行存在的延時任務
  9. 通過上面的層層檢查後,調用startActivity方法啓動活動
  • startActivity()
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
    int result = START_CANCELED;
    try {
        mService.mWindowManager.deferSurfaceLayout(); // 調用WindowManager處理繪製
        result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, doResume, options, inTask, outActivity); //調用startActivityUnchecked()
    } finally {.
        final ActivityStack stack = mStartActivity.getStack();
        if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {
            stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
                    null /* intentResultData */, "startActivity", true /* oomAdj */);
        }
        mService.mWindowManager.continueSurfaceLayout();
    }
    postStartActivityProcessing(r, result, mTargetStack); 
    return result;
}
  • startActivityUnchecked():主要執行功能
 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
        voiceInteractor); // 1、初始化ActivityStarter每個屬性信息
computeLaunchingTaskFlags(); //2、計算目標活動的Flag
computeSourceStack(); // 3、計算活動的任務棧Stack
mIntent.setFlags(mLaunchFlags); 設置新的Flag
ActivityRecord reusedActivity = getReusableIntentActivity(); //4、從mHistory歷史棧中匹配已經存在的Record對象,準備複用此對象
if (reusedActivity != null) {
if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {
    mStartActivity.setTask(reusedActivity.getTask()); // 設置目標活動棧爲要複用Activity的所在stack棧
}
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
        || isDocumentLaunchesIntoExisting(mLaunchFlags)
        || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {// 5、處理clearTop模式,清空之上的Record
    final TaskRecord task = reusedActivity.getTask();
    final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
            mLaunchFlags); //移除目標mStartActivity之上的活動,返回目標record;
if (top.frontOfTask) {
    top.getTask().setIntent(mStartActivity); // 如果top爲棧中第一個則設置啓動的ActiivityRecord
}
// 6、找到要複用目標所在的棧,並將其移動到ActivityStack的最上面,同時設置mFocusStack;
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);

 final ActivityRecord outResult = // 取出要啓動的目標Activity
                    outActivity != null && outActivity.length > 0 ? outActivity[0] : null;

if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { // 7、只需將Activity放置在前臺,不需要啓動(桌面點擊已啓動程序圖標時)
    resumeTargetStackIfNeeded();
    return START_RETURN_INTENT_TO_CALLER;
}
setTaskFromIntentActivity(reusedActivity); // 8、根據mLaunchFlags和resumeActiivity處理最終的Task的選擇

//取出當前活動棧頂的ActivityRecord
final ActivityStack topStack = mSupervisor.mFocusedStack;
final ActivityRecord topFocused = topStack.getTopActivity(); // 從mHistory中獲取最頂的Activity
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); //9、
final boolean dontStart = top != null && mStartActivity.resultTo == null  // 此時topActivity和目標Activity一致
        && top.realActivity.equals(mStartActivity.realActivity)
        && top.userId == mStartActivity.userId
        && top.app != null && top.app.thread != null
        && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
        || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
if (dontStart) 
    if (mDoResume) {
        mSupervisor.resumeFocusedStackTopActivityLocked();//此時只需要將要重用的ActivityRecord,重新resume即可
    }
    deliverNewIntent(top); //發送NewIntent
    return START_DELIVERED_TO_TOP;
}
boolean newTask = false;
int result = START_SUCCESS; //10、對於沒有複用的模式,處理要啓動Activity的Task
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
    newTask = true;
    result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);//創建新的TaskRecord
} else if (mSourceRecord != null) {
    result = setTaskFromSourceRecord(); // 從mSourceRecord中獲取stack,並將stack移動到最前端
} else if (mInTask != null) {
    result = setTaskFromInTask(); // 從mInTask中獲取task
} else {
    setTaskToCurrentTopOrCreateNewTask(); // 其他情況處理
}
if (result != START_SUCCESS) {
    return result;
}
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
        mOptions); // 12、對與沒有或不能複用的情況,直接啓動Activity實例
}

startActivityUnchecked()方法很長,但其中的功能很主要,下面一一分析相應的功能邏輯:

  1. 調用setInitialState()方法,根據現有信息重新設置成員屬性
private void setInitialState() {
reset(false /* clearRequest */); // 重置ActivityStarter對象屬性
mStartActivity = r;
mIntent = r.intent;
mOptions = options;
mCallingUid = r.launchedFromUid;
mSourceRecord = sourceRecord;
mVoiceSession = voiceSession;
mVoiceInteractor = voiceInteractor;
mLaunchMode = r.launchMode;//初始化launchMode
mLaunchFlags = adjustLaunchFlagsToDocumentMode(r, LAUNCH_SINGLE_INSTANCE == mLaunchMode, // 根據launchMode調整Flags
LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());
}
  1. 執行computeLaunchingTaskFlags()計算LaunchFlag中是否需要添加NewTask標誌
private void computeLaunchingTaskFlags() {
    if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
        final Intent baseIntent = mInTask.getBaseIntent();
        final ActivityRecord root = mInTask.getRootActivity();
if (root == null) { // 如果此時stack爲空,則將目標ActivityRecord作爲根Record
    final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
            | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
    mLaunchFlags = (mLaunchFlags & ~flagsOfInterest) | (baseIntent.getFlags() & flagsOfInterest);
    mIntent.setFlags(mLaunchFlags);
    mInTask.setIntent(mStartActivity); // 設置根Record對象
    mAddingToTask = true;
} else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
    mAddingToTask = false; // 對於NewTask設置爲false,創建新的NewTask
} else {
    mAddingToTask = true;
}
mReuseTask = mInTask;
}else {
            mInTask = null;
            if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
                    && mSourceRecord.inFreeformWindowingMode())  {
                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 (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
                mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
            }
        }

(1). 如果mInTask不爲空,則說名當前請求已經設置了要求加入的TaskStack中,然後判斷mInTask中是否爲空,如果爲空則將當前活動作爲根部活動保存ActivityRecord信息,如果mInTask不爲空且設置了NewTask標誌,則將mAddingToTask只爲false表示需要創建新的Task對象;
(2) 如果未制定mInTask對象,則判斷父類的Task是否可用,如果可用則將目標Activity啓動到父Activity的棧中;
(3) 最後設置mLaunchFlags屬性,如果mSourceRecord爲空、或父mSourceRecord指定Single_Instance模式、目標活動設置的Single模式,則添加NewTask標誌;
3. 調用computeSourceStack()處理父Activity棧的記錄問題

private void computeSourceStack() {
    if (!mSourceRecord.finishing) { // 獲取發起啓動Activity的所在棧
        mSourceStack = mSourceRecord.getStack();
        return;
    }
    if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) { // 處理NEW_TASK標誌啓動新的棧
        mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; // 添加NewTask標誌
        mNewTaskInfo = mSourceRecord.info; // 並保存原來的taskInfo、Intent
        final TaskRecord sourceTask = mSourceRecord.getTask();
        mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
    }
    mSourceRecord = null;
    mSourceStack = null;
}

如果mSourceRecord爲空直接返回null,如果mSourceRecord存在且沒有finish則獲取其所在的棧保存在mSourceStack中,如果父mSourceRecord的finishing爲true,則表示當前Activity即將銷燬,那就不能使用其所在的棧,此時會創建一個新棧對象然後保存mSourceRecord的棧信息;

  1. getReusableIntentActivity():查找是否存在可以複用的對象
private ActivityRecord getReusableIntentActivity() { // 設置NewTask但未設置MULTIPLE_TASK,此時可以複用Activity
boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&(mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)|| isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK); // 處理可以複用ActivityRecord的FLAG
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 (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
       intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
               mStartActivity.isActivityTypeHome()); // 針對Single_instance模式查找對應的ActivityRecord
    } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
        intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
                !(LAUNCH_SINGLE_TASK == mLaunchMode)); // 
    } else {
        intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId); //從歷史記錄中查找
    }
}
return intentActivity;
}

在getReusableIntentActivity()中,首先判斷是否設置NewTask但未設置MULTIPLE_TASK標誌、是否設置LAUNCH_SINGLE_INSTANCE或LAUNCH_SINGLE_TASK標誌,因爲這幾種情況下是可以從棧中複用Activity的,
(1)對於mOptions中設置了TaskId的,根據TaskId取出相應的task並獲取頂部的活動
(2)對於LAUNCH_SINGLE_INSTANCE模式的調用findActivityLocked()查找ActivityRecord
(3)對於其他的情況直接調用findTaskLocked()從歷史記錄中查找信息
5. 處理clearTop模式,清空之上的Record
6. setTargetStackAndMoveToFrontIfNeeded()將複用的棧移動到最頂部位置

private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
mTargetStack = intentActivity.getStack(); // 要查找的目標棧
final ActivityStack focusStack = mSupervisor.getFocusedStack();
ActivityRecord curTop = (focusStack == null)
        ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop); // 獲取當前棧,並從棧中獲取最頂層的ActivityRecord
final TaskRecord topTask = curTop != null ? curTop.getTask() : null; // 此時處於最上面的TaskRecord
if (topTask != null // 如果最頂部的TaskStack並不是目標需要的棧
        && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
        && !mAvoidMoveToFront) {
    mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); // 添加移動TaskRecord的標誌
mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions, // 將目標棧移動到棧頂
        mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
mMovedToFront = true;
}

在setTargetStackAndMoveToFrontIfNeeded()中查找到要複用的ActivityRecord所在的棧,然後獲取當正在交互的focusStack,如果二者不同則調用moveTaskToFrontLocked()將要複用的棧移動到ActivityStack的最前面;

  1. setTaskFromIntentActivity():處理TaskStack中的任務
private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {// 處理clear_task清空所在的棧task
    final TaskRecord task = intentActivity.getTask();
    task.performClearTaskLocked(); // 清空所有Record
    mReuseTask = task;
    mReuseTask.setIntent(mStartActivity); // 設置目標活動爲root ActivityRecord
} else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0 //clear_top
        || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
    ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,mLaunchFlags);
} else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
    if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                || LAUNCH_SINGLE_TOP == mLaunchMode)
            && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
        if (intentActivity.frontOfTask) {
            intentActivity.getTask().setIntent(mStartActivity); // 當前頂部的活動就是要啓動的目標活動
        }
        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);
}
}

在setTaskFromIntentActivity()中,如果設置了FLAG_ACTIVITY_CLEAR_TASK標誌,則清除棧中所有的ActivityRecord並將目標活動設置爲Task的根部活動,繼續處理CLEAR_TOP、FLAG_ACTIVITY_SINGLE_TOP標誌的清除工作;

  1. 調用topRunningNonDelayedActivityLocked()返回歷史記錄中最上面的可resume的ActivityRecord,前面的處理知道已經將複用的棧移動到最前面且清空了複用棧之上的所有ActivityRecord對象,那此時取出的就是要複用的對象,比較相應的模式和對象相等後此時只需將活動resume即可;
  2. 對於沒有複用的模式,處理要啓動Activity的Task,此處會針對情況創建新Task
  3. 對與沒有或不能複用的情況,直接啓動Activity創建新的實例

2.1 顯示覆用的活動

對於已經能複用且已經找到複用ActivityRecord對象的,直接調用ActivityStack的resumeTopActivityInnerLocked()實現Resume複用的ActivityRecord對象;

  • resumeTopActivityInnerLocked():
ActivityRecord next = topRunningActivityLocked(null); //1、
 if (next == null) {
    if (mMainStack) {
      return mService.startHomeActivityLocked(); // 
    }
}
 next.delayedResume = false;
// 2、
if (mResumedActivity == next && next.state == ActivityState.RESUMED)  { 
}
mStackSupervisor.mStoppingActivities.remove(next); // 3、
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);
if (!mStackSupervisor.allPausedActivitiesComplete()) {// 4、
    return false;
}
if (mResumedActivity != null) { // 5、
    pausing |= startPausingLocked(userLeaving, false, next, false); // 執行暫停
}
if (pausing && !resumeWhilePausing) {
    if (next.app != null && next.app.thread != null) {
        mService.updateLruProcessLocked(next.app, true, null); // 6、
    }
    return true;
} else if (mResumedActivity == next && next.isState(RESUMED)
        && mStackSupervisor.allResumedActivitiesComplete()) {
    return true;
}

在resumeTopActivityInnerLocked()中實現對父活動的暫停操作,和新Activity的resume過程:

  1. 獲取mHistory中第一個Activity,因爲前面已經將要啓動的目標添加爲第一個,此時如果mHistory中沒有活動記錄,則啓動Main界面;
  2. 判斷當前resumed的活動和目標活動是否一致,一致不做任何操作;
  3. 從Stop和WaitingVisiable集合中移除信息,因爲該活動即將被啓動;
  4. 判斷是否有活動正在停止,如果直接返回false,不能執行啓動任務
  5. 如果存在正在交互的活動,需要先暫停正在交互的活動
  6. 將要啓動的Activity所在的進程添加到mLruProcesses集合中

在執行上述過程後AMS中的處理過程就完成了,在第五步中判斷當前是否存在正在交互的活動,如果存在則先執行去暫停操作,即回調onPause()方法,AMS‘回到的方法使用LifecycleManager具體過程見AMS中Activity生命週期回調,方法會執行到ActivityThread中執行活動的handlePauseActivity()

@Override
public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
        int configChanges, PendingTransactionActions pendingActions, String reason) {
    ActivityClientRecord r = mActivities.get(token); // 從保存的Activity列表中返回
    if (r != null) {
        performPauseActivity(r, finished, reason, pendingActions); 
    }
}
  • performPauseActivity(): Android P 中處理Activity暫停的方法
if (!r.activity.mFinished && saveState) { // 對於pause的活動回調onSaveInstanceState()保存數據
       state = new Bundle();
       mInstrumentation.callActivitycallActivityOnSaveInstanceState(r.activity, state); 
       r.state = state; // 保存包含數據的state
 }
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity); // 調用onPause()
r.paused = true;

在performPauseActivity中首先回到Activity的callActivityOnSaveInstanceState()方法,大家都知道此方法是保存界面數據,在界面重建時可以回覆數據的,然後執行Activity的onPause()方法,在執行完之後會回調AMS.activityPaused()方法通知暫停結束,AMS可以繼續執行任務,在activityPaused()中調用了completePauseLocked()方法;

  • completePauseLocked():執行onPause()事件結束完畢後回調
 ActivityRecord prev = mPausingActivity; // 1、
boolean wasStopping = prev.isState(STOPPING);
prev.setState(PAUSED, "completePausedLocked");

prev.waitingVisible = false; // 設置狀態
mWaitingVisibleActivities.remove(prev);
if (prev.finishing) { // 結束當前Activity
    prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,"completedPausedLocked");
} 
if (prev.app != null) {
mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(prev)

if (!prev.visible || shouldSleepOrShutDownActivities()) {
    prev.setDeferHidingClient(false);
    addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */); //將執行了pause()的活動加入stopping集合中
}
   }
}
 mPausingActivity = null; // 指控mPausingActivity
if (resumeNext) { // 繼續處理目標Activity的Resume
    final ActivityStack topStack = mStackSupervisor.getFocusedStack();
    if (!topStack.shouldSleepOrShutDownActivities()) {
        mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null); // 執行Activity的resume()
    } else {
        ActivityRecord top = topStack.topRunningActivityLocked();
        if (top == null || (prev != null && top != prev)) {
        mStackSupervisor.resumeFocusedStackTopActivityLocked();
        }
    }
}

在completePauseLocked中獲取當前Pause的ActivityRecord,設置狀態屬性並清空mPausingActivity,如果ActivityRecord設置finish爲true則執行銷燬操作,然後調用addToStopping()將ActivityRecord加入到mStoppingActivities集合中,當存在需要啓動的活動時,會從棧頂取出ActivityRecord並執行resumeFocusedStackTopActivityLocked()方法顯示活動;

  • resumeTopActivityInnerLocked():在處理paused後會繼續執行resumeTopActivityInnerLocked(),此時傳入prev
if (prev != null && prev != next) {
    if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
            && next != null && !next.nowVisible) {
     mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev); // 加入 WaittingVisiable集合
    } else {
        if (prev.finishing) {
            prev.setVisibility(false);
    }
}
。。。。。。。
mService.mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE); // 處理WMS執行動畫窗口切換
 if (next.app != null && next.app.thread != null) { // 1、判斷目標活動的進程是否啓動,此時是Resumed的活動
if (!next.visible || next.stopped || lastActivityTranslucent) {
    next.setVisibility(true); // 設置visibility爲true
}
final ActivityState lastState = next.getState();
next.setState(RESUMED, "resumeTopActivityInnerLocked”); // 設置State爲resume
mService.updateLruProcessLocked(next.app, true, null); // 2、

final ClientTransaction transaction = ClientTransaction.obtain(next.app.thread,
        next.appToken);
transaction.addCallback(ActivityResultItem.obtain(a));
if (next.newIntents != null) {
    transaction.addCallback(NewIntentItem.obtain(next.newIntents,false /* andPause */));// 回調onNewIntent()
}
transaction.setLifecycleStateRequest(
        ResumeActivityItem.obtain(next.app.repProcState,
                mService.isNextTransitionForward()));
mService.getLifecycleManager().scheduleTransaction(transaction);// 3、
}else{
mStackSupervisor.startSpecificActivityLocked(next, true, true); //4、對於新創建的ActivityRecord,其中的app和app.thread = null
}

resumeTopActivityInnerLocked()中將prev對象加入 WaittingVisiable集合中,然後調用WMS處理窗口切換操作,最後執行顯示過程:

  1. 判斷目標活動的進程是否啓動,如果啓動則將可見性設爲true並更新ActivityRecord的狀態
  2. 更新最近使用的進程集合
  3. 執行調用ActivityThread的handleResumeActivity(),內部同樣使用LifecycleManager機制
  4. 對於新創建的ActivityRecord內部進程信息爲null,則調用startSpecificActivityLocked()方法處理
  • ActivityThread.handleResumeActivity
ActivityClientRecord r = performResumeActivity(token, clearHide); // 執行Activity的onResume()
View decor = r.window.getDecorView(); // 處理Window添加DecorView、Activity配置變化、輸入法等窗口問題
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
if (!a.mWindowAdded) {
    a.mWindowAdded = true;
    wm.addView(decor, l);
}
if ((l.softInputMode
        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
        != forwardBit) { // 處理輸入法對界面的改變
    l.softInputMode = (l.softInputMode
            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)) | forwardBit;
    if (r.activity.mVisibleFromClient) {
        ViewManager wm = a.getWindowManager();
        View decor = r.window.getDecorView();
        wm.updateViewLayout(decor, l);
    }
}
if (r.activity.mVisibleFromClient) {
    r.activity.makeVisible(); // 調用WMS添加視圖View到窗口中
}
r.nextIdle = mNewActivities;
mNewActivities = r;
Looper.myQueue().addIdleHandler(new Idler());  // 加入一個Idler對象,處理內存消息機制

執行了onResume()的活動此時即處於可交互的狀態,到此活動的複用啓動結束;

2.2 創建新對象啓動活動

對於未找到匹配的ActivityRecord實例,需要判斷進程是否啓動或重新創建Activity對象,此時在resumeTopActivityLocked()中,會調用 startSpecificActivityLocked(next, true, true)

  • startSpecificActivityLocked()
private final void startSpecificActivityLocked(ActivityRecord r,
595            boolean andResume, boolean checkConfig) {
597        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
598                r.info.applicationInfo.uid); // 1、
           getLaunchTimeTracker().setLaunchTime(r); // 設置啓動時間
609        if (app != null && app.thread != null) { // 判斷進程是否啓動
611       realStartActivityLocked(r, app, andResume, checkConfig); // 2、進程已啓動的直接執行創建Activity實例
612                return;
613         } 
622        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, // 3、進程未啓動的,先啓動進程
623                "activity", r.intent.getComponent(), false);
624    }

在startSpecificActivityLocked()中首先獲取目標Activity所在的進程,設置活動的啓動時間,然後判斷進程是否啓動,對於已經啓動的進程執行realStartActivityLocked()創建Activity實例,對於未啓動的進程調用startProcessLocked()啓動進程;

  • realStartActivityLocked():進程已啓動的情況下,直接創建Activity實例完成DecorView相關初始化
 mService.mWindowManager.setAppVisibility(r, true);
r.app = app; // 賦值進程信息
final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread, r.appToken);
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
        System.identityHashCode(r), r.info,
        mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(), r.compat,
        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
        profilerInfo));
mService.getLifecycleManager().scheduleTransaction(clientTransaction); // 執行ActivityThread中方法啓動Activity

app.thread.scheduleLaunchActivity(new Intent(r.intent), r,  // 執行scheduleLaunchActivity()啓動活動,參見四大組件的啓動過程

在realStartActivityLocked中完成創建Activity實例和DecorView相關初始化,具體信息查看Android四大組件啓動過程

2.3 處理進程未啓動

對於應用進程未啓動的執行startProcessLocked()啓動相應進程,關於程序的進程啓動參見(應用程序的進程啓動)進程啓動後進入ActivityThread.main()中,在main()中會調用attach()方法,然後調用AMS.attachApplication()中

final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid); // 獲取客戶端進程的pid,調用attachApplicationLocked()通知啓動完成
  • attachApplicationLocked()
ProcessRecord app = mPidsSelfLocked.get(pid); // 1、
String processName = app.processName; // 獲取進程名稱
thread.asBinder().linkToDeath(new AppDeathRecipient(app, pid, thread), 0); // 設置Binder的死亡監聽
app.thread = thread; // 賦值AMS中持有的thread
thread.bindApplication(processName, app.instrumentationInfo != null // 2、
           ? app.instrumentationInfo : app.info, providers,
           app.instrumentationClass, app.instrumentationProfileFile,
           app.instrumentationArguments, app.instrumentationWatcher, testMode,
           isRestrictedBackupMode || !normalMode,
           mConfiguration, getCommonServicesLocked());
if (mStackSupervisor.attachApplicationLocked(app)) { // 調用ActivitySupervisor方法
}
final ActivityRecord top = stack.topRunningActivityLocked(); // 3、
if (activity.app == null && app.uid == activity.info.applicationInfo.uid
        && processName.equals(activity.processName)) {
    try {
        if (realStartActivityLocked(activity, app,  // 4、
                top == activity /* andResume */, true /* checkConfig */)) {
            didSomething = true;
        }
    } 
}. 

在attachApplication()中,

  1. 首先根據pid獲取進程信息ProcessRecord對象,然後爲啓動的進程設置死亡監聽
  2. 回調bindApplication(),執行handleBindApplication()
  3. 獲取stack頂部的ActivityRecord,判斷是否等待啓動,此時是獲取到棧頂的活動正式要啓動的Activity
  4. 執行realStartActivityLocked完成啓動Activity

總結:AMS在接收到啓動請求時,會先使用PMS找到最佳處理的活動,然後根據請求設置的Flag和活動中設置的Mode確定是否可重用活動,如果可重用處理其Task棧的相關信息並將ActivityRecord放置在棧頂,然後執行當前可交互Activity的Pause操作,執行結束後回調AMS方法,AMS取出要啓動的活動執行Resume操作,對於未匹配重用的,首先判斷進程是否啓動,若未啓動先啓動進程,啓動完成後重新創建Activity對象,實現活動的啓動;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章