基于Android 6.0的源碼剖析, 分析android Activity啟動流程,相關源碼:
<code>startActivity</code>的整體流程與startService啟動過程分析非常相近,但比Service啟動更為複雜,多了stack/task以及UI的相關内容以及Activity的生命周期更為豐富。
Activity啟動發起後,通過Binder最終交由system程序中的AMS來完成,則啟動流程如下圖:

接下來,從源碼來說說每個過程。
[-> Activity.java]
execStartActivity()方法的參數:
<code>mAppThread</code>: 資料類型為ApplicationThread,通過mMainThread.getApplicationThread()方法擷取。
<code>mToken</code>: 資料類型為IBinder.
[-> Instrumentation.java]
關于 ActivityManagerNative.getDefault()傳回的是ActivityManagerProxy對象. 此處startActivity()的共有10個參數, 下面說說每個參數傳遞AMP.startActivity()每一項的對應值:
caller: 目前應用的ApplicationThread對象mAppThread;
callingPackage: 調用目前ContextImpl.getBasePackageName(),擷取目前Activity所在包名;
intent: 這便是啟動Activity時,傳遞過來的參數;
resolvedType: 調用intent.resolveTypeIfNeeded而擷取;
resultTo: 來自于目前Activity.mToken
resultWho: 來自于目前Activity.mEmbeddedID
requestCode = -1;
startFlags = 0;
profilerInfo = null;
options = null;
[-> ActivityManagerNative.java :: ActivityManagerProxy]
AMP經過binder IPC,進入ActivityManagerNative(簡稱AMN)。接下來程式進入了system_servr程序,開始繼續執行。
[-> ActivityManagerNative.java]
[-> ActivityManagerService.java]
此處mStackSupervisor的資料類型為<code>ActivityStackSupervisor</code>
當程式運作到這裡時, ASS.startActivityMayWait的各個參數取值如下:
caller = ApplicationThreadProxy, 用于跟調用者程序ApplicationThread進行通信的binder代理類.
callingUid = -1;
callingPackage = ContextImpl.getBasePackageName(),擷取調用者Activity所在包名
intent: 這是啟動Activity時傳遞過來的參數;
resolvedType = intent.resolveTypeIfNeeded
voiceSession = null;
voiceInteractor = null;
resultTo = Activity.mToken, 其中Activity是指調用者所在Activity, mToken對象儲存自己所處的ActivityRecord資訊
resultWho = Activity.mEmbeddedID, 其中Activity是指調用者所在Activity
outResult = null;
config = null;
ignoreTargetSecurity = false;
userId = AMS.handleIncomingUser, 當調用者userId跟目前處于同一個userId,則直接傳回該userId;當不相等時則根據調用者userId來決定是否需要将callingUserId轉換為mCurrentUserId.
iContainer = null;
inTask = null;
再來看看這個方法的源碼:
[-> ActivityStackSupervisor.java]
該過程主要功能:通過resolveActivity來擷取ActivityInfo資訊, 然後再進入ASS.startActivityLocked().先來看看
ActivityManager類有如下4個flags用于調試:
START_FLAG_DEBUG:用于調試debug app
START_FLAG_OPENGL_TRACES:用于調試OpenGL tracing
START_FLAG_NATIVE_DEBUGGING:用于調試native
START_FLAG_TRACK_ALLOCATION: 用于調試allocation tracking
AppGlobals.getPackageManager()經過函數層層調用,擷取的是ApplicationPackageManager對象。經過binder IPC調用,最終會調用PackageManagerService對象。故此時調用方法為PMS.resolveIntent().
[-> PackageManagerService.java]
ASS.resolveActivity()方法的核心功能是找到相應的Activity元件,并儲存到intent對象。
其中有兩個傳回值代表啟動Activity失敗:
START_INTENT_NOT_RESOLVED: 從Intent中無法找到相應的Component或者ActivityInfo
START_NOT_CURRENT_USER_ACTIVITY:該Activity對目前使用者不可見
當mAppSwitchesAllowedTime時間小于目前時長,或者具有STOP_APP_SWITCHES的權限,則允許app發生切換操作.
其中mAppSwitchesAllowedTime, 在<code>AMS.stopAppSwitches()</code>的過程中會設定為:<code>mAppSwitchesAllowedTime = SystemClock.uptimeMillis() + APP_SWITCH_DELAY_TIME</code>. 禁止app切換的timeout時長為5s(APP_SWITCH_DELAY_TIME = 5s).
當發送5秒逾時或者執行<code>AMS.resumeAppSwitches()</code>過程會将mAppSwitchesAllowedTime設定0, 都會開啟允許app執行切換的操作.另外,禁止App切換的操作,對于同一個app是不受影響的,有興趣可以進一步檢視<code>checkComponentPermission</code>過程.
<code>mPendingActivityLaunches</code>記錄着所有将要啟動的Activity, 是由于在<code>startActivityLocked</code>的過程時App切換功能被禁止, 也就是不運作切換Activity, 那麼此時便會把相應的Activity加入到<code>mPendingActivityLaunches</code>隊列. 該隊列的成員在執行完<code>doPendingActivityLaunchesLocked</code>便會清空.
啟動mPendingActivityLaunches中所有的Activity, 由于doResume = false, 那麼這些activtity并不會進入resume狀态,而是設定delayedResume = true, 會延遲resume.