【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )
文章目錄
- 前言
- 一、熱啟動與冷啟動選擇
- 二、AMS 進(jìn)程中執(zhí)行的相關(guān)操作
- 三、通過 Binder 機制轉(zhuǎn)到 ActivityThread 中執(zhí)行的操作
- 總結(jié)
前言
上一篇博客 【Android 啟動過程】Activity 啟動源碼分析 ( AMS -> ActivityThread、AMS 線程階段 ) 分析的分支是啟動 Activity 時 , 沒有 Activity 對應(yīng)的進(jìn)程 , 需要先調(diào)用 Zygote 啟動相應(yīng)進(jìn)程 , 然后再啟動 Activity , 屬于冷啟動 ;
本篇博客補充下 " 熱啟動 " 的流程 ;
一、熱啟動與冷啟動選擇
在 ActivityStackSupervisor.startSpecificActivityLocked 方法中 , 判定要啟動的 Activity 是否存在 , 決定要使用冷啟動還是熱啟動 ;
如果啟動時 , 發(fā)現(xiàn)已經(jīng)存在 Activity 對應(yīng)進(jìn)程 , 那么執(zhí)行下面的熱啟動方法 :
// 如果啟動 Activity 時 , 發(fā)現(xiàn)進(jìn)程存在 , 則直接啟動 Activity , 熱啟動realStartActivityLocked(r, app, andResume, checkConfig);如果啟動時 , 發(fā)現(xiàn)不存在 Activity 對應(yīng)進(jìn)程 , 那么執(zhí)行下面的冷啟動方法 :
// 如果啟動 Activity 時 , 發(fā)現(xiàn)進(jìn)程不存在 , 則啟動進(jìn)程, 然后再啟動 Activity , 冷啟動 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);ActivityStackSupervisor.startSpecificActivityLocked 方法代碼 :
public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,RecentTasks.Callbacks {void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {// 此活動的應(yīng)用程序是否已在運行?ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);getLaunchTimeTracker().setLaunchTime(r);if (app != null && app.thread != null) {try {if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0|| !"android".equals(r.info.packageName)) {// 如果它是一個標(biāo)記為在多個進(jìn)程中運行的平臺組件,請不要添加此項,// 因為它實際上是框架的一部分,因此在進(jìn)程中作為單獨的apk進(jìn)行跟蹤沒有意義。app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,mService.mProcessStats);}// 如果啟動 Activity 時 , 發(fā)現(xiàn)進(jìn)程存在 , 則直接啟動 Activity , 熱啟動realStartActivityLocked(r, app, andResume, checkConfig);return;} catch (RemoteException e) {Slog.w(TAG, "Exception when starting activity "+ r.intent.getComponent().flattenToShortString(), e);}// 如果拋出了死對象異常,則通過fall-through重新啟動應(yīng)用程序。}// 如果啟動 Activity 時 , 發(fā)現(xiàn)進(jìn)程不存在 , 則啟動進(jìn)程, 然后再啟動 Activity , 冷啟動 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);} }完整代碼參考 /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java ;
二、AMS 進(jìn)程中執(zhí)行的相關(guān)操作
在 ActivityStackSupervisor.realStartActivityLocked 啟動 Activity ;
最終調(diào)用 mService.getLifecycleManager().scheduleTransaction(clientTransaction) 方法 , 啟動相關(guān) Activity 啟動事物 ;
ActivityStackSupervisor.realStartActivityLocked 相關(guān)代碼如下 :
public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,RecentTasks.Callbacks {final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,boolean andResume, boolean checkConfig) throws RemoteException {if (!allPausedActivitiesComplete()) {// 當(dāng)有活動暫停時,我們將跳過開始任何新活動,直到暫停完成。// 注意:對于在暫停狀態(tài)下啟動的活動,我們也會這樣做,因為它們將首先恢復(fù),然后在客戶端暫停。if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,"realStartActivityLocked: Skipping start of r=" + r+ " some activities pausing...");return false;}final TaskRecord task = r.getTask();final ActivityStack stack = task.getStack();beginDeferResume();try {r.startFreezingScreenLocked(app, 0);// 安排啟動時間以收集有關(guān)慢速應(yīng)用程序的信息。r.startLaunchTickingLocked();r.setProcess(app);if (getKeyguardController().isKeyguardLocked()) {r.notifyUnknownVisibilityLaunched();}// 讓窗口管理器根據(jù)新的活動順序重新評估屏幕方向。// 注意,這樣做的結(jié)果是,它可以使用新的方向調(diào)用activity manager。// 我們不關(guān)心這一點,因為活動當(dāng)前未運行,所以我們只是重新啟動它。if (checkConfig) {// 推遲恢復(fù),因為我們將很快啟動新活動。// 我們不希望在確保配置和嘗試恢復(fù)重點堆棧的頂級活動的同時,重復(fù)啟動同一記錄。ensureVisibilityAndConfig(r, r.getDisplayId(),false /* markFrozenIfConfigChanged */, true /* deferResume */);}if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */,true /* isTop */)) {// 僅當(dāng)基于keyguard狀態(tài)允許活動可見時,我們才將可見性設(shè)置為true。// 這樣可以避免在窗口管理器中將此設(shè)置為運動狀態(tài),// 而由于以后的調(diào)用而取消該設(shè)置,以確保將可見性設(shè)置回false的可見活動。r.setVisibility(true);}try {// 下面的代碼是啟動 Activity 的核心代碼// Create activity launch transaction.final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,r.appToken);clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,// TODO: Have this take the merged configuration instead of separate global// and override configs.mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,r.persistentState, results, newIntents, mService.isNextTransitionForward(),profilerInfo));// 設(shè)置所需的最終狀態(tài)。配置生命周期final ActivityLifecycleItem lifecycleItem;if (andResume) {// 開啟新的 ActivitylifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());} else {// 終止 ActivitylifecycleItem = PauseActivityItem.obtain();}clientTransaction.setLifecycleStateRequest(lifecycleItem);// 安排事務(wù)。mService.getLifecycleManager().scheduleTransaction(clientTransaction);// 上面的代碼是啟動 Activity 的核心代碼} catch (RemoteException e) {}} finally {endDeferResume();}return true;} }完整代碼參考 /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java ;
mService.getLifecycleManager().scheduleTransaction(clientTransaction) 中調(diào)用了 ClientLifecycleManager.scheduleTransaction , 在該方法中調(diào)用了傳入?yún)?shù) ClientTransaction transaction 的 schedule() 方法 ;
// 此處直接調(diào)用傳入?yún)?shù)的 schedule 方法transaction.schedule();ClientLifecycleManager.scheduleTransaction 方法如下 :
/*** 該類能夠組合多個客戶端生命周期轉(zhuǎn)換請求和/或回調(diào),并將它們作為單個事務(wù)執(zhí)行。** @see ClientTransaction*/ class ClientLifecycleManager {/*** 安排一個事務(wù),該事務(wù)可能包括多個回調(diào)和一個生命周期請求。* @param transaction 客戶端事務(wù)項的序列。* @throws RemoteException** @see ClientTransaction*/void scheduleTransaction(ClientTransaction transaction) throws RemoteException {final IApplicationThread client = transaction.getClient();// 此處直接調(diào)用傳入?yún)?shù)的 schedule 方法transaction.schedule();if (!(client instanceof Binder)) {// 如果客戶機不是Binder的實例,則它是一個遠(yuǎn)程調(diào)用,// 此時可以安全地回收該對象。// 在ActivityThread中的客戶端上執(zhí)行事務(wù)后,將回收用于本地調(diào)用的所有對象。transaction.recycle();}} }完整代碼參考 /frameworks/base/services/core/java/com/android/server/am/ClientLifecycleManager.java ;
調(diào)用的是 IApplicationThread mClient 成員的 scheduleTransaction 方法 , 該成員類型 IApplicationThread 是 ActivityThread 的內(nèi)部類 ;
/*** 一種容器,它保存一系列消息,這些消息可以發(fā)送給客戶機。這包括回調(diào)列表和最終生命周期狀態(tài)。** @see com.android.server.am.ClientLifecycleManager* @see ClientTransactionItem* @see ActivityLifecycleItem* @hide*/ public class ClientTransaction implements Parcelable, ObjectPoolItem {/** Target client. */private IApplicationThread mClient;/*** 在事務(wù)初始化后安排事務(wù)。它將發(fā)送給客戶,其所有單獨部分將按以下順序應(yīng)用:* 1. 客戶端調(diào)用{@link#preExecute(ClientTransactionHandler)},* 這將觸發(fā)在實際調(diào)度回調(diào)和生命周期狀態(tài)請求的事務(wù)之前需要完成的所有工作。* 2. 已計劃事務(wù)消息。* 3. 客戶端調(diào)用{@link TransactionExecutor#execute(ClientTransaction)},* 它執(zhí)行所有回調(diào)和必要的生命周期轉(zhuǎn)換。*/public void schedule() throws RemoteException {mClient.scheduleTransaction(this);} }完整代碼參考 /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java ;
三、通過 Binder 機制轉(zhuǎn)到 ActivityThread 中執(zhí)行的操作
通過 Binder 機制 , 調(diào)用 ActivityThread 的內(nèi)部類 IApplicationThread 的 scheduleTransaction 方法 ; 這樣就進(jìn)入到了 ActivityThread 主線程中 , 在該主線程中執(zhí)行相關(guān)源碼 ;
/*** 它管理應(yīng)用程序進(jìn)程中主線程的執(zhí)行、調(diào)度和執(zhí)行活動、廣播以及活動管理器請求的其他操作。** {@hide}*/ public final class ActivityThread extends ClientTransactionHandler {private class ApplicationThread extends IApplicationThread.Stub {@Overridepublic void scheduleTransaction(ClientTransaction transaction) throws RemoteException {ActivityThread.this.scheduleTransaction(transaction);}} }完整代碼參考 /frameworks/base/core/java/android/app/ActivityThread.java ;
上述方法最終執(zhí)行的是 ActivityThread.this.scheduleTransaction(transaction) , ActivityThread 繼承了 ClientTransactionHandler 方法 ,
ClientTransactionHandler 中定義的 scheduleTransaction 方法中 , 主要是發(fā)出了 ActivityThread.H.EXECUTE_TRANSACTION 159159159 消息 ;
/*** 定義{@link android.app.servertransaction.ClientTransaction}或其項可以在客戶端上執(zhí)行的操作。* @hide*/ public abstract class ClientTransactionHandler {// 安排與階段相關(guān)的邏輯和處理程序。/** 準(zhǔn)備并安排事物執(zhí)行。 */void scheduleTransaction(ClientTransaction transaction) {transaction.preExecute(this);sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);}}完整代碼參考 /frameworks/base/core/java/android/app/ClientTransactionHandler.java ;
總結(jié)
本博客分析的源碼對應(yīng)分支 AMS -> ActivityThread ( ApplicationThread ) 分支 , Activity 的熱啟動 ;
總結(jié)
以上是生活随笔為你收集整理的【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 启动过程】Activi
- 下一篇: 【Android 启动过程】Activi