Android源码解析四大组件系列(七)---广播的发送过程

本篇文章的目录

1、广播数据结构分析
2、线程的切换
3、processNextBroadcast分析
  • 3.1、处理并行广播
  • 3.2、处理Pending广播
  • 3.3、处理有序广播
  • 3.4、获取下一条广播
  • 3.5、检查是否是动态广播
  • 3.6、检查是否是静态广播
  • 3.7、启动进程,处理未发送的静态广播
4、动态广播receiver处理
5、静态广播receiver处理

先了解一下广播的数据结构,然后在分析广播的处理过程。建议看本文,需要先看前面两篇文章

Android源码解析---广播的注册过程
Android源码解析---广播的处理过程

1、广播数据结构分析

final class BroadcastRecord extends Binder {
  
   final Intent intent;    // the original intent that generated us
   final ComponentName targetComp; // original component name set on the intent
   final ProcessRecord callerApp; // 广播调用者进程
 
   final String[] requiredPermissions; // 调用者需要的权限
  
   final List receivers;   //存储广播接收者, 包含 BroadcastFilter 和 ResolveInfo
  
   IIntentReceiver resultTo; // who receives final result if non-null
   long enqueueClockTime;  // 加入队列的时间
   long dispatchTime;      // 分发时间
   long dispatchClockTime; //分发时间
   long receiverTime;      // 接收时间.
   long finishTime;        ////广播完成时间
 
   int nextReceiver;       // 下一个广播接收者
   IBinder receiver;       //当前广播接收者
   int state;
   int anrCount;           //广播ANR次数
 
   ProcessRecord curApp;       // hosting application of current receiver.
   ComponentName curComponent; // the receiver class that is currently running.
   ActivityInfo curReceiver;   // info about the receiver that is currently running.

}

比较重要的数据成员有receivers,存储的都是广播接收器,callerApp是广播调用者进程,还要注意四个时间点,有入队列,分发,接收,完成,另外动态广播节点用BroadcastFilter描述,静态的用ResolveInfo描述。

  • ReceiverDispatcher: 客户端广播分发者对象,第一篇讲的很清楚了,ReceiverDispatcher的内部类InnerReceiver为binder对象,用于与AMS的传递与通信。

  • ReceiverList: 继承自ArrayList,存放了Receiver的binder对象以及其注册的BroadcastFilter列表。AMS中定义了
    final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();key为InnerReceiver的binder对象,值为ReceiverList,ReceiverList内部记录的是动态注册的广播接收者,mRegisteredReceivers只有动态注册的时候才会有内容。

  • BroadcastFilter: 封装了IntentFilter,描述动态广播,是动态广播节点。

  • ResolveInfo:Parcelable子类,描述静态广播,是静态广播节点。

  • IntentResolver: 解析Intent,在addFilter时即进行解析。其内部有mSchemeToFilter,mActionToFilter,mTypedActionToFilter三个map对象。key为对应的action(scheme或者type),value为Filter。

  • BroadcastRecord:描述一个广播, 将intent等一堆信息,封装成BroadcastRecord,交给BroadcastQueue进行处理。

  • BroadcastQueue: BroadcastQueue为Broadcast处理队列,分为前台队列mFgBroadcastQueue和后台队列mBgBroadcastQueue,mFgBroadcastQueue会有更高的权限,被优先处理。mFgBroadcastQueue和mBgBroadcastQueue两个队列中都含有mOrderedBroadcasts和mParallelBroadcasts两个列表用来表示有序广播列表和无序广播列表。

2、线程的切换

上篇说到不管是有序广播、无序广播还是粘性广播最终都是调用scheduleBroadcastsLocked处理的。那么scheduleBroadcastsLocked做了什么?

   public void scheduleBroadcastsLocked() {
       if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
               + mQueueName + "]: current="
               + mBroadcastsScheduled);

       //mBroadcastsScheduled参数是用来标记是否已经向消息队列发送了一个类型为BROADCAST_INTENT_MSG消息
       if (mBroadcastsScheduled) {
           return;
       }
       //发送一个BROADCAST_INTENT_MSG消息
       mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
       mBroadcastsScheduled = true;
   }

mHandler是BroadcastQueue的成员变量,定义如下

final BroadcastHandler mHandler;

它在BroadcastQueue构造函数中初始化

  BroadcastQueue(ActivityManagerService service, Handler handler,
           String name, long timeoutPeriod, boolean allowDelayBehindServices) {
       mService = service;
       mHandler = new BroadcastHandler(handler.getLooper());
       mQueueName = name;
       mTimeoutPeriod = timeoutPeriod;
       mDelayBehindServices = allowDelayBehindServices;
   }

参数中的handler是AMS中的MainHandler,所以BroadcastHandler采用的是ActivityManager线程的Looper,所以通过上面发送一个BROADCAST_INTENT_MSG消息,现在由system_server的binder线程切换到system_server的ActivityManager线程中。

   private final class BroadcastHandler extends Handler {
       public BroadcastHandler(Looper looper) {
           super(looper, null, true);
       }

       @Override
       public void handleMessage(Message msg) {
           switch (msg.what) {
               case BROADCAST_INTENT_MSG: {
                   if (DEBUG_BROADCAST) Slog.v(
                           TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
                   // 处理广播
                   processNextBroadcast(true);
               } break;
               case BROADCAST_TIMEOUT_MSG: {
                   synchronized (mService) {
                     //超时的时候走这里
                       broadcastTimeoutLocked(true);
                   }
               } break;
               case SCHEDULE_TEMP_WHITELIST_MSG: {
                   DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;
                   if (dic != null) {
                       dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
                               msg.arg2, true, (String)msg.obj);
                   }
               } break;
           }
       }
   }

所以现在重点分析processNextBroadcast方法。

3、processNextBroadcast分析

processNextBroadcast方法的代码跟broadcastIntentLocked方法一样,也是很长,所以分段来分析。

3.1、处理并行广播

  mService.updateCpuStats();

   //fromMsg字段标记是否是从handleMessage中调用的该方法  
   if (fromMsg) {
       //设置该参数为false,表示前面发送到消息队列中的BROADCAST_INTENT_MSG消息已经被处理了
       mBroadcastsScheduled = false;
   }

   //并行广播在这里循环一次性处理掉
   while (mParallelBroadcasts.size() > 0) {
       r = mParallelBroadcasts.remove(0);
       r.dispatchTime = SystemClock.uptimeMillis();
       r.dispatchClockTime = System.currentTimeMillis();
       final int N = r.receivers.size();
       if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
               + mQueueName + "] " + r);
       for (int i=0; i<N; i++) {
           Object target = r.receivers.get(i);
           if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                   "Delivering non-ordered on [" + mQueueName + "] to registered "
                   + target + ": " + r);
           //并行广播都是从deliverToRegisteredReceiverLocked发送出去的,此时r.receivers里面的都是BroadcastFilter
           deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
       }
       
       addBroadcastToHistoryLocked(r);
       if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
               + mQueueName + "] " + r);
   }

3.2、处理Pending广播

如果一个广播在发送的时候,进程还没有启动起来,那么会将它存在mPendingBroadcast中。由于动态广播是不会保证一定能够收到的,所以mPendingBroadcast是用来描述一个正在等待静态注册的目标广播接收者启动的广播。

 // Now take care of the next serialized one...

   // If we are waiting for a process to come up to handle the next
   // broadcast, then do nothing at this point.  Just in case, we
   // check that the process we're waiting for still exists.
   if (mPendingBroadcast != null) {
       if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
               "processNextBroadcast [" + mQueueName + "]: waiting for "
               + mPendingBroadcast.curApp);

       boolean isDead;
       // 检查这个静态注册的目标广播接收者所运行在的应用程序进程是否已经启动起来  
       synchronized (mService.mPidsSelfLocked) {
           ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
           isDead = proc == null || proc.crashing;
       }
       如果这个应用程序进程还活着,就会继续等待,否则就不等了
       if (!isDead) {
           // It's still alive, so keep waiting
           return;
       } else {
           Slog.w(TAG, "pending app  ["
                   + mQueueName + "]" + mPendingBroadcast.curApp
                   + " died before responding to broadcast");
           mPendingBroadcast.state = BroadcastRecord.IDLE;
           mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
           mPendingBroadcast = null;
       }
   }
   boolean looped = false;

3.3、处理有序广播

有序广播是一个接着一个处理的,并且还可以拦截,

do {
        //有序广播队列为0,不用处理,返回
        if (mOrderedBroadcasts.size() == 0) {
            // No more broadcasts pending, so all done!
            mService.scheduleAppGcsLocked();
            if (looped) {
                // If we had finished the last ordered broadcast, then
                // make sure all processes have correct oom and sched
                // adjustments.
                //更改一下OOM
                mService.updateOomAdjLocked();
            }
            return;
        }
        //获取一个有序广播(最顶部的BroadcastRecord)
        r = mOrderedBroadcasts.get(0);
        boolean forceReceive = false;

         //广播超时处理,这个会在下一节具体分析
        int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
        if (mService.mProcessesReady && r.dispatchTime > 0) {
            long now = SystemClock.uptimeMillis();
            if ((numReceivers > 0) &&
                    (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
                Slog.w(TAG, "Hung broadcast ["
                        + mQueueName + "] discarded after timeout failure:"
                        + " now=" + now
                        + " dispatchTime=" + r.dispatchTime
                        + " startTime=" + r.receiverTime
                        + " intent=" + r.intent
                        + " numReceivers=" + numReceivers
                        + " nextReceiver=" + r.nextReceiver
                        + " state=" + r.state);
                 //超时不能接收,就强制结束广播
                broadcastTimeoutLocked(false); // forcibly finish this broadcast
                forceReceive = true;
                //恢复初始状态。
                r.state = BroadcastRecord.IDLE;
            }
        }

        if (r.state != BroadcastRecord.IDLE) {
            if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
                    "processNextBroadcast("
                    + mQueueName + ") called when not idle (state="
                    + r.state + ")");
            return;
        }
         // 进入下面的条件有以下集中可能,一:广播没有接收者了,二:默认第一次r.nextReceiver = 0,但是它每次都会++,等待最后一个处理完了,再++就会得到一个不存在的nextReceiver,此时r.nextReceiver >= numReceivers,条件成立,三:
广播是否已经被拦截了,四:广播是否已经被强制结束了  
        if (r.receivers == null || r.nextReceiver >= numReceivers
                || r.resultAbort || forceReceive) {
            // No more receivers for this broadcast!  Send the final
            // result if requested...
            if (r.resultTo != null) {
                try {
                    if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
                            "Finishing broadcast [" + mQueueName + "] "
                            + r.intent.getAction() + " app=" + r.callerApp);
                   //处理广播消息消息,调用到onReceive()
                    performReceiveLocked(r.callerApp, r.resultTo,
                        new Intent(r.intent), r.resultCode,
                        r.resultData, r.resultExtras, false, false, r.userId);
                    // Set this to null so that the reference
                    // (local and remote) isn't kept in the mBroadcastHistory.
                    r.resultTo = null;
                } catch (RemoteException e) {
                    r.resultTo = null;
                    Slog.w(TAG, "Failure ["
                            + mQueueName + "] sending broadcast result of "
                            + r.intent, e);

                }
            }

            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");
                //r所描述的广播转发任务已经在规定时间内处理完了,需要remove掉前面给mHandler发送的BROADCAST_TIMEOUT_MSG消息。
            cancelBroadcastTimeoutLocked();

            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                    "Finished with ordered broadcast " + r);

            // ... and on to the next...
            addBroadcastToHistoryLocked(r);
            if (r.intent.getComponent() == null && r.intent.getPackage() == null
                    && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                // This was an implicit broadcast... let's record it for posterity.
                mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
                        r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
            }
            // 将r所描述的广播转发任务从有序广播队列中删除  
            mOrderedBroadcasts.remove(0);
            //赋值为null,进入下一次循环
            r = null;
            looped = true;
            continue;
        }
 } while (r == null);

3.4、获取下一条广播

  //通过上面的循环,r就有值了,获取下一条广播
  int recIdx = r.nextReceiver++;

  // Keep track of when this receiver started, and make sure there
  // is a timeout message pending to kill it if need be.
  r.receiverTime = SystemClock.uptimeMillis();
  if (recIdx == 0) {
      r.dispatchTime = r.receiverTime;
      r.dispatchClockTime = System.currentTimeMillis();
      if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
              + mQueueName + "] " + r);
  }
  if (! mPendingBroadcastTimeoutMessage) {
      long timeoutTime = r.receiverTime + mTimeoutPeriod;
      if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
              "Submitting BROADCAST_TIMEOUT_MSG ["
              + mQueueName + "] for " + r + " at " + timeoutTime);
      setBroadcastTimeoutLocked(timeoutTime);
  }ComponentName component

  final BroadcastOptions brOptions = r.options;
  final Object nextReceiver = r.receivers.get(recIdx);

3.5、检查是否是动态广播

   //检查是否是动态广播
 if (nextReceiver instanceof BroadcastFilter) {
      BroadcastFilter filter = (BroadcastFilter)nextReceiver;
      if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
              "Delivering ordered ["
              + mQueueName + "] to registered "
              + filter + ": " + r);
     //动态注册的广播给deliverToRegisteredReceiverLocked处理
      deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
     //判断是否是无序广播
      if (r.receiver == null || !r.ordered) {
          // The receiver has already finished, so schedule to
          // process the next one.
          if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Quick finishing ["
                  + mQueueName + "]: ordered="
                  + r.ordered + " receiver=" + r.receiver);
         //将 r.state设置为IDLE,表示不需要等待它的前一个目标广播接收者处理完成一个广播,  
         // 就可以将该广播继续发送给它的下一个目标广播接收者处理  
          r.state = BroadcastRecord.IDLE;
      //执行下一个广播,内部也是发送消息
          scheduleBroadcastsLocked();
      } else {
          ....
      }
     //有序广播一次只处理一个,直接返回就行
      return;
  }

3.6、检查是否是静态广播

 //如果上面没有return,那么肯定是静态注册的广播,静态注册注册的广播节点是ResolveInfo
  ResolveInfo info = (ResolveInfo)nextReceiver;
  //这个ComponentName会一直传递到ActivityThread,用来反射new广播接收者对象的
  ComponentName component = new ComponentName(
          info.activityInfo.applicationInfo.packageName,
          info.activityInfo.name);
  //很多的条件判断,skip不满足就为true
   boolean skip = false;
   .......
 
   String targetProcess = info.activityInfo.processName;
   ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
          info.activityInfo.applicationInfo.uid, false);

   if (skip) {
      if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
              "Skipping delivery of ordered [" + mQueueName + "] "
              + r + " for whatever reason");
      r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
      r.receiver = null;
      r.curFilter = null;
  //变成初始状态
      r.state = BroadcastRecord.IDLE;
  //执行下个广播
      scheduleBroadcastsLocked();
      return;
   }

.......
//如果当前进程存在,调用processCurBroadcastLocked处理,静态广播都是走processCurBroadcastLocked处理的
if (app != null && app.thread != null) {
      try {
          app.addPackage(info.activityInfo.packageName,
                  info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
          processCurBroadcastLocked(r, app);
      //处理完直接返回,一次处理一个
          return;
      } catch (RemoteException e) {
          Slog.w(TAG, "Exception when sending broadcast to "
                + r.curComponent, e);
      } catch (RuntimeException e) {
          Slog.wtf(TAG, "Failed sending broadcast to "
                  + r.curComponent + " with " + r.intent, e);
          // If some unexpected exception happened, just skip
          // this broadcast.  At this point we are not in the call
          // from a client, so throwing an exception out from here
          // will crash the entire system instead of just whoever
          // sent the broadcast.
          logBroadcastReceiverDiscardLocked(r);
          finishReceiverLocked(r, r.resultCode, r.resultData,
                  r.resultExtras, r.resultAbort, false);
          scheduleBroadcastsLocked();
          // We need to reset the state if we failed to start the receiver.
          r.state = BroadcastRecord.IDLE;
          return;
      }

      // If a dead object exception was thrown -- fall through to
      // restart the application.
  }

 //程序走到这里,说明进程不存在,那么调用startProcessLocked启动进程,
if ((r.curApp=mService.startProcessLocked(targetProcess,
          info.activityInfo.applicationInfo, true,
          r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
          "broadcast", r.curComponent,
          (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                  == null) {
      // Ah, this recipient is unavailable.  Finish it if necessary,
      // and mark the broadcast record as ready for the next.
      Slog.w(TAG, "Unable to launch app "
              + info.activityInfo.applicationInfo.packageName + "/"
              + info.activityInfo.applicationInfo.uid + " for broadcast "
              + r.intent + ": process is bad");
      logBroadcastReceiverDiscardLocked(r);
      finishReceiverLocked(r, r.resultCode, r.resultData,
              r.resultExtras, r.resultAbort, false);
  //启动失败就执行下一个
      scheduleBroadcastsLocked();
      r.state = BroadcastRecord.IDLE;
      return;
  }
  //把当前的r存下来,方便下一次处理
   mPendingBroadcast = r;
  //设置当前的receiver的索引,用来表示将要启动的。
  mPendingBroadcastRecvIndex = recIdx;

3.7、启动进程,处理未发送的静态广播

当进程启动完成之后,会回调AMS的attachApplication,然后走到attachApplicationLocked。

   // Check if a next-broadcast receiver is in this process...
      if (!badApp && isPendingBroadcastProcessLocked(pid)) {
          try {
              didSomething |= sendPendingBroadcastsLocked(app);
          } catch (Exception e) {
              // If the app died trying to launch the receiver we declare it 'bad'
              Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
              badApp = true;
          }
     }

  // The app just attached; send any pending broadcasts that it should receive
  boolean sendPendingBroadcastsLocked(ProcessRecord app) {
      boolean didSomething = false;
      for (BroadcastQueue queue : mBroadcastQueues) {
          didSomething |= queue.sendPendingBroadcastsLocked(app);
      }
      return didSomething;
  }


 public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
      boolean didSomething = false;
      final BroadcastRecord br = mPendingBroadcast;
      if (br != null && br.curApp.pid == app.pid) {
          if (br.curApp != app) {
              Slog.e(TAG, "App mismatch when sending pending broadcast to "
                      + app.processName + ", intended target is " + br.curApp.processName);
              return false;
          }
          try {
              //目标进程已经成功启动了,那么mPendingBroadcast就可以赋值为null了
              mPendingBroadcast = null;
          //调用processCurBroadcastLocked处理广播
              processCurBroadcastLocked(br, app);
              didSomething = true;
          } catch (Exception e) {
              Slog.w(TAG, "Exception in new application when starting receiver "
                      + br.curComponent.flattenToShortString(), e);
              logBroadcastReceiverDiscardLocked(br);
              finishReceiverLocked(br, br.resultCode, br.resultData,
                      br.resultExtras, br.resultAbort, false);
              scheduleBroadcastsLocked();
              // We need to reset the state if we failed to start the receiver.
              br.state = BroadcastRecord.IDLE;
              throw new RuntimeException(e.getMessage());
          }
      }
      return didSomething;
  }

看完上面的三个小节,到这里总结一下 processNextBroadcast()的代码逻辑:

  • 如果是动态广播接收者(无序),会调用deliverToRegisteredReceiverLocked一次性处理,即遍历并行列表(mParallelBroadcasts)的每一个BroadcastRecord以及其中的receivers列表,是一个双重循环。
  • 如果是静态广播接收者(有序),且对应进程已经创建,会调用processCurBroadcastLocked继续处理;
  • 如果是静态广播接收者(有序),且对应进程尚未创建,会调用startProcessLocked创建进程,之后仍然会调用processCurBroadcastLocked继续处理。

4、动态广播receiver处理

上面主要分析了动态广播接收者和静态广播接收者该如何处理,现在先看动态广播是如何处理的。就是分析deliverToRegisteredReceiverLocked方法实现。

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
          BroadcastFilter filter, boolean ordered, int index) {
      boolean skip = false;
      //权限判断,  检查发送者是否有权限,检查接收者是否有发送者所需的权限等等,
  //此处省略,不符合的skip==true,下面就return。
      ....

      if (skip) {
          r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
          return;
      }

        ....
      //只有有序广播才会进入这个分支
      if (ordered) {
          r.receiver = filter.receiverList.receiver.asBinder();
          r.curFilter = filter;
          filter.receiverList.curBroadcast = r;
          r.state = BroadcastRecord.CALL_IN_RECEIVE;
          if (filter.receiverList.app != null) {
              // Bump hosting application to no longer be in background
              // scheduling class.  Note that we can't do that if there
              // isn't an app...  but we can only be in that case for
              // things that directly call the IActivityManager API, which
              // are already core system stuff so don't matter for this.
              r.curApp = filter.receiverList.app;
              filter.receiverList.app.curReceiver = r;
              mService.updateOomAdjLocked(r.curApp);
          }
      }
      try {
          if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
                  "Delivering to " + filter + " : " + r);
          if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
              // Skip delivery if full backup in progress
              // If it's an ordered broadcast, we need to continue to the next receiver.
              if (ordered) {
                  skipReceiverLocked(r);
              }
          } else {
          //处理广播,filter.receiverList.receiver对应的是客户端ReceiverDispatcher的Binder实体——InnerReceiver
              performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                      new Intent(r.intent), r.resultCode, r.resultData,
                      r.resultExtras, r.ordered, r.initialSticky, r.userId);
          }
          if (ordered) {
              r.state = BroadcastRecord.CALL_DONE_RECEIVE;
          }
      } catch (RemoteException e) {
         ....
      }
  }
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
           Intent intent, int resultCode, String data, Bundle extras,
           boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
       // Send the intent to the receiver asynchronously using one-way binder calls.
       if (app != null) {
           if (app.thread != null) {
               try {
                   //终于走到ActivityThread里面了
                   app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                           data, extras, ordered, sticky, sendingUser, app.repProcState);
               } catch (RemoteException ex) {
                   .....
               }
           } else {
               // Application has died. Receiver doesn't exist.
               throw new RemoteException("app.thread must not be null");
           }
       } else {
           //调用者进程不存在,则执行该分支
           receiver.performReceive(intent, resultCode, data, extras, ordered,
                   sticky, sendingUser);
       }
   }

      public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
               int resultCode, String dataStr, Bundle extras, boolean ordered,
               boolean sticky, int sendingUser, int processState) throws RemoteException {
           updateProcessState(processState, false);
          //走到ReceiverDispatcher中的performReceive实际是InnerReceiver内部类当中的方法
           receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                   sticky, sendingUser);
       }

终于走到客户端的ReceiverDispatcher(广播分发者)了,ReceiverDispatcher知道我们这个广播要分发给谁。此时正式由SystemServer进程回到客户端进程了。

   @Override
    public void performReceive(Intent intent, int resultCode, String data,
           Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
       final LoadedApk.ReceiverDispatcher rd;
        ......
       if (rd != null) {
           rd.performReceive(intent, resultCode, data, extras,
                   ordered, sticky, sendingUser);
       } else {
           // The activity manager dispatched a broadcast to a registered
           // receiver in this process, but before it could be delivered the
           // receiver was unregistered.  Acknowledge the broadcast on its
           // behalf so that the system's broadcast sequence can continue.
           if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                   "Finishing broadcast to unregistered receiver");
           IActivityManager mgr = ActivityManagerNative.getDefault();
           try {
               if (extras != null) {
                   extras.setAllowFds(false);
               }
               mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
           } catch (RemoteException e) {
               throw e.rethrowFromSystemServer();
           }
       }
   }

可以看到我们调用ReceiverDispatcher中InnerReceiver的performReceive之后,紧接着在内部调用了ReceiverDispatcher的performReceive方法,再看ReceiverDispatcher的performReceive方法。

public void performReceive(Intent intent, int resultCode, String data,
               Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
           final Args args = new Args(intent, resultCode, data, extras, ordered,
                   sticky, sendingUser);
           if (intent == null) {
               Log.wtf(TAG, "Null intent received");
           } else {
               if (ActivityThread.DEBUG_BROADCAST) {
                   int seq = intent.getIntExtra("seq", -1);
                   Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
                           + " seq=" + seq + " to " + mReceiver);
               }
           }
           //post了一个消息给主线程
           if (intent == null || !mActivityThread.post(args)) {
               if (mRegistered && ordered) {
                   IActivityManager mgr = ActivityManagerNative.getDefault();
                   if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                           "Finishing sync broadcast to " + mReceiver);
                   ///发送完成本次广播处理,用来进行下次的广播处理。
                   args.sendFinished(mgr);
               }
           }
       }

上面的mActivityThread在第一篇文章说过,代表主线程,所以现在会执行args的run方法。

  public void run() {
       final BroadcastReceiver receiver = mReceiver;
       final boolean ordered = mOrdered;
       
       if (ActivityThread.DEBUG_BROADCAST) {
           int seq = mCurIntent.getIntExtra("seq", -1);
           Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
                   + " seq=" + seq + " to " + mReceiver);
           Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
                   + " mOrderedHint=" + ordered);
       }
       
       final IActivityManager mgr = ActivityManagerNative.getDefault();
       final Intent intent = mCurIntent;
       if (intent == null) {
           Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
       }

       ......
       try {
           ClassLoader cl =  mReceiver.getClass().getClassLoader();
           intent.setExtrasClassLoader(cl);
           intent.prepareToEnterProcess();
           setExtrasClassLoader(cl);
           receiver.setPendingResult(this);
       //onReceive方法回调
           receiver.onReceive(mContext, intent);
       } catch (Exception e) {
           .....
   }

到此,deliverToRegisteredReceiverLocked是怎么处理动态广播就分析完毕了。总结一下主要流程

------|-BroadcastQueue.performReceiveLocked()
------|-------|-ActivityThread.ApplicationThread.scheduleRegisteredReceiver()
------|-------|-------|- ReceiverDispatcher.InnerReceiver.performReceive()
------|-------|-------|-------|-Handler.post(args)
------|-------|-------|-------|-------|-Args.run()
------|-------|-------|-------|-------|-------|-BroadcastReceiver.onReceive()

5、静态广播receiver处理

刚刚说了静态广播是processCurBroadcastLocked处理的

   private final void processCurBroadcastLocked(BroadcastRecord r,
           ProcessRecord app) throws RemoteException {
       .....

       r.receiver = app.thread.asBinder();
       r.curApp = app;
       app.curReceiver = r;
      //更新进程状态
       app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
       //更新内存
       mService.updateLruProcessLocked(app, false, null);
       //更新adj
       mService.updateOomAdjLocked();

       // Tell the application to launch this receiver.告诉客户端启动这个receiver
       r.intent.setComponent(r.curComponent);

       boolean started = false;
       try {
             .....
           //走到了ActivityThread中的ApplicationThread中对应的方法。
           app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
                   mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
                   r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
                   app.repProcState);
           if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                   "Process cur broadcast " + r + " DELIVERED for app " + app);
           started = true;
       } finally {
           .....
           }
        }
    }

此时正式由SystemServer进程进入了客户端进程了

public final void scheduleReceiver(Intent intent, ActivityInfo info,
               CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
               boolean sync, int sendingUser, int processState) {
           updateProcessState(processState, false);
           ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
                   sync, false, mAppThread.asBinder(), sendingUser);
           r.info = info;
           r.compatInfo = compatInfo;
           sendMessage(H.RECEIVER, r);
       }

一样的套路,发送一个消息给主线程,进入对应的case,执行 handleReceiver((ReceiverData)msg.obj);

   private void handleReceiver(ReceiverData data) {
     
      // 这个最初就是在processNextBroadcast处理静态注册的ResolveInfo时,new的ComponentName。
       String component = data.intent.getComponent().getClassName();

       LoadedApk packageInfo = getPackageInfoNoCheck(
               data.info.applicationInfo, data.compatInfo);

       IActivityManager mgr = ActivityManagerNative.getDefault();

       BroadcastReceiver receiver;
       try {
       //反射出BroadcastReceiver
           java.lang.ClassLoader cl = packageInfo.getClassLoader();
           data.intent.setExtrasClassLoader(cl);
           data.intent.prepareToEnterProcess();
           data.setExtrasClassLoader(cl);
           receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
       } catch (Exception e) {
           if (DEBUG_BROADCAST) Slog.i(TAG,
                   "Finishing failed broadcast to " + data.intent.getComponent());
           data.sendFinished(mgr);
           throw new RuntimeException(
               "Unable to instantiate receiver " + component
               + ": " + e.toString(), e);
       }

       try {
           Application app = packageInfo.makeApplication(false, mInstrumentation);

           if (localLOGV) Slog.v(
               TAG, "Performing receive of " + data.intent
               + ": app=" + app
               + ", appName=" + app.getPackageName()
               + ", pkg=" + packageInfo.getPackageName()
               + ", comp=" + data.intent.getComponent().toShortString()
               + ", dir=" + packageInfo.getAppDir());

           ContextImpl context = (ContextImpl)app.getBaseContext();
           sCurrentBroadcastIntent.set(data.intent);
           receiver.setPendingResult(data);
       //这个和动态的不一样,静态的广播onReceive方法中的context是RestrictedContext
           receiver.onReceive(context.getReceiverRestrictedContext(),
                   data.intent);
       } catch (Exception e) {
           if (DEBUG_BROADCAST) Slog.i(TAG,
                   "Finishing failed broadcast to " + data.intent.getComponent());
           data.sendFinished(mgr);
           if (!mInstrumentation.onException(receiver, e)) {
               throw new RuntimeException(
                   "Unable to start receiver " + component
                   + ": " + e.toString(), e);
           }
       } finally {
           sCurrentBroadcastIntent.set(null);
       }

       if (receiver.getPendingResult() != null) {
           data.finish();
       }
   }

到这总结一下静态广播接收者的处理流程,如下:
如果应用程序已经启动(app.thread != null)
------|-ActivityThread.ApplicationThread.scheduleReceiver()
------|------|- ActivityThread.handleReceiver()
------|-------|-------|- BroadcastReceiver.onReceive()
否则
------|-LoadedApk.ReceiverDispatcher.IntentReceiver.performReceive()
------|-------|-LoadedApk.ReceiverDispatcher.performReceiver()
------|-------|-------|- LoadedApk.ReceiverDispatcher.Args.run()
------|-------|-------|-------|-BroadcastReceiver.onReceive()

至此广播的处理过程就结束了,下篇写一下广播细节,加深理解,比如广播有序是怎么保证的?怎么实现广播拦截处理的?广播超时是怎么处理的?onReceive方法中可以在发送广播吗?registerReceiver方法发返回值有什么用?粘性广播等等

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容