activity的啟動關閉最終都是由AMS控制的。從刷了rom到第一開機引導、launcher啟動、點選啟動特定app,這之間ams控制開機引導activity、launcher、app啟動有什麼不同嗎?還是same流程?下面讓我們一探究竟。
文章分三部分:第一部總體概述、第二部分流程圖、第三部分講解下具體一些細節點。
一、總體概述:
無所做什麼,一定先是了解概況,然後在看細節,不然就是隻見樹木不見森林。
這裡就會有區分,開機廣告/開機引導類似(電視現在都是先播放廣告,然後啟動launcher)、launcher、其他app;
本文也從這個角度進行一下分析。
簡單的說,啟動一個activity,先看是否已經有activity是resume狀态,沒有則直接啟動;有則先pause掉目前resume的,然後啟動想啟動的;這裡也不關注activity如何調用到AMS的,隻關注AMS内部如何排程最終啟動相關的activity的。
除了開機廣告,launcher和app啟動都是兩個階段:一pause目前resume的activity;二resume需要啟動的activity。(先finish後pause)
牢記,就這兩個階段,不過launcher和app啟動在這兩個階段有些許的差別而已。
開機廣告就不多說了,後面也會給出AMS添加的方案,從AMS直接啟動廣告Activity播放廣告,然後主動finish;系統會啟動Launcher;點選相關app,啟動自己想打開的應用(順序三個階段)。
二、流程圖
1.正常啟動Launcher
這裡先看下正常情況下的Luancher啟動,即開機即啟動Launcher。然後在看下先播放開機廣告,然後在自動Launcher,看下異同點。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2Lc1DNXFGN5YVYv50MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DNwYTOwQTM1EjMwcDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
AMS被SystemServer啟動之後,SystemServer會通過AMS調用startHomeActtivity啟動Launcher,流程見上流程圖。
其中有幾個關鍵函數,需要關注一下:startHomeActivityLocked、startActivityLocked、addActivityToTop、resumeTopActivityLocked、realStartActivityLocked、attachApplicationLocked;幾個點記住:ProcessLocked中有Process.start,最終會觸發AMS的attachApplication。
從流程途中看到,起點可以算startHomeActivityLocked,終點是realStartActivityLocked;
第一階段是startHomeActivity,觸發activity的程序建立;第二階段就是AMS的attachApplication在程序建立後被調用,最終執行realStartActivityLocked會回調Activity的onCreate函數。
這裡第一階段和上面說的不太一樣,不過沒關系,下面看下先播開機廣告在啟動launcher的流程。
2.開機廣告之後啟動Launcher
AMS啟動廣告的就不看了,看下廣告finish之後,Launcher啟動的流程:
先看下調用棧:
第一階段:開機廣告finish掉,觸發paused:
06-28 18:07:14.098 4200 4391 W System.err: at com.android.server.am.ActivityStack.startPausingLocked(ActivityStack.java:825)
06-28 18:07:14.098 4200 4391 W System.err: at com.android.server.am.ActivityStack.finishActivityLocked(ActivityStack.java:2745)
06-28 18:07:14.098 4200 4391 W System.err: at com.android.server.am.ActivityStack.requestFinishActivityLocked(ActivityStack.java:2572)
06-28 18:07:14.098 4200 4391 W System.err: at com.android.server.am.ActivityManagerService.finishActivity(ActivityManagerService.java:4543)
06-28 18:07:14.098 4200 4391 W System.err: at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:325)
06-28 18:07:14.098 4200 4391 W System.err: at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2267)
06-28 18:07:14.098 4200 4391 W System.err: at android.os.Binder.execTransact(Binder.java:446)
第二階段:paused并啟動launcher
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.realStartActivityLocked(ActivityStackSupervisor.java:1182)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.startSpecificActivityLocked(ActivityStackSupervisor.java:1285)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.resumeTopActivityInnerLocked(ActivityStack.java:1898)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.resumeTopActivityLocked(ActivityStack.java:1459)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.resumeTopActivitiesLocked(ActivityStackSupervisor.java:2477)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.startActivityLocked(ActivityStack.java:2097)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.startActivityUncheckedLocked(ActivityStackSupervisor.java:2217)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.startActivityLocked(ActivityStackSupervisor.java:1519)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.startHomeActivity(ActivityStackSupervisor.java:833)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityManagerService.startHomeActivityLocked(ActivityManagerService.java:3248)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.resumeHomeStackTask(ActivityStackSupervisor.java:459)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.resumeTopActivityInnerLocked(ActivityStack.java:1504)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.resumeTopActivityLocked(ActivityStack.java:1459)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStackSupervisor.resumeTopActivitiesLocked(ActivityStackSupervisor.java:2477)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.completePauseLocked(ActivityStack.java:998)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityStack.activityPausedLocked(ActivityStack.java:896)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityManagerService.activityPaused(ActivityManagerService.java:6591)
06-29 15:18:57.860 4196 4213 W System.err: at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:512)
06-29 15:18:57.860 4196 4213 W System.err: at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2267)
06-29 15:18:57.860 4196 4213 W System.err: at android.os.Binder.execTransact(Binder.java:446)
流程圖:
這裡是開機廣告播放完畢,主動調用finish();系統主動啟動launcher。 這裡看差别還是蠻大的。
直接啟動launcher,通過程序建立,觸發attach就起來了;而開機廣告這種情況則複雜很多,先是finish掉開機廣告,然後由pause流程觸發startHomeActivity并遞歸調用了一次resume的流程之後才走到realStartActivityLocked,回調launcher的onCreate函數。
3.Launcher啟動之後啟動app
流程圖:
和正常點選圖示得差別不一樣;主要差別是startActivity調用時機; 都有兩個階段:launcher一階段:finish調用pause,二階段pause調用到startHome并先調用resume之後才調用得startActivityLocked;
正常啟動:一階段:先調用startActivityLocked,并調用pause,二階段pause調用resume直接啟動activity了。
正常啟動activity,會走startActivity(這裡會将ActivityRecord資訊加入task頂,并也調用startPausingLocked);
在後續流程中,也不同,主要是2中launcher啟動遞歸調用了resume得幾個函數;而正常啟動則不會遞歸,
原因就是正常啟動在首次就将ActivityRecord資訊入task頂了,而2中launcher則沒有;
三、一些注意點
1.addActivityToTop這個函數比較重要,會将要啟動的activity的AcitivityRecord加入TASK頂端;這個非常重要,決定着realStartActivityLocked會不會被調用,還是啟動launcher;如果執行了,即加入了Task的棧頂則這裡next!=null而是相關的ActivityRecord,否則為null(final ActivityRecord next = topRunningActivityLocked(null););
final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
// Find the first activity that is not finishing.
final ActivityRecord next = topRunningActivityLocked(null);
final TaskRecord prevTask = prev != null ? prev.task : null;
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
// Only resume home if on home display
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "noMoreActivities");
}
2.resumeTopActivityLocked這個函數比較坑(5.1~9.0都這樣),函數裡有個判斷會導緻2.2部分的launcher啟動不起來,2.2中的調用邏輯是我将AOSP代碼注釋掉一行以後,啟動的。
看下這個函數:注意标志位:inResumeTopActivity
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;//注釋掉即可,既能如2.2中所示調用流程,否則嵌套調用就傳回,launcher無法啟動
if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
mService.updateSleepIfNeededLocked();
}
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
return result;
}
可以看到這個函數使用标志位inResumeTopActivity ,但是2.2中開機廣告這種情況下,就會出現問題;
在2.2中,第一階段隻是進行finish處理和pause調用;第二階段才會通過pause進行resume,但是先走到這個函數而後觸發的startActivityLocked(調用addActivityToTop),随後又走到這裡的時候就傳回了,并沒有繼續執行,是以luancher就沒有啟動,會出現開機廣告播放完成之後,一直黑屏的現象。
相關關鍵函數:
startHomeActivityLocked:調用啟動Launcher;
startActivityLocked(ActivityStack中 ):調用觸發addActivityToTop将ActivityRecord加入棧頂;
resumeTopActivityLocked:這個函數是3.1中說的函數,不修改會導緻廣告後launcher不啟動;
realStartActivityLocked:觸發app.thread.scheduleLaunchActivity,去回調mainactivity的onCreate函數;
attachApplicationLocked:由建立相關程序之後觸發,此函數會觸發realStartActivityLocked的調用。
總結:
整體上,這篇文章涉及較多,AMS管理task即生命周期都有涉及,如果之前沒有接觸過,基本看不懂,很頭痛。
這裡放上幾篇基礎文章,可以閱讀後再來讀本篇文章,應該會又更深刻的了解。
附上AMS關系圖:
1.Android應用程式啟動過程源代碼分--羅升陽
2.Android系統啟動流程--從SystemServer啟動Launcher--百度文庫
3.Android源碼解析之(十五)-->Activity銷毀流程--劉超
4.四大元件之ActivityRecord--GitYuan
大元件之ActivityRecord