AMS之開機啓動Launcher、開機廣告後啓動Launcher、Launcher啓動activity

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,看下異同點。


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,否則爲nullfinal 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





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章