Android應用程序發送廣播(sendBroadcast)的過程分析

轉自:http://blog.csdn.net/luoshengyang/article/details/6744448

有時間要好好研究一下

前面我們分析了Android應用程序註冊廣播接收器的過程,這個過程只完成了萬里長征的第一步,接下來它還要等待ActivityManagerService將廣播分發過來。ActivityManagerService是如何得到廣播並把它分發出去的呢?這就是本文要介紹的廣播發送過程了。

        廣播的發送過程比廣播接收器的註冊過程要複雜得多了,不過這個過程仍然是以ActivityManagerService爲中心。廣播的發送者將廣播發送到ActivityManagerService,ActivityManagerService接收到這個廣播以後,就會在自己的註冊中心查看有哪些廣播接收器訂閱了該廣播,然後把這個廣播逐一發送到這些廣播接收器中,但是ActivityManagerService並不等待廣播接收器處理這些廣播就返回了,因此,廣播的發送和處理是異步的。概括來說,廣播的發送路徑就是從發送者到ActivityManagerService,再從ActivityManagerService到接收者,這中間的兩個過程都是通過Binder進程間通信機制來完成的,因此,希望讀者在繼續閱讀本文之前,對Android系統的Binder進程間通信機制有所瞭解,具體可以參考Android進程間通信(IPC)機制Binder簡要介紹和學習計劃一文。

        本文繼續以Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中所開發的應用程序爲例子,並且結合上文Android應用程序註冊廣播接收器(registerReceiver)的過程分析的內容,一起來分析Android應用程序發送廣播的過程。

        回顧一下Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中所開發的應用程序的組織架構,MainActivity向ActivityManagerService註冊了一個CounterService.BROADCAST_COUNTER_ACTION類型的計數器服務廣播接收器,計數器服務CounterService在後臺線程中啓動了一個異步任務(AsyncTask),這個異步任務負責不斷地增加計數,並且不斷地將當前計數值通過廣播的形式發送出去,以便MainActivity可以將當前計數值在應用程序的界面線程中顯示出來。

        計數器服務CounterService發送廣播的代碼如下所示:

  1. public class CounterService extends Service implements ICounterService {    
  2.     ......   
  3.   
  4.     public void startCounter(int initVal) {    
  5.         AsyncTask<Integer, Integer, Integer> task = new AsyncTask<Integer, Integer, Integer>() {        
  6.             @Override    
  7.             protected Integer doInBackground(Integer... vals) {    
  8.                 ......    
  9.             }    
  10.   
  11.             @Override     
  12.             protected void onProgressUpdate(Integer... values) {    
  13.                 super.onProgressUpdate(values);    
  14.   
  15.                 int counter = values[0];    
  16.   
  17.                 Intent intent = new Intent(BROADCAST_COUNTER_ACTION);    
  18.                 intent.putExtra(COUNTER_VALUE, counter);    
  19.   
  20.                 sendBroadcast(intent);    
  21.             }    
  22.   
  23.             @Override    
  24.             protected void onPostExecute(Integer val) {    
  25.                 ......   
  26.             }    
  27.   
  28.         };    
  29.   
  30.         task.execute(0);        
  31.     }    
  32.   
  33.     ......  
  34. }  
        在onProgressUpdate函數中,創建了一個BROADCAST_COUNTER_ACTION類型的Intent,並且在這裏個Intent中附加上當前的計數器值,然後通過CounterService類的成員函數sendBroadcast將這個Intent發送出去。CounterService類繼承了Service類,Service類又繼承了ContextWrapper類,成員函數sendBroadcast就是從ContextWrapper類繼承下來的,因此,我們就從ContextWrapper類的sendBroadcast函數開始,分析廣播發送的過程。

        在繼承分析廣播的發送過程前,我們先來看一下廣播發送過程的序列圖,然後按照這個序圖中的步驟來一步一步分析整個過程。


點擊查看大圖

        Step 1. ContextWrapper.sendBroadcast

        這個函數定義在frameworks/base/core/java/android/content/ContextWrapper.java文件中:

  1. public class ContextWrapper extends Context {  
  2.     Context mBase;  
  3.   
  4.     ......  
  5.   
  6.     @Override  
  7.     public void sendBroadcast(Intent intent) {  
  8.         mBase.sendBroadcast(intent);  
  9.     }  
  10.   
  11.     ......  
  12.   
  13. }  
         這裏的成員變量mBase是一個ContextImpl實例,這裏只簡單地調用ContextImpl.sendBroadcast進一行操作。

         Step 2. ContextImpl.sendBroadcast

         這個函數定義在frameworks/base/core/java/android/app/ContextImpl.java文件中:

  1. class ContextImpl extends Context {  
  2.     ......  
  3.   
  4.     @Override  
  5.     public void sendBroadcast(Intent intent) {  
  6.         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());  
  7.         try {  
  8.             ActivityManagerNative.getDefault().broadcastIntent(  
  9.                 mMainThread.getApplicationThread(), intent, resolvedType, null,  
  10.                 Activity.RESULT_OK, nullnullnullfalsefalse);  
  11.         } catch (RemoteException e) {  
  12.         }  
  13.     }  
  14.   
  15.     ......  
  16.   
  17. }  
        這裏的resolvedType表示這個Intent的MIME類型,我們沒有設置這個Intent的MIME類型,因此,這裏的resolvedType爲null。接下來就調用ActivityManagerService的遠程接口ActivityManagerProxy把這個廣播發送給ActivityManagerService了。

        Step 3. ActivityManagerProxy.broadcastIntent

        這個函數定義在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:

  1. class ActivityManagerProxy implements IActivityManager  
  2. {  
  3.     ......  
  4.   
  5.     public int broadcastIntent(IApplicationThread caller,  
  6.         Intent intent, String resolvedType,  IIntentReceiver resultTo,  
  7.         int resultCode, String resultData, Bundle map,  
  8.         String requiredPermission, boolean serialized,  
  9.         boolean sticky) throws RemoteException  
  10.     {  
  11.         Parcel data = Parcel.obtain();  
  12.         Parcel reply = Parcel.obtain();  
  13.         data.writeInterfaceToken(IActivityManager.descriptor);  
  14.         data.writeStrongBinder(caller != null ? caller.asBinder() : null);  
  15.         intent.writeToParcel(data, 0);  
  16.         data.writeString(resolvedType);  
  17.         data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);  
  18.         data.writeInt(resultCode);  
  19.         data.writeString(resultData);  
  20.         data.writeBundle(map);  
  21.         data.writeString(requiredPermission);  
  22.         data.writeInt(serialized ? 1 : 0);  
  23.         data.writeInt(sticky ? 1 : 0);  
  24.         mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);  
  25.         reply.readException();  
  26.         int res = reply.readInt();  
  27.         reply.recycle();  
  28.         data.recycle();  
  29.         return res;  
  30.     }  
  31.   
  32.     ......  
  33.   
  34. }  
         這裏的實現比較簡單,把要傳遞的參數封裝好,然後通過Binder驅動程序進入到ActivityManagerService的broadcastIntent函數中。

         Step 4. ctivityManagerService.broadcastIntent

         這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

  1. public final class ActivityManagerService extends ActivityManagerNative  
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
  3.     ......  
  4.   
  5.     public final int broadcastIntent(IApplicationThread caller,  
  6.             Intent intent, String resolvedType, IIntentReceiver resultTo,  
  7.             int resultCode, String resultData, Bundle map,  
  8.             String requiredPermission, boolean serialized, boolean sticky) {  
  9.         synchronized(this) {  
  10.             intent = verifyBroadcastLocked(intent);  
  11.   
  12.             final ProcessRecord callerApp = getRecordForAppLocked(caller);  
  13.             final int callingPid = Binder.getCallingPid();  
  14.             final int callingUid = Binder.getCallingUid();  
  15.             final long origId = Binder.clearCallingIdentity();  
  16.             int res = broadcastIntentLocked(callerApp,  
  17.                 callerApp != null ? callerApp.info.packageName : null,  
  18.                 intent, resolvedType, resultTo,  
  19.                 resultCode, resultData, map, requiredPermission, serialized,  
  20.                 sticky, callingPid, callingUid);  
  21.             Binder.restoreCallingIdentity(origId);  
  22.             return res;  
  23.         }  
  24.     }  
  25.   
  26.     ......  
  27. }  
         這裏調用broadcastIntentLocked函數來進一步處理。

         Step 5. ActivityManagerService.broadcastIntentLocked

         這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

  1. public final class ActivityManagerService extends ActivityManagerNative  
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
  3.     ......  
  4.   
  5.     private final int broadcastIntentLocked(ProcessRecord callerApp,  
  6.             String callerPackage, Intent intent, String resolvedType,  
  7.             IIntentReceiver resultTo, int resultCode, String resultData,  
  8.             Bundle map, String requiredPermission,  
  9.             boolean ordered, boolean sticky, int callingPid, int callingUid) {  
  10.         intent = new Intent(intent);  
  11.   
  12.         ......  
  13.   
  14.         // Figure out who all will receive this broadcast.  
  15.         List receivers = null;  
  16.         List<BroadcastFilter> registeredReceivers = null;  
  17.         try {  
  18.             if (intent.getComponent() != null) {  
  19.                 ......  
  20.             } else {  
  21.                 ......  
  22.                 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);  
  23.             }  
  24.         } catch (RemoteException ex) {  
  25.             ......  
  26.         }  
  27.   
  28.         final boolean replacePending =  
  29.             (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;  
  30.   
  31.         int NR = registeredReceivers != null ? registeredReceivers.size() : 0;  
  32.         if (!ordered && NR > 0) {  
  33.             // If we are not serializing this broadcast, then send the  
  34.             // registered receivers separately so they don't wait for the  
  35.             // components to be launched.  
  36.             BroadcastRecord r = new BroadcastRecord(intent, callerApp,  
  37.                 callerPackage, callingPid, callingUid, requiredPermission,  
  38.                 registeredReceivers, resultTo, resultCode, resultData, map,  
  39.                 ordered, sticky, false);  
  40.             ......  
  41.             boolean replaced = false;  
  42.             if (replacePending) {  
  43.                 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {  
  44.                     if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {  
  45.                         ......  
  46.                         mParallelBroadcasts.set(i, r);  
  47.                         replaced = true;  
  48.                         break;  
  49.                     }  
  50.                 }  
  51.             }  
  52.   
  53.             if (!replaced) {  
  54.                 mParallelBroadcasts.add(r);  
  55.   
  56.                 scheduleBroadcastsLocked();  
  57.             }  
  58.   
  59.             registeredReceivers = null;  
  60.             NR = 0;  
  61.         }  
  62.   
  63.         ......  
  64.   
  65.     }  
  66.   
  67.     ......  
  68. }  
         這個函數首先是根據intent找出相應的廣播接收器:
  1.    // Figure out who all will receive this broadcast.  
  2.    List receivers = null;  
  3.    List<BroadcastFilter> registeredReceivers = null;  
  4.    try {  
  5. if (intent.getComponent() != null) {  
  6.         ......  
  7. else {  
  8.     ......  
  9.     registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);  
  10. }  
  11.    } catch (RemoteException ex) {  
  12. ......  
  13.    }  
        回憶一下前面一篇文章Android應用程序註冊廣播接收器(registerReceiver)的過程分析中的Step 6(ActivityManagerService.registerReceiver)中,我們將一個filter類型爲BROADCAST_COUNTER_ACTION類型的BroadcastFilter實例保存在了ActivityManagerService的成員變量mReceiverResolver中,這個BroadcastFilter實例包含了我們所註冊的廣播接收器,這裏就通過mReceiverResolver.queryIntent函數將這個BroadcastFilter實例取回來。由於註冊一個廣播類型的接收器可能有多個,所以這裏把所有符合條件的的BroadcastFilter實例放在一個List中,然後返回來。在我們這個場景中,這個List就只有一個BroadcastFilter實例了,就是MainActivity註冊的那個廣播接收器。

       繼續往下看:

  1. final boolean replacePending =  
  2.   (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;  
       這裏是查看一下這個intent的Intent.FLAG_RECEIVER_REPLACE_PENDING位有沒有設置,如果設置了的話,ActivityManagerService就會在當前的系統中查看有沒有相同的intent還未被處理,如果有的話,就有當前這個新的intent來替換舊的intent。這裏,我們沒有設置intent的Intent.FLAG_RECEIVER_REPLACE_PENDING位,因此,這裏的replacePending變量爲false。

       再接着往下看:

  1.   int NR = registeredReceivers != null ? registeredReceivers.size() : 0;  
  2.   if (!ordered && NR > 0) {  
  3. // If we are not serializing this broadcast, then send the  
  4. // registered receivers separately so they don't wait for the  
  5. // components to be launched.  
  6. BroadcastRecord r = new BroadcastRecord(intent, callerApp,  
  7.     callerPackage, callingPid, callingUid, requiredPermission,  
  8.     registeredReceivers, resultTo, resultCode, resultData, map,  
  9.     ordered, sticky, false);  
  10. ......  
  11. boolean replaced = false;  
  12. if (replacePending) {  
  13.     for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {  
  14.         if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {  
  15.             ......  
  16.             mParallelBroadcasts.set(i, r);  
  17.             replaced = true;  
  18.             break;  
  19.         }  
  20.     }  
  21. }  
  22.   
  23. if (!replaced) {  
  24.     mParallelBroadcasts.add(r);  
  25.   
  26.     scheduleBroadcastsLocked();  
  27. }  
  28.   
  29. registeredReceivers = null;  
  30. NR = 0;  
  31.    }  
        前面我們說到,這裏得到的列表registeredReceivers的大小爲1,且傳進來的參數ordered爲false,表示要將這個廣播發送給所有註冊了BROADCAST_COUNTER_ACTION類型廣播的接收器,因此,會執行下面的if語句。這個if語句首先創建一個廣播記錄塊BroadcastRecord,裏面記錄了這個廣播是由誰發出的以及要發給誰等相關信息。由於前面得到的replacePending變量爲false,因此,不會執行接下來的if語句,即不會檢查系統中是否有相同類型的未處理的廣播。

        這樣,這裏得到的replaced變量的值也爲false,於是,就會把這個廣播記錄塊r放在ActivityManagerService的成員變量mParcelBroadcasts中,等待進一步處理;進一步處理的操作由函數scheduleBroadcastsLocked進行。

        Step 6. ActivityManagerService.scheduleBroadcastsLocked

        這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

  1. public final class ActivityManagerService extends ActivityManagerNative  
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
  3.     ......  
  4.   
  5.     private final void scheduleBroadcastsLocked() {  
  6.         ......  
  7.   
  8.         if (mBroadcastsScheduled) {  
  9.             return;  
  10.         }  
  11.   
  12.         mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);  
  13.         mBroadcastsScheduled = true;  
  14.     }  
  15.   
  16.     ......  
  17. }  
        這裏的mBroadcastsScheduled表示ActivityManagerService當前是不是正在處理其它廣播,如果是的話,這裏就先不處理直接返回了,保證所有廣播串行處理。

        注意這裏處理廣播的方式,它是通過消息循環來處理,每當ActivityManagerService接收到一個廣播時,它就把這個廣播放進自己的消息隊列去就完事了,根本不管這個廣播後續是處理的,因此,這裏我們可以看出廣播的發送和處理是異步的。

        這裏的成員變量mHandler是一個在ActivityManagerService內部定義的Handler類變量,通過它的sendEmptyMessage函數把一個類型爲BROADCAST_INTENT_MSG的空消息放進ActivityManagerService的消息隊列中去。這裏的空消息是指這個消息除了有類型信息之外,沒有任何其它額外的信息,因爲前面已經把要處理的廣播信息都保存在mParcelBroadcasts中了,等處理這個消息時,從mParcelBroadcasts就可以讀回相關的廣播信息了,因此,這裏不需要把廣播信息再放在消息內容中。

        Step 7. Handler.sendEmptyMessage

        這個自定義的Handler類實現在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中,它是ActivityManagerService的內部類,調用了它的sendEmptyMessage函數來把一個消息放到消息隊列後,一會就會調用它的handleMessage函數來真正處理這個消息:

  1. public final class ActivityManagerService extends ActivityManagerNative  
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
  3.     ......  
  4.   
  5.     final Handler mHandler = new Handler() {  
  6.         public void handleMessage(Message msg) {  
  7.             switch (msg.what) {  
  8.             ......  
  9.             case BROADCAST_INTENT_MSG: {  
  10.                 ......  
  11.                 processNextBroadcast(true);  
  12.             } break;  
  13.             ......  
  14.             }  
  15.         }  
  16.     }  
  17.   
  18.     ......  
  19. }   
        這裏又調用了ActivityManagerService的processNextBroadcast函數來處理下一個未處理的廣播。

        Step 8. ActivityManagerService.processNextBroadcast

        這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

  1. public final class ActivityManagerService extends ActivityManagerNative  
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
  3.     ......  
  4.   
  5.     private final void processNextBroadcast(boolean fromMsg) {  
  6.         synchronized(this) {  
  7.             BroadcastRecord r;  
  8.   
  9.             ......  
  10.   
  11.             if (fromMsg) {  
  12.                 mBroadcastsScheduled = false;  
  13.             }  
  14.   
  15.             // First, deliver any non-serialized broadcasts right away.  
  16.             while (mParallelBroadcasts.size() > 0) {  
  17.                 r = mParallelBroadcasts.remove(0);  
  18.                 ......  
  19.                 final int N = r.receivers.size();  
  20.                 ......  
  21.                 for (int i=0; i<N; i++) {  
  22.                     Object target = r.receivers.get(i);  
  23.                     ......  
  24.   
  25.                     deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);  
  26.                 }  
  27.                 addBroadcastToHistoryLocked(r);  
  28.                 ......  
  29.             }  
  30.   
  31.             ......  
  32.   
  33.         }  
  34.     }  
  35.   
  36.     ......  
  37. }  
        這裏傳進來的參數fromMsg爲true,於是把mBroadcastScheduled重新設爲false,這樣,下一個廣播就能進入到消息隊列中進行處理了。前面我們在Step 5中,把一個廣播記錄塊BroadcastRecord放在了mParallelBroadcasts中,因此,這裏就把它取出來進行處理了。廣播記錄塊BroadcastRecord的receivers列表中包含了要接收這個廣播的目標列表,即前面我們註冊的廣播接收器,用BroadcastFilter來表示,這裏while循環中的for循環就是把這個廣播發送給每一個訂閱了該廣播的接收器了,通過deliverToRegisteredReceiverLocked函數執行。

        Step 9. ActivityManagerService.deliverToRegisteredReceiverLocked

        這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

  1. public final class ActivityManagerService extends ActivityManagerNative  
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
  3.     ......  
  4.   
  5.     private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,  
  6.             BroadcastFilter filter, boolean ordered) {  
  7.         boolean skip = false;  
  8.         if (filter.requiredPermission != null) {  
  9.             ......  
  10.         }  
  11.         if (r.requiredPermission != null) {  
  12.             ......  
  13.         }  
  14.   
  15.         if (!skip) {  
  16.             // If this is not being sent as an ordered broadcast, then we  
  17.             // don't want to touch the fields that keep track of the current  
  18.             // state of ordered broadcasts.  
  19.             if (ordered) {  
  20.                 ......  
  21.             }  
  22.   
  23.             try {  
  24.                 ......  
  25.                 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,  
  26.                     new Intent(r.intent), r.resultCode,  
  27.                     r.resultData, r.resultExtras, r.ordered, r.initialSticky);  
  28.                 ......  
  29.             } catch (RemoteException e) {  
  30.                 ......  
  31.             }  
  32.         }  
  33.   
  34.     }  
  35.   
  36.     ......  
  37. }  
         函數首先是檢查一下廣播發送和接收的權限,在我們分析的這個場景中,沒有設置權限,因此,這個權限檢查就跳過了,這裏得到的skip爲false,於是進入下面的if語句中。由於上面傳時來的ordered參數爲false,因此,直接就調用performReceiveLocked函數來進一步執行廣播發送的操作了。

        Step 10. ActivityManagerService.performReceiveLocked

        這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

  1. public final class ActivityManagerService extends ActivityManagerNative  
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
  3.     ......  
  4.   
  5.     static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,  
  6.             Intent intent, int resultCode, String data, Bundle extras,  
  7.             boolean ordered, boolean sticky) throws RemoteException {  
  8.         // Send the intent to the receiver asynchronously using one-way binder calls.  
  9.         if (app != null && app.thread != null) {  
  10.             // If we have an app thread, do the call through that so it is  
  11.             // correctly ordered with other one-way calls.  
  12.             app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,  
  13.                     data, extras, ordered, sticky);  
  14.         } else {  
  15.             ......  
  16.         }  
  17.     }  
  18.   
  19.     ......  
  20. }  
        注意,這裏傳進來的參數app是註冊廣播接收器的Activity所在的進程記錄塊,在我們分析的這個場景中,由於是MainActivity調用registerReceiver函數來註冊這個廣播接收器的,因此,參數app所代表的ProcessRecord就是MainActivity所在的進程記錄塊了;而參數receiver也是註冊廣播接收器時傳給ActivityManagerService的一個Binder對象,它的類型是IIntentReceiver,具體可以參考上一篇文章Android應用程序註冊廣播接收器(registerReceiver)的過程分析中的Step 2。

       MainActivity在註冊廣播接收器時,已經把自己的ProcessRecord記錄下來了,所以這裏的參數app和app.thread均不爲null,於是,ActivityManagerService就調用app.thread.scheduleRegisteredReceiver函數來把這個廣播分發給MainActivity了。這裏的app.thread是一個Binder遠程對象,它的類型是ApplicationThreadProxy,我們在前面介紹應用程序的Activity啓動過程時,已經多次看到了,具體可以參考主題Android應用程序的Activity啓動過程簡要介紹和學習計劃

       Step 11. ApplicationThreadProxy.scheduleRegisteredReceiver
       這個函數定義在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中:

  1. class ApplicationThreadProxy implements IApplicationThread {  
  2.     ......  
  3.   
  4.     public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,  
  5.             int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)  
  6.             throws RemoteException {  
  7.         Parcel data = Parcel.obtain();  
  8.         data.writeInterfaceToken(IApplicationThread.descriptor);  
  9.         data.writeStrongBinder(receiver.asBinder());  
  10.         intent.writeToParcel(data, 0);  
  11.         data.writeInt(resultCode);  
  12.         data.writeString(dataStr);  
  13.         data.writeBundle(extras);  
  14.         data.writeInt(ordered ? 1 : 0);  
  15.         data.writeInt(sticky ? 1 : 0);  
  16.         mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,  
  17.             IBinder.FLAG_ONEWAY);  
  18.         data.recycle();  
  19.     }  
  20.   
  21.     ......  
  22. }  
        這裏通過Binder驅動程序就進入到ApplicationThread.scheduleRegisteredReceiver函數去了。ApplicationThread是ActivityThread的一個內部類,具體可以參考Activity啓動主題Android應用程序的Activity啓動過程簡要介紹和學習計劃

        Step 12. ApplicaitonThread.scheduleRegisteredReceiver
        這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:

  1. public final class ActivityThread {  
  2.     ......  
  3.   
  4.     private final class ApplicationThread extends ApplicationThreadNative {  
  5.         ......  
  6.   
  7.         // This function exists to make sure all receiver dispatching is  
  8.         // correctly ordered, since these are one-way calls and the binder driver  
  9.         // applies transaction ordering per object for such calls.  
  10.         public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,  
  11.                 int resultCode, String dataStr, Bundle extras, boolean ordered,  
  12.                 boolean sticky) throws RemoteException {  
  13.             receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);  
  14.         }  
  15.   
  16.         ......  
  17.     }  
  18.   
  19.     ......  
  20.   
  21. }  
        這裏的receiver是在前面一篇文章Android應用程序註冊廣播接收器(registerReceiver)的過程分析中的Step 4中創建的,它的具體類型是LoadedApk.ReceiverDispatcher.InnerReceiver,即定義在LoadedApk類的內部類ReceiverDispatcher裏面的一個內部類InnerReceiver,這裏調用它的performReceive函數。

        Step 13. InnerReceiver.performReceive

        這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:

  1. final class LoadedApk {    
  2.     ......   
  3.   
  4.     static final class ReceiverDispatcher {    
  5.   
  6.         final static class InnerReceiver extends IIntentReceiver.Stub {   
  7.             ......  
  8.   
  9.             public void performReceive(Intent intent, int resultCode,  
  10.                     String data, Bundle extras, boolean ordered, boolean sticky) {  
  11.               
  12.                 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();  
  13.                 ......  
  14.                 if (rd != null) {  
  15.                     rd.performReceive(intent, resultCode, data, extras,  
  16.                             ordered, sticky);  
  17.                 } else {  
  18.                     ......  
  19.                 }  
  20.             }  
  21.         }  
  22.   
  23.         ......  
  24.     }  
  25.   
  26.     ......  
  27. }  
         這裏,它只是簡單地調用ReceiverDispatcher的performReceive函數來進一步處理,這裏的ReceiverDispatcher類是LoadedApk類裏面的一個內部類。

         Step 14. ReceiverDispatcher.performReceive

         這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:

  1. final class LoadedApk {    
  2.     ......   
  3.   
  4.     static final class ReceiverDispatcher {    
  5.         ......  
  6.   
  7.         public void performReceive(Intent intent, int resultCode,  
  8.                 String data, Bundle extras, boolean ordered, boolean sticky) {  
  9.             ......  
  10.   
  11.             Args args = new Args();  
  12.             args.mCurIntent = intent;  
  13.             args.mCurCode = resultCode;  
  14.             args.mCurData = data;  
  15.             args.mCurMap = extras;  
  16.             args.mCurOrdered = ordered;  
  17.             args.mCurSticky = sticky;  
  18.             if (!mActivityThread.post(args)) {  
  19.                 ......  
  20.             }   
  21.         }  
  22.   
  23.         ......  
  24.     }  
  25.   
  26.     ......  
  27. }  
        這裏mActivityThread成員變量的類型爲Handler,它是前面MainActivity註冊廣播接收器時,從ActivityThread取得的,具體可以參考前面一篇文章Android應用程序註冊廣播接收器(registerReceiver)的過程分析中的Step 3。這裏ReceiverDispatcher藉助這個Handler,把這個廣播以消息的形式放到MainActivity所在的這個ActivityThread的消息隊列中去,因此,ReceiverDispatcher不等這個廣播被MainActivity處理就返回了,這裏也體現了廣播的發送和處理是異步進行的。

        注意這裏處理消息的方式是通過Handler.post函數進行的,post函數的參數是Runnable類型的,這個消息最終會調用這個這個參數的run成員函數來處理。這裏的Args類是LoadedApk類的內部類ReceiverDispatcher的一個內部類,它繼承於Runnable類,因此,可以作爲mActivityThread.post的參數傳進去,代表這個廣播的intent也保存在這個Args實例中。

        Step 15. Hanlder.post

        這個函數定義在frameworks/base/core/java/android/os/Handler.java文件中,這個函數我們就不看了,有興趣的讀者可以自己研究一下,它的作用就是把消息放在消息隊列中,然後就返回了,這個消息最終會在傳進來的Runnable類型的參數的run成員函數中進行處理。

        Step 16. Args.run

        這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:

  1. final class LoadedApk {    
  2.     ......   
  3.   
  4.     static final class ReceiverDispatcher {  
  5.         ......  
  6.   
  7.         final class Args implements Runnable {  
  8.             ......  
  9.   
  10.             public void run() {  
  11.                 BroadcastReceiver receiver = mReceiver;  
  12.   
  13.                 ......  
  14.   
  15.                 Intent intent = mCurIntent;  
  16.                   
  17.                 ......  
  18.   
  19.                 try {  
  20.                     ClassLoader cl =  mReceiver.getClass().getClassLoader();  
  21.                     intent.setExtrasClassLoader(cl);  
  22.                     if (mCurMap != null) {  
  23.                         mCurMap.setClassLoader(cl);  
  24.                     }  
  25.                     receiver.setOrderedHint(true);  
  26.                     receiver.setResult(mCurCode, mCurData, mCurMap);  
  27.                     receiver.clearAbortBroadcast();  
  28.                     receiver.setOrderedHint(mCurOrdered);  
  29.                     receiver.setInitialStickyHint(mCurSticky);  
  30.                     receiver.onReceive(mContext, intent);  
  31.                 } catch (Exception e) {  
  32.                     ......  
  33.                 }  
  34.   
  35.                 ......  
  36.             }  
  37.   
  38.             ......  
  39.         }  
  40.   
  41.         ......  
  42.     }  
  43.   
  44.     ......  
  45. }  
        這裏的mReceiver是ReceiverDispatcher類的成員變量,它的類型是BroadcastReceiver,這裏它就是MainActivity註冊廣播接收器時創建的BroadcastReceiver實例了,具體可以參考前面一篇文章Android應用程序註冊廣播接收器(registerReceiver)的過程分析中的Step 2。

        有了這個ReceiverDispatcher實例之後,就可以調用它的onReceive函數把這個廣播分發給它處理了。

        Step 17. BroadcastReceiver.onReceive

        這個函數定義Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中所介紹的Android應用程序Broadcast的工程目錄下的src/shy/luo/broadcast/MainActivity.java文件中:

  1. public class MainActivity extends Activity implements OnClickListener {      
  2.     ......    
  3.   
  4.     private BroadcastReceiver counterActionReceiver = new BroadcastReceiver(){    
  5.         public void onReceive(Context context, Intent intent) {    
  6.             int counter = intent.getIntExtra(CounterService.COUNTER_VALUE, 0);    
  7.             String text = String.valueOf(counter);    
  8.             counterText.setText(text);    
  9.   
  10.             Log.i(LOG_TAG, "Receive counter event");    
  11.         }      
  12.     }  
  13.   
  14.     ......    
  15.   
  16. }  
        這樣,MainActivity裏面的定義的BroadcastReceiver實例counterActionReceiver就收到這個廣播並進行處理了。
        至此,Android應用程序發送廣播的過程就分析完成了,結合前面這篇分析廣播接收器註冊過程的文章Android應用程序註冊廣播接收器(registerReceiver)的過程分析,就會對Android系統的廣播機制且個更深刻的認識和理解了。

        最後,我們總結一下這個Android應用程序發送廣播的過程:

        1. Step 1 - Step 7,計數器服務CounterService通過sendBroadcast把一個廣播通過Binder進程間通信機制發送給ActivityManagerService,ActivityManagerService根據這個廣播的Action類型找到相應的廣播接收器,然後把這個廣播放進自己的消息隊列中去,就完成第一階段對這個廣播的異步分發了;

        2. Step 8 - Step 15,ActivityManagerService在消息循環中處理這個廣播,並通過Binder進程間通信機制把這個廣播分發給註冊的廣播接收分發器ReceiverDispatcher,ReceiverDispatcher把這個廣播放進MainActivity所在的線程的消息隊列中去,就完成第二階段對這個廣播的異步分發了;

        3. Step 16 - Step 17, ReceiverDispatcher的內部類Args在MainActivity所在的線程消息循環中處理這個廣播,最終是將這個廣播分發給所註冊的BroadcastReceiver實例的onReceive函數進行處理。

        這樣,Android系統廣播機制就學習完成了,希望對讀者有所幫助。重新學習Android系統的廣播機制,請回到Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章