天天看點

startActivity啟動過程分析(轉)

基于Android 6.0的源碼剖析, 分析android Activity啟動流程,相關源碼:

​<code>​startActivity​</code>​的整體流程與​​startService啟動過程分析​​非常相近,但比Service啟動更為複雜,多了stack/task以及UI的相關内容以及Activity的生命周期更為豐富。

Activity啟動發起後,通過Binder最終交由system程序中的AMS來完成,則啟動流程如下圖:

startActivity啟動過程分析(轉)

接下來,從源碼來說說每個過程。

[-&gt; Activity.java]

execStartActivity()方法的參數:

​<code>​mAppThread​</code>​: 資料類型為ApplicationThread,通過mMainThread.getApplicationThread()方法擷取。

​<code>​mToken​</code>​: 資料類型為IBinder.

[-&gt; 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;

[-&gt; ActivityManagerNative.java :: ActivityManagerProxy]

AMP經過binder IPC,進入ActivityManagerNative(簡稱AMN)。接下來程式進入了system_servr程序,開始繼續執行。

[-&gt; ActivityManagerNative.java]

[-&gt; 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;

再來看看這個方法的源碼:

[-&gt; 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().

[-&gt; 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.