Activity啓動(3)----Task,Activity,Process的管理

    ActivityManagerService管理着Activity,Task和應用程序進程。三者在AMS中的表現形式分別爲:ActivityRecord,TaskRecord,ProcessRecord。這三者的關係以下圖所示:前端

從圖中能夠看出,AMS是按層次關係進行管理全部的Activity的。
(1) ActivityStackSupervisor的成員mStacks是AMS管理層次的頂層,類型爲ArrayList<ActivityStack>,它只包含兩個stack: mHomeStack和mFocusedStack。mHomeStack保存Luncher App的Task(activity), mFocusedStack保存非Laucher App的Task(activity)。
(2) mHomeStack和mFocusedStack的類型是ActivityStack,它有一個ArrayList<TaskRecord>類型的成員mTaskHistory,用於存儲TaskRecord。
(3) TaskRecord有一個類型爲ArrayList<ActivityRecord>的成員mActivities,用於保存屬於該Task的全部Activity。類型爲ActivityStack的成員stack,記錄所屬的棧。numActivities記錄當前Task中Activity的數量。
(4) 每一個ActivityRecord會對應到一個TaskRecord,ActivityRecord中類型爲TaskRecord的成員task,記錄所屬的Task。
(5) AMS經過輔助類ActivityStackSupervisor來操做Task, 經過ActivityStack操做Activity。想找到某個Activity,須要按層次查找:先找到對應的棧, 再找到棧中的Task,再在該Task中查找Activity
(6) 同一個TaskRecord的Activity能夠分別處於不一樣的進程中,每一個Activity所處的進程跟所處的Task沒有關係。java

 1. 建立ActivityRecordandroid

startActivityLocked()@ActivityStackSupervisor.java瀏覽器

final int startActivityLocked(IApplicationThread caller,    // caller是請求啓動當前Activity的應用方,IApplicationThread類是AMS調用ActivityThread的IBinder接口。
                              Intent intent, String resolvedType, ActivityInfo aInfo,
                              IBinder resultTo,       // 調用方Activity的ActivityRecord,每一個Activity在啓動以後,AMS均會將這個Activity的ActivityRecord的IBinder再傳遞給Activity,做爲其在AMS中的標識。
                              String resultWho, int requestCode,
                              int callingPid, int callingUid,  // 用於權限檢查,檢查請求方是否有權限啓動這個Activity.
                              String callingPackage, int startFlags, Bundle options,
                              boolean componentSpecified, ActivityRecord[] outActivity) {
    int err = ActivityManager.START_SUCCESS;
    
    ProcessRecord callerApp = null;
    if (caller != null) {       // caller不爲空,callingPid和callingUid爲caller activity所在進程的PID和UID。若caller爲空,則爲請求啓動Activity的進程的PID和UID。
        callerApp = mService.getRecordForAppLocked(caller);
        if (callerApp != null) {
            callingPid = callerApp.pid;
            callingUid = callerApp.info.uid;
        } else {
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }

    ActivityRecord sourceRecord = null;           // 表示請求啓動當前activity的activity.
    ActivityRecord resultRecord = null;           // 表示當前activity啓動以後須要獲得返回結果的activity。
    if (resultTo != null) {
        sourceRecord = isInAnyStackLocked(resultTo);
        if (sourceRecord != null) {       // 通常狀況下,sourceRecord的activity使用startActivityForResult()啓動當前activity且requestCode>=0,那麼resultRecord = sourceRecord。
            if (requestCode >= 0 && !sourceRecord.finishing) {
                resultRecord = sourceRecord;
            }
        }
    }

    ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;

    int launchFlags = intent.getFlags();
        // 特殊狀況,若sourceRecord啓動當前activity時設置了標記Intent.FLAG_ACTIVITY_FORWARD_RESULT,且requestCode<0, 那麼當前activity的resultRecord等於sourceRecord.resultTo,也就是sourceRecord的resultRecord。
    if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
        // 將sourceRecord的resultRecord轉移給當前新啓動的activity.
        if (requestCode >= 0) {
            ActivityOptions.abort(options);
            return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
        }
        resultRecord = sourceRecord.resultTo;
        resultWho = sourceRecord.resultWho;
        requestCode = sourceRecord.requestCode;
        sourceRecord.resultTo = null;
        if (resultRecord != null) {
            resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
        }
    }
    
    if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
        // We couldn't find a class that can handle the given Intent. That's the end of that!
        err = ActivityManager.START_INTENT_NOT_RESOLVED;
    }

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

    if (err != ActivityManager.START_SUCCESS) {
        if (resultRecord != null) {     // 啓動新activity出錯,發送result給resultRecord。
            resultStack.sendActivityResultLocked(-1,
                    resultRecord, resultWho, requestCode,
                    Activity.RESULT_CANCELED, null);
        }
        setDismissKeyguard(false);
        ActivityOptions.abort(options);
        return err;
    }
    // 檢查啓動權限
    final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid, callingUid);
    final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid, callingUid, aInfo.applicationInfo.uid, aInfo.exported);
    if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
        if (resultRecord != null) {
            resultStack.sendActivityResultLocked(-1,
                        resultRecord, resultWho, requestCode,
                        Activity.RESULT_CANCELED, null);
        }
        setDismissKeyguard(false);
        String msg;
        if (!aInfo.exported) {
            msg = "Permission Denial: starting " + intent.toString()
                            + " from " + callerApp + " (pid=" + callingPid
                            + ", uid=" + callingUid + ")"
                            + " not exported from uid " + aInfo.applicationInfo.uid;
        } else {
            msg = "Permission Denial: starting " + intent.toString()
                            + " from " + callerApp + " (pid=" + callingPid
                            + ", uid=" + callingUid + ")"
                            + " requires " + aInfo.permission;
        }
        throw new SecurityException(msg);
    }
    
    // IntentFirewall.checkStartActivity()函數檢查一個start activity的intent是否容許。
    boolean abort = !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
                                 callingPid, resolvedType, aInfo.applicationInfo);

    if (mService.mController != null) {
        // 判斷這個activity是否正在啓動。
        try {
            Intent watchIntent = intent.cloneFilter();
            abort |= !mService.mController.activityStarting(watchIntent, aInfo.applicationInfo.packageName);
        } catch (RemoteException e) {
            mService.mController = null;
        }
    }
    
    // intent不容許或者被請求的activity正在啓動,則停止本次啓動請求。
    if (abort) {
        if (resultRecord != null) {
            resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
                            Activity.RESULT_CANCELED, null);
        }
       // 僞裝告訴caller是真正開始了,但它將只獲得一個取消的結果。
        setDismissKeyguard(false);
        ActivityOptions.abort(options);
        return ActivityManager.START_SUCCESS;
    }
    
    // 建立ActivityRecord
    ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                                          intent, resolvedType, aInfo, mService.mConfiguration,
                                          resultRecord, resultWho, requestCode, componentSpecified, this);
    if (outActivity != null) {
        outActivity[0] = r;       // 將建立的ActivityRecord返回
    }
    
    final ActivityStack stack = getFocusedStack();
    if (stack.mResumedActivity == null || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
        if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
            PendingActivityLaunch pal = new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
            mService.mPendingActivityLaunches.add(pal);
            setDismissKeyguard(false);
            ActivityOptions.abort(options);
            return ActivityManager.START_SWITCHES_CANCELED;
        }
    }
    ......    
    mService.doPendingActivityLaunchesLocked(false);

    err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
    ......
    return err;
}

1.1 Permission檢查app

checkPermission()@ActivityManagerService.java函數

public int checkPermission(String permission, int pid, int uid) {
    if (permission == null) {
        return PackageManager.PERMISSION_DENIED;
    }
    return checkComponentPermission(permission, pid, UserHandle.getAppId(uid), -1, true);
}

checkComponentPermission()@ActivityManagerService.javaui

int checkComponentPermission(String permission, int pid, int uid, int owningUid, boolean exported) {

    Identity tlsIdentity = sCallerIdentity.get();
    if (tlsIdentity != null) {
         uid = tlsIdentity.uid;
         pid = tlsIdentity.pid;
    }

    if (pid == MY_PID) {  // 在本身所在進程(own process), 則受權
        return PackageManager.PERMISSION_GRANTED;
    }

    return ActivityManager.checkComponentPermission(permission, uid, owningUid, exported);
}

checkComponentPermission()@ActivityManager.javathis

public static int checkComponentPermission(String permission, int uid, int owningUid, boolean exported) {
    // Root uid(0), system server uid(Process.SYSTEM_UID)受權permission.
    if (uid == 0 || uid == Process.SYSTEM_UID) {
        return PackageManager.PERMISSION_GRANTED;
    }

    // Isolated processes不受權.
    if (UserHandle.isIsolated(uid)) {
        return PackageManager.PERMISSION_DENIED;
    }

    // 若是一個uid擁有被訪問的全部東西,不管它請求什麼permissions,它均可以徹底訪問它們,即被受權。
    if (owningUid >= 0 && UserHandle.isSameApp(uid, owningUid)) {
        return PackageManager.PERMISSION_GRANTED;
    }

    // 若是被請求啓動的activity屬性android:exported=false, 則不受權。
    if (!exported) {
        return PackageManager.PERMISSION_DENIED;
    }

    // 若是被請求啓動的activity的permission爲空,則受權。
    if (permission == null) {
        return PackageManager.PERMISSION_GRANTED;
    }
    
    // 被請求啓動的activity設定了permission,那麼檢查請求方的activity中是否聲明瞭使用這個permission,若是聲明,受權。
    try {
        return AppGlobals.getPackageManager().checkUidPermission(permission, uid);
    } 

    return PackageManager.PERMISSION_DENIED;
}

 

2. Task的建立與管理spa

2.1 Task與Application的區別3d

Application能夠當作是在Android開發中的一個容器,用於存放和組織一個應用程序的activity,這些activity與Application之間是靜態關係,而且是一一對應的,也就是說activity在PackManager中的最終形式是惟一的,而且只對應一個Application。而Task和activity之間是動態關係,是運行應用程序時,activity的調用棧,同一個Task中的activity可能來自不一樣的Application。

2.2 startActivityUncheckedLocked()

    ActivityStackSupervisor.startActivityLocked()函數在建立了ActivityRecord以後,調用了startActivityUncheckedLocked,處理Task相關的內容就是在這個函數裏。
startActivityUncheckedLocked()@ActivityStackSupervisor.java

final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,
                                       int startFlags, boolean doResume, Bundle options) {
    final Intent intent = r.intent;
    final int callingUid = r.launchedFromUid;
    
    int launchFlags = intent.getFlags();
    
    // 只有正在啓動的activity沒明確聲明這是自動啓動時,在onPause()調用以前纔會調用onUserLeaving()。
    mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0; // 若是caller要求如今這個點不要resume, 在record裏記錄下來,在尋找top running activity的時候調過它。
    if (!doResume) {
        r.delayedResume = true;
    }
    
    ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;

    // 若是設置了onlyIfNeeded,若是正在被啓動的activity與調用方同樣,能夠這樣作,或者做爲一種特殊狀況,若是不知道caller是誰,把當前top activity做爲caller。
    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
        ActivityRecord checkedCaller = sourceRecord;
        if (checkedCaller == null) {
            checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
        }
        if (!checkedCaller.realActivity.equals(r.realActivity)) {
            // caller不是launcher, 一般須要這個標誌。
            startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
        }
    }
    //須要建立新task的狀況
    if (sourceRecord == null) {
        // activity不是由另一個activity啓動的,這種狀況下一般須要開啓一個新的task.
        if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
        }
    } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
        // 若是原始activity(sourceRecord)以single instance方式運行,那它請求啓動的activity必須運行在它本身的task裏。
        launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
        // 若是被請求啓動的activity的launchMaode是LAUNCH_SINGLE_INSTANCE或者LAUNCH_SINGLE_TASK,那麼它一般在它本身的task裏啓動。
        launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    }

    final ActivityStack sourceStack;
    if (sourceRecord != null) {
        if (sourceRecord.finishing) {
            // 若是source activity正在finishing, 不能把它看成被啓動activity的source, 由於source關聯的那個task如今可能爲空並正在退出,所以不能盲目地把將要啓動的activity放到那個task裏,而是走NEW_TASK的路徑去爲它找到一個task。
            if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
            }
            sourceRecord = null;
            sourceStack = null;
        } else {
            sourceStack = sourceRecord.task.stack;
        }
    } else {
        sourceStack = null;
    }

    // 若設置了FLAG_ACTIVITY_NEW_TASK, 新的activity是經過startActivityForResult()請求啓動的,而且requestCode >=0,則斷開與caller的依賴。
    if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        // 新的activity無論哪一種緣由須要在新task裏啓動,可是caller卻要求獲得返回結果。這會引發混亂,所以當即返回一個取消的結果,讓新的task不依賴於它的source而繼續正常的啓動。
        r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho, r.requestCode, Activity.RESULT_CANCELED, null);
        r.resultTo = null;
    }

    boolean addingToTask = false;
    boolean movedHome = false;
    TaskRecord reuseTask = null;
    ActivityStack targetStack;
    if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                    (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                    || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
                    || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
        // 若是被要求到前臺,不要求返回結果,並且能夠找到一個使用相同組件啓動的task, 那麼將它移到前臺。
        if (r.resultTo == null) {
            // 看看是否有一個task能夠帶到前臺。若是這是SINGLE_INSTANCE的activity, 在history裏它可能有並且只有一個實例,並且在它獨佔的task裏,所以查找一下。
            ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE ? findTaskLocked(r) : findActivityLocked(intent, r.info); if (intentActivity != null) {
                if (r.task == null) {
                    r.task = intentActivity.task;
                }
                targetStack = intentActivity.task.stack;
                targetStack.mLastPausedActivity = null;
                moveHomeStack(targetStack.isHomeStack());
                if (intentActivity.task.intent == null) {
                    // 若是task的啓動是因爲activity基於affinity的活動,如今就真正去啓動它,並指定基本的intent。
                    intentActivity.task.setIntent(intent, r.info);
                }

                // 若是目標task不在前臺,那麼須要把它移到前臺,可是由於SINGLE_TASK_LAUNCH,它並不徹底清楚該怎麼作。咱們但願有相同的行爲,就像啓動一個新的實例同樣,這意味着若是caller本身不在前臺,那就不將它移到前臺。
                // 由於要複用task, 所以將taskTop所在的task移至前臺。
final ActivityStack lastStack = getLastStack(); ActivityRecord curTop = lastStack == null? null : lastStack.topRunningNonDelayedActivityLocked(notTop); if (curTop != null && (curTop.task != intentActivity.task || curTop.task != lastStack.topTask())) { r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); if (sourceRecord == null || (sourceStack.topActivity() != null && sourceStack.topActivity().task == sourceRecord.task)) { // 但願立刻將activity展現在用戶面前。 movedHome = true; if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {                             // caller想出如今home activity. intentActivity.task.mOnTopOfHome = true; } targetStack.moveTaskToFrontLocked(intentActivity.task, r, options); options = null; } } // 若是caller要求目標task reset,那就照作。
                // Reset Task。
if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r); }
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { // 不須要啓動一個新的activity,若是是這樣的話client要求不作任何事,那麼就是它了。確保top activity正確resumed。 if (doResume) { resumeTopActivitiesLocked(targetStack, null, options); } else { ActivityOptions.abort(options); } return ActivityManager.START_RETURN_INTENT_TO_CALLER; } if ((launchFlags & (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) { // caller要求使用新activity徹底替換已經存在的task,這個工做不該該困難。 reuseTask = intentActivity.task; reuseTask.performClearTaskLocked(); reuseTask.setIntent(r.intent, r.info); } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { // 這種狀況下,task移除要啓動的activity以上的全部activity。在大多數狀況下,這意味着重置task到其初始狀態。 ActivityRecord top = intentActivity.task.performClearTaskLocked(r, launchFlags); if (top != null) { if (top.frontOfTask) { // activity別名可能意味着top activity使用不一樣的intents,那麼確保task如今有新intent的特性。 top.task.setIntent(r.intent, r.info); } ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); top.deliverNewIntentLocked(callingUid, r.intent); } else { // 一種特殊狀況:由於這個activity不是當前正在運行的, 因此須要去啓動它,並且caller已經要求清除當前的task,好讓這個activity在頂部。 addingToTask = true; // 如今能夠看成activity是由它的task的頂部啓動的,所以它在正確的地方了。 sourceRecord = intentActivity; } } else if (r.realActivity.equals(intentActivity.task.realActivity)) { // 在這中狀況下,task中的top activity與被啓動的activity是相同的,所以咱們把這項工做的要求看做是要把task移到前臺。若task的top activity是root activity, 若是它要求就將新的intent傳遞給它。 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) && intentActivity.realActivity.equals(r.realActivity)) { ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, intentActivity.task); if (intentActivity.frontOfTask) { intentActivity.task.setIntent(r.intent, r.info); } intentActivity.deliverNewIntentLocked(callingUid, r.intent); } else if (!r.intent.filterEquals(intentActivity.task.intent)) { // 這種狀況下,啓動task的root activity, 使用不容的intent。應該在top啓動一個新的實例。 addingToTask = true; sourceRecord = intentActivity; } } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) { // 這種狀況下,啓動activity到一個已存在的task裏,這個task沒有reset。這一般是從notification或者快捷方式啓動activity的狀況。咱們但願將新的activity放置在當前task的top。 addingToTask = true; sourceRecord = intentActivity; } else if (!intentActivity.task.rootWasReset) { // 在這種狀況下,啓動activity到一個已存在的task裏,這個task尚未從它的前門啓動。當前task已經被移至前臺。理想狀況下,咱們可能但願將新的task放到它的stack的底部,但目前的代碼組織實現這個比較困難,所以放棄這種作法。 intentActivity.task.setIntent(r.intent, r.info); } if (!addingToTask && reuseTask == null) { // 不作任何事情,但這步是必要的(client沒有使用intent),確保top activity正確地resume。 if (doResume) { targetStack.resumeTopActivityLocked(null, options); } else { ActivityOptions.abort(options); } return ActivityManager.START_TASK_TO_FRONT; } } } } if (r.packageName != null) { // 若是正在啓動的activity與當前top的activity相同,那麼須要檢查它是否應該只被啓動一次。 ActivityStack topStack = getFocusedStack(); ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop); if (top != null && r.resultTo == null) { if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) { if (top.app != null && top.app.thread != null) { if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task); // 確保top activity正確地resume。 topStack.mLastPausedActivity = null; if (doResume) { resumeTopActivitiesLocked(); } ActivityOptions.abort(options); if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { // 不須要啓動一個新的activity,client不作任何事,若是是這樣的話,那這就是它。 return ActivityManager.START_RETURN_INTENT_TO_CALLER; } top.deliverNewIntentLocked(callingUid, r.intent); return ActivityManager.START_DELIVERED_TO_TOP; } } } } } else { if (r.resultTo != null) { r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho, r.requestCode, Activity.RESULT_CANCELED, null); } ActivityOptions.abort(options); return ActivityManager.START_CLASS_NOT_FOUND; } boolean newTask = false; boolean keepCurTransition = false; // 這是否應該算是一個新的task ? if (r.resultTo == null && !addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { targetStack = adjustStackFocus(r); moveHomeStack(targetStack.isHomeStack()); if (reuseTask == null) { r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true), null, true);  // 在新的task中啓動新的activity         } else { r.setTask(reuseTask, reuseTask, true); } newTask = true; if (!movedHome) { if ((launchFlags & (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {                 // caller想要在home activity中出現,那麼在開始它們本身的activity以前將home移至前臺。 r.task.mOnTopOfHome = true; } } } else if (sourceRecord != null) { TaskRecord sourceTask = sourceRecord.task; targetStack = sourceTask.stack; moveHomeStack(targetStack.isHomeStack()); if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { // 這種狀況下,將activity加入到一個存在的task中,可是若是activity已經運行的話,caller要求清除task。 ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags); keepCurTransition = true; if (top != null) { ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); top.deliverNewIntentLocked(callingUid, r.intent); // 確保top activity正確地resume。 targetStack.mLastPausedActivity = null; if (doResume) { targetStack.resumeTopActivityLocked(null); } ActivityOptions.abort(options); return ActivityManager.START_DELIVERED_TO_TOP; } } else if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) { // 這種狀況下,在本身的task中啓動activity, 這個activity可能之前在某個地方運行過,若是這樣的話,將它移到stack的前面。 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r); if (top != null) { final TaskRecord task = top.task; task.moveActivityToFrontLocked(top); ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task); top.updateOptionsLocked(options); top.deliverNewIntentLocked(callingUid, r.intent); targetStack.mLastPausedActivity = null; if (doResume) { targetStack.resumeTopActivityLocked(null); } return ActivityManager.START_DELIVERED_TO_TOP; } } // 一個已存在的activity正在啓動這個新的activity, 新的activity與啓動它的activity在同一個task裏。 r.setTask(sourceTask, sourceRecord.thumbHolder, false); } else { // 不是從一個已存在的activity啓動,也不是一個新的task的一部分,就把它放到top task,雖然這種狀況不該該發生。 targetStack = adjustStackFocus(r); moveHomeStack(targetStack.isHomeStack()); ActivityRecord prev = targetStack.topActivity(); r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true), null, true); } mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, intent, r.getUriPermissionsLocked()); if (newTask) { EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId); } ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task); targetStack.mLastPausedActivity = null; targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options); mService.setFocusedActivityLocked(r); return ActivityManager.START_SUCCESS; }

    這個函數涉及的內容很繁雜,在這裏對部份內容作一些解析。

2.3 Intent flag介紹

Intent攜帶的flag對於task的影響很大,這裏簡單介紹下上面函數中用到的flag。

(1) Intent.FLAG_ACTIVITY_NO_USER_ACTION

     若是設置了這個flag, 在新啓動的activity被移到前臺,當前最前面的activity被paused以前,將會阻止回調onUserLeaveHint(),能夠在避免用戶離開當前Activity時回調到 onUserLeaveHint(). 一般,Activity能夠經過這個回調代表有明確的用戶行爲致使當前activity切出前臺。 這個回調標記了activity生命週期中的一個恰當的點,能夠「在用戶看過通知以後」將通知清除,如閃爍LED燈。
     若是Activity是由非用戶驅動的事件(如電話呼入或鬧鐘響鈴)啓動的,那這個標誌就應該被傳入Context.startActivity,以確保被打斷的activity不會認爲用戶已經看過通知。

(2) Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP

     若是設置了這個flag,並且這個intent被用於從已有activity啓動另一個新的activity, 那麼當前的activity不會被當成top activity用來決定是否傳送這個新intent給top activity而不是啓動一個新的activity。當前activity的前一個的activity會被看成top activity,假定當前的Acitvity會當即把本身finish掉。

    例如A-->B-->C,若B啓動C時設置了這個標誌位,那在啓動時B並不會被看成top activity,而是用A作top來啓動C。
    典型的場景是在應用選擇頁面,若是在文本中點擊一個網址要跳轉到瀏覽器,而系統中又裝了不止一個瀏覽器應用,此時會彈出應用選擇頁面。在應用選擇頁面選擇某一款瀏覽器啓動時,就會用到這個Flag。而後應用選擇頁面將本身finish,以保證從瀏覽器返回時不會在回到選擇頁面。

(3) Intent.FLAG_ACTIVITY_NEW_TASK

    若是設置了這個flag, 這個activity將會成爲一個新task歷史棧的開始。一個task(從啓動它的activity到task中的下一個activity)定義了用戶能夠跳轉的原子的activities羣。Tasks能夠在前臺和後臺之間切換;一個特定task中的全部activities會一直保持一樣的順序。
    這個flag一般被activity用來展現一種"launcher"類型的行爲:爲用戶提供可以完成的獨立事件列表,這些事件的運行徹底獨立於啓動它們的activity。
    當使用這個activity時,若是一個task已經運行了你要啓動的activity,那麼就不會啓動一個新的activity,而是將現有task以現有狀態直接切換至前臺。
    這個flag不能在caller請求要啓動的activity返回結果時使用。
    注意:假設A啓動B,若是要讓B在新的task中建立,那麼要求這兩個Activity的taskAffinity不能相同。也就是說,設置了這個標誌後,新啓動的activity並不是就必定在新的task中建立,若是A和B在屬於同一個package,並且都是使用默認的taskAffinity,那B仍是會在A的task中被建立。 因此,只有A和B的taskAffinity不一樣時,設置了這個標誌纔會使B被建立到新的task。

(4) Intent.FLAG_ACTIVITY_MULTIPLE_TASK

    除非你要實現本身的頂級的應用啓動器,不然不要用這個flag。與FLAG_ACTIVITY_NEW_TASK聯合使用,禁止將已有的task移到前臺。當設置了,總會爲這個intent啓動一個新的task做爲activity的宿主,而無論是否已經存在運行一樣事情的task.由於系統默認不包含task的圖形化管理,除非你爲用戶提供返回到已啓動task的方法,不然不要用這個flag。
    若是沒有設置FLAG_ACTIVITY_NEW_TASK,那麼這個flag也被忽視。

(5) Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT

    一般在應用代碼中不須要設置這個flag,當launchMode爲singleTask時系統會默認設置這個flag。

(6) Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

    若是設置了這個flag, 這個activity正在一個新的task中啓動或者正在從一個已存在的task中移到top,那麼它被看成這個task的前門來啓動。這會致使須要任何affinities的應用程序保證那個task處於適當的狀態下(無論activity是移進仍是移出),或者若是必要的話簡單地重置task至初始狀態。

(7) Intent.FLAG_ACTIVITY_CLEAR_TASK

    若是設置了這個flag, 會致使包含已存在待啓動的activity的task在該activity啓動前被清空。即,該activity會成爲一個空task的新的root,並且其它舊的activities都被finish掉。這個flag只能與FLAG_ACTIVITY_NEW_TASK一塊兒使用。

(8) Intent.FLAG_ACTIVITY_CLEAR_TOP

    若是設置了這個flag,被啓動的activity已經存在於當前task中,那麼不會爲這個activity啓動一個新的實例,這個將task中這個activity之上的其它activity都關閉掉,這個intent被看成新的intent傳給這個舊的activity(當前已在top)。
    例如,一個task中包含4個activity,從棧底到棧頂順序爲:A,B,C,D。若是D調用startActivity()啓動B,那麼C和D將會被finished掉,而且B收到這個intent,結果是如今task棧爲:A,B。
    上面例子中正在運行的實例B,既能夠在onNewIntent函數中接收新的intent,也能夠先本身finish掉本身,而後用新的intent從新啓動。若是activity聲明瞭它的launch mode爲「multiple」(默認值),並且intent中沒有設置Intent.FLAG_ACTIVITY_SINGLE_TOP, 那麼它將會被finish掉而後從新建立。對於其它的launch mode或者設置了Intent.FLAG_ACTIVITY_SINGLE_TOP,那麼這個intent將會被傳給當前activity實例的onNewIntent()。
    注意:這種啓動模式能夠與FLAG_ACTIVITY_NEW_TASK一塊兒使用:若是用來啓動一個task的root activity,它會將這個任務中如今運行的實例調到前臺,而後將任務清空至只有root activity的狀態。例如要從通知中內心啓動一個Activity時。

(9) Intent.FLAG_ACTIVITY_SINGLE_TOP 

    若是設置了這個標記,若被啓動的activity已經在棧頂運行,那麼它不會被再次啓動。

(10) Intent.FLAG_ACTIVITY_TASK_ON_HOME

    若是設置了這個flag, 這個flag將會致使新啓動的task被置於當前home activity task之上(若是有的話),也就是說,在這個task中按返回鍵時,老是回退到home界面,即便home不是用戶最後看到的界面。這個flag只能與Intent.FLAG_ACTIVITY_NEW_TASK一塊兒使用。
    例如,A-->B-->C-->D,若是C啓動D時設置了這個flag, 那麼在D中按返回鍵時就會直接返回到桌面,而不是返回到C。注意,只有D是在新的task中被建立時(即D的launch mode是singleInstance時,或者是D指定了與C不懂的taskAffinity並設置了FLAG_ACTIVITY_NEW_TASK時),使用Intent.FLAG_ACTIVITY_TASK_ON_HOME纔有效。

(11) Intent.FLAG_ACTIVITY_REORDER_TO_FRONT

    若是設置了這個flag, 若是被啓動的activity已經運行,那麼這個已啓動的activity將被移至task的棧頂。
    例如,一個task中包含4個activity,從棧底到棧頂順序爲:A,B,C,D。若是D調用startActivity()啓動B時使用了這個flag,那麼B將會被調節到棧頂,結果順序:A,C,D,B。不然,順序會是:A,B,C,D,B。
    若設置了Intent.FLAG_ACTIVITY_CLEAR_TOP,那麼這個flage將會被忽視。

2.4 launchMode介紹

ActivityInfo.LAUNCH_MULTIPLE  : standard

ActivityInfo.LAUNCH_SINGLE_TOP : singleTop

ActivityInfo.LAUNCH_SINGLE_TASK : singleTask

ActivityInfo.LAUNCH_SINGLE_INSTANCE : singleInstance

分兩種狀況討論下這四種launchMode :

(1) 一個task的狀況:

standard :無論當前task是否存在要啓動的activity,都會建立一個新的activity。好比task爲A B,這時要啓動B,那麼task將變爲A B B。

singleTop :若是要啓動的activity就在task的top, 那麼不會建立新的activity, 只會調用onNewIntent()。若是不在top(或者task中沒有該activity),那麼就會建立新的activity。例如task爲A B,這時若啓動B,則task仍爲A B;若啓動A,

                  那麼task將變爲A B A。

singleTask :若是當前task中存在要啓動的activity, 那麼不會建立新的activity,會將該activity上面的activity移除並將該activity移至top;若是不存在,則會建立新的activity,如task爲A B C,啓動B,那麼task將變爲A B。

singleInstance : 具備該mode的activity獨佔一個task,不容許加入其它task。

(2) 多個task的狀況

standard :若是要啓動的activity在後臺task中,那麼無論這個activity在後臺task是否存在,都會建立一個新的activity,並將它加入到前臺的task中去。

singleTop :若是要啓動的activity在後臺task中,且這個activity在後臺task的top,這時須要結合Intent.FLAG_ACTIVITY_NEW_TASK進行判斷。

                 若啓動activity的intent設置了這個flag,那麼將會把後臺task移至前臺,例如前臺task爲A B,後臺task爲C E F,如今前臺task須要啓動一個F,intent設置了FLAG_ACTIVITY_NEW_TASK,那麼後臺task將被移至前臺,並調用F

                 的onNewIntent(),A B所在的task變爲後臺task;若沒設置該flag,那就在前臺task中新建立一個activity F。

                 singleTask :若是要啓動的activity在後臺task中, 那麼無論該activity是否在top,都會將後臺task移至前臺,前臺task移至後臺。不須要考慮flag,由於要啓動的activity若是是singleTask,那麼自動在啓動activity的intent中加上

                 FLAG_ACTIVITY_NEW_TASK。

singleInstance : 若是要啓動的activity在後臺task中,那麼會調用該activity的onNewIntent,而且後臺task仍然在後臺。若是後臺task中沒有該activity,那麼會從新建立一個activity,並單獨放入一個task中,其實在啓動的intent中也會加上

                FLAG_ACTIVITY_NEW_TASK。

(3) taskAffinity屬性介紹

 

2.5 須要建立新的task的狀況

(1) 若是sourceRecord爲null(從Launcher啓動一個Activity或者經過Context啓動一個Activity時sourceRecord爲null)。

(2) 若是sourceRecord的launchMode設置的是singleinstance,那麼在Intent添加 FLAG_ACTIVITY_NEW_TASK,由於對於singleinstance的activity,是不會與其它activity共享一個 task的。

(3) 若是被啓動的activity的launchMode是singleinstance或者singletask,那麼也會在Intent中添加FLAG_ACTIVITY_NEW_TASK。

2.6 Task複用

2.6.1 Task的基本屬性

(1) task的root activity是指啓動一個activity時新建立一個新的task,則這個activity就是這個task的activity。

(2) task.affinity是指root activity的affinity。

(3) task.intent是指啓動root activity的intent。

(4) task.affinityIntent是指activity在進行了TaskReparenting操做後,AMS爲activity分配新的task,這個新的task的affinityIntent則是啓動該activity的Intent,此時task.intent爲null。

     TaskReparenting操做示例:假設有A,B兩個activity,它們擁有不一樣的affinity,並且從activity A中啓動activity B, 假設A是所在task的root activity,如圖所示:

    

    假設activity B設置了ActivityInfo.FLAG_ALLOW_TASK_REPARENTING, 若是此時另一個applicationy要求啓動activity B並要求它在新的task中,那麼activity B將被從task A中移到新的task中,如圖所示:    

           

 2.6.2 查找可複用的Task

 2.6.2.1 須要查找可複用task的條件

(1) (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0
    若是設置了Intent.FLAG_ACTIVITY_MULTIPLE_TASK,那麼無論是否有可複用的task,都會去啓動一個新的task。所以,若沒有設置Intent.FLAG_ACTIVITY_MULTIPLE_TASK,但設置了Intent.FLAG_ACTIVITY_NEW_TASK,那麼就須要查找是否存在可複用的task。

(2) r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK

(3) r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE

 2.6.2.2 查找可複用task的規則

(1) launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE的狀況

findTaskLocked()@ActivityStackSupervisor.java

ActivityRecord findTaskLocked(ActivityRecord r) {
    for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
        final ActivityStack stack = mStacks.get(stackNdx);
        if (!r.isApplicationActivity() && !stack.isHomeStack()) {
            continue;
        }
        final ActivityRecord ar = stack.findTaskLocked(r);
        if (ar != null) {
            return ar;
        }
    }
    return null;
}

 findTaskLocked()@ActivityStack.java

// 返回任何已存在與給定intent匹配的的task中的top activity,若沒有這樣的task,則返回null。
ActivityRecord findTaskLocked(ActivityRecord target) {
    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);

    for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
        final TaskRecord task = mTaskHistory.get(taskNdx);
        if (task.userId != userId) {
            // 忽略不一樣user的task。
            continue;
        }
        final ActivityRecord r = task.getTopActivity();
        if (r == null || r.finishing || r.userId != userId || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
            // task的root activity不匹配忽略。
            continue;
        }

        if (task.affinity != null) {          //task.affinity不爲空,若task的affinity與要啓動的activity的affinity相同,即root activity的affinity與要啓動的activity的affinity相同,那麼就找到了可複用的task。
            if (task.affinity.equals(info.taskAffinity)) {
                // 找到匹配的affinity。
                return r;
            }
        } else if (task.intent != null && task.intent.getComponent().equals(cls)) { // task.affinity爲空,即android:taskAffinity被設置爲""。此時判斷task的root activity與啓動的activity是否相同。
            // 找到匹配的class    
            return r;
        } else if (task.affinityIntent != null && task.affinityIntent.getComponent().equals(cls)) {
            // task.intent爲空,task.affinityIntent不爲空,這種狀況發生在TaskReparenting以後。
            // 此時須要經過task.affinityIntent.getComponent()與要啓動的activity的Component比較,看是否與啓動的activity相同。
// 找到匹配的class return r; } else if (DEBUG_TASKS) { // 沒有找到匹配的task。 Slog.d(TAG, "Not a match: " + task); } } return null; }

該函數返回的均是找到的task中最上面的activity,而不必定是task的root activity,至於如何處理要啓動的activity和task中已有的activity,後面會繼續介紹。

(2) launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE的狀況

findActivityLocked()@ActivityStackSupervisor.java

ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
    for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
        final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
        if (ar != null) {
            return ar;
        }
    }
    return null;
}

findActivityLocked()@ActivityStack.java

// 返回從stack的top啓動的第一個activity,這個activity與給定的activity同樣。若沒找到這樣的activity,則返回null。
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
    ComponentName cls = intent.getComponent();
    if (info.targetActivity != null) {
        cls = new ComponentName(info.packageName, info.targetActivity);
    }
    final int userId = UserHandle.getUserId(info.applicationInfo.uid);

    for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
        TaskRecord task = mTaskHistory.get(taskNdx);
        if (task.userId != mCurrentUser) {
            return null;
        }
        final ArrayList<ActivityRecord> activities = task.mActivities;
        for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
            ActivityRecord r = activities.get(activityNdx);
            if (!r.finishing && r.intent.getComponent().equals(cls) && r.userId == userId) {
                // 找到匹配的class
                return r;
            }
        }
    }
    return null;
}

2.6.3 將task移到mTaskHistory頂部

    上面獲得的是ActivityRecord intentActivity,接下來將intentActivity所在的task移到mTaskHistory的前端。

moveTaskToFrontLocked()@ActivityStack.java

final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
    final int numTasks = mTaskHistory.size();
    final int index = mTaskHistory.indexOf(tr);
    if (numTasks == 0 || index < 0)  {
        // 什麼也不作
        if (reason != null && (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
            ActivityOptions.abort(options);
        } else {
            updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
        }
        return;
    }

    mStackSupervisor.moveHomeStack(isHomeStack());
    
    // 將task中全部的activities轉移到stack的頂部,使它們保持相同的內部順序。 insertTaskAtTop(tr); if (reason != null && (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false); ActivityRecord r = topRunningActivityLocked(null); if (r != null) { mNoAnimActivities.add(r); } ActivityOptions.abort(options); } else { updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options); } mWindowManager.moveTaskToTop(tr.taskId); mStackSupervisor.resumeTopActivitiesLocked(); if (VALIDATE_TOKENS) { validateAppTokensLocked(); } }

insertTaskAtTop()@ActivityStack.java

private void insertTaskAtTop(TaskRecord task) {
    // 若是這是由另一個activity或者從home activity啓動引起的移至top的動做,那麼設置響應的mOnTopOfHome。
    ActivityStack lastStack = mStackSupervisor.getLastStack();
    final boolean fromHome = lastStack == null ? true : lastStack.isHomeStack();
    if (!isHomeStack() && (fromHome || topTask() != task)) {
        task.mOnTopOfHome = fromHome;
    }

    mTaskHistory.remove(task);

    // 將task放到頂部
    int stackNdx = mTaskHistory.size();
    if (task.userId != mCurrentUser) {
        // 將非當前用戶tasks放到當前用戶task的下面。
        while (--stackNdx >= 0) {
            if (mTaskHistory.get(stackNdx).userId != mCurrentUser) {
                break;
            }
        }
        ++stackNdx;
    }
    mTaskHistory.add(stackNdx, task);
}

2.6.4 Reset Task

       若是Intent設置Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,最多見的狀況,當從Home啓動應用程序時,會設置這個flag;從當前task進入應用程序時,則不會設置這個falg。若設置了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,AMS會對複用的task做一些處理。

activity的幾個關鍵處理屬性:

      ① 若是複用task在後臺時間超過30min,那麼將刪除除root activity以外的全部的activity。

      ② 若是新啓動的activity設置了屬性ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE,那麼代表它並不要求後臺30min的複用task刪除activity。

      ③ 若是新啓動的activity設置了屬性ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH,那麼代表無論複用task在後臺是否超過30min,都要求刪除除root activity以外的全部的activity。

      ④ 若是複用task中的activity設置了屬性ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH,那麼複用task從home中再次被啓動到前臺時,這個activity會被刪除。

      ⑤ 若是複用task中的activity設置了屬性ActivityInfo.FLAG_ALLOW_TASK_REPARENTIN,而且這個 activity的resultTo爲空,那麼也就是說這個activity和它的caller沒有依賴關係,那麼AMS認爲這個activity暫時沒 有用處了,須要對其進行TaskReparenting操做。

      ⑥ 若是複用task中的activity的Intent設置了屬性 Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET,那麼下次再從home中進入到task中時,將刪除設置了該屬 性的activity以上全部的activity,例如A-->B-->C-->D-->E, 假如在C啓動D時設置了該屬性,那麼下次從HOME中再次進入到這個task中時,將會是A-->B-->C。

      ⑦ 若是複用task中的activity的resultTo不爲空,即啓動這個activity的是一個activity,那麼這個activity的處理 將按照它的前一個activity的處理方式來處理。無論在何種狀況下,它的前一個activity都是啓動它的activity,即使resultTo 不是前一個activity,如設置了Intent.FLAG_ACTIVITY_FORWARD_RESULT。若是複用task中每一個 activity的resultTo都不爲空,而且上述處理優先級在其前面的屬性沒有設置的話,那麼這個複用task中的activity將不做任何的處 理。通常狀況下,activity的resultTo都不爲空,除非設置了Intent.FLAG_ACTIVITY_FORWARD_RESULT,那 麼此時被啓動的activity的caller的resultTo將會爲空。

(1) 對於複用task中的除root activity外的activity,有以下處理方式。

     task中的activity的屬性設置是上述屬性的組合,所以reset task過程要按照必定的優先級來處理,上述屬性的處理優先級是:⑥=④>⑦>⑤>③=②>①

     具體操做順序以下:
     Ⅰ. 根據⑥,④條件來刪除複用task中相應的activity;

     Ⅱ. ⑦條件下,將會暫時不作處理,再根據它的前一個activity的屬性來作處理,即便這個activity設置了allowTaskReparenting;

     Ⅲ. 若是activity的resultTo爲空,而且知足條件⑤,那麼將其及其以上未做處理的,知足條件⑦的全部activity,一併進行 TaskReparenting操做,並放置在mHistory棧底。它們在mHistory棧底順序如同在複用task中的順序;

     Ⅳ. 根據①②③的條件來刪除複用task中相應的activity。

(2) 不屬於複用task的activity,而且它的resultTo不爲空,那麼將根據它的前一個activity的處理來處理。

(3) 不屬於複用task,可是和當前啓動的activity有相同affinity,而且容許TaskReparenting操做,那麼將進行如下操做:
    Ⅰ. 若是知足上述的①②③④的條件,可是其中的task不是複用task,而是這個activity所處的task,那麼將返回這個activity,而不是進行TaskReparenting操做。
       由於它和啓動的activity有相同的affinity,所以AMS認爲這個activity是和啓動activity相關的,之後可能會從新調用,所 以當其知足刪除條件後,這時它將不容許TaskReparenting操做,而且不該該再容許它存在於其餘的task中,此時應該刪除。

    Ⅱ. 若是沒有知足①②③④的條件,那麼將會對其進行TaskReparenting操做,從新將其移動到複用task或新啓動的task中。

Task reset代碼以下:

resetTaskIfNeededLocked()@ActivityStack.java

final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop, ActivityRecord newActivity) {
    boolean forceReset = (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
    if (ACTIVITY_INACTIVE_RESET_TIME > 0
                    && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
        if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
            forceReset = true;
        }
    }
    
    final TaskRecord task = taskTop.task;
    
    // taskFound值爲false, 直到咱們評價TaskRecord與taskTop相關聯。由於剩餘的tasks,taskFound會被設爲true。在之後tasks reparenting過程當中被使用。
    boolean taskFound = false;

    // 若是ActivityOptions被移除,那麼須要停止或者移到taskTop。
    ActivityOptions topOptions = null;

    // 保留reparenting時在新task中的位置。
    int reparentInsertionPoint = -1;
    for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
        final TaskRecord targetTask = mTaskHistory.get(i);
    
        if (targetTask == task) {
            topOptions = resetTargetTaskIfNeededLocked(task, forceReset);
            taskFound = true;
        } else {
            reparentInsertionPoint = resetAffinityTaskIfNeededLocked(targetTask, task, taskFound, forceReset, reparentInsertionPoint);
        }
    }    
    int taskNdx = mTaskHistory.indexOf(task);
    do {
        taskTop = mTaskHistory.get(taskNdx--).getTopActivity();
    } while (taskTop == null && taskNdx >= 0);
    
    if (topOptions != null) {
        // 若是從task移除的top activity中獲得有些ActivityOptions,則將它們傳給新的正在的top。
        if (taskTop != null) {
            taskTop.updateOptionsLocked(topOptions);
        } else {
            topOptions.abort();
        }
    }    
    return taskTop;
}

resetTargetTaskIfNeededLocked()@ActivityStack.java

// 若是須要做爲啓動的一部分,對給定的task執行一個reset操做。返回task top的新的HistoryRecord。
// resetTaskIfNeededLocked的輔助方法,咱們處在正在reset的task的內部,咱們可能finish掉這個activity,把它推到另一個task,或者讓它保持原樣。
// 參數task是包含了可能被reset的activity(taskTop)。
final ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset) {
    ActivityOptions topOptions = null;
    
    int replyChainEnd = -1;
    boolean canMoveOptions = true;
    
    // 只有當activity不是task的root時才作這個操做,由於若是咱們finish掉root了,可能再也不有task了。
    final ArrayList<ActivityRecord> activities = task.mActivities;
    final int numActivities = activities.size();
    for (int i = numActivities - 1; i > 0; --i ) {
        ActivityRecord target = activities.get(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;
    
        if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
            // 若是這個activity正在發送一個回覆給前一個activity,咱們如今不能作任何事,直到咱們到達回覆鏈的開端。
            // 咱們假設result老是給前一個activity,幾乎老是這樣,但咱們真的不該該期望老是這種狀況。
            if (replyChainEnd < 0) {
                replyChainEnd = i;
            }
        } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
                   && target.taskAffinity != null && !target.taskAffinity.equals(task.affinity)) {
            // 若是這個activity有給另一個task的affinity,那麼須要將它移出這裏。儘量將它移到activity棧的底部。同時讓它與以前移動的activity保持正確的順序。
            final ActivityRecord bottom = !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
                                            mTaskHistory.get(0).mActivities.get(0) : null;
            if (bottom != null && target.taskAffinity != null && target.taskAffinity.equals(bottom.task.affinity)) {
                // 若是當前bottom的activity與咱們正在移動的activity有相同的affinity,那麼就將它合進同一個task中。
                target.setTask(bottom.task, bottom.thumbHolder, false);
            } else {
                target.setTask(createTaskRecord(mStackSupervisor.getNextTaskId(), target.info, null, false), null, false);
                target.task.affinityIntent = target.intent;
            }

            final TaskRecord targetTask = target.task;
            final int targetTaskId = targetTask.taskId;
            mWindowManager.setAppGroupId(target.appToken, targetTaskId);

            boolean noOptions = canMoveOptions;
            final int start = replyChainEnd < 0 ? i : replyChainEnd;
            for (int srcPos = start; srcPos >= i; --srcPos) {
                final ActivityRecord p = activities.get(srcPos);
                if (p.finishing) {
                    continue;
                }

                ThumbnailHolder curThumbHolder = p.thumbHolder;
                canMoveOptions = false;
                if (noOptions && topOptions == null) {
                    topOptions = p.takeOptionsLocked();
                    if (topOptions != null) {
                        noOptions = false;
                    }
                }
                p.setTask(targetTask, curThumbHolder, false);
                targetTask.addActivityAtBottom(p);

                mWindowManager.setAppGroupId(p.appToken, targetTaskId);
            }
    
            mWindowManager.moveTaskToBottom(targetTaskId);
            if (VALIDATE_TOKENS) {
                validateAppTokensLocked();
            }
    
            replyChainEnd = -1;
        } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
            // 若是activity應該被刪除,或者它要求被刪除,或者task要被清除,那麼finish掉它和做爲它回覆鏈的一部分的任何內容。
            int end;
            if (clearWhenTaskReset) {
                // 這種狀況下,咱們想要finish這個activity和它上面的全部東西,因此要假設這些都是在回覆鏈上。
                end = numActivities - 1;
            } else if (replyChainEnd < 0) {
                end = i;
            } else {
                end = replyChainEnd;
            }
            boolean noOptions = canMoveOptions;
            for (int srcPos = i; srcPos <= end; srcPos++) {
                ActivityRecord p = activities.get(srcPos);
                if (p.finishing) {
                    continue;
                }
                canMoveOptions = false;
                if (noOptions && topOptions == null) {
                    topOptions = p.takeOptionsLocked();
                    if (topOptions != null) {
                        noOptions = false;
                    }
                }

                // 調用finishActivityLocked來finish一個activity
                if (finishActivityLocked(p, Activity.RESULT_CANCELED, null, "reset", false)) {
                    end--;
                    srcPos--;
                }
            }
            replyChainEnd = -1;
        } else {
            // 若是咱們在一個鏈的中間,啓動它的activity不想有什麼特別的操做,那麼保持它的原樣。
            replyChainEnd = -1;
        }
    }
    return topOptions;
}

2.6.5 判斷是否存在可複用的activity

 若是history中有可複用的task,那麼在某些狀況下並不須要啓動這個activity,下面分析緣由:

(1) Intent設置了Intent.FLAG_ACTIVITY_CLEAR_TOP,或者launchMode == ActivityInfo.LAUNCH_SINGLE_TASK,或者r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;這3種條件有一個共同點,就是啓動的activity啓動之

     後,在這個task中, 這個activity之上不能有其餘的activity。

     通常狀況下,須要將複用task中要啓動的activity之上的全部activity刪除。

    當activity的launchMode == ActivityInfo.LAUNCH_MULTIPLE,而且Intent沒有設置singletop模式時,那麼要刪除複用task中與啓動activity相同的activity,也就是不但願複用相同的activity。

    若是有可複用的activity,而且這個activity是task的root activity,因爲task的Intent是root activity的Intent,因此須要從新設置task的Intent。向可複用的activity發送新的Intent,通知它Intent的變化,最終會調用到這個activity的onNewIntent()方法。

(2) 若是不知足(1)條件的話,可是啓動的activity與複用task的root activity相同,那麼按狀況處理:

  •     若是Intent設置了Intent.FLAG_ACTIVITY_SINGLE_TOP,而且複用task的top activity正好是要啓動的activity,則複用這個activity,同時更新activity的Intent,若是須要也會更新task的Intent。
  •     若是Intent沒有設置了Intent.FLAG_ACTIVITY_SINGLE_TOP,即便設置了,可是當前的top activity不是正要啓動的activity,那麼判斷若是當前啓動的Intent和task的Intent不一樣,那麼將會從新啓動這個activity。
  •     其餘狀況,將直接resume top activity。

(3) 若是(1)(2)條件均不知足,那麼複用的task中就不存在與啓動的activity相同的activity了,若是啓動的Intent沒有設置Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,那麼必定不會複用任何的activity。

(4) 若是(1)(2)條件均不知足,而且Intent設置了Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,那麼須要檢查當前複用task的Intent是否設置了Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED。

    若是沒有設置,從新設置新的Intent, 一樣不可複用activity。

    這種狀況下,將不會顯示要啓動的activity,而是改成顯示覆用的task中的內容。

2.6.6 ActivityInfo.LAUNCH_SINGLE_TOP和ActivityInfo.LAUNCH_SINGLE_TASK屬性的處理

    當設置Intent.FLAG_ACTIVITY_SINGLE_TOP或者launchMode == ActivityInfo.LAUNCH_SINGLE_TOP或者launchMode == ActivityInfo.LAUNCH_SINGLE_TASK這幾種狀況下,若是top activity與啓動的activity爲同一個activity,那麼將復

用top activity,並直接resume top activity。

2.6.7 standard和ActivityInfo.LAUNCH_SINGLE_INSTANCE模式

    代碼中爲何沒有明顯的針對ActivityInfo.LAUNCH_SINGLE_INSTANCE模式的處理,這是由於這種啓動模式,若是Task複用失敗,直接爲其啓動一個Intent.FLAG_ACTIVITY_NEW_TASK便可。

    (1) 設置了Intent.FLAG_ACTIVITY_NEW_TASK,則爲該activity建立一個新的task。

    (2) 在當前的task中啓動新的activity,

          ① 當前的caller是一個activity,若是設置Intent.FLAG_ACTIVITY_CLEAR_TOP,當前的task若是存在要啓動的activity(這個和上面中的Task複用時的clear top過程不一樣,二者是互斥的過程,不衝突),清除其上的全部的activity。

          ② 當前的caller是一個activity,若是設置Intent.FLAG_ACTIVITY_REORDER_TO_FRONT,這個flag表示若是啓動的activity已經在當前的task中,那麼若是當前啓動的Intent設置了該flag,那麼則會將這個activity從task中移動到top。

             若是A-->B-->C-->D,D啓動B時,設置了該flag,那麼將變爲A-->C-->D-->B。

             ①②兩個條件,都不須要再啓動新的activity,直接resume top。        

         ③ 當前的caller是一個activity,其餘狀況則須要啓動新的activity。

    (3) 當前的caller不是activity,那麼仍將新啓動的activity放在top的task中。

相關文章
相關標籤/搜索