天天看點

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之開機啟動Launcher、開機廣告後啟動Launcher、Launcher啟動activity一、總體概述:二、流程圖三、一些注意點總結:

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)
           

流程圖:

AMS之開機啟動Launcher、開機廣告後啟動Launcher、Launcher啟動activity一、總體概述:二、流程圖三、一些注意點總結:

這裡是開機廣告播放完畢,主動調用finish();系統主動啟動launcher。 這裡看差别還是蠻大的。

直接啟動launcher,通過程序建立,觸發attach就起來了;而開機廣告這種情況則複雜很多,先是finish掉開機廣告,然後由pause流程觸發startHomeActivity并遞歸調用了一次resume的流程之後才走到realStartActivityLocked,回調launcher的onCreate函數。

3.Launcher啟動之後啟動app

流程圖:

AMS之開機啟動Launcher、開機廣告後啟動Launcher、Launcher啟動activity一、總體概述:二、流程圖三、一些注意點總結:

和正常點選圖示得差別不一樣;主要差別是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關系圖:

AMS之開機啟動Launcher、開機廣告後啟動Launcher、Launcher啟動activity一、總體概述:二、流程圖三、一些注意點總結:

1.Android應用程式啟動過程源代碼分--羅升陽

2.Android系統啟動流程--從SystemServer啟動Launcher--百度文庫

3.Android源碼解析之(十五)-->Activity銷毀流程--劉超

4.四大元件之ActivityRecord--GitYuan

大元件之ActivityRecord