剖析Frameworks筆記

談?wù)剬?duì)Zygote的理解

  • Zygote的作用是什么?

    • 啟動(dòng)SystemServer(從Zygote直接獲取常用類、JNI函數(shù)、主題資源、共享庫(kù)等)
    • 孵化應(yīng)用進(jìn)程(進(jìn)程啟動(dòng)->準(zhǔn)備工作 ->LOOP)
  • Zygote的啟動(dòng)流程

    • Zygote進(jìn)程是怎么啟動(dòng)的?

      • Init進(jìn)程通過init.rc獲取配置然后啟動(dòng)Zygote進(jìn)程

      <u>啟動(dòng)進(jìn)程的方法:</u>

      1. <u>fork+handle</u>
      2. <u>fork+execve</u>
    • 啟動(dòng)后做了什么事

      • Zygote的Native世界
        1. 啟動(dòng)Android虛擬機(jī)
        2. 注冊(cè)Android的JNI函數(shù)
        3. 進(jìn)入Java世界
      • Zygote的Java世界
        1. preload resources預(yù)加載資源
        2. fork 出system server
        3. loop循環(huán)
    1. Zygote fork要單線程
    2. Zygote 的IPC沒有采用binder,而是采用socket

說說Android系統(tǒng)的啟動(dòng)流程

  • Android有哪些主要的系統(tǒng)進(jìn)程

查看init.rc啟動(dòng)配置文件:

zygote、servicemanager、surfaceflinger、media等

SystemServer不在init.rc中,它是zygote創(chuàng)建的

SystemServer啟動(dòng)系統(tǒng)服務(wù)

  • 這些系統(tǒng)進(jìn)程是怎么啟動(dòng)的
  • 進(jìn)程啟動(dòng)之后主要做了什么事
  1. zygote是怎么啟動(dòng)的
  2. systemServer是怎么啟動(dòng)的
  3. 系統(tǒng)服務(wù)是怎么啟動(dòng)的?如何解決相互依賴問題?如何發(fā)布這些系統(tǒng)服務(wù)的?桌面如何啟動(dòng)的?

你知道怎么添加一個(gè)系統(tǒng)服務(wù)嗎?

  • 如何使用系統(tǒng)服務(wù)?

    context.getSystemService()獲取系統(tǒng)服務(wù)的接口對(duì)象

    最終是通過SYSTEM_SERVICE_FETCHERS這個(gè)hashmap獲取的

  • 系統(tǒng)服務(wù)的創(chuàng)建

    通過createService()方法從ServiceManager.getService()獲取系統(tǒng)服務(wù)的ibinder對(duì)象,然后獲取系統(tǒng)服務(wù)的代理對(duì)象,進(jìn)行返回

  • 如何注冊(cè)系統(tǒng)服務(wù)?

    SystemManager.addService()方法將系統(tǒng)服務(wù)的name和IBinder添加到ServiceManager中

  • 什么時(shí)候注冊(cè)系統(tǒng)服務(wù)?

    SystemServer啟動(dòng)過程:

    1. 啟動(dòng)binder機(jī)制
    2. 啟動(dòng)各類系統(tǒng)服務(wù)
    3. 進(jìn)入loop循環(huán)
  • 獨(dú)立進(jìn)程的系統(tǒng)服務(wù)

    進(jìn)程啟動(dòng)后去獲取IServiceManager,然后調(diào)用addService方法

  • 啟動(dòng)binder機(jī)制

    1. 打開binder驅(qū)動(dòng)
    2. 映射內(nèi)存,分配緩沖區(qū)
    3. 啟動(dòng)binder線程,進(jìn)入binder loop

1、添加系統(tǒng)服務(wù)的時(shí)機(jī)

  • 在systemServer中,可以加到啟動(dòng)系統(tǒng)服務(wù)的位置
  • 跑在單獨(dú)進(jìn)程中,可以添加到init.rc中

2、服務(wù)要做那些事?

  • 啟動(dòng)binder機(jī)制
  • 設(shè)置工作
  • 將自己注冊(cè)到serviceManager中

3、應(yīng)用端要做的事?

  • 應(yīng)用端使用context.getSystemService()方法獲取系統(tǒng)服務(wù)

系統(tǒng)服務(wù)和bind的應(yīng)用服務(wù)有什么區(qū)別?

  • 啟動(dòng)方法
    • 系統(tǒng)服務(wù):在SystemServer中啟動(dòng)或者自己有獨(dú)立進(jìn)程啟動(dòng)
    • 應(yīng)用服務(wù):通過context.startServiceCommon()調(diào)用AMS啟動(dòng),管理service,最終通過應(yīng)用的handleCreateService()啟動(dòng)service
  • 注冊(cè)方法
    • 系統(tǒng)服務(wù):不論是Java層還是native層都是通過serviceManager的addService方法進(jìn)行注冊(cè)
    • 應(yīng)用服務(wù):
      1. 應(yīng)用端發(fā)起bindService調(diào)用
      2. AMS 向Service端請(qǐng)求binder對(duì)象
      3. Service端發(fā)布binder對(duì)象到AMS
      4. AMS將binder對(duì)象通過回調(diào)給應(yīng)用端
      5. 應(yīng)用端通過binder調(diào)用service端功能
  • 使用方式
    • 系統(tǒng)服務(wù):先通過context.getSystemService()獲取服務(wù),然后使用
    • 應(yīng)用服務(wù):通過bindService綁定服務(wù),在onServiceConnected的回調(diào)中獲取IBinder對(duì)象,最終獲得binder端接口對(duì)象,進(jìn)行調(diào)用

ServiceManager的啟動(dòng)和工作原理

  • ServiceManager的啟動(dòng)

    1. 啟動(dòng)進(jìn)程(ServiceManager是一個(gè)單獨(dú)的進(jìn)程,在init.rc中存在)
    2. 啟動(dòng)BInder機(jī)制
    3. 發(fā)布自己的服務(wù)
    4. 等待并響應(yīng)請(qǐng)求
  • 如何獲取ServiceManager

    • 獨(dú)立線程的Service通過BpBinder(0)獲取ServiceManager的代理對(duì)象
  • 怎么添加Service?

    ServiceManager代理對(duì)象的addService會(huì)調(diào)用對(duì)ServiceManager進(jìn)程發(fā)送一個(gè)handle消息,ServiceManager在handle中處理消息,對(duì)service進(jìn)行添加

  • 怎么獲取Service?

    先獲取ServiceManager代理對(duì)象,再調(diào)用getService()方法


應(yīng)用進(jìn)程是怎么啟動(dòng)的?

  • 進(jìn)程啟動(dòng)方法:

    • fork-handle這種方法共享父進(jìn)程資源
    • fork-execve
  • 應(yīng)用進(jìn)程啟動(dòng)原理

    啟動(dòng)組件時(shí)會(huì)監(jiān)測(cè)組件的進(jìn)程是否啟動(dòng),如果沒有則先去啟動(dòng)進(jìn)程。

    應(yīng)用中的IActivityManager時(shí)AMS的代理對(duì)象,AMS中的IAPPlicationThread是應(yīng)用中ApplicationThread的代理對(duì)象,進(jìn)行binder雙向調(diào)用

  • 進(jìn)程啟動(dòng)流程:

    1. AMS調(diào)用startProcessLocked方法打開本地socket,發(fā)送參數(shù)列表給zygote,等待zygotefork出進(jìn)程并把進(jìn)程id傳給AMS
    2. zygote的loop中調(diào)用runOnce方法fork進(jìn)程,并執(zhí)行進(jìn)程的main方法,對(duì)于一般應(yīng)用來(lái)說就是執(zhí)行ActivityTThread的main()
    3. 進(jìn)程啟動(dòng)后會(huì)獲取AMS的代理對(duì)象,并通過這個(gè)代理對(duì)象向AMS發(fā)送應(yīng)用進(jìn)程的ApplicationThread對(duì)象的代理,實(shí)現(xiàn)binder雙向調(diào)用。

應(yīng)用是怎么啟動(dòng)Binder機(jī)制的?

zygote 在fork一個(gè)應(yīng)用進(jìn)程后,這個(gè)進(jìn)程會(huì)先去啟動(dòng)Binder機(jī)制:

  1. 打開binder驅(qū)動(dòng)
  2. 映射內(nèi)存,分配緩沖區(qū)
  3. 注冊(cè)binder線程
  4. 進(jìn)入binder loop

應(yīng)用天生就支持Binder機(jī)制是不是從zygote繼承過來(lái)的?


談?wù)勀銓?duì)Application的理解

  • Application有什么作用
    • Application的生命周期與應(yīng)用的生命周期相同,可以保存應(yīng)用進(jìn)程內(nèi)的全局變量
    • 做初始化操作
    • 提供應(yīng)用上下文(不會(huì)內(nèi)存泄漏)
  • Application的生命周期
    • 構(gòu)造函數(shù)
    • attachBaseContext
    • onCreate
  • Application怎么初始化?
    1. 應(yīng)用進(jìn)程的main方法中調(diào)用AMS的代理類進(jìn)行注冊(cè)
    2. AMS通過應(yīng)用的applicationThread調(diào)用bindApplication()方法發(fā)送消息
    3. 應(yīng)用主線程通過handleBindApplication()進(jìn)程創(chuàng)建Application
      1. 使用class.newInstance調(diào)用Application的構(gòu)造函數(shù)創(chuàng)建application
      2. 使用application.attachBaseContext方法設(shè)置上下文contextImpl
      3. 調(diào)用application.onCreate()方法

談?wù)勀銓?duì)Context的理解

  • 應(yīng)用里面有多少個(gè)Context?不同的Context之間有什么區(qū)別?

  • Activity里的this和getBaseContext有什么區(qū)別?

  • getApplication和getApplicationContext有什么區(qū)別?

    getApplication是Activity和service中的方法,getApplicationContext是Context的抽象方法,二者返回的都是application對(duì)象。

  • 應(yīng)用組件的構(gòu)造,onCreate、attachBaseContext調(diào)用順序?

  • Context的作用

    作為應(yīng)用組件的上下文,調(diào)用系統(tǒng)服務(wù)、調(diào)用資源、啟動(dòng)activity、service等組件

  • Context在哪里創(chuàng)建:

    擁有自己的Context的類:

    • Application
    • Activity
    • Service

    Application和Service都是繼承自ContextWrapper,ContextWrapper繼承自Context,ContextWrapper的實(shí)現(xiàn)方法都是,內(nèi)部的mBase去完成的,這個(gè)mBase就是一個(gè)ContextImpl對(duì)象,這里使用了靜態(tài)代理的設(shè)計(jì)模式。

    Activity繼承自ContextThemeWrapper,ContextThemeWrapper繼承自ContextWrapper。ContextThemeWrapper比ContextWrapper多了一個(gè)mTheme成員變量。

    Activity啟動(dòng)是調(diào)用performLaunchActivity()方法,activity會(huì)使用attach方法,這里傳入了一個(gè)context對(duì)象。


說說Activity的啟動(dòng)流程

在應(yīng)用端:

  1. 創(chuàng)建Activity對(duì)象
  2. 準(zhǔn)備好Application
  3. 創(chuàng)建ContextImpl
  4. attach上下文
  5. 開始什么周期回調(diào)

整體過程:

  1. 發(fā)送startActivity請(qǐng)求
  2. AMS查看需要啟動(dòng)的Activity的進(jìn)程是否啟動(dòng)
  3. 如果已經(jīng)啟動(dòng)則使用scheduleLaunchActivity()方法,通過binder在應(yīng)用端開啟Activity的創(chuàng)建過程
  4. 如果沒有啟動(dòng)進(jìn)程,則AMS發(fā)送啟動(dòng)進(jìn)程請(qǐng)求給Zygote,讓Zygote去fork一個(gè)進(jìn)程,并執(zhí)行ActivityThread.main()方法
  5. fork出的進(jìn)程將pid傳給AMS,并且在main中向AMS傳入IApplicationThread進(jìn)行binder的雙向通行。
  6. AMS中會(huì)給這個(gè)應(yīng)用進(jìn)程創(chuàng)建Application,再執(zhí)行第3步

說說Activity的顯示原理

  1. 在onCreate中調(diào)用setContentView()

    • 創(chuàng)建mDecor(一個(gè)FrameLayout布局)
    • 將設(shè)置的布局加入mDecor
    • 獲取主顯示區(qū)的view(mContentParent)
    • 將自定義的布局加載到主顯示區(qū)中
  2. 主線程在執(zhí)行handleResumeActivity方法中(onResume之后),會(huì)對(duì)UI進(jìn)行操作:

    1. 獲取window對(duì)象

    2. 獲取decorView對(duì)象

    3. 獲取windowManager對(duì)象

    4. 將decorView加入windowManager中

      1. 創(chuàng)建ViewRootImpl對(duì)象

      2. ViewRootImpl.setView(mDecor, )

        1. requestLayout()觸發(fā)繪制

        2. mWindowSession.addToDisplay(mWindow, )

          mWindowSession是應(yīng)用與WMS進(jìn)行通信的對(duì)象,mWindow注冊(cè)到WMS后,應(yīng)用與WMS就可以進(jìn)行binder雙向調(diào)用

          WMS功能:

          • 給應(yīng)用端分配surface
          • 掌管surface顯示順序及位置尺寸
          • 控制窗口動(dòng)畫
          • 輸入事件分發(fā)
    5. mDecor.setVisibility(View.VISIBLE),設(shè)置可見進(jìn)行重繪

  • PhoneWindow是什么?怎么創(chuàng)建的?
  • setContentView原理,DecorView是什么?
  • ViewRoot是什么?有什么作用?
  • View的顯示原理是什么?WMS發(fā)揮什么作用?

應(yīng)用的UI線程是怎么啟動(dòng)的?

  • 對(duì)Activity來(lái)說,UI線程就是主線程

    activity.runOnUiThread()

  • 對(duì)View來(lái)說,UI線程就是ViewRootImpl創(chuàng)建的時(shí)候所在的線程

    View.post(Runnable r)

  • Activity的DecorView對(duì)應(yīng)的ViewRootImpl是在主線程創(chuàng)建的

    checkThread()

結(jié)論:UI線程就是主線程

UI線程的啟動(dòng)流程:

  1. Zygote fork進(jìn)程
  2. 啟動(dòng)binder線程
  3. 執(zhí)行入口函數(shù)(ActivityThread.main())
  • 說說UI線程是什么?
  • UI線程消息循環(huán)是怎么創(chuàng)建的?
  • UI線程和UI體系的關(guān)系
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • App應(yīng)用啟動(dòng)方式: (1) 冷啟動(dòng) 當(dāng)啟動(dòng)應(yīng)用時(shí),后臺(tái)沒有該應(yīng)用的進(jìn)程,這時(shí)系統(tǒng)會(huì)重新創(chuàng)建一個(gè)新的進(jìn)程分配給該...
    Johnson_Coding閱讀 534評(píng)論 0 1
  • 先上整體流程圖,看不懂下面會(huì)有介紹 一、理論基礎(chǔ) 1.zygote zygote意為“受精卵“。Android是基...
    蘇州丸子閱讀 2,757評(píng)論 1 4
  • 最近在一個(gè)飯局上,有個(gè)同事提出一個(gè)問題“我們?yōu)槭裁匆獙W(xué)習(xí),學(xué)習(xí)的動(dòng)力是什么?” 這個(gè)問題似乎把大家伙一下問住了,隨...
    布克愛讀書閱讀 17,797評(píng)論 0 1
  • 季春燕 江陰嘉鴻橡塑科技有限公司 【日精進(jìn)打卡第98天】 【知~學(xué)習(xí)】 《六項(xiàng)精進(jìn)》2遍 共160遍 《大學(xué)》2遍...
    Mrs_C_4db5閱讀 149評(píng)論 0 0
  • 大概每個(gè)人都有難以控制自己情緒的時(shí)候,比如:心情郁悶,莫名的煩躁,突如其來(lái)的焦慮等等。 誰(shuí)都想擁有一個(gè)好心情,可現(xiàn)...
    貳姑娘2閱讀 879評(píng)論 6 7

友情鏈接更多精彩內(nèi)容