AMS-Broadcast和BroadcastReceiver

              《AMS-Broadcast和BroadcastReceiver》

注册BroadcastReceiver

通过ActivityManagerService#registerReceiver注册到AMS中

              《AMS-Broadcast和BroadcastReceiver》

介绍几个跟注册有关的重要成员

* mRegisteredReceivers :  HashMap<IBinder,ReceiverList>    ReceiverList

  ReceiverList extends ArrayList,持有PorcessRecord和IIntentReceiver,并且保存了该IIntentReceiver对应的所有BroadcastIntent。

  其中IIntentReceiver持有BroadcastReceiver。

                《AMS-Broadcast和BroadcastReceiver》

在注册的时候,有一种stickyBroadcast,发送过一次后,AMS会记录下来,每次有新注册的Receiver,都会发给这个新的Receiver。

 

 

发送广播(sendBroadcast):

ActivityManagerService#broadcastIntentLocked(…)

* 若是特殊广播,如UID_REMOVED, PACKEAGE_REMOVED, PACKAGE_ADDED,

  TIMEZONE变化广播,CLEAR_DNS_CACHE广播,PROXY_CHANGE广播等

  需要特殊处理

* 关于sticky广播的一些处理

* 在该方法中,定义了两个List,分别是receivers:Lsit<ResolveInfo>和registeredReceivers<BroadcastReceiver>

  分别保存所有符合条件的广播接收者(包括静态和动态)和动态接收者。

  receiver = AppGlobals.getPackageManager().queryIntentReceivers(inent, resolvedType, STOCK_PM_FLAGS);

  registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);

* 若不是有序广播,创建一个BroadcastRecord,代表了一个广播,该对象持有所有能接收该广播的动态接收者的引用。

   将该广播加入一个queue,并开始广播,即与各进程通信,使receiver的onreceive方法在各自进程中执行。

 

 if (!replaced) {
                queue.enqueueParallelBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }

queque:BroadcastQueue,其中scheduleBroadcastsLocked会触发processNextBroadcast
BroadcastQueue#processNextBroadcast

 

  该方法重要的一段代码:

 

// First, deliver any non-serialized broadcasts right away.
            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, (BroadcastFilter)target, false);
                }
                addBroadcastToHistoryLocked(r);
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
                        + mQueueName + "] " + r);
            }

逐个启动各进程中的receiver的onreceive方法。最后将给broadcasstRecord放入History中。

 

* 还要处理静态的接收者,因静态接收者所在进程可能没有启动,所以不能像静态接收者一样处理。

  需要逐个处理,像有序广播那样处理

ActivityThread#scheduleRegisteredReceiver(…)

 

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);
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
        }

IIntentReceiver的实例类型是LoadedAPK.ReceiverDispatcher,而ReceiverDispatcher持有BroadcastReceiver

 

最终去到LoadedAPK.ReceiverDispatcher.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;
                mCurIntent = null;
                
                if (receiver == null || mForgotten) {
                    if (mRegistered && ordered) {
                        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                                "Finishing null broadcast to " + mReceiver);
                        sendFinished(mgr);
                    }
                    return;
                }

                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
                try {
                    ClassLoader cl =  mReceiver.getClass().getClassLoader();
                    intent.setExtrasClassLoader(cl);
                    setExtrasClassLoader(cl);
                    receiver.setPendingResult(this);
                    receiver.onReceive(mContext, intent);//在此调用了onreceive()
                } catch (Exception e) {
                    if (mRegistered && ordered) {
                        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                                "Finishing failed broadcast to " + mReceiver);
                        sendFinished(mgr);
                    }
                    if (mInstrumentation == null ||
                            !mInstrumentation.onException(mReceiver, e)) {
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                        throw new RuntimeException(
                            "Error receiving broadcast " + intent
                            + " in " + mReceiver, e);
                    }
                }
                
                if (receiver.getPendingResult() != null) {
                    finish();
                }
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }

1.注册广播

/*

   功能和前面类似,但增加了两个参数,分别是broadcastPermission和scheduler,作用有

   两个:

   其一:对广播者的权限增加了控制,只有拥有相应权限的广播者发出的广播才能被此接收者接收

   其二:BroadcastReceiver对象的onReceiver函数可调度到scheduler所在的线程中执行

*/

 publicIntent registerReceiver(BroadcastReceiver receiver,

       IntentFilterfilter, String broadcastPermission, Handler scheduler) {

/*

 用上面这些参数通过LoadedApk.ReceiverDispatcher.getIIntentReceiver(…)构造一个个IIntentReceiver,传给AMS,同时ApplicationThread也会传给AMS,调用AMS以下方法:

public Intent registerReceiver(IApplicationThreadcaller, String callerPackage,

           IIntentReceiver receiver, IntentFilter filter, String permission)

注册时并没有把本地创建的 BroadcastReceiver对象保存到本应用进程的某个结构体中,而是

2.接收广播。

IIntentReceiver是一个Binder对象,但是最后AMS和应用进程通信时使用的是ApplicationThread,通过ApplicationThread#scheduleRegisteredReceiver的方法

public voidscheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,

       intresultCode, String dataStr, Bundle extras, boolean ordered,

      boolean sticky) throws RemoteException {

  //又把receiver对象传了回来。还记得注册时传递的一个IIntentReceiver类型

  //的对象吗?

   receiver.performReceive(intent,resultCode, dataStr, extras, ordered,

                               sticky);

 }

通过该方法把注册时传递过去的IIntentReceiver又传回来了。然后就调用该对象performReceiver,最终会调用到BroadcastReceiver#onReceive()。

 

    原文作者:淡淡的宁静
    原文地址: https://blog.csdn.net/b1480521874/article/details/76549137
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞