1. 程式人生 > >Android系統篇之----解讀AMS遠端服務呼叫機制以及Activity的啟動流程

Android系統篇之----解讀AMS遠端服務呼叫機制以及Activity的啟動流程

一、為何本文不介紹Hook系統的AMS服務

在之前一篇文章中已經講解了 Android中Hook系統服務,以及攔截具體方法的功能了,按照流程本文應該介紹如何Hook系統的AMS服務攔截應用的啟動流程操作,但是本文並不會,因為在介紹這個知識點之前,還有一件大事要做,那就是得先分析一下Android中應用的啟動流程,如果這個流程不搞清楚的話,後面沒辦法Hook的,因為你都找不到Hook點,當然Hook代理物件倒是很容易獲得,如果沒有Hook點,是沒辦法後續的操作的,所以得先把流程分析清楚了,當然現在關於應用的啟動流程的知識已經爛大街了,但是每個人都有不同的分析方式和總結方式,我始終相信我的分析流程是最清晰最有用的。

二、Android中應用的啟動流程分析

下面就先來看一下Activity的啟動流程,分析啟動流程其實很簡單,我們直接看原始碼即可,我們一般在啟動Activity的時候都是使用系統的一個方法startActivity操作的,關於這個方法通過跟進程式碼是在ContextImpl.java中:


這裡用到了mMainThread變數去執行的操作,再看看這個變數:


的確是ActivityThread類,這個類我們在之前分析原始碼的時候多次提到它了,他是一個應用非常關鍵的一個類,首先他是一個應用的主執行緒,其次就是他也是一個程式的入口的地方:


後面會介紹這個入口main方法什麼時候會執行,下面繼續看ActivityThread中的getInstrumentation方法:


其實是獲取到Instrumentation型別,其實這個類相當於啟動Activity的中間者,啟動Activity中間都是由它來操作的:


看到又呼叫了ActivityManagerNative.getDefault方法去啟動activity了。去看看ActivityManagerNative類:


看到這裡就有點明白了吧,其實ActivityManagerNative類就是遠端服務的中間者Stub類,其實名字不叫Stub罷了,以後其實只要看到是繼承了Binder類和實現了AIDL介面型別的就是Stub類,不要關心類名了。看到他的asInterface方法的時候也是和之前的其他系統服務都是類似的,而這裡的本地端代理是ActivityManagerProxy

類。

下面繼續看他的getDefault方法實現,是通過變數gDefault獲取的:


在這裡可以看到了,其實gDefalut藉助Singleton實現的單例模式,而在內部可以看到先從ServiceManager中獲取到AMS遠端服務的Binder物件,然後使用asInterface方法轉化成本地化物件,其實就是ActivityManagerProxy物件。然後我們在看看上面呼叫了startActivityAsUser方法,其實就是呼叫了ActivityManagerProxy物件的這個方法:


這裡其實ActivityManagerProxy物件中的方法最終都會呼叫遠端服務Binder物件的transact方法,然後會轉接到遠端服務中間者ActivityManagerNative的onTransact方法中:


這裡看到會回撥IActivityManager介面中的startActivityAsUser方法,而這個具體實現一般都是在遠端服務中的,這裡我們可以猜想應該是叫做ActivityManagerService中:


有一層呼叫了,這裡是ActivityStackSupervisor類了,這裡就不在細分了,最終會在他內部又會呼叫到ActivityTask類中,又多了一層,然後會呼叫到ActivityManagerService中的startProcessLocked方法,這裡就會執行一段命令:


看到了,其實在這個過程之前還有一個操作就是通知Zygote程序需要啟動一個新的應用程序,然後執行命令執行ActivityThread的入口方法main,所以這個main方法其實就是一個應用程序的入口方法了,下面就繼續分析main方法中都幹了什麼:


在main方法中,呼叫了自身的attach方法:


這裡又要回到ActivityManagerService中了,然後又會呼叫ActivityStackSupervisor中的realStartActivityLocked方法:


而在這個方法中,會呼叫ProcessRecord型別的thread變數的scheduleLaunchActivity方法,而這個thread變數是IApplicationThread型別的:


哎,這裡看到了IApplicationThread可以想到,這裡可能又是一次遠端通訊了:


哎,果然是,不過這裡看到這些方法會意外的發現,大部分都是和Activity的生命週期相關的,那麼可以猜想這個通訊應該是操作Activity的生命週期的,在去看一下遠端服務的中間者實現了ApplicationThreadNative:


的確,這裡的實現機制都是類似的,那麼我們在上面瞭解了AMS的整個通訊機制之後,應該知道具體的服務端實現應該是ApplicationThread中,全域性搜尋一下,這個類盡然是定義在ActivityThread中的:


的確,這裡是遠端的具體方法實現,那麼咋們找一下scheduleLaunchActivity方法:


最終會呼叫ActivityThread中的傳送訊息的方法:


然後會呼叫ActivityThread中全域性的Handler型別mH傳送訊息


那麼咋們直接去看看訊息處理邏輯:


繼續看這個方法的實現:


使用performLaunchActivity構造出一個Activity了:


在performLaunchActivity方法中還會構造一個Application出來,繼續看:


最終又呼叫了Instrumentation的newActivity方法:


好吧,居然在這裡構造了一個Activity例項出來了,以前使用Activity的時候,一直好奇這個Activity什麼時候創建出來的,這樣找到地方了。

然後依然在ActivityManagerService中呼叫了Activity的生命週期方法:


當然,其他的回撥方法就不在一一列舉了,比如Application中的幾個回撥方法像記憶體低的時候,程式異常的時候的回撥也都在這裡。

三、流程總結

到了這裡我們就大致分析完了Android中的Activity啟動流程了,從過程中看,還是非常複雜的,其實分析完了之後會發現,自己都有點迷糊了,但是一定要自己一邊分析一邊記錄,下面就是我嘔心瀝血整理的一張流程圖(圖片很大,可以下載下來檢視高清原圖):


對照這張圖,下面就從頭到尾精簡的總結狠心知識點:

第一、AMS通訊機制分析

首選通過ContextImpl類中的startActivity方法,進入到了Instrumentation類中的execStartActivity方法,然後進入到了ActivityManagerNative中的方法startActivity,到這裡就出現第一個轉折點和重點了,那就是AMS遠端服務架構:


在這個過程中,我們在上一篇分析系統中的剪下板服務的時候,這裡分析就不難了,主要有四個物件:

1、IActivityManager:這個是遠端服務AIDL協議介面型別,定義了很多方法

2、ActivityManagerProxy:這個是本地端中間者物件,也就是我們應用實際操作的本地化物件,他一般是由ActivityManagerNative的asInterface方法獲取到的。在這個方法中會實現IActivityManager介面的所有方法,而在具體的方法中會使用遠端服務的Binder物件方法transact傳送命令給遠端中間者。

3、ActivityManagerNative:這個是遠端中間者物件,也就是我們之前分析的Stub類,只是不知道為何AMS中不叫這個名稱了,所以這裡以後分析系統服務原始碼的時候,應該看到如果繼承Binder類同時實現了IXXX介面,那麼這個類就是遠端服務的中間者,他主要有兩個功能,一個是可以將遠端服務的Binder物件轉化成本地實際物件,還有一個就是可以接受本地端中間者也就是Proxy物件傳送的命令,在onTransact方法中做處理,而在這個方法中其實會回撥IActivityManager介面中指定的方法,而具體的介面方法實現則是在ActivityManagerService中

4、ActivityManagerService:這個是遠端服務中具體方法實現的類,在這裡就是真正的邏輯處理了,而這個類是執行在系統服務程序中的,也就是system_server中。

從上面的流程可以看到,Android中的服務大部分都符合這個規則:

IXXX是AIDL介面型別定義邏輯方法

XXXProxy是本地端代理物件,也是給應用操作的實際物件

XXXNative/XXX$Stub是遠端服務的中間者物件,主要用來處理應用傳送過來的命令處理工作

XXXService是最終的服務邏輯實現方法的地方,執行在遠端程序中

第二、Activity棧機制分析

過了第一個轉折點之後,我們可以直接去ActivityManagerService中檢視具體方法實現邏輯,在這裡會出現多層呼叫,主要是ActivityStackSupervisor類和ActivityStack類,這兩個類主要是用來處理Activity棧資訊的,因為在啟動Activity的時候都會涉及到啟動模式,那麼這裡肯定要處理好應用的Activity棧資訊,這裡也就是那四種經典的啟動模式實現的邏輯的地方,感興趣的同學可以仔細分析原始碼。同時在這個過程中出現了幾個重要型別:

1》ActivityStack這個是管理本應用中所有Activity的棧結構。
2》ActivityRecord這個是記錄當前Activity的資訊的,比如在哪程序中ProcessState,當前的狀態CurentState等,和Activity是一一對應的。
3》Task這個記錄所有Activity的資訊的,這裡不會區分是哪個應用的Activity了。而這個Task就是我們經常講到的那個Activity啟動模式中的singleTask模式在啟動一個Activity的時候就會另外啟動一個Task。

4》ProcessRecord這個類記錄的是一個程序中的資訊,因為一個應用中可能會包含多個程序。

第三、建立和啟動應用程序

過了Activity棧資訊處理之後,會回到ActivityManagerService中的startProcessLocked方法,在這個方法中幹了一件最重要的事,那就是啟動應用程序了,當然在這之前還有一步就是向Zygote程序傳送請求建立應用程序,啟動應用程序其實就是呼叫Process類執行ActivityThread類,這樣就會執行這個類的main函式入口,到這裡我們的應用程序就算起來了,然後在看看ActivityThread中的main函式中幹了什麼呢?

第四、Activity生命週期程序通訊機制分析

分析到ActivityThread的main函式中,發現也是一件最重要的事就是attach操作,這個操作主要是繫結一些資訊的,首先得繫結Application操作吧,然後跟進方法實現,最後在ActivityStackSupervisor類的realStartActivityLocked方法中呼叫了ApplicationThread的scheduleLaunchActivity方法,好了,這裡就要出現一個轉折點了,就是又要出現一個AIDL通訊機制了:


這個過程其實和上面的AMS通訊機制是差不多的,但是這裡的物件變了,是ApplicationThread類了,而這通訊機制主要是為了Activity的生命週期服務的,上面的AMS通訊機制是為了Activity啟動服務,兩者分開操作也算是比較清晰了,但是我們在這裡可以看到,這裡的服務端和客戶端通訊的角色會發生變化了:

在AMS通訊中,應用作為客戶端會發送指令給服務端處理

在ApplicationThread通訊中,應用會作為服務端介紹來自服務端的指令

所以會發現在ActivityManagerService這個服務端類中呼叫的物件其實是ApplicationThreadProxy物件的。

那具體處理指令的遠端是在應用程序中,也就是ApplicationThread類,這個類是在ActivityThread中實現的。

第五、分析Activity的構造和生命週期方法

瞭解了ApplicationThread通訊機制之後,可以去類中看看具體的生命週期方法呼叫邏輯了,裡面處理還是比較簡單的,是利用ActivityThread中的Handler變數作為訊息傳送和處理,然後在呼叫指定方法即可,最終會發現通過Instrumentation類中的newActivity方法構造一個Activity例項物件,然後啟動Activity的處理。然後後續會呼叫Activity的生命週期方法了。

到這裡我們就非常清晰的說明了Activity的啟動流程了,這裡最關鍵的點就是要理解Android中的系統服務遠端呼叫機制和Binder機制即可,弄清楚通訊中那幾個類物件和具體關係。而這裡比較複雜的會出現了兩個程序通訊操作:


同時在這個過程中我們發現了Activity啟動的過程中棧的處理,幾種Activity的啟動模式的具體邏輯處理等資訊。在這個分析過程中剛開始你會覺得系統這麼設計真是夠複雜的,但是當你真的理解了,會發現這個設計真的很清晰的。AMS程序通訊是為了處理Activity啟動工作,ApplicationThread程序通訊是為了處理Activity的生命週期工作。

四、總結

Android中瞭解了Activity啟動流程之後,後面我們就可以開始Hook掉系統的AMS服務,攔截Activity的啟動方法以及各種生命週期方法了,從而能夠達到我們想要的目的。作為一個Android開發者到最後都會避免不了這個Activity啟動流程的梳理工作,雖然網上的知識點已經爛大街了,但是真正自己去實踐分析效果是截然不同的,所以一定要靜下心來自己去分析一遍流程,收穫還是非常大的。

《Android應用安全防護和逆向分析》

點選立即購買:京東  天貓

更多內容:點選這裡

關注微信公眾號,最新技術乾貨實時推送