天天看點

[Android]從Launcher開始啟動App流程源碼分析

以下内容為原創,歡迎轉載,轉載請注明

<code>com.android.launcher.Launcher</code>就是我們的Launcher頁面了,可以看到Launcher其實也是一個<code>Activity</code>:

既然是<code>Activity</code>,那當然也會有<code>onCreate</code>、<code>onResume</code>等生命周期了,按照邏輯,應該會去加載所有App,以網格的布局顯示在頁面上,果然,在<code>onResume</code>看到了這個方法:

看方法名就可以猜到這個方法就是用來加載所有App資訊的,進入這個方法:

這裡調用<code>sModel</code>(<code>LauncherModel</code>類型)的<code>loadUserItems</code>方法去加載資料了,<code>sModel</code>明顯屬于<code>Model</code>層,進入<code>loadUserItems</code>方法:

然後使用<code>DesktopItemsLoader</code>在<code>mDesktopLoaderThread</code>線程中加載,:

然後我們回到<code>Launcher</code>的<code>onDesktopItemsLoaded</code>方法:

繼續進入<code>bindDesktopItems</code>方法:

進入<code>startBindingItems</code>方法:

這裡使用了<code>Handler</code>發送消息,進入<code>Handler</code>的<code>handleMessage</code>方法:

接收到消息之後調用<code>bindItems</code>方法:

這裡我們隻考慮app或者app快捷方式的情況,檔案夾和widgets暫時不考慮。app或者app快捷方式實質上都是進入了這個邏輯中,調用<code>createShortcut</code>方法:

這裡首先inflater出item的布局,然後設定<code>text</code>和<code>OnClickListener</code>,還有tag,這個tag是<code>ApplicationInfo</code>,裡面包含了各種App資訊,是從App的<code>AndroidManifest.xml</code>的<code>&lt;application&gt;</code>标簽中解析出來的。既然設定了點選事件,顯然,點選後應該會打開對應的App才對。是以繼續看<code>onClick</code>方法:

點選App就會通過<code>startActivitySafely</code>方法使用剛才設定的tag,也就是<code>ApplicationInfo</code>中的intent進行跳轉:

然後我們來看看打開某個app的時候整個流程是怎麼走的。接着上面的的<code>startActivity()</code>方法走:

可以看到,不管你是調用了<code>startActivity</code>還是<code>startActivityForResult</code>方法,<code>startActivityForResult</code>方法,并且如果是調用的<code>startActivity</code>,則預設<code>requestCode</code>就是-1,是以如果你想調用<code>startActivityForResult</code>的時候,注意不能把<code>requestCode</code>設定為-1,否則它的效果就跟<code>startActivity</code>一樣了,不會再回調<code>onActivityResult</code>!,再看看<code>startActivityForResult</code>的實作:

可以看到,Activity内部是使用<code>mInstrumentation</code>(<code>Instrumentation</code>類型)執行<code>execStartActivity</code>方法來實作<code>Activity</code>跳轉的,執行完畢後會傳回一個<code>Instrumentation.ActivityResult</code>。

然後檢視<code>Instrumentation::execStartActivity</code>:

首先通過<code>ActivityManagerNative.getDefault()</code>獲得一個<code>IActivityManager</code>的實作類:

先通過Binder IPC的方式從服務端擷取一個<code>Activity Manager</code>,然後通過<code>ActivityManagernative</code>封裝成一個代理<code>ActivityManagerProxy</code>對象,然後調用<code>startActivity</code>也是使用了Binder IPC進行與伺服器端的通信,(整個Android系統的通信機制使用了大量的Binder IPC,這個以後再專門讨論這個吧),接着,我們進入到了<code>com.android.server.am.ActivityManagerService</code>的<code>startActivity</code>方法:

接下來的調用鍊:

-&gt; <code>startActivityAsUser</code>

-&gt; <code>startActivityMayWait</code>

-&gt; <code>startActivityLocked</code>

-&gt; <code>startActivityUncheckedLocked</code>

-&gt; <code>targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options)</code>

-&gt; <code>mStackSupervisor.resumeTopActivitiesLocked(this, r, options)</code>

-&gt; <code>resumeTopActivityInnerLocked(prev, options);</code>

-&gt; <code>mStackSupervisor.startSpecificActivityLocked(next, true, true)</code>

<code>startSpecificActivityLocked</code>方法如下:

首先從<code>mService</code>找出對應需要啟動Activity的程序(通過程序名字和uid,程序名字可以在<code>AndroidManifest.xml</code>中配置)如果可以擷取到,說明這個Activity所屬的程序已經存在了,也就是說app已經在運作了,那就會調用<code>realStartActivityLocked</code>,否則,如果該Activity所在的App是第一次啟動,則會調用<code>mService.startProcessLocked</code>方法:

這3個重載方法做的事情就是,先根據程序名字調用<code>getProcessRecordLocked()</code>擷取<code>ProcessRecord</code>,如果<code>ProcessRecord</code>不存在,則調用<code>newProcessRecordLocked()</code>方法建立一個<code>ProcessRecord</code>,并且新的<code>ProcessRecord</code>綁定了<code>ApplicationInfo</code>,<code>uid</code>等資訊,但後進入第三個重載方法,執行建立、啟動程序。

再看<code>Process::start</code>的實作:

接下來就是通過<code>Zygote</code>程序<code>fork</code>一個新的程序作為app的程序。這裡要需要講的一個參數是<code>processClass</code>,這個參數表示一個類,它用來作為新建立的程序的主入口,會調用這個類的靜态<code>main</code>方法,這個參數在<code>startProcessLocked</code>方法中會被檢查重置,如果是null的話,就預設是<code>android.app.ActivityThread</code>。

現在App的程序也建立成功了,就會進入<code>android.app.ActivityThread</code>的靜态的<code>main</code>中:

然後建立了一個<code>ActivityThread</code>,說明每當一個新的app程序被建立,都會對應一個新的<code>ActivityThread</code>執行個體,然後調用它的<code>attach</code>方法:

然後再次通過Binder IPC調用<code>ActivityManagerProxy</code>的<code>attachApplication</code>,傳入的<code>ApplicationThread</code>(Binder)參數用于在服務端進行回調通信。最後進入<code>ActivityManagerService::attachApplication</code>,再調用<code>attachApplicationLocked(thread, callingPid)</code>

首先,通過pid擷取剛剛建立的程序,然後對app進行一些初始化工作,然後調用<code>bindApplication</code>遠端調用用戶端<code>ActivityThread::bindApplication</code>,再通過<code>Handler</code>調用到<code>ActivityThread::handleBindApplication</code>方法:

首先,建立一個目前App的<code>Context</code>,然後如果<code>data.instrumentationName != null</code>,則初始化<code>Instrumentation</code>相關的變量,并建立<code>Instrumentation</code>的<code>ApplicationInfo</code>等對象來建立<code>Instrumentation</code>的<code>Context</code>,然後建立<code>Instrumentation</code>對象,并調用它的<code>init</code>方法進行初始化。如果<code>data.instrumentationName == null</code>,則new一個<code>Instrumentation</code>(在一個程序中隻會有一個<code>Instrumentation</code>執行個體)然後建立<code>Application</code>對象,并調用它的<code>onCreate</code>方法,這樣<code>Application</code>就會被回調了。

然後我們回到<code>ActivityManagerService::attachApplicationLocked</code>方法,遠端執行完<code>thread.bindApplication</code>方法之後,接下來會調用<code>mStackSupervisor.attachApplicationLocked(app)</code>方法:

先通過<code>topRunningActivityLocked</code>從堆棧頂端擷取要啟動的Activity,然後<code>realStartActivityLocked(hr, app, true, true)</code>:

繼續通過Binder IPC遠端調用<code>scheduleLaunchActivity</code>方法,然後進入<code>ActivityThread</code>的<code>scheduleLaunchActivity</code>方法中,然後通過<code>Handler</code>進入<code>handleLaunchActivity</code>方法:

先調用<code>performLaunchActivity</code>方法傳回一個<code>Activity</code>,然後調用<code>handleResumeActivity</code>方法讓該<code>Activity</code>進入<code>onResume</code>狀态。是以很顯然在<code>performLaunchActivity</code>中肯定是生成了<code>Activity</code>執行個體,并調用了<code>onCreate</code>方法了,來看下代碼:

首先,初始化<code>LoadedApk</code>,然後通過<code>Instrumentation</code>來建立一個<code>Activity</code>執行個體,通過<code>createBaseContextForActivity</code>方法建立一個<code>Activity Context</code>,調用<code>activity</code>的<code>attach</code>方法,然後依次觸發該<code>Activity</code>的<code>onCreate</code>、<code>onRestoreInstanceState</code>、<code>onPostCreate</code>等生命周期方法。

<code>createBaseContextForActivity</code>方法如下:

通過<code>ContextImpl::createActivityContext</code>建立的<code>Context</code>對象,可以發現,不論是<code>System Context/App Context/Activity Context</code>,這些<code>Context</code>都是通過<code>ContextImpl</code>生成的,具體這裡再挖個坑先。

再繼續進入<code>Activity::attach</code>方法:

上面對<code>Activity</code>與<code>ActivityThread</code>、<code>Instrumentation</code>等進行了綁定,是以說每個<code>Activity</code>都含有一個<code>ActivityThread</code>引用和一個<code>Instrumentation</code>引用,而<code>ActivityThread</code>執行個體和<code>Instrumentation</code>執行個體在一個程序中都隻有一個執行個體,因為<code>ActivityThread</code>是在程序被建立成功後,進入<code>ActivityThread</code>的<code>static main()</code>時才會被建立,而<code>Instrumentation</code>則是在<code>ActivityThread</code>被建立後進行<code>attach</code>的之後被建立。

<code>Activity::startActivity</code>

<code>Activity::startActivityForResult</code>

<code>Instrumentation::execStartActivity</code>:

攜帶參數:

<code>who</code>:from的Context

<code>contextThread</code>:from的<code>ActivityThread</code>的<code>ApplicationThread</code>,<code>ApplicationThread</code>中可以通過Binder IPC提供給服務端回調<code>Activity</code>生命周期等操作(from的主線程)。

<code>mToken</code>:<code>Binder</code>類型,用來辨別from的Activity,可能為null。

<code>target</code>:from的Activity(是以是用來接收跳轉結果的),如果不是從Activity跳轉則為null。

<code>intent</code>:跳轉Intent。

<code>requestCode</code>:如果是<code>startActivity</code>,則為-1。

<code>options</code>:額外Bundle資料。

<code>ActivityManagerProxy::startActivity()</code>:

<code>caller</code>:上面的<code>contextThread</code>,from主線程。

<code>callingPackage</code>:from的Context包名。

<code>resolvedType</code>:跳轉Intent的MIME類型。

<code>resultTo</code>:上面的<code>token</code>,<code>Binder</code>類型,用來辨別from的Activity。

<code>resultWho</code>:from的Activity的mEmbeddedID(唯一标示字元串)

<code>startFlags</code>:預設傳入為0。

<code>profilerInfo</code>:預設傳入為null。

<code>ActivityManagerService::startActivity()</code>(通過Binder IPC調用):

攜帶參數跟上面一樣。

<code>ActivityManagerService::startActivityAsUser</code>

攜帶參數包括<code>ActivityManagerService::startActivity()</code>所有的參數,最再加一個:

<code>userId</code>:userId,根據給目前程序配置設定的Linux UID(這個UID可以用來讓上層系統服務進行身份識别和權限檢查)得到一個userId(如果不是多使用者,則直接傳回0)。

<code>ActivityStackSupervisor::startActivityMayWait()</code>

參數:

<code>caller</code>:上面的<code>caller/contextThread</code>,from主線程。

<code>callingUid</code>:調用使用者uid。

<code>voiceSession</code>:傳null。

<code>voiceInteractor</code>:傳null。

<code>resultTo</code>:上面的<code>resultTo/token</code>,<code>Binder</code>類型,用來辨別from的Activity。

<code>startFlags</code>:傳null。

<code>profilerInfo</code>:傳null。

<code>outResult</code>:傳null。

<code>config</code>:傳null。

<code>options</code>:額外資料。

<code>ignoreTargetSecurity</code>:false。

<code>userId</code>:上面的<code>userId</code>,根據給目前程序配置設定的Linux UID(這個UID可以用來讓上層系統服務進行身份識别和權限檢查)得到一個userId(如果不是多使用者,則直接傳回0)。

<code>iContainer</code>:傳null。

<code>inTask</code>:null。

<code>ActivityStackSupervisor::startActivityLocked()</code>:

<code>aInfo</code>:<code>ActivityInfo</code>類型,解析from的Activity的Intent資訊。

<code>componentSpecified</code>:是否顯示指定了<code>component</code>。

<code>outActivity</code>:傳null。

<code>container</code>:上面的<code>iContainer</code>,轉型成了<code>ActivityContainer</code>,還是null。

在這個方法中,通過<code>ProcessRecord callerApp = mService.getRecordForAppLocked(caller);</code>擷取到之前建立的<code>ProcessRecord</code>,然後從<code>Activity</code>棧中根據<code>resultTo/token</code>擷取到對應from Activity的<code>ActivityRecord</code>(sourceRecord),然後__建立将要跳轉的Activity的ActivityRecord對象__(<code>Token</code>也是在這個時候生成的)。

<code>ActivityStackSupervisor::startActivityUncheckedLocked()</code>:

<code>r</code>:<code>ActivityRecord</code>類型,就是<code>ActivityStackSupervisor::startActivityLocked()</code>中建立的将要跳轉的Activity的ActivityRecord對象。

<code>sourceRecord</code>:就是<code>ActivityStackSupervisor::startActivityLocked()</code>方法擷取的from Activity的<code>sourceRecord</code>。

<code>doResume</code>:傳true。

這個方法中有大量的代碼來處理<code>task/stack</code>等方面的邏輯,以後再仔細深入這個方法。

<code>ActivityStrack::startActivityLocked()</code>:

方法調用者:<code>ActivityStack</code>類型,

<code>targetStack</code>:在<code>ActivityStackSupervisor::startActivityUncheckedLocked()</code>中确定的需要添加到的<code>ActivityStack</code>。

<code>r</code>:<code>ActivityRecord</code>類型,就是<code>ActivityStackSupervisor::startActivityLocked()</code>中建立的跳轉的Activity的ActivityRecord對象。

<code>newTask</code>:是否<code>Intent</code>是否設定了<code>Intent.FLAG_ACTIVITY_NEW_TASK</code>。

<code>keepCurTransition</code>:這個具體後面再研究,跟<code>Intent</code>的flag有關。

同樣,這個方法中有大量的代碼來處理<code>task/stack</code>等方面的邏輯,以後再仔細深入這個方法__(執行完這個方法後,<code>ActivityRecord</code>就會被真正加入到<code>ActivityStack</code>中)__。

<code>ActivityStackSupervisor::resumeTopActivitiesLocked()</code>:

<code>target</code>:<code>ActivityRecord</code>類型,就是<code>ActivityStackSupervisor::startActivityLocked()</code>中建立的跳轉的Activity的ActivityRecord對象。

<code>targetOptions</code>:額外資料。

<code>ActivityStack::resumeTopActivityLocked()</code>:

<code>prev</code>:<code>ActivityRecord</code>類型,就是<code>ActivityStackSupervisor::startActivityLocked()</code>中建立的跳轉的Activity的ActivityRecord對象。

<code>ActivityStack::resumeTopActivityInnerLocked()</code>:

<code>ActivityStackSupervisor::startSpecificActivityLocked()</code>:

<code>r</code>:最頂部沒有處于finishing的Activity,就是剛剛在<code>startActivityLocked</code>中加入的将要跳轉的<code>ActivityRecord</code>,通過<code>topRunningActivityLocked(null)</code>查找

<code>andResume</code>:傳true

<code>checkConfig</code>:傳true

<code>ActivityManagerService::startProcessLocked()</code>:

<code>processName</code>:建立程序的名稱,就是<code>ActivityStack::startSpecificActivityLocked()</code>中的<code>r.processName</code>

<code>info</code>:<code>ApplicationInfo</code>,也是<code>r.info.applicaitonInfo</code>,具體可以檢視<code>ActivityStackSupervisor::startActivityLocked()</code>中建立<code>ActivityRecord</code>的代碼。

<code>knownToBeDead</code>:傳true。

<code>intentFlags</code>:傳0。

<code>hostingType</code>:傳字元串“activity”。

<code>hostingName</code>:<code>ComponentName</code>類型,<code>intent</code>中的<code>Componentname</code>

<code>allowWhileBooting</code>:傳false。

<code>isolated</code>:傳false

<code>keepIfLarge</code>傳true

<code>ActivityManagerService::startProcessLocked()</code>(重載方法):

參數包含上面所有,多了以下幾個:

<code>isolatedUid</code>:傳0

<code>abiOverride</code>:傳null

<code>entryPoint</code>:傳null

<code>entryPointArgs</code>傳null

<code>crashHandler</code>傳null

注意:在這個方法中,會建立新程序的<code>ProcessRecord</code>對象,并綁定<code>ApplicationInfo</code>等資訊,這樣,啟動程序後進行<code>bindApplicaiton</code>的時候就可以根據程序PID擷取到所有的<code>ApplicationInfo</code>資訊了。

<code>app</code>:<code>ProcessRecord</code>類型,建立的程序。

<code>hostingNameStr</code>:通過<code>hostingName</code>生成的字元串(包名 + "/" + 類的簡單類名)

<code>Process.start()</code>

參數(省略部分參數):

<code>processClass</code>:上面的<code>entryPoint</code>,但是并不是null了,而是<code>android.app.ActivityThread</code>,因為在<code>ActivityManagerService::startProcessLocked()</code>中被設定預設值了,它表示一個類,用來作為新建立的程序的主入口,會調用這個類的靜态main方法。是以啟動完這個程序就會進入<code>ActivityThread</code>的<code>static main()</code>方法。

<code>zygoteArgs</code>:fork zygote程序時的參數。

<code>ActivityThread::main()</code>

<code>ActivityThread::attach()</code>

<code>ActivityManagerProxy::attachApplication()</code>:

<code>mAppThread</code>:<code>ApplicationThread()</code>類型,Binder,用來提供給AMS調用。

<code>ActivityManagerService::attachApplication()</code>:

<code>ActivityManagerService::attachApplicationLocked()</code>:

<code>thread</code>:<code>ApplicationThread()</code>類型,Binder,用來提供給AMS調用。上面的<code>mAppThread</code>。

<code>pid</code>:目前調用的程序PID。

<code>IApplicationThread::bindApplication()</code>:

方法調用調用者:上面的<code>thread/mAppThread</code>,Binder,用來提供給AMS調用。

<code>packageName</code>:用的程序名字<code>processName</code>

<code>info</code>:<code>ApplicationInfo</code>類型,從<code>ProcessRecord</code>中的<code>instrumentationInfo或者info</code>,這個<code>ApplicationInfo</code>是在建立<code>ProcessRecord</code>時就儲存了。

<code>ActivityThread::bindApplication()</code>:

參數:同上

<code>ActivityThread::handleBindApplication()</code>:

通過Handler調用。

<code>data</code>:<code>AppBindData</code>類型,裡面包含的類型<code>processName</code>,<code>providers</code>,<code>instrumentationName</code>,<code>instrumentationArgs</code>,<code>instrumentationWatcher</code>,<code>instrumentationUiAutomationConnection</code>,<code>config</code>等資料。

<code>ActivityManagerService</code>中的<code>ActivityThread::bindApplication()</code>執行完畢之後

<code>ActivityStackSupervisor::attachApplicationLocked()</code>:

<code>app</code>:建立的程序綁定的<code>ProcessRecord</code>。

<code>ActivityStackSupervisor::realStartActivityLocked()</code>:

<code>r</code>:<code>ActivityRecord</code>類型,topRunningActivityLocked從堆棧頂端擷取要啟動的Activity。

<code>andResume</code>:傳入true

<code>checkConfig</code>:傳入true

<code>IApplicationThread::scheduleLaunchActivity()</code>:

參數(部分):

<code>intent</code>:将要啟動的<code>ActivityRecord</code>中的<code>intent</code>。

<code>token</code>:将要啟動的<code>ActivityRecord</code>中的<code>token</code>。

<code>info</code>:将要啟動的<code>ActivityRecord</code>中的<code>ApplicationInfo</code>。

<code>ActivityThread::scheduleLaunchActivity()</code>:

Binder IPC調用,參數與<code>IApplicationThread::scheduleLaunchActivity()</code>相同。

<code>ActivityThread::handleLaunchActivity()</code>:

該方法通過Handler調用,參數同上。

<code>r</code>:<code>ActivityClientRecord</code>類型,在<code>ActivityThread::scheduleLaunchActivity()</code>中封裝,包括的資料有<code>token</code>, <code>ident</code>, <code>intent</code>, <code>activityInfo</code>等等,但是<code>LoadedApk</code>是這時根據包名從<code>ActivityThread</code>中弱引用緩存中擷取的的。

<code>customIntent</code>:null

<code>ActivityThread::performLaunchActivity()</code>:

參數與<code>ActivityThread::handleLaunchActivity()</code>相同。

<code>Activity::attach()</code>:

<code>context</code>:<code>ActivityThread::performLaunchActivity()</code>中建立的<code>Activity Context</code>。

<code>aThread</code>:<code>ActivityThread</code>類型,主線程,一個程序都共用一個。

<code>token</code>:建構<code>ActivityRecord</code>時生成的<code>token</code>。

<code>application</code>:<code>Application</code>第一次的時候建立一遍。

<code>intent</code>:将要啟動的ActivityRecord中的intent。

<code>info</code>:<code>ActivityInfo</code>類型,将要啟動的ActivityRecord中的<code>ActivityInfo</code>。

<code>Instrumentation::callActivityOnCreate()</code>:

<code>activity</code>:<code>ActivityThread::performLaunchActivity()</code>中建立的<code>Activity</code>。

<code>Activity::performCreate()</code>

<code>Activity::onCreate()</code>

繼續閱讀