天天看點

Android手機從開機到APP啟動經過的流程

版權聲明:轉載請務必注明作者與原文連結

引言

本文講解從開機到app顯示畫面的流程,但不分析源碼,如果想閱讀源碼請到參考文章中查閱。

本文把這段流程分為三部分:

  • 從開機到顯示應用清單
  • 從點選應用圖示到Activity建立成功
  • 從Activity建立成功到顯示畫面

從開機到顯示應用清單

先看流程圖:

Android手機從開機到APP啟動經過的流程

開機加電後,CPU先執行預設代碼、加載ROM中的引導程式Bootloader和Linux核心到RAM記憶體中去,然後初始化各種軟硬體環境、加載驅動程式、挂載根檔案系統,執行init程序。

init程序會啟動各種系統本地服務,如SM(ServiceManager)、MS(Media Server)、bootanim(開機動畫)等,然後init程序會在解析init.rc檔案後fork()出Zygoto程序。

Zygote會啟動Java虛拟機,通過jni進入Zygote的java代碼中,并建立socket實作IPC程序通訊,然後啟動SS(SystemServer)程序。

SS程序負責啟動和管理整個framework,包括AMS(ActivityManagerService)、WMS(WindowManagerService)、PMS(PowerManagerService)等服務、同時啟動binder線程池,當SS程序将系統服務啟動就緒以後,就會通知AMS啟動Home。

AMS通過Intent隐式啟動的方式啟動Launcher,Launcher根據已安裝應用解析對應的xml、通過findBiewById()獲得一個RecycleView、加載應用圖示、最後成功展示App清單。

解釋

  • 預設代碼:cpu制造廠商會預設一個位址,這個位址是各廠家約定統一的,Android手機會将固态儲存設備ROM預先映射到該位址上;
  • Bootloader:類似BIOS,在系統加載前,用以初始化硬體裝置,建立記憶體空間的映像圖,為最終調用系統核心準備好環境;
  • init程序:init程序時Android系統中使用者程序的鼻祖程序,主要作用是啟動系統本地服務、fork出Zygoto程序;
  • SM:ServiceManager是一個守護程序,它維護着系統服務和用戶端的binder通信;
  • Zygoto程序:Zygoto程序是所有Java程序的父程序,我們的APP都是由Zygoto程序fork出來的;
  • socket:一種獨立于協定用于兩個應用程式之間的資料傳輸的網絡程式設計接口,是IPC中的一種;(但是在Android中一般使用Binder來實作IPC,這裡使用socket的原因後面有寫到)
  • SS:Framework兩大重要程序之一(另一個是Zygote),載着framework的核心服務,系統裡面重要的服務都是SS開啟的;
  • AMS:服務端對象,負責系統中所有Activity的生命周期,打開App、Activity的開啟、暫停、關閉都需要AMS來控制;
  • WMS:視窗管理服務,視窗的啟動、添加、删除、大小、層級都是由WMS管理;(下面會解釋什麼是視窗)
  • Launcher:Launcher就是系統桌面,主要用來啟動應用桌面,同時管理快捷方式和其他元件,本質上也是一個應用程式,和我們的App一樣,也是繼承自Activity,有自己的AndroidManifest;(是以才可以被AMS用Intent啟動)

Question 1: Zygote程序為什麼使用Socket而不是Binder?

fork不允許存在多線程,而Binder通訊恰巧就是多線程;

Question 2:什麼是視窗?

Android系統中的窗體是螢幕上的一塊用于繪制各種UI元素并能夠響應應使用者輸入的一個矩形區域,從原理上來講,窗體的概念是獨自占有一個Surface執行個體的顯示區域,比如Dialog、Activity的界面、桌面、狀态欄以及Toast等都是窗體;

從點選應用圖示到Activity建立成功

先看流程圖:

Android手機從開機到APP啟動經過的流程
//然後點選應用圖示後,先檢查要打卡的Activity是否存在
--> Launcher.startActivitySafely()
--> Launcher.startActivity()
--> Activity.startActivity()
--> Activity.startActivityForResult()

//然後擷取AMS的代理AMP
--> Instrumentation.execStartActivity()
--> ActivityManagerNative.getDefault().startActivity()
--> ActivityManagerProxy.startActivity()
--> ActivityManagerService.startActivity()
--> startActivityAsUser(intent, requestCode, userId)
--> ActivityStackSupervisor.startActivityMayWait()
--> ActivityStackSupervisor.resolveActivity()
--> ActivityStackSupervisor.startActivityLocked()
--> new ActivityRecord對象,擷取ActivityStack
--> 找到ActivityStack後Launcher.onPause()

//準備啟動程序
--> ActivityManagerService.startProcessLocked()
//通過socket通知Zygote建立程序
--> zygoteSendArgsAndGetResult()
//建立ActivityThread
--> ActivityThread.main()
//告訴AMS我已經建立好了
--> ActivityThread.attach()
--> ActivityManagerProxy.attachApplication()
--> ActivityMangerService.attachApplication()
//找到Application執行個體并初始化
--> ActivityMangerService.attachApplicationLocked()

--> ApplicationThread.bindApplication()
//建立Application
--> AcitvityThread.bindApplication()
--> Application.oncreate()

//啟動Activity
--> ActivityStackSupervisor.attachApplicationLocked()
--> ActivityStackSupervisor.realStartActivityLocked()
--> ActivityThread.scheduleLaunchActivity()

//進入UI線程
--> handleLaunchActivity()
--> performLaunchActivity()
//建立Activity執行個體
--> Instrumentation.newActivity()
--> Activity.onCreate()
           

解釋

  • ActivityThread:App的真正入口。當開啟App之後,會調用main()開始運作,開啟消息循環隊列,這就是傳說中的UI線程或者叫主線程。與ActivityManagerServices配合,一起完成Activity的管理工作;
  • ApplicationThread:用來實作ActivityManagerService與ActivityThread之間的互動。在ActivityManagerService需要管理相關Application中的Activity的生命周期時,通過ApplicationThread的代理對象與ActivityThread通訊;
  • Instrumentation:可以了解為應用程序的管家,每個應用程式隻有一個,每個Activity内都有該對象的引用,ActivityThread要建立或暫停某個Activity時,都需要通過Instrumentation來進行具體的操作;
  • ActivityStack:Activity在AMS的棧管理,用來記錄已經啟動的Activity的先後關系,狀态資訊等。通過ActivityStack決定是否需要啟動新的程序;
  • ActivityRecord:ActivityStack的管理對象,每個Activity在AMS對應一個ActivityRecord,來記錄Activity的狀态以及其他的管理資訊。其實就是伺服器端的Activity對象的映像;

Question 1: 如何判斷APP是否已經啟動?

AMS會儲存一個ProcessRecord資訊,有兩部分構成,“uid + process”,每個應用工程式都有自己的uid,而process就是AndroidManifest.xml中Application的process屬性,預設為package名。每次在建立新程序前的時候會先判斷這個 ProcessRecord 是否已存在,如果已經存在就不會建立程序了,這就屬于應用内打開 Activity 的過程了。

從Activity建立成功到顯示畫面

onCreate()方法中先執行setContentView()方法将對應的xml檔案傳入,之後會去調用window.setContentView(),最終會在這裡建立Decorview并填充标題欄、狀态欄,然後擷取contentParent,然後調用LayoutInflater.inflate解析xml檔案擷取根root(ViewRootImpl),通過root.addView()将contentParent添加到ViewRootImpl中去,至此onCreate()結束。

開始onResume()階段,在開始會向H類發送一個消息,然後在ActivityThread中擷取之前建立的Decorview并調用windowManager.add(),最後在windowManager中将視窗和視窗的參數傳到root.setView(),然後ViewRoot通過Binder調用WMS,使WMS所在的SS程序接收到按鍵事件時,可以回調到該root,同時ViewRoot會向自己的handler發送一條消息,然後進行處理(performTraversals),之後開始繪制過程(在Surface的canvas上繪制)。

先利用MeasureSpec完成onmeasure(),然後在onlayout()中确定各元素的坐标,ondraw()負責将view畫到canvas上,再通過Surface進行跨程序最終調用Native層的SGL、openGI,最後再去調用硬體CPU進行渲染操作,最終界面顯示在你眼前

解釋

  • DecorView:界面的根View,PhoneWindow的内部類
  • contentParent:所有View的根View,在DecorView裡面
  • ViewRootImpl:ViewRoot是GUI管理系統與GUI呈現系統之間的橋梁,

    WindowManager

    通過

    ViewRootImpl

    DecorView

    起聯系。并且,

    View

    的繪制流程都是由

    ViewRootImpl

    發起的
  • SGL:底層的2D圖形渲染引擎

參考文章:

  • http://gityuan.com/android/
  • https://www.jianshu.com/p/af8e1ebdf902
  • https://blog.csdn.net/lb84_007/article/details/47774973
  • https://blog.csdn.net/freekiteyu/article/details/79318031
  • https://blog.csdn.net/qq_39037047/article/details/88066589#
  • https://baijiahao.baidu.com/s?id=1617072163535121555&wfr=spider&for=pc