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沒有關系。

 1. 創建ActivityRecord

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檢查

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.java

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.java

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的創建與管理

2.1 Task與Application的區別

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中。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM