1. 程式人生 > >Android外掛化開發之AMS與應用程式(客戶端ActivityThread、Instrumentation、Activity)通訊模型分析

Android外掛化開發之AMS與應用程式(客戶端ActivityThread、Instrumentation、Activity)通訊模型分析

今天主要分析下ActivityManagerService(服務端) 與應用程式(客戶端)之間的通訊模型,在介紹這個通訊模型的基礎上,再

   簡單介紹實現這個模型所需要資料型別。

        本文所介紹內容基於android2.2版本。由於Android版本的不同,本文所包含的一些類可能在命名等細節上做了一些更改,但

   萬變不離其宗,整個核心思想和通訊流程依舊如下。

            例如,①、在android2.3上就將android2.2中ActivityManagerService的很處理邏輯提煉出來,形成了一個單獨的

        ActivityStack類,因而顯得更“高階”;

                     ②、將後文講解到的HistoryRecord.Java直接重名名ActivityRecord.java等。

             很多不同點我也就不在細說了。大家在研究原始碼的過程裡,注意差異就成。

       Android的三大核心功能有如下三個:

                   功能有: 繪製圖形、處理觸控、按鍵事件等;

           2、ActivityManagerService.java  簡稱為 AMS

                   功能有:管理所有應用程式的Activity 、記憶體管理等 。

           3、WindowManagerService.java 

簡稱為WMS

                   功能有:為所有應用程式分配視窗,並管理這些視窗。

        從上可知,AMS作為一種系統級服務管理所有Activity,當操作某個Activity時,例如: 啟動一個新的Activity、停止當前

    Activity,必須報告給AMS,而不能“擅自處理”。當AMS接受到具體通知時,會根據該通知的型別,首先會更新內部記錄,

    然後在通知相應客戶程序去執行一個新的Activity或者停止指定的Activity。另外,由於AMS記錄了所有Activity的資訊,當然

    能夠主動的排程這些Activity,甚至在記憶體不足時,主動殺死後臺的Activity。

首先對模型中可能運到的類做一個介紹:

 ActivityThread.java    路徑位於:\frameworks\base\core\java\android\app\ActivityThread.java

         說明: 該類為應用程式(即APK包)所對應程序(一個程序裡可能有多個應用程式)的主執行緒類,即我們通常所說的UI執行緒。

           一個ActivityThread類對應於一個程序。最重要的是,每個應用程式的入口是該類中的static main()函式 。

     Activity.java               路徑位於:\frameworks\base\core\java\android\app\Activity.java

        說明:該類是與使用者互動的物件,同時也是APK應用程式執行的最小單元。ActivityThread類會根據使用者的操作選擇執行

          哪個Activity。當前執行的Activity是出於resume狀態(有且僅有一個),其他Activity出於pause或stop狀態。

     Instrumentation.java 路徑位於 :\frameworks\base\core\java\android\app\ActivityThread.java

         說明: 該類用於具體操作某個Activity的功能----單向(oneway)呼叫AMS以及統計、測量該應用程式的所有開銷。

            一個Instrumentation類對應於一個程序。每個Activity內部都有一個該Instrumentation物件的引用。

     舉個例子吧。

           我們將我們應用程式比作一個四合院,那麼Activity對應於四合院的人,ActivithThread對應於院子的主人----管理所有人,

    Instrumentation對應於管家------受氣的命,接受來自人(Activity/ActivithThread)的命令 ,去單向(oneway)呼叫AMS 。

ApplicationThread類是ActivityThread的內部類:

       說明:該類是一個Binder類,即可實現跨程序通訊。主要用於接受從AMS傳遞過來的訊息,繼而做相應處理。

ActivityManagerService.java 路徑位於:        

                                       \frameworks\base\services\java\com\android\server\am\ActivityManagerService.java

       說明:該類是一個Binder類,即可實現跨程序通訊。因此可以接受從客戶端,例如Instrumentation、Context等呼叫過來的

           資訊。ActivityManagerService提供了全域性的代理物件,供IPC呼叫。

  AMS與ActivityThread的通訊模型圖如下:

從該模型圖我們得知以下知識點:

       第一、 引起呼叫AMS的物件通常有Context 、 Instrumentatio、ActivityThread等 。

       第二、當AMS接受到來自某個應用程式傳來的訊息後,在AMS內部處理完畢後,會通過Binder機制回調回該應用程式

             所在ApplicationThread服務端類,即ActivityThread.java類。

       第三、當ActivityThread接受到AMS傳遞過來的訊息後,進行內部處理。如果需要的話,會繼續與AMS通訊。

       最後,當整個通訊完成時,ActivityThread會選擇合適的物件,例如Service、Activity、BroadcastReceiver等去做相應的

            處理。

  最後,對通訊模型設計到的設計到的資料類進行介紹:

  AMS 服務端用到的資料類:

    ProcessRecord.java  路徑:  \frameworks\base\services\java\com\android\server\am\ ProcessRecord.java

說明: 記錄每個程序的裡的全部資訊 。 主要資訊包括該程序中包含的Activity、Provider、Service等資訊、程序檔案資訊、

             該程序的記憶體狀態資訊。

        原始碼(部分)如下:

class ProcessRecord implements Watchdog.PssRequestor {  
  
    // 第一個應用程式的ApplicationInfo物件  
    final ApplicationInfo info; // all about the first app in the process  
    final String processName; // name of the process 程序名  
    // List of packages running in the process  
    final HashSet<String> pkgList = new HashSet(); // 該程序裡執行的應用程式包名  
    // contains HistoryRecord objects  
    final ArrayList activities = new ArrayList(); // 儲存該程序下所有Activity的資訊<activty  
                                                    // /> AndroidManifest.xml  
    // all ServiceRecord running in this process  
    final HashSet services = new HashSet(); // 儲存該程序下所有Service的資訊 <Service />  
}  

 HistoryRecord.java   路徑:\frameworks\base\services\java\com\android\server\am\HistoryRecord.java

         說明: 記錄每個Activity的全部資訊,因為AMS不知道客戶端Activity的存在,因此在服務端用HistroyRecord物件來方便

     管理和統計對應客戶端Activity的資訊。而且該類也是一個Binder類,因此可以跨程序呼叫。在客戶端中,ActivityThread同樣

     用HistroyRecord的“代理“ Proxy物件去標記對應的Activity。

           原始碼(部分)如下:

**  
 * An entry in the history stack, representing an activity.  
 */  
class HistoryRecord extends IApplicationToken.Stub {  
  
    final ActivityInfo info; // all about me     
    final Intent intent; // the original intent that generated us   
    final String shortComponentName; // the short component name of the intent    
    TaskRecord task;        // the task this is in.  該Activity對應Task的資訊  
    ProcessRecord app;  // if non-null, hosting application 該Activity所在的程序資訊  
      
    boolean stopped;        // is activity pause finished?  該Activity是否已經停止 即onStop();  
    boolean delayedResume;  // not yet resumed because of stopped app switches? 是否需要暫時停止啟動  
    boolean finishing;      // activity in pending finish list?  是否正在finish 即殺死該Activity  
      
    ...  
}  

 TaskRecord.java       路徑:\frameworks\base\services\java\com\android\server\am\TaskRecord.java

         說明: 記錄每個任務 Task的資訊。 Activity可以執行在不同的Task中。

           原始碼(部分)如下:

class TaskRecord {  
    // id   
    final int taskId;       // Unique identifier for this task.  
    final String affinity;  // The affinity name for this task, or null.  
    final boolean clearOnBackground; // As per the original activity.  
    //啟動一個新的Task的的Intent資訊  
    Intent intent;          // The original intent that started the task.  
    Intent affinityIntent;  // Intent of affinity-moved activity that started this task.  
    ComponentName origActivity; // The non-alias activity component of the intent.  
    ComponentName realActivity; // The actual activity component that started the task.  
    //執行在該Task的Activity數目  
    int numActivities;      // Current number of activities in this task.  
}  

ActivityManagerService.java

        PS:該類還是相當龐大的,有著琳琅滿目的資料物件,稍不注意,就給迷失了。

           原始碼(部分)如下:

class ActivityManagerService extends ActivityManagerNative implements xxx {  
    // This is the maximum number of activities that we would like to have  
    // running at a given time.  
    static final int MAX_ACTIVITIES = 20;  //系統中正在執行的Activity數目,最大為20  
    // Maximum number of recent tasks that we can remember.  
    static final int MAX_RECENT_TASKS = 20; //最大的Task數目為20      
    /** 
     * The back history of all previous (and possibly still 
     * running) activities.  It contains HistoryRecord objects. 
     */  //當前系統中正在執行的Activity資訊,即處於onPause、onStop、onResume狀態的Activity資訊  
    final ArrayList mHistory = new ArrayList();    
  
    /** 
     * Current activity that is resumed, or null if there is none. 
     */  
    HistoryRecord mResumedActivity = null;  //當前正在於使用者互動的Activity資訊,即處於onResume狀態。  
    /** 
     * When we are in the process of pausing an activity, before starting the 
     * next one, this variable holds the activity that is currently being paused. 
     */  
    HistoryRecord mPausingActivity = null;  //當前正在暫停的Activity資訊,即正在onPause();  
    /** 
     * All of the applications we currently have running organized by name. 
     * The keys are strings of the application package name (as 
     * returned by the package manager), and the keys are ApplicationRecord 
     * objects. 
     */  //當前正在執行的Process資訊  
    final ProcessMap<ProcessRecord> mProcessNames  = new ProcessMap<ProcessRecord>();  
    //開始啟動一個Activity  
    public final int startActivity(){ ...}  
}  

ActivityThread所在客戶端 :

   基本物件都已在開篇介紹過,ActivityThread 、ApplicationThread 類。

     ActivityThread .java 

          原始碼(部分)如下:

/** 
 * This manages the execution of the main thread in an 
 * application process, scheduling and executing activities, 
 * broadcasts, and other operations on it as the activity 
 * manager requests. 
 * 
 * {@hide} 
 */  
public final class ActivityThread {  
      
     //儲存了該程序裡所有正在執行的Activity資訊  , 即沒有onDestroy()的Activity  
     //IBinder物件是HistoryRecord的代理物件,在客戶端已IBinder標記每個Activity資訊  
     final HashMap<IBinder, ActivityRecord> mActivities = new HashMap<IBinder, ActivityRecord>();  
       
     final H mH = new H();  // H物件 ,Handler子類  
     Instrumentation mInstrumentation;  
     ...  
}  

ApplicationThread    是ActivityThread的內部類

        原始碼(部分)如下:

public final class ActivityThread {  
    ...   
    //Binder類 主用功能是接受從AMS傳遞過來的訊息,做處理後轉發給H類去進一步處理。  
    private final class ApplicationThread extends ApplicationThreadNative{  
         public final void schedulePauseActivity(){...}  
          public final void scheduleSendResult{...}  
          public final void scheduleSendResult(){...}  
    }  
}  

最後介紹一下ActivityThread的兩個內部類。

    H類      是ActivityThread的內部類

       說明 :H類是一個Hander子類 ,該類僅僅是為了非同步呼叫而設計的,使用方法同Hander類一樣。

           原始碼(部分)如下:

public final class ActivityThread {   
    ...  
    private final class H extends Handler {  
            
        private H() {  
           SamplingProfiler.getInstance().setEventThread(mLooper.getThread());  
        }  
        //處理訊息  
        public void handleMessage(Message msg){  
             switch (msg.what) {  
               case LAUNCH_ACTIVITY: {  
                 //啟動一個Activity  
                 ActivityRecord r = (ActivityRecord)msg.obj;  
                 r.packageInfo = getPackageInfoNoCheck(  
                         r.activityInfo.applicationInfo);  
                 handleLaunchActivity(r, null);                   
               }   
               ...  
             }  
        }  
   }  
}  

 ActivityRecord類同樣是ActivityThread的內部類

說明:在客戶端儲存當前Activity的相關資訊,方便ActivityThread管理維護Activity。這個類在實現和功能上對應於AMS的

          HistoryRecord類。

           原始碼(部分)如下:

public final class ActivityThread{  
    ...  
    //記錄了客戶端Activity的資訊  
    private static final class ActivityRecord {  
         IBinder token;  //該變數對應於AMS服務端HistoryRecord物件  
         Intent intent;  //啟動該Activity對應的intent資訊  
         Bundle state;   //儲存一些資訊  onCreate(state)  
         Activity activity;  //對應於Activity類  
         ActivityInfo activityInfo;  //對應的ActivityInfo物件  
         ...  
    }  
}

另外我再對客戶端Activity、ActivityRecord、ActivityThread 類包含的IBinder token屬性進行一下說明:該token變數

     實際上指向的的ActivityManagerService的HistoryRecord物件,他們是一一對應的。在應用程式內部和AMS都通過該token

     變數來標記我們實際需要的Activity資訊。 如下圖所示:

對ActivityManagerService通訊模型以及資料類有一定認識後,那麼現在你就可以具體去接觸每個操作是怎麼實現的了。 例

  如 startActivity()、 registerReceiver()等。 後面我也會慢慢講解到的,有興趣的可以先看如下兩篇吧。講解的都挺詳細的,反正

  我是偷了 不少經。 O(∩_∩)O~