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相同,那麼按狀況處理:
(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中。