美文网首页进阶
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