Broadcast学习笔记

来源:互联网 发布:中国新歌声 台湾 知乎 编辑:程序博客网 时间:2024/05/17 22:26


整个广播发送流程如下图:



1、mIntentSenderRecords

是一个PendingIntentRecord哈希表。一个PendingIntentRecord对象对应的是应用层的一个PendingIntent对象(延迟性的intent),其中包含send系列方法,主要用于触发PendingIntent的Intent行为。上层应用每获取一个PendingIntent对象时在AMS这边便会生成对应的PendingIntentRecord对象,并保存在mIntentSenderRecords哈希列表中,当上层应用调用PendingIntent.send()时,最终会调用到PendingIntentRecord.sendInner()函数,这个函数会将之前上层应用传下来的Intent进行触发(起Activity、发广播、起service)。PendingIntent对象是可以传递给其他应用的,这个应该才是设计初衷?

2、mRegisteredReceivers

是一个ReceiverList哈希表。ReceiverList对应一个广播接收器,mRegisteredReceivers保存着系统中的所有广播接收器。ReceiverList继承于ArrayList<BroadcastFilter>,实质上就是一个BroadcastFilter列表,源码是这样解释ReceiverList的:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. **  
  2.  * A receiver object that has registered for one or more broadcasts.  
  3.  * The ArrayList holds BroadcastFilter objects.  
  4.  *  
熟悉广播接收器的都知道,一个广播接收器可以有多个IntentFilter过滤器,每个过滤器可以通过addAction添加多个action。

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. public Intent registerReceiver(IApplicationThread caller, String callerPackage,  
  2.             IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {  
  3.             ...........  
  4.             ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());  
  5.             if (rl == null) {  
  6.                 rl = new ReceiverList(this, callerApp, callingPid, callingUid,  
  7.                         userId, receiver);  
  8.                 if (rl.app != null) {  
  9.                     rl.app.receivers.add(rl);  
  10.                 } else {  
  11.                     try {  
  12.                         receiver.asBinder().linkToDeath(rl, 0);  
  13.                     } catch (RemoteException e) {  
  14.                         return sticky;  
  15.                     }  
  16.                     rl.linkedToDeath = true;  
  17.                 }  
  18.                 mRegisteredReceivers.put(receiver.asBinder(), rl);  
  19.             }  
  20.            .............  
  21.            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,  
  22.                     permission, callingUid, userId);  
  23.             rl.add(bf);  
  24.             mReceiverResolver.addFilter(bf);  
  25.             if (allSticky != null) {  
  26.                 ArrayList receivers = new ArrayList();  
  27.                 receivers.add(bf);  
  28.                 int N = allSticky.size();  
  29.                 for (int i=0; i<N; i++) {  
  30.                     Intent intent = (Intent)allSticky.get(i);  
  31.                     BroadcastQueue queue = broadcastQueueForIntent(intent);  
  32.                     BroadcastRecord r = new BroadcastRecord(queue, intent, null,  
  33.                             null, -1, -1nullnull, AppOpsManager.OP_NONE, receivers, null0,  
  34.                             nullnullfalsetruetrue, -1);  
  35.                     queue.enqueueParallelBroadcastLocked(r);  
  36.                     queue.scheduleBroadcastsLocked();  
  37.                 }  
  38.             }  
  39.             return sticky;  
  40.         }  
  41. }  

上面的代码可以看出一个广播接收器在AMS这边对应有一个ReceiverList,其实是一个BroadcastFilter列表,属于这个广播接受器的IntentFilter对应的BroadcastFilter对象保存在ReceiverList列表中。IntentFilter中的每个action,都会生成一个Intent,每个Intent又会对应new一个BroadcastRecord,然后根据这个Intent是否设置Intent.FLAG_RECEIVER_FOREGROUND来选择一个BroadcastQueue队列来将这个BroadcastRecord加入到队列中。有两个BroadcastQueue队列,分别是mFgBroadcastQueue和mBgBroadcastQueue。所有的BroadcastFilter会保存在mReceiverResolver(IntentResolver对象)中。

2、broadcastIntent()

发送广播处理函数。详情请看:博客

ContextImpl.sendBroadcastAsUser()-->AMS.broadcastIntent()-->AMS.broadcastIntentLocked(),broadcastIntentLocked()函数关键代码如下:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1.   private final int broadcastIntentLocked(ProcessRecord callerApp,  
  2.             String callerPackage, Intent intent, String resolvedType,  
  3.             IIntentReceiver resultTo, int resultCode, String resultData,  
  4.             Bundle map, String requiredPermission, int appOp,  
  5.             boolean ordered, boolean sticky, int callingPid, int callingUid,  
  6.             int userId) {  
  7.   
  8.         //①首先进行权限检查  
  9.   
  10.         //②检查是否是特别广播,如ACTION_PACKAGE_REMOVED、ACTION_PACKAGE_ADDED、ACTION_TIMEZONE_CHANGED、ACTION_CLEAR_DNS_CACHE、PROXY_CHANGE_ACTION  
  11.   
  12.         if (sticky) {  
  13.             //③粘性广播处理  
  14.         }  
  15.   
  16.         // Figure out who all will receive this broadcast.  
  17.         List receivers = null;  
  18.         List<BroadcastFilter> registeredReceivers = null;  
  19.         // Need to resolve the intent to interested receivers...  
  20.         if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)  
  21.                  == 0) {  
  22.             receivers = collectReceiverComponents(intent, resolvedType, users);         //③从PackageManagerService中收集静态注册的广播接收器;  
  23.         }  
  24.         if (intent.getComponent() == null) {                                            //③如果广播没有指定组件,那么就从mReceiverResolver中进行queryIntent()匹配  
  25.             registeredReceivers = mReceiverResolver.queryIntent(intent,  
  26.                     resolvedType, false, userId);  
  27.         }  
  28.   
  29.         final boolean replacePending =  
  30.                 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;  
  31.           
  32.         int NR = registeredReceivers != null ? registeredReceivers.size() : 0;  
  33.         if (!ordered && NR > 0) {  
  34.          //④如果该广播是无序广播,并且存在动态注册的接收器,那么先将该广播(BroadcastRecord)加入到BroadcastQueue.mParallelBroadcasts中,注意此BroadcastRecord.Receivers只包含动态注册的接收器。  
  35.             // If we are not serializing this broadcast, then send the  
  36.             // registered receivers separately so they don't wait for the  
  37.             // components to be launched.  
  38.             final BroadcastQueue queue = broadcastQueueForIntent(intent);     //④从mFgBroadcastQueue和mBgBroadcastQueue中挑一个广播队列(前台后台广播);  
  39.             BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,  
  40.                     callerPackage, callingPid, callingUid, resolvedType, requiredPermission,  
  41.                     appOp, registeredReceivers, resultTo, resultCode, resultData, map,  
  42.                     ordered, sticky, false, userId);  
  43.             if (DEBUG_BROADCAST) Slog.v(  
  44.                     TAG, "Enqueueing parallel broadcast " + r);  
  45.             final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);  
  46.             if (!replaced) {  
  47.                 queue.enqueueParallelBroadcastLocked(r);             //④将BroadcastRecord加入广播队列,并启动发送;  
  48.                 queue.scheduleBroadcastsLocked();  
  49.             }  
  50.             registeredReceivers = null;  
  51.             NR = 0;  
  52.         }  
  53.          
  54.   
  55.         // Merge into one list.  
  56.         int ir = 0;  
  57.         if (receivers != null) {  
  58.             //⑤对于有序广播,根据优先级合并动态注册、静态注册的广播接收器;对于无序广播,代码运行到此处必然只剩下静态注册广播接收器了,也会add到receivers列表中;  
  59.             int NT = receivers != null ? receivers.size() : 0;  
  60.             int it = 0;  
  61.             ResolveInfo curt = null;  
  62.             BroadcastFilter curr = null;  
  63.             while (it < NT && ir < NR) {  
  64.                 if (curt == null) {  
  65.                     curt = (ResolveInfo)receivers.get(it);  
  66.                 }  
  67.                 if (curr == null) {  
  68.                     curr = registeredReceivers.get(ir);  
  69.                 }  
  70.                 if (curr.getPriority() >= curt.priority) {  
  71.                     // Insert this broadcast record into the final list.  
  72.                     receivers.add(it, curr);  
  73.                     ir++;  
  74.                     curr = null;  
  75.                     it++;  
  76.                     NT++;  
  77.                 } else {  
  78.                     // Skip to the next ResolveInfo in the final list.  
  79.                     it++;  
  80.                     curt = null;  
  81.                 }  
  82.             }  
  83.         }  
  84.         while (ir < NR) {  
  85.             if (receivers == null) {  
  86.                 receivers = new ArrayList();  
  87.             }  
  88.             receivers.add(registeredReceivers.get(ir));  
  89.             ir++;  
  90.         }  
  91. //⑥如果是有序广播,将会合并动态注册、静态注册的接收器,然后将合并好的接收器list保存在BroadcastRecord.Receivers中,同时把BroadcastRecord加入到BroadcastQueue.mOrderedBroadcasts中  
  92. //⑦如果是无序广播,存在静态注册的接收器,那么又会new BroadcastRecord,将静态注册的接收器保存在BroadcastRecord.Receivers中,同时把BroadcastRecord加入到BroadcastQueue.mOrderedBroadcasts中  
  93.         if ((receivers != null && receivers.size() > 0)  
  94.                 || resultTo != null) {  
  95.             BroadcastQueue queue = broadcastQueueForIntent(intent);  
  96.             BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,  
  97.                     callerPackage, callingPid, callingUid, resolvedType,  
  98.                     requiredPermission, appOp, receivers, resultTo, resultCode,  
  99.                     resultData, map, ordered, sticky, false, userId);  
  100.             if (DEBUG_BROADCAST) Slog.v(  
  101.                     TAG, "Enqueueing ordered broadcast " + r  
  102.                     + ": prev had " + queue.mOrderedBroadcasts.size());  
  103.             if (DEBUG_BROADCAST) {  
  104.                 int seq = r.intent.getIntExtra("seq", -1);  
  105.                 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);  
  106.             }  
  107.             boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);   
  108.             if (!replaced) {  
  109.                 queue.enqueueOrderedBroadcastLocked(r);  
  110.                 queue.scheduleBroadcastsLocked();  
  111.             }  
  112.         }  
  113.         return ActivityManager.BROADCAST_SUCCESS;  
  114.     }  

在第①条中提到当注册一个广播接收器时,会将BroadcastFilter保存在mReceiverResolver(IntentResolver对象)中,何种方式保存的呢?就是以BroadcastFilter和action成对地保存在mReceiverResolver.mActionToFilter中。这段代码的逻辑是①通过queryIntent()从mReceiverResolver.mActionToFilter中根据action找出所有的BroadcastFilter;②选取一个合适的BroadcastQueue;③new一个BroadcastRecord,将①②两步获取的对象都作为参数保存到BroadcastRecord中;④将BroadcastRecord加入到合适的BroadcastQueue队列中,其实就是加入到一个待发送广播list中;⑥启动将广播发送给对应Receiver流程(scheduleBroadcastsLocked())。

总结:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. public void scheduleBroadcastsLocked() {  
  2.         if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts ["  
  3.                 + mQueueName + "]: current="  
  4.                 + mBroadcastsScheduled);  
  5.   
  6.         if (mBroadcastsScheduled) {  
  7.             return;  
  8.         }  
  9.         mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));  
  10.         mBroadcastsScheduled = true;  
  11.     }  
scheduleBroadcastsLocked()函数发送一个BROADCAST_INTENT_MSG handle消息,并将mBroadcastsScheduled设为true。
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. final Handler mHandler = new Handler() {  
  2.        public void handleMessage(Message msg) {  
  3.            switch (msg.what) {  
  4.                case BROADCAST_INTENT_MSG: {  
  5.                    if (DEBUG_BROADCAST) Slog.v(  
  6.                            TAG, "Received BROADCAST_INTENT_MSG");  
  7.                     processNextBroadcast(true);  
  8.                } break;  
  9.                case BROADCAST_TIMEOUT_MSG: {  
  10.                    synchronized (mService) {  
  11.                        broadcastTimeoutLocked(true);  
  12.                    }  
  13.                } break;  
  14.            }  
  15.        }  
  16.    };  

收到BROADCAST_INTENT_MSG消息,调用processNextBroadcast()函数继续处理。processNextBroadcast()函数:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. final void processNextBroadcast(boolean fromMsg){  
  2.      synchronized(mService) {  
  3.            
  4.          // First, deliver any non-serialized broadcasts right away.  
  5.          while (mParallelBroadcasts.size() > 0) {  
  6.   
  7.              //①无序广播,并且接收器为动态注册,直接调用deliverToRegisteredReceiverLocked()进行处理  
  8.   
  9.              r = mParallelBroadcasts.remove(0);  
  10.              r.dispatchTime = SystemClock.uptimeMillis();  
  11.              r.dispatchClockTime = System.currentTimeMillis();  
  12.              final int N = r.receivers.size();  
  13.              if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast ["  
  14.                      + mQueueName + "] " + r);  
  15.              for (int i=0; i<N; i++) {  
  16.                  Object target = r.receivers.get(i);  
  17.                  if (DEBUG_BROADCAST)  Slog.v(TAG,  
  18.                          "Delivering non-ordered on [" + mQueueName + "] to registered "  
  19.                          + target + ": " + r);  
  20.                  deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);  
  21.              }  
  22.              addBroadcastToHistoryLocked(r);  
  23.              if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast ["  
  24.                      + mQueueName + "] " + r);  
  25.          }  
  26.   
  27.          // Now take care of the next serialized one...  
  28.   
  29.          // If we are waiting for a process to come up to handle the next  
  30.          // broadcast, then do nothing at this point.  Just in case, we  
  31.          // check that the process we're waiting for still exists.  
  32.          if (mPendingBroadcast != null) {  
  33.              if (DEBUG_BROADCAST_LIGHT) {  
  34.                  Slog.v(TAG, "processNextBroadcast ["  
  35.                          + mQueueName + "]: waiting for "  
  36.                          + mPendingBroadcast.curApp);  
  37.              }  
  38.   
  39.              boolean isDead;  
  40.              synchronized (mService.mPidsSelfLocked) {  
  41.                  ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);  
  42.                  isDead = proc == null || proc.crashing;  
  43.              }  
  44.              if (!isDead) {  
  45.                  // It's still alive, so keep waiting  
  46.                  return;  
  47.              } else {  
  48.                  Slog.w(TAG, "pending app  ["  
  49.                          + mQueueName + "]" + mPendingBroadcast.curApp  
  50.                          + " died before responding to broadcast");  
  51.                  mPendingBroadcast.state = BroadcastRecord.IDLE;  
  52.                  mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;  
  53.                  mPendingBroadcast = null;  
  54.              }  
  55.          }  
  56.   
  57.          boolean looped = false;  
  58.            
  59.          do {  
  60.              if (mOrderedBroadcasts.size() == 0) {  
  61.            //②由broadcastIntentLocked()函数知道,mOrderedBroadcasts可保存两种类型广播,一种是无序广播,接收器为静态注册,另一种是有序广播,接收器是动态注册和静态注册的合并。如果mOrderedBroadcasts为空,直接返回。  
  62.   
  63.                  // No more broadcasts pending, so all done!  
  64.                  mService.scheduleAppGcsLocked();  
  65.                  if (looped) {  
  66.                      // If we had finished the last ordered broadcast, then  
  67.                      // make sure all processes have correct oom and sched  
  68.                      // adjustments.  
  69.                      mService.updateOomAdjLocked();  
  70.                  }  
  71.                  return;  
  72.              }  
  73.              //③按顺序取出mOrderedBroadcasts中的广播  
  74.   
  75.              r = mOrderedBroadcasts.get(0);  
  76.              boolean forceReceive = false;  
  77.   
  78.              // Ensure that even if something goes awry with the timeout  
  79.              // detection, we catch "hung" broadcasts here, discard them,  
  80.              // and continue to make progress.  
  81.              //  
  82.              // This is only done if the system is ready so that PRE_BOOT_COMPLETED  
  83.              // receivers don't get executed with timeouts. They're intended for  
  84.              // one time heavy lifting after system upgrades and can take  
  85.              // significant amounts of time.  
  86.              int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;  
  87.                                                                       //④判断是否广播超时,超时则调用broadcastTimeoutLocked(false),forceReceive = true;  
  88.              if (mService.mProcessesReady && r.dispatchTime > 0) {  
  89.                  long now = SystemClock.uptimeMillis();  
  90.                  if ((numReceivers > 0) &&  
  91.                          (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {  
  92.                      Slog.w(TAG, "Hung broadcast ["  
  93.                              + mQueueName + "] discarded after timeout failure:"  
  94.                              + " now=" + now  
  95.                              + " dispatchTime=" + r.dispatchTime  
  96.                              + " startTime=" + r.receiverTime  
  97.                              + " intent=" + r.intent  
  98.                              + " numReceivers=" + numReceivers  
  99.                              + " nextReceiver=" + r.nextReceiver  
  100.                              + " state=" + r.state);  
  101.                      broadcastTimeoutLocked(false); // forcibly finish this broadcast  
  102.                      forceReceive = true;  
  103.                      r.state = BroadcastRecord.IDLE;  
  104.                  }  
  105.              }  
  106.   
  107.              if (r.state != BroadcastRecord.IDLE) {                          //这个条件限制非常重要,对于有序广播来说只有上层应用调用了ActivityManagerService.finishReceiver(),才能继续后续的有序广播发送;(finishReceiver中会将r.state置为BroadcastRecord.IDLE)  
  108.                  if (DEBUG_BROADCAST) Slog.d(TAG,  
  109.                          "processNextBroadcast("  
  110.                          + mQueueName + ") called when not idle (state="  
  111.                          + r.state + ")");  
  112.                  return;  
  113.              }  
  114.   
  115.              if (r.receivers == null || r.nextReceiver >= numReceivers  
  116.                      || r.resultAbort || forceReceive) {  
  117.   
  118.                  //⑤如果该广播没有接收器,或被终止继续传递,或超时,或(r.nextReceiver >= numReceivers)???则终结这个广播:如果指定了resultTo,那么调用performReceiveLocked()来将该广播发送到resultTo,然后从mOrderedBroadcasts中进行移除。  
  119.   
  120.                  // No more receivers for this broadcast!  Send the final  
  121.                  // result if requested...  
  122.                  if (r.resultTo != null) {  
  123.                      try {  
  124.                          if (DEBUG_BROADCAST) {  
  125.                              int seq = r.intent.getIntExtra("seq", -1);  
  126.                              Slog.i(TAG, "Finishing broadcast ["  
  127.                                      + mQueueName + "] " + r.intent.getAction()  
  128.                                      + " seq=" + seq + " app=" + r.callerApp);  
  129.                          }  
  130.                          performReceiveLocked(r.callerApp, r.resultTo,  
  131.                              new Intent(r.intent), r.resultCode,  
  132.                              r.resultData, r.resultExtras, falsefalse, r.userId);  
  133.                          // Set this to null so that the reference  
  134.                          // (local and remote) isn't kept in the mBroadcastHistory.  
  135.                          r.resultTo = null;  
  136.                      } catch (RemoteException e) {  
  137.                          Slog.w(TAG, "Failure ["  
  138.                                  + mQueueName + "] sending broadcast result of "  
  139.                                  + r.intent, e);  
  140.                      }  
  141.                  }  
  142.   
  143.                  if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");  
  144.                  cancelBroadcastTimeoutLocked();  
  145.   
  146.                  if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "  
  147.                          + r);  
  148.   
  149.                  // ... and on to the next...  
  150.                  addBroadcastToHistoryLocked(r);  
  151.                  mOrderedBroadcasts.remove(0);  
  152.                  r = null;  
  153.                  looped = true;  
  154.                  continue;  
  155.              }  
  156.          //⑥此while循环意在清除mOrderedBroadcasts中没有接收器、被终止继续传递、超时等广播。  
  157.          } while (r == null);  
  158.   
  159.          // Get the next receiver...  
  160.            
  161.          //  
  162.          int recIdx = r.nextReceiver++;  
  163.   
  164.          // Keep track of when this receiver started, and make sure there  
  165.          // is a timeout message pending to kill it if need be.  
  166.          r.receiverTime = SystemClock.uptimeMillis();  
  167.          if (recIdx == 0) {  
  168.              r.dispatchTime = r.receiverTime;  
  169.              r.dispatchClockTime = System.currentTimeMillis();  
  170.              if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast ["  
  171.                      + mQueueName + "] " + r);  
  172.          }  
  173.          if (! mPendingBroadcastTimeoutMessage) {  
  174.              long timeoutTime = r.receiverTime + mTimeoutPeriod;  
  175.              if (DEBUG_BROADCAST) Slog.v(TAG,  
  176.                      "Submitting BROADCAST_TIMEOUT_MSG ["  
  177.                      + mQueueName + "] for " + r + " at " + timeoutTime);  
  178.              setBroadcastTimeoutLocked(timeoutTime);  
  179.          }  
  180.          //⑦取出一个广播接收器,将该广播发送到该接收器(deliverToRegisteredReceiverLocked()),前面说了receivers保存着两种:静态接收器(无序广播)、静态和动态接收器的合并(有序广播)。如果是无序广播在deliverToRegisteredReceiverLocked()完这个接收器后,立马调用scheduleBroadcastsLocked()准备deliver给下一个接收器;如果是有序广播,则必须在deliver到当前接收器,并finished后(r.receiver == null)才能调用scheduleBroadcastsLocked()准备deliver给下一个接收器,如果没有finished,那么直接return。这块逻辑也是控制有序广播有序地的deliver给接收器的关键所在。  
  181.          Object nextReceiver = r.receivers.get(recIdx);  
  182.        
  183.          if (nextReceiver instanceof BroadcastFilter) {  
  184.              // Simple case: this is a registered receiver who gets  
  185.              // a direct call.  
  186.              BroadcastFilter filter = (BroadcastFilter)nextReceiver;  
  187.              if (DEBUG_BROADCAST)  Slog.v(TAG,  
  188.                      "Delivering ordered ["  
  189.                      + mQueueName + "] to registered "  
  190.                      + filter + ": " + r);  
  191.              deliverToRegisteredReceiverLocked(r, filter, r.ordered);  
  192.              if (r.receiver == null || !r.ordered) {  
  193.                  // The receiver has already finished, so schedule to  
  194.                  // process the next one.  
  195.                  if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing ["  
  196.                          + mQueueName + "]: ordered="  
  197.                          + r.ordered + " receiver=" + r.receiver);  
  198.                  r.state = BroadcastRecord.IDLE;  
  199.                  scheduleBroadcastsLocked();  
  200.              }  
  201.              return;  
  202.          }  
  203.        //⑧既然return掉了,后面的逻辑真不知道是干嘛的?  
  204.        …………  
  205.  }  

在前面scheduleBroadcastsLocked()中将mBroadcastsScheduled设为true,现在将mBroadcastsScheduled重新设为false。mParallelBroadcasts中保存的就是无序待分发广播BroadcastRecord,BroadcastRecord.receivers中保存的是前面第①条中的广播接受对象BroadcastFilter。deliverToRegisteredReceiverLocked()函数重点逻辑如下:
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,  
  2.            Intent intent, int resultCode, String data, Bundle extras,  
  3.            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {  
  4.     …………  
  5.       if (!skip) {  
  6.            // If this is not being sent as an ordered broadcast, then we  
  7.            // don't want to touch the fields that keep track of the current  
  8.            // state of ordered broadcasts.  
  9.            if (ordered) {  
  10.                r.receiver = filter.receiverList.receiver.asBinder();  
  11.                r.curFilter = filter;  
  12.                filter.receiverList.curBroadcast = r;  
  13.                r.state = BroadcastRecord.CALL_IN_RECEIVE;  
  14.                if (filter.receiverList.app != null) {  
  15.                    // Bump hosting application to no longer be in background  
  16.                    // scheduling class.  Note that we can't do that if there  
  17.                    // isn't an app...  but we can only be in that case for  
  18.                    // things that directly call the IActivityManager API, which  
  19.                    // are already core system stuff so don't matter for this.  
  20.                    r.curApp = filter.receiverList.app;  
  21.                    filter.receiverList.app.curReceiver = r;  
  22.                    mService.updateOomAdjLocked(r.curApp, true);  
  23.                }  
  24.            }  
  25.            try {  
  26.                if (DEBUG_BROADCAST_LIGHT) {  
  27.                    int seq = r.intent.getIntExtra("seq", -1);  
  28.                    Slog.i(TAG, "Delivering to " + filter  
  29.                            + " (seq=" + seq + "): " + r);  
  30.                }  
  31.                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,  
  32.                    new Intent(r.intent), r.resultCode, r.resultData,  
  33.                    r.resultExtras, r.ordered, r.initialSticky, r.userId);  
  34.                if (ordered) {  
  35.                    r.state = BroadcastRecord.CALL_DONE_RECEIVE;  
  36.                }  
  37.            } catch (RemoteException e) {  
  38.                Slog.w(TAG, "Failure sending broadcast " + r.intent, e);  
  39.                if (ordered) {  
  40.                    r.receiver = null;  
  41.                    r.curFilter = null;  
  42.                    filter.receiverList.curBroadcast = null;  
  43.                    if (filter.receiverList.app != null) {  
  44.                        filter.receiverList.app.curReceiver = null;  
  45.                    }  
  46.                }  
  47.            }  
  48.        }  
函数最开始进行一些权限检查,如果检查通过skip为false,上面这段代码便会调用。对于有序广播,设置BroadcastRecord中一些成员变量,然后调用performReceiveLocked()函数:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,  
  2.            Intent intent, int resultCode, String data, Bundle extras,  
  3.            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {  
  4.        // Send the intent to the receiver asynchronously using one-way binder calls.  
  5.        if (app != null && app.thread != null) {  
  6.            // If we have an app thread, do the call through that so it is  
  7.            // correctly ordered with other one-way calls.  
  8.            app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,  
  9.                    data, extras, ordered, sticky, sendingUser, app.repProcState);  
  10.        } else {  
  11.            receiver.performReceive(intent, resultCode, data, extras, ordered,  
  12.                    sticky, sendingUser);  
  13.        }  
  14.    }  
app.thread.scheduleRegisteredReceiver()函数最终也会调用receiver.performReceive()函数。receiver是一个IIntentReceiver的Binder代理对象,本地对象在应用层ContextImpl中(调用ContextImpl.registerReceiver()时会new LoadedApk.ReceiverDispatcher(),并new InnerReceiver(),同时把BroadcastReceiver对象保存在ReceiverDispatcher.mReceiver中,InnerReceiver就是IIntentReceiver本地对象)。由Binder调用机制知道调用IIntentReceiver代理对象,最终肯定会调用本地对象InnerReceiver.performReceive()函数,InnerReceiver.performReceive()函数就是简单调用ReceiverDispatcher.performReceive()。InnerReceiver的存在就是AMS分发广播给对应Receive的Binder通信实现。

继续研究ReceiverDispatcher.performReceive():

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. public void performReceive(Intent intent, int resultCode, String data,  
  2.              Bundle extras, boolean ordered, boolean sticky, int sendingUser) {  
  3.          if (ActivityThread.DEBUG_BROADCAST) {  
  4.              int seq = intent.getIntExtra("seq", -1);  
  5.              Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq  
  6.                      + " to " + mReceiver);  
  7.          }  
  8.          Args args = new Args(intent, resultCode, data, extras, ordered,  
  9.                  sticky, sendingUser);  
  10.          if (!mActivityThread.post(args)) {  
  11.              if (mRegistered && ordered) {  
  12.                  IActivityManager mgr = ActivityManagerNative.getDefault();  
  13.                  if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,  
  14.                          "Finishing sync broadcast to " + mReceiver);  
  15.                  args.sendFinished(mgr);  
  16.              }  
  17.          }  
  18.      }  
函数中首先new Args()将广播的信息封装起来,Args extends BroadcastReceiver.PendingResult implements Runnable,然后post到Handler消息队列,如果post不成功,那么对于有序广播需要调用args.sendFinished(mgr)来通知AMS已处理掉该广播(实际是没有处理该广播,只因为有序广播只有收到前一个广播的finish消息后才能进行下一个广播的dispatch)。post成功后,自然会调用Args.run()函数:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. public void run() {  
  2.             final BroadcastReceiver receiver = mReceiver;  
  3.             final boolean ordered = mOrdered;  
  4.               
  5.             final IActivityManager mgr = ActivityManagerNative.getDefault();  
  6.             final Intent intent = mCurIntent;  
  7.             mCurIntent = null;  
  8.               
  9.             if (receiver == null || mForgotten) {  
  10.                 if (mRegistered && ordered) {  
  11.                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,  
  12.                             "Finishing null broadcast to " + mReceiver);  
  13.                     sendFinished(mgr);  
  14.                 }  
  15.                 return;  
  16.             }  
  17.   
  18.             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");  
  19.             try {  
  20.                 ClassLoader cl =  mReceiver.getClass().getClassLoader();  
  21.                 intent.setExtrasClassLoader(cl);  
  22.                 setExtrasClassLoader(cl);  
  23.                 receiver.setPendingResult(this);  
  24.                 receiver.onReceive(mContext, intent);  
  25.             } catch (Exception e) {  
  26.                 if (mRegistered && ordered) {  
  27.                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,  
  28.                             "Finishing failed broadcast to " + mReceiver);  
  29.                     sendFinished(mgr);  
  30.                 }  
  31.                 if (mInstrumentation == null ||  
  32.                         !mInstrumentation.onException(mReceiver, e)) {  
  33.                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
  34.                     throw new RuntimeException(  
  35.                         "Error receiving broadcast " + intent  
  36.                         + " in " + mReceiver, e);  
  37.                 }  
  38.             }  
  39.               
  40.             if (receiver.getPendingResult() != null) {  
  41.                 finish();  
  42.             }  
  43.             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
  44.         }  
  45.     }  
函数逻辑很简单,最终的就是调用receiver.setPendingResult(this);和receiver.onReceive(mContext, intent)。前面说了ReceiverDispatcher.mReceiver中保存的是应用注册的BroadcastReceiver对象,setPendingResult(this)就是将Args对象保存到BroadcastReceiver.mPendingResult中,onReceive()是一个回调函数,应用一般会重写该函数,实现收到对应广播时逻辑。

总结广播机制:①广播注册—上层应用调用registerReceiver()注册广播接收器时,AMS会成对保存IntentFilter和Intent.action,同时也会保存一个与广播接收器对应的Receiver;②广播发送—sendBroadcast()发送一个广播时,在AMS侧会对应生成一个BroadcastRecord,然后从①中保存的IntentFilter和Intent.action对中找出相同Intent.action的IntentFilter,最后将广播信息通过Binder机制的Receiver传递给上层应用的BroadcastReceiver对象,onReceive()函数自然将被调用。

文章中processNextBroadcast()函数理解可能有偏差,后续再修正。

0 0
原创粉丝点击