美文网首页进阶
BroadCastReceiver- 工作流程

BroadCastReceiver- 工作流程

作者: shuixingge | 来源:发表于2016-10-15 10:28 被阅读86次

    一:广播注册过程

    注册过程

    注册过程补充

    1. ContextImpl.registerReceiverInternal():
    (1) 获得一个ItentReceiver对象,用来进行Binder通信。
    (2) 通过ActivityManagerProxy来进行跨进程注册广播。

    private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
               IntentFilter filter, String broadcastPermission,
               Handler scheduler, Context context) {
           IIntentReceiver rd = null;
            if (receiver != null) {
                if (mPackageInfo != null && context != null) {
                   if (scheduler == null) {
                       scheduler = mMainThread.getHandler();
                   }
                   rd = mPackageInfo.getReceiverDispatcher(
                       receiver, context, scheduler,
                       mMainThread.getInstrumentation(), true);
                } else {
                    if (scheduler == null) {
                      scheduler = mMainThread.getHandler();
                    }
                   rd = new LoadedApk.ReceiverDispatcher(
                           receiver, context, scheduler, null, true).getIIntentReceiver();
               }
           }
            try {
               return ActivityManagerNative.getDefault().registerReceiver(
                        mMainThread.getApplicationThread(), mBasePackageName,
                       rd, filter, broadcastPermission, userId);
           } catch (RemoteException e) {
               return null;
               }
        }
    

    2. LoadApk.getReceiverDispatcher():
    1 获得LoadApk.ReceiverDispacher. IIntentReceiver对象,IIntentReceiver对象 是一个Binder对象,可以用来跨进程传输。
    2 BroadCastReceiver是系统组件,不能跨进程传输,所以用IIntentReceiver来进行代替BroadCastReceiver来进行跨进程传输。
    3 map里面存储的是 <BroadcastReceiver, LoadedApk.ReceiverDispatcher>键值对,用来做缓存。

    public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
                Context context, Handler handler,
                 Instrumentation instrumentation, boolean registered) {
           synchronized (mReceivers) {
                LoadedApk.ReceiverDispatcher rd = null;
                 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
                if (registered) {
                     map = mReceivers.get(context);
                   if (map != null) {
                        rd = map.get(r);
                    }
                 }
                 if (rd == null) {
                     rd = new ReceiverDispatcher(r, context, handler,
                           instrumentation, registered);
                    if (registered) {
                        if (map == null) {
                             map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                             mReceivers.put(context, map);
                        }
                        map.put(r, rd);
                     }
                 } else {
                    rd.validate(context, handler);
               }
                 rd.mForgotten = false;
                return rd.getIIntentReceiver();
            }
        }
    
    

    3. LoadApk.ReceiverDispatcher.InnerReceiver:是IIntentReceiver.Stub的实现类.是Binder对象

    final static class InnerReceiver extends IIntentReceiver.Stub {
               final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
               final LoadedApk.ReceiverDispatcher mStrongRef;
    
                InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
                    mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                     mStrongRef = strong ? rd : null;
                 }
                public void performReceive(Intent intent, int resultCode, String data,
                         Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                    LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
                   if (ActivityThread.DEBUG_BROADCAST) {
                        int seq = intent.getIntExtra("seq", -1);
                        Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
                                 + " to " + (rd != null ? rd.mReceiver : null));
                    }
                    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);
                         } catch (RemoteException e) {
                           Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
                         }
                     }
                }
            }
    

    二:广播的发送和接收过程

    广播的发送和接收过程

    三:广播工作过程细致分析

    (1)BroadcastReceiver和广播的匹配过程

    在broadcastIntentLocked方法内部有如下代码:

    // Figure out who all will receive this broadcast.
    List receivers = null;
    List<BroadcastFilter> registeredReceivers = null;
    // Need to resolve the intent to interested receivers...
    if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
             == 0) {
        receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
    }
    if (intent.getComponent() == null) {
        if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
            // Query one target user at a time, excluding shell-restricted users
            // 略
        } else {
            registeredReceivers = mReceiverResolver.queryIntent(intent,
                    resolvedType, false, userId);
        }
    }
    
    receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
    registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false, userId);
    

    receivers:是对这个广播感兴趣的静态BroadcastReceiver列表
    mReceiverResolver:存储了动态注册的BroadcastReceiver的信息;通过mReceiverResolver.qureyIntent匹配出了对应的BroadcastReceiver供进一步使用。

    (2)接收过程

    broadcastIntentLocked方法的后半部分有如下代码
    1 首先创建了一个BroadcastRecord代表此次发送的这条广播,然后把它丢进一个队列,最后通过scheduleBroadcastsLocked通知队列对广播进行处理。

    
    BroadcastQueue queue = broadcastQueueForIntent(intent);
    BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
            callerPackage, callingPid, callingUid, resolvedType,
            requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
            resultData, resultExtras, ordered, sticky, false, userId);
    
    boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
    if (!replaced) {
        queue.enqueueOrderedBroadcastLocked(r);
        queue.scheduleBroadcastsLocked();
    }
    

    BroadcastQueue.scheduleBroadcastsLocked()
    在BroadcastQueue中通过Handler调度了对于广播处理的消息,调度过程由processNextBroadcast方法完成。

    public void scheduleBroadcastsLocked() {
           if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts ["
                     + mQueueName + "]: current="
                   + mBroadcastsScheduled);
    
           if (mBroadcastsScheduled) {
                return;
             }
             mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
             mBroadcastsScheduled = true;
         }
    }
    

    BroadcastQueue.processNextBroadcast():这个方法通过performReceiveLocked最终调用了IIntentReceiver的performReceive方法。

    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, "Received BROADCAST_INTENT_MSG");
                         processNextBroadcast(true);
                    } break;
                     case BROADCAST_TIMEOUT_MSG: {
                         synchronized (mService) {
                            broadcastTimeoutLocked(true);
                         }
                   } break;
                 }
            }
    };
    

    相关文章

      网友评论

        本文标题:BroadCastReceiver- 工作流程

        本文链接:https://www.haomeiwen.com/subject/uqknyttx.html