搜索
 找回密码
 立即注册

简单一步 , 微信登陆

Android应用程序发送广播(sendBroadcast)的过程分析(2)

作者:liuwei | 时间:2016-10-11 17:09:54 | 阅读:3922| 只看该作者
  前面我们说到,这里得到的列表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文件中:
  • public final class ActivityManagerService extends ActivityManagerNative
  •         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  •     ......
  •     private final void scheduleBroadcastsLocked() {
  •         ......
  •         if (mBroadcastsScheduled) {
  •             return;
  •         }
  •         mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
  •         mBroadcastsScheduled = true;
  •     }
  •     ......
  • }

        这里的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函数来真正处理这个消息:
  • public final class ActivityManagerService extends ActivityManagerNative
  •         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  •     ......
  •     final Handler mHandler = new Handler() {
  •         public void handleMessage(Message msg) {
  •             switch (msg.what) {
  •             ......
  •             case BROADCAST_INTENT_MSG: {
  •                 ......
  •                 processNextBroadcast(true);
  •             } break;
  •             ......
  •             }
  •         }
  •     }
  •     ......
  • }

        这里又调用了ActivityManagerService的processNextBroadcast函数来处理下一个未处理的广播。
        Step 8. ActivityManagerService.processNextBroadcast
        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
  • public final class ActivityManagerService extends ActivityManagerNative
  •         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  •     ......
  •     private final void processNextBroadcast(boolean fromMsg) {
  •         synchronized(this) {
  •             BroadcastRecord r;
  •             ......
  •             if (fromMsg) {
  •                 mBroadcastsScheduled = false;
  •             }
  •             // First, deliver any non-serialized broadcasts right away.
  •             while (mParallelBroadcasts.size() > 0) {
  •                 r = mParallelBroadcasts.remove(0);
  •                 ......
  •                 final int N = r.receivers.size();
  •                 ......
  •                 for (int i=0; i<N; i++) {
  •                     Object target = r.receivers.get(i);
  •                     ......
  •                     deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
  •                 }
  •                 addBroadcastToHistoryLocked(r);
  •                 ......
  •             }
  •             ......
  •         }
  •     }
  •     ......
  • }

        这里传进来的参数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文件中:
  • public final class ActivityManagerService extends ActivityManagerNative
  •         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  •     ......
  •     private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
  •             BroadcastFilter filter, boolean ordered) {
  •         boolean skip = false;
  •         if (filter.requiredPermission != null) {
  •             ......
  •         }
  •         if (r.requiredPermission != null) {
  •             ......
  •         }
  •         if (!skip) {
  •             // If this is not being sent as an ordered broadcast, then we
  •             // don't want to touch the fields that keep track of the current
  •             // state of ordered broadcasts.
  •             if (ordered) {
  •                 ......
  •             }
  •             try {
  •                 ......
  •                 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
  •                     new Intent(r.intent), r.resultCode,
  •                     r.resultData, r.resultExtras, r.ordered, r.initialSticky);
  •                 ......
  •             } catch (RemoteException e) {
  •                 ......
  •             }
  •         }
  •     }
  •     ......
  • }

         函数首先是检查一下广播发送和接收的权限,在我们分析的这个场景中,没有设置权限,因此,这个权限检查就跳过了,这里得到的skip为false,于是进入下面的if语句中。由于上面传时来的ordered参数为false,因此,直接就调用performReceiveLocked函数来进一步执行广播发送的操作了。
        Step 10. ActivityManagerService.performReceiveLocked
        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
  • public final class ActivityManagerService extends ActivityManagerNative
  •         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  •     ......
  •     static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
  •             Intent intent, int resultCode, String data, Bundle extras,
  •             boolean ordered, boolean sticky) throws RemoteException {
  •         // Send the intent to the receiver asynchronously using one-way binder calls.
  •         if (app != null && app.thread != null) {
  •             // If we have an app thread, do the call through that so it is
  •             // correctly ordered with other one-way calls.
  •             app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
  •                     data, extras, ordered, sticky);
  •         } else {
  •             ......
  •         }
  •     }
  •     ......
  • }

        注意,这里传进来的参数app是注册广播接收器的Activity所在的进程记录块,在我们分析的这个场景中,由于是MainActivity调用registerReceiver函数来注册这个广播接收器的,因此,参数app所代表的ProcessRecord就是MainActivity所在的进程记录块了;而参数receiver也是注册广播接收器时传给ActivityManagerService的一个Binder对象,它的类型是IIntentReceiver。
       MainActivity在注册广播接收器时,已经把自己的ProcessRecord记录下来了,所以这里的参数app和app.thread均不为null,于是,ActivityManagerService就调用app.thread.scheduleRegisteredReceiver函数来把这个广播分发给MainActivity了。这里的app.thread是一个Binder远程对象,它的类型是ApplicationThreadProxy,我们在前面介绍应用程序的Activity启动过程时,已经多次看到了。

       Step 11. ApplicationThreadProxy.scheduleRegisteredReceiver
       这个函数定义在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中:
  • class ApplicationThreadProxy implements IApplicationThread {
  •     ......
  •     public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
  •             int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)
  •             throws RemoteException {
  •         Parcel data = Parcel.obtain();
  •         data.writeInterfaceToken(IApplicationThread.descriptor);
  •         data.writeStrongBinder(receiver.asBinder());
  •         intent.writeToParcel(data, 0);
  •         data.writeInt(resultCode);
  •         data.writeString(dataStr);
  •         data.writeBundle(extras);
  •         data.writeInt(ordered ? 1 : 0);
  •         data.writeInt(sticky ? 1 : 0);
  •         mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
  •             IBinder.FLAG_ONEWAY);
  •         data.recycle();
  •     }
  •     ......
  • }

        这里通过Binder驱动程序就进入到ApplicationThread.scheduleRegisteredReceiver函数去了。ApplicationThread是ActivityThread的一个内部类
        Step 12. ApplicaitonThread.scheduleRegisteredReceiver
        这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:
  • public final class ActivityThread {
  •     ......
  •     private final class ApplicationThread extends ApplicationThreadNative {
  •         ......
  •         // This function exists to make sure all receiver dispatching is
  •         // correctly ordered, since these are one-way calls and the binder driver
  •         // applies transaction ordering per object for such calls.
  •         public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
  •                 int resultCode, String dataStr, Bundle extras, boolean ordered,
  •                 boolean sticky) throws RemoteException {
  •             receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
  •         }
  •         ......
  •     }
  •     ......
  • }

        这里的receiver它的具体类型是LoadedApk.ReceiverDispatcher.InnerReceiver,即定义在LoadedApk类的内部类ReceiverDispatcher里面的一个内部类InnerReceiver,这里调用它的performReceive函数。
        Step 13. InnerReceiver.performReceive
        这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中:
  • final class LoadedApk {
  •     ......
  •     static final class ReceiverDispatcher {
  •         final static class InnerReceiver extends IIntentReceiver.Stub {
  •             ......
  •             public void performReceive(Intent intent, int resultCode,
  •                     String data, Bundle extras, boolean ordered, boolean sticky) {
  •                 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
  •                 ......
  •                 if (rd != null) {
  •                     rd.performReceive(intent, resultCode, data, extras,
  •                             ordered, sticky);
  •                 } else {
  •                     ......
  •                 }
  •             }
  •         }
  •         ......
  •     }
  •     ......
  • }

         这里,它只是简单地调用ReceiverDispatcher的performReceive函数来进一步处理,这里的ReceiverDispatcher类是LoadedApk类里面的一个内部类。
         Step 14. ReceiverDispatcher.performReceive
         这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中:
  • final class LoadedApk {
  •     ......
  •     static final class ReceiverDispatcher {
  •         ......
  •         public void performReceive(Intent intent, int resultCode,
  •                 String data, Bundle extras, boolean ordered, boolean sticky) {
  •             ......
  •             Args args = new Args();
  •             args.mCurIntent = intent;
  •             args.mCurCode = resultCode;
  •             args.mCurData = data;
  •             args.mCurMap = extras;
  •             args.mCurOrdered = ordered;
  •             args.mCurSticky = sticky;
  •             if (!mActivityThread.post(args)) {
  •                 ......
  •             }
  •         }
  •         ......
  •     }
  •     ......
  • }

        这里mActivityThread成员变量的类型为Handler,它是前面MainActivity注册广播接收器时,从ActivityThread取得的,这里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文件中:
  • final class LoadedApk {
  •     ......
  •     static final class ReceiverDispatcher {
  •         ......
  •         final class Args implements Runnable {
  •             ......
  •             public void run() {
  •                 BroadcastReceiver receiver = mReceiver;
  •                 ......
  •                 Intent intent = mCurIntent;
  •                 ......
  •                 try {
  •                     ClassLoader cl =  mReceiver.getClass().getClassLoader();
  •                     intent.setExtrasClassLoader(cl);
  •                     if (mCurMap != null) {
  •                         mCurMap.setClassLoader(cl);
  •                     }
  •                     receiver.setOrderedHint(true);
  •                     receiver.setResult(mCurCode, mCurData, mCurMap);
  •                     receiver.clearAbortBroadcast();
  •                     receiver.setOrderedHint(mCurOrdered);
  •                     receiver.setInitialStickyHint(mCurSticky);
  •                     receiver.onReceive(mContext, intent);
  •                 } catch (Exception e) {
  •                     ......
  •                 }
  •                 ......
  •             }
  •             ......
  •         }
  •         ......
  •     }
  •     ......
  • }

        这里的mReceiver是ReceiverDispatcher类的成员变量,它的类型是BroadcastReceiver,这里它就是MainActivity注册广播接收器时创建的BroadcastReceiver实例了,
        有了这个ReceiverDispatcher实例之后,就可以调用它的onReceive函数把这个广播分发给它处理了。
        Step 17. BroadcastReceiver.onReceive
        这个函数定义Android应用程序Broadcast的工程目录下的src/shy/luo/broadcast/MainActivity.java文件中:
  • public class MainActivity extends Activity implements OnClickListener {
  •     ......
  •     private BroadcastReceiver counterActionReceiver = new BroadcastReceiver(){
  •         public void onReceive(Context context, Intent intent) {
  •             int counter = intent.getIntExtra(CounterService.COUNTER_VALUE, 0);
  •             String text = String.valueOf(counter);
  •             counterText.setText(text);
  •             Log.i(LOG_TAG, "Receive counter event");
  •         }
  •     }
  •     ......
  • }

        这样,MainActivity里面的定义的BroadcastReceiver实例counterActionReceiver就收到这个广播并进行处理了。
        至此,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函数

收藏
收藏0
分享
分享
点赞
点赞0
反对
反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册
手机版