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