Android Ams淺析

前兩天項目不怎麼忙,就忙裏偷閒,揹着老大看了下ActivityManagerService(android 2.3)的一些東東,初淺理解,僅當拋磚引玉。。。
進入正題:
一  涉及的主要類及解釋
1.    Ams --- ActivityManagerService.java, android系統服務,Activity管理的服務端,用於管理activity的各類行爲,控制activity的生命週期,派發消息事件,低內存管 理等等。實現了IBinder接口,能夠用於進程間通訊。
2.    ApplicationThread.java, 實現了IBinder接口,activity整個框架中客戶端和服務端(Ams)通訊的接口。同時也是類ActivityThread的內部類。這樣就有 效地把Ams和ActivityThread綁在了一塊兒。代理模式?有點像。。。
3.    ActivityThread.java,如第2點所述,ApplicationThread所綁定的客戶端就是ActivityThread。ActivityThread這個類在Activity客戶端很是重要。
a.    它是應用程序的入口,衆所周知,java程序的入口時main()方法,一樣,當Ams拉起一個新的進程,同時啓動一個主線程的時候,主線程就從 ActivityThread.main方法開始執行,它會初始化一些對象,而後本身進入消息等待隊列, 也就是Looper.loop(); 一旦進入loop()方法,線程就進入了死循環,不再會退出;一直在等待別人給他消息,而後執行這個消息。這也是edt(事件驅動模型)的原理。
b.    它是Activity客戶端的管理類,由它來決定,何時調用onCreate(),何時調用onResume()方法。當Activity發起一 個請求時,好比startActivity(),或者finish()的時候,它會來處理這個請求,而後調用其它的人來具體作事。

4.    Instrumentation.java, 這個類除了跟android的測試有關以外,仍是activity管理中實際作事情的人。好比,startActivity(), 在某種狀況下,就是調用這個類,而後調用到ams.固然有個時候是經過ApplicationThread去訪問Ams的。
問題:有的同窗就會想了,既然ApplicationThread能夠訪問Ams,那麼咱們應用程序是否是能夠調用ApplicationThread類來訪問ams,直接啓動Activity呢?
答案是不能夠的。由於ApplicationThread是ActivityThead的私有內部類,外界沒法訪問。而ActivityThread是 hide的,因此,咱們應用程序不能經過sdk去訪問ActivityThread類。同理,拿到Ams引用的接口是 ActivityManagerNative類,而這個類也是hide的。因此應用程序也不能直接操做ams.
5.    Activity.java,這個類你們就再熟悉不過了,android最重要的組件之一;其實從java角度看,它一點也不特殊,它就是一個java對 象,它會被建立,同時也會被垃圾回收機制銷燬,只不過它受ams管理,因此它纔有它的生命週期。因此顯得比較重要。
6.    ActivityResult.java, Activity管理服務端中,activity的記錄緩存。換句話說,就是客戶端啓動一個activity, ams會對它進行緩存,類型就是ActivityResult。咱們可能會想,爲何不直接緩存Activity類型的值,而要新定義一個 ActivityResult類型呢?
由於Activity類沒有實現IBinder接口,不能用於進程之間通訊。而這個緩存值是Ams和客戶端通訊用的。因此必須實現IBinder接口。而 且Activity設計的時候,也沒有打算讓它用於進程通訊,看它的成員變量就能夠知道,裏面有不少的龐大對象,如list, map等等。這些對象是不適合跨進程傳輸的。由於java裏面跨進程調用就是序列化和反序列化,那些龐大對象在序列化和反序列化的時候,會消耗大量的時間 和資源。另外,根據設計法則,一個類的做用盡量的單一,不要出現那種萬能類。因此,這也是緣由之一。

AMS是什麼?
全名是ActivityManagerService, 顧名思義,就是Activity管理機制的服務器端。屬於一個系統服務,位置systemProcess進程中。
能夠從多個角度來看ams;
1.    從java的角度來看,ams就是一個java對象,實現了IBinder接口,因此它是一個用於進程間通訊的接口。
這個對象初始化是在SystemServer.java的run()方法裏面。
Slog.i(TAG, "Activity Manager");
context = ActivityManagerService.main(factoryTest);
這是一段很普通的java靜態工廠代碼,咱們在這裏建立咱們的Ams對象。
初始化方法
public static final Context main(int factoryTest) {
AThread thr = new AThread();
        thr.start();  //啓動一個線程去初始化Ams對象
        synchronized (thr) {
            while (thr.mService == null) {
                try {
                    thr.wait(); //等待AThread初始化Ams完成
                } catch (InterruptedException e) {
                }
            }
}
//…
         //…..
}
AThread的run()方法
public void run() {
            Looper.prepare();
            android.os.Process.setThreadPriority(
                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);

            ActivityManagerService m = new ActivityManagerService();  //初始化Ams對象

            synchronized (this) {
                mService = m;
                notifyAll();  //初始化完成 ,notify main方法的wait()方法,告訴它已經完成,能夠往下面走了。
            }
     //……
   Looper.loop();  //本身進入消息循環等待狀態
}
思考:
這裏是另外啓動了一個線程AThread去建立Ams對象,而後用wait/notify機制來實現線程之間的同步。
a.    建立一個對象徹底沒必要要另外開啓個線程來處理,直接new出來不就能夠了。有多此一舉的感受
b.    AThread在建立了Ams對象以後,進入消息循環狀態而不是直接退出。可是看代碼沒有發現有向這個線程的handler發送消息的地方,也就是說AThread線程的狀態接下來會永遠阻塞。不明白這樣作有什麼意義。
思考結果:
它是AThread的run方法裏面new ActivityManagerService(), 而ActivityManagerService裏面有個變量mHandler,這樣的話mHandler綁定的線程就是AThread這個線程了。經過 向mHandler發消息,AThread就不停地從消息隊列獲取消息,處理消息。因此,上面a,b問題都已經解決。

2. AMS是一個服務
ActivityManagerService從名字就能夠看出,它是一個服務,用來管理Activity,並且是一個系統服務,就像包管理服務,電池管理,震動管理服務同樣。
3.    Ams是一個Binder
Ams實現了IBinder接口,因此它是一個Binder,這意味着它不但能夠用於進程間通訊,仍是一個線程。由於一個Binder就是一個線程。
這個怎麼理解呢?能夠這麼理解,若是咱們啓動一個Hello World安卓應用程序,裏面不另外啓動其餘線程,那我以爲,這個進程裏面咱們最起碼啓動了4個線程
a.    Main線程, 這是程序的主線程,也是咱們平常編寫代碼時用到最多的那個線程。好比咱們重寫了Activity的onCreate()方法,通常就是這個main線程來 執行代碼,也叫ui線程。這是由於安卓的組件(包括TextView, Button等等這些ui控件)都是非線程安全的,因此只容許main線程來操做。
b.    GC線程。咱們都知道,java有垃圾回收機制,每一個java程序(一個java虛擬機)都有一個垃圾回收線程,專門回收再也不使用的對象。
c.    Binder1 就是咱們的ApplicationThread,這個類實現了IBinder接口,用於進程間通訊。具體來講,是咱們的應用程序和Ams通訊的工具。
d.    Binder2 就是咱們的ViewRoot.W對象,它也是實現了IBinder接口,是用於咱們的應用程序和Wms通訊的工具。
Ps: wms就是WindowManagerServier,和Ams差很少的概念,不過它是管理窗口的系統服務。

4.     Ams是一個單獨的線程
a.    首先系統服務不可能運行在systemProcess進程的主線程中。由於這麼多系統服務若是都是運行在主線程中的話,確定會發生阻塞。好比這個線程正在 管理Activity,而後手機來電震動,那就沒人來處理震動管理。因此通常服務都是運行在單獨的線程裏面(有些服務例外)
b.    Ams實現了IBinder接口,因此它就是一個單獨的線程了,就是這個線程來處理Ams對Activity的管理。
疑問: 若是Ams只有一個線程來執行Activity管理的話,會不會發生阻塞。好比兩個客戶端同時發起請求。
我本身的見解是應該不會。由於手機操做系統是單界面的操做系統,就是說,在同一個時刻,只有一個Activity能展現在用戶面前 (TabActivity看起來同時展現了多個Activity,但安卓作了特殊的處理,暫不討論),不像windows是多任務多窗口的操做系統。單窗 口的話,那麼發送的onPause(),onResume()之類的請求時,在同一時刻,應該只有一我的發起。

Ams管理Activity流程
1.  以Activity.startActivityForResult()爲例說明,通常咱們見的最多的是調用 Activity.startActivity()方法。不過startActivity()的內部實現也是調用 startActivityForResult()方法,只不過requestCode=-1
。                                                   Activity.startActivity();
這裏Activity start一個Activity 是異步的。換句話說,Activity沒必要等待ams結果的返回,直接往下面執行。當把接下來的代碼執行完畢後,它就進入消息循環等待隊列,繼續等待別人 給他消息。不然就一直阻塞。不過ams很快就會給它發送一個暫停當前activity的消息。就是下面的調用流程。
                                                      Instrumentation. execStartActivity ();
                                                      Ams.startActivity();
                                                      ActivityStack. startActivityMayWait ();

調用ActivityThread的暫停方法時候,同時向本身發送一個暫停消息,延遲500ms執行,若是500ms以後沒有remove掉這個消息,就會說暫停出現異常。
    這裏要說明的是,Ams發送暫停消息給ActivityThread以後,就直接往下面走了。因此這是一個異步調用,非阻塞。發送消息後,再等待ActivityThread把暫停完畢的消息返回給本身。
                                                      ActivityThread. schedulePauseActivity ();

暫停完畢調用ActivityManagerNative.getDefault().activityPaused(token, state);
告訴Ams本身已經暫停完畢.

在Ams.activityPaused()方法內會移除掉上面那個500ms的消息。而後調用新activity的onResume之類的方法。

2.    startActivityForResult()方法啓動一個Activity,目標Acitivty結束後,會調用到onActivityResult()方法。
這個流程也是相似的,以Activity.finish()方法是入口,ams在接到finishActivity()以後,就會展轉調用到Activity.onActivityResult()方法。

這裏Activity和ActivityManagerService就是經過Binder來完成進程間通訊.

四  關係圖
應用程序進程                                                                                                     系統進程
Activity1

Activity2                ActivityThread                         ApplicationThread                 Ams

Activity3   

原本想上傳個圖,可是公司上傳實在不方便,只能用文字描述了。。 sorry..
這裏的意思是ActivityThread經過AppliactionThread這個Binder來和Ams通訊


這裏只是初略的分析了下ams,其實它的功能還有不少,如進程方面的,task方面的管理,低內存的管理等等。
Android裏面有oom模塊,當系統內存不夠用的時候,這個模塊會發生做用。其實ams並不能直接操做oom模塊,不過oom模塊在殺死進程釋放資源 的時候有一個優先級哦oom_adj(-16~15),值越低,說明越重要。Ams也正是經過給killer設置oom_adj這個值來管理各個應用程序 的。
其實咱們分析這些東西也不是爲了修改ams,只是爲了知其然,知其因此然。這樣咱們纔會寫出更健壯的應用程序。同時對咱們的代碼能力也是一種提升。
初略分析,歡迎各類板磚,臭雞蛋。
java

相關文章
相關標籤/搜索