本專欄專一分享大型Bat面試知識,後續會持續更新,喜歡的話麻煩點擊一個關注java
面試官: AMS在Android起到什麼做用,簡單的分析下Android的源碼android
心理分析:這道題在發生在大多數場景下。面對這道題 不少求職很茫然,不知道該如何提及。AMS自己比較複雜難以理解。工做多年也很難弄清AMS的做用,其實咱們大可從如下幾點入手組件啓動、進程切換、Crash異常入手程序員
求職者:AMS難以表述 咱們就從最熟知 的Activity啓動入手,逐步深刻和分析,用定力告訴面試官,我層深刻研究過。接下來咱們從五條線分析AMS做用及機制面試
概述
相信大多數動腦同窗對文章中提到的ActivityManagerService(之後簡稱AMS)都有所耳聞。
AMS是Android中最核心的服務,主要負責系統中四大組件的啓動、切換、調度及應用進程的管理和調度等工做,其職責與操做系統中的進程管理和調度模塊相相似,所以它在Android中很是重要。 AMS是碰到的第一塊難啃的骨頭[①],涉及的知識點較多。爲了幫助讀者更好地理解AMS,接下來將帶小夥伴麼按五條不一樣的線來分析它。框架
- 第一條線:同其餘服務同樣,將分析SystemServer中AMS的調用軌跡。
- 第二條線:以am命令啓動一個Activity爲例,分析應用進程的建立、Activity的啓動,以及它們和AMS之間的交互等知識。
- 第三條線和第四條線:分別以Broadcast和Service爲例,分析AMS中Broadcast和Service的相關處理流程。
- 第五條線:以一個Crash的應用進程爲出發點,分析AMS如何打理該應用進程的身後事。 除了這五條線外,還將統一分析在這五條線中頻繁出現的與AMS中應用進程的調度、內存管理等相關的知識。 提示ContentProvider將放到下一章分析,不過本章將涉及和ContentProvider有關的知識點。 先來看AMS的家族圖譜:
![](http://static.javashuo.com/static/loading.gif)
由圖可知:ide
- AMS由ActivityManagerNative(之後簡稱AMN)類派生,並實現Watchdog.Monitor和BatteryStatsImpl.BatteryCallback接口。而AMN由Binder派生,實現了IActivityManager接口。
- 客戶端使用ActivityManager類。因爲AMS是系統核心服務,不少API不能開放供客戶端使用,因此設計者沒有讓ActivityManager直接加入AMS家族。在ActivityManager類內部經過調用AMN的getDefault函數獲得一個ActivityManagerProxy對象,經過它可與AMS通訊。
AMS由SystemServer的ServerThread線程建立;函數
1. 初識ActivityManagerService總結
本節所分析的4個關鍵函數均較複雜,與之相關的知識點總結以下:學習
- AMS的main函數:建立AMS實例,其中最重要的工做是建立Android運行環境,獲得一個ActivityThread和一個Context對象。
- AMS的setSystemProcess函數:該函數註冊AMS和meminfo等服務到ServiceManager中。另外,它爲SystemServer建立了一個ProcessRecord對象。因爲AMS是Java世界的進程管理及調度中心,要作到對Java進程一視同仁,儘管SystemServer貴爲系統進程,此時也不得不將其併入AMS的管理範圍內。
- AMS的installSystemProviders:爲SystemServer加載SettingsProvider。
- AMS的systemReady:作系統啓動完畢前最後一些掃尾工做。該函數調用完畢後,HomeActivity將呈如今用戶面前。 對AMS 調用軌跡分析是咱們破解AMS的第一條線,但願讀者反覆閱讀,以真正理解其中涉及的知識點,尤爲是和Android運行環境及Context相關的知識。
2. startActivity
總結 本文詳細startActivity的整個啓動流程,spa
- 流程[2.1 ~2.4]:運行在調用者所在進程,好比從桌面啓動Activity,則調用者所在進程爲launcher進程,launcher進程利用ActivityManagerProxy做爲Binder Client,進入system_server進程(AMS相應的Server端)。
- 流程[2.5 ~2.18]:運行在system_server系統進程,整個過程最爲複雜、核心的過程,下面其中部分步驟:
- 流程[2.7]:會調用到resolveActivity(),藉助PackageManager來查詢系統中全部符合要求的Activity,當存在多個知足條件的Activity則會彈框讓用戶來選擇;
- 流程[2.8]:建立ActivityRecord對象,並檢查是否運行App切換,而後再處理mPendingActivityLaunches中的activity;
- 流程[2.9]:爲Activity找到或建立新的Task對象,設置flags信息;
- 流程[2.13]:當沒有處於非finishing狀態的Activity,則直接回到桌面; 不然,當mResumedActivity不爲空則執行startPausingLocked()暫停該activity;而後再進入startSpecificActivityLocked()環節;
- 流程[2.14]:當目標進程已存在則直接進入流程[2.17],當進程不存在則建立進程,通過層層調用仍是會進入流程[2.17];
- 流程[2.17]:system_server進程利用的ATP(Binder Client),通過Binder,程序接下來進入目標進程。
- 流程[2.19 ~2.18]:運行在目標進程,經過Handler消息機制,該進程中的Binder線程向主線程發送H.LAUNCH_ACTIVITY,最終會經過反射建立目標Activity,而後進入onCreate()生命週期。 從另外一個角度下圖來歸納:
![](http://static.javashuo.com/static/loading.gif)
啓動流程:
- 點擊桌面App圖標,Launcher進程採用Binder IPC向system_server進程發起startActivity請求;
- system_server進程接收到請求後,向zygote進程發送建立進程的請求;
- Zygote進程fork出新的子進程,即App進程;
- App進程,經過Binder IPC向sytem_server進程發起attachApplication請求;
- system_server進程在收到請求後,進行一系列準備工做後,再經過binder IPC向App進程發送scheduleLaunchActivity請求;
- App進程的binder線程(ApplicationThread)在收到請求後,經過handler向主線程發送LAUNCH_ACTIVITY消息;
- 主線程在收到Message後,經過發射機制建立目標Activity,並回調Activity.onCreate()等方法。 到此,App便正式啓動,開始進入Activity生命週期,執行完onCreate/onStart/onResume方法,UI渲染結束後即可以看到App的主界面。
![](http://static.javashuo.com/static/loading.gif)
startActivity後半程總結操作系統
![](http://static.javashuo.com/static/loading.gif)
starActivity總結
Activity的啓動就介紹到這裏。這一路分析下來,相信讀者也和筆者同樣以爲此行毫不輕鬆。先回顧一下這次旅程:
- 行程的起點是am。am是Android中很重要的程序,讀者務必要掌握它的用法。咱們利用am start命令,發起本次目標Activity的啓動請求。
- 接下來進入ActivityManagerService和ActivityStack這兩個核心類。對於啓動Activity來講,這段行程又可分細分爲兩個階段:第一階段的主要工做就是根據啓動模式和啓動標誌找到或建立ActivityRecord及對應的TaskRecord;第二階段工做就是處理Activity啓動或切換相關的工做。
- 首先討論了AMS直接建立目標進程並運行Activity的流程,其中涉及目標進程的建立,在目標進程中Android運行環境的初始化,目標Activity的建立以及觸發onCreate、onStart及onResume等其生命週期中重要函數調用等相關知識點。
- 接着又討論了AMS先pause當前Activity,而後再建立目標進程並運行Activity的流程。其中牽扯到兩個應用進程和AMS的交互,其難度之大可見一斑。 讀者在閱讀本節時,務必要區分此旅程中兩個階段工做的重點:其一是找到合適的ActivityRecord和TaskRecord;其二是調度相關進程進行Activity切換。在SDK文檔中,介紹最爲詳細的是第一階段中系統的處理策略,例如啓動模式、啓動標誌的做用等。第二階段工做實際上是與Android組件調度相關的工做。SDK文檔只是針對單個Activity進行生命週期方面的介紹。 坦誠地說,此次旅程略過很多邏輯狀況。緣由有二,一方面受限於精力和篇幅,另方面是做爲調度核心類,和AMS相關的代碼及處理邏輯很是複雜,並且其間還夾雜了與WMS的交互邏輯,使複雜度更甚。再者,筆者我的感受這部分代碼絕談不上高效、嚴謹和美觀,甚至有些醜陋(在分析它們的過程當中,遠沒有研究Audio、Surface時那種暢快淋漓的感受)。 此處列出幾個供讀者深刻研究的點:
- 各類啓動模式、啓動標誌的處理流程。
- Configuration發生變化時Activity的處理,以及在Activity中對狀態保存及恢復的處理流程。
- Activity生命週期各個階段的轉換及相關處理。Android 2.3之後新增的與Fragment的生命週期相關的轉換及處理。
3. 廣播處理總結
![](http://static.javashuo.com/static/loading.gif)
4. startService流程圖
總結 5.1 流程說明 在整個startService過程,從進程角度看服務啓動過程
- Process A進程:是指調用startService命令所在的進程,也就是啓動服務的發起端進程,好比點擊桌面App圖標,此處Process A即是Launcher所在進程。
- system_server進程:系統進程,是java framework框架的核心載體,裏面運行了大量的系統服務,好比這裏提供ApplicationThreadProxy(簡稱ATP),ActivityManagerService(簡稱AMS),這個兩個服務都運行在system_server進程的不一樣線程中,因爲ATP和AMS都是基於IBinder接口,都是binder線程,binder線程的建立與銷燬都是由binder驅動來決定的,每一個進程binder線程個數的上限爲16。
- Zygote進程:是由init進程孵化而來的,用於建立Java層進程的母體,全部的Java層進程都是由Zygote進程孵化而來;
- Remote Service進程:遠程服務所在進程,是由Zygote進程孵化而來的用於運行Remote服務的進程。主線程主要負責Activity/Service等組件的生命週期以及UI相關操做都運行在這個線程; 另外,每一個App進程中至少會有兩個binder線程 ApplicationThread(簡稱AT)和ActivityManagerProxy(簡稱AMP),固然還有其餘線程,這裏不是重點就不提了。
![](http://static.javashuo.com/static/loading.gif)
圖中涉及3種IPC通訊方式:Binder、Socket以及Handler,在圖中分別用3種不一樣的顏色來表明這3種通訊方式。通常來講,同一進程內的線程間通訊採用的是 Handler消息隊列機制,不一樣進程間的通訊採用的是binder機制,另外與Zygote進程通訊採用的Socket。
啓動流程:
- Process A進程採用Binder IPC向system_server進程發起startService請求;
- system_server進程接收到請求後,向zygote進程發送建立進程的請求;
- zygote進程fork出新的子進程Remote Service進程;
- Remote Service進程,經過Binder IPC向sytem_server進程發起attachApplication請求;
- system_server進程在收到請求後,進行一系列準備工做後,再經過binder IPC向remote Service進程發送scheduleCreateService請求;
- Remote Service進程的binder線程在收到請求後,經過handler向主線程發送CREATE_SERVICE消息;
- 主線程在收到Message後,經過發射機制建立目標Service,並回調Service.onCreate()方法。 到此,服務便正式啓動完成。當建立的是本地服務或者服務所屬進程已建立時,則無需通過上述步驟二、3,直接建立服務便可。
![](http://static.javashuo.com/static/loading.gif)
5. AMS中的進程管理
前面曾反覆提到,Android平臺中不多能接觸到進程的概念,取而代之的是有明肯定義的四大組件。可是做爲運行在Linux用戶空間內的一個系統或框架,Android不只不能脫離進程,反而要大力利用Linux OS提供的進程管理機制和手段,更好地爲本身服務。做爲Android平臺中組件運行管理的核心服務,ActivityManagerService當仁不讓地接手了這方面的工做。目前,AMS對進程的管理僅涉及兩個方面:
- 調節進程的調度優先級和調度策略。
- 調節進程的OOM值。
6. App的Crash處理總結
![](http://static.javashuo.com/static/loading.gif)
應用進程進行Crash處理的流程。
一.概述
ActivityManagerService是Framework層的核心服務之一,ActivityManagerService是Binder的子類,它的功能主要如下三點:
三.ActivityManagerService的啓動過程
ActivityManagerService的啓動是在systemserver進程的startBootstrapServices方法中啓動的. SystemServiceManager.startService(ActivityManagerService.Lifecycle.class) 功能主要: 建立ActivityManagerService.Lifecycle對象; 調用Lifecycle.onStart()方法。
四.主要功能之一的四大組件的統一調度
ActivityManagerService最主要的功能就是統一的管理者activity,service,broadcast,provider的建立,運行,關閉.咱們在應用程序中啓動acitivity,關閉acitiviy等操做最終都是要經過ams來統一管理的.這個過程很是的複雜,不是一會兒能夠講的清楚的,我這裏推薦老羅的博客來說解四大組件的啓動過程:
Android應用程序內部啓動Activity過程(startActivity)的源代碼分析 Android系統在新進程中啓動自定義服務過程(startService)的原理分析 Android應用程序註冊廣播接收器(registerReceiver)的過程分析 Android應用程序發送廣播(sendBroadcast)的過程分析 Android應用程序組件Content Provider簡要介紹和學習計劃
五.主要功能之一的內存管理
咱們知道當一個進程中的acitiviy所有都關閉之後,這個空進程並不會當即就被殺死.而是要等到系統內存不夠時纔會殺死.可是實際上ActivityManagerService並不可以管理內存,android的內存管理是Linux內核中的內存管理模塊和OOM進程一塊兒管理的.Android進程在運行的時候,會經過Ams把每個應用程序的oom_adj值告訴OOM進程,這個值的範圍在-16-15,值越低說明越重要,越不會被殺死.當發生內存低的時候,Linux內核內存管理模塊會通知OOm進程根據AMs提供的優先級強制退出值較高的進程.所以Ams在內存管理中只是扮演着一個提供進程oom_adj值的功能.真正的內存管理仍是要調用OOM進程來完成.下面經過調用Activity的finish()方法來看看內存釋放的狀況.
當咱們手動調用finish()方法或者按back鍵時都是會關閉activity的,,在調用finish的時候只是會先調用ams的finishActivityLocked方法將當前要關閉的acitiviy的finish狀態設置爲true,而後就會先去啓動新的acitiviy,當新的acitiviy啓動完成之後就會經過消息機制通知Ams,Ams在調用activityIdleInternalLocked方法來關閉以前的acitiviy.
關於我
更多信息能夠點擊關於我 , 很是但願和你們一塊兒交流 , 共同進步
也能夠掃一掃, 目前是一名程序員,不只分享 Android開發相關知識,同時還分享技術人成長曆程,包括我的總結,職場經驗,面試經驗等,但願能讓你少走一點彎路。
![](http://static.javashuo.com/static/loading.gif)