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


    文章转载至CSDN社区罗升阳的安卓之旅,原文地址: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, null, null, null, false, false);  
    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)机制简要介绍和学习计划一文中。

    老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!

  • 相关阅读:
    新概念 Lesson 2 Sorry, sir.
    记一次无法正常本地登陆Linux服务器(确定密码正确)
    English trip -- VC(情景课)5 D
    新概念 Lesson 1 Excuse me!
    English trip -- VC(情景课)5 C It's on Main Street 在主街上
    English trip -- Iris老师整理的一般时态
    English trip -- VC(情景课)5 B Places around town 城市设施
    English trip -- VC(情景课)5 Around Town
    Ploya定理学习笔记
    莫比乌斯反演学习笔记
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4142248.html
Copyright © 2020-2023  润新知