Broadcast is divided into dynamic registration and static registration, where static registration is declared in AndroidManifeat and then registered by PackageManagerService upon application installation. Dynamic registration is registered by calling the registerReceiver method.

Let’s look at the sequence diagram for dynamic registration

ContextImpl’s registerReceiverInternal method is called when registerReceiver is called

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
        IntentFilter filter, String broadcastPermission,
        Handler scheduler, Context context, int flags) {
    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 {
        final Intent intent = ActivityManager.getService().registerReceiver(
                mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                broadcastPermission, userId, flags);
        if(intent ! =null) {
            intent.setExtrasClassLoader(getClassLoader());
            intent.prepareToEnterProcess();
        }
        return intent;
    } catch (RemoteException e) {
        throwe.rethrowFromSystemServer(); }}Copy the code

Whether the LoadedApk mPackageInfo and context are null is checked. If neither of them is null, the IIntentReceiver is obtained using the getReceiverDispatcher method of mPackageInfo. IIntentReceiver is a Binder interface for broadcast cross-process communication. His achievement in LoadedApk. ReceiverDispatcher. InnerReceiver. Otherwise a new IIntentReceiver will be created. Finally, AMS’s registerReceiver method is called and the IIntentReceiver obtained is passed in.

public Intent registerReceiver(IApplicationThread caller, String callerPackage,
        IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
        int flags) {
    enforceNotIsolatedCaller("registerReceiver");
    ArrayList<Intent> stickyIntents = null;
    ProcessRecord callerApp = null;
    final boolean visibleToInstantApps
            = (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
    int callingUid;
    int callingPid;
    boolean instantApp;
    synchronized(this) {
        if (caller != null) {
            //获取到ProcessRecord,这个用来描述注册广播的Activity所在进程的信息
            callerApp = getRecordForAppLocked(caller);
            if (callerApp == null) {
                throw new SecurityException(
                        "Unable to find app for caller " + caller
                        + " (pid=" + Binder.getCallingPid()
                        + ") when registering receiver " + receiver);
            }
            if (callerApp.info.uid != SYSTEM_UID &&
                    !callerApp.pkgList.containsKey(callerPackage) &&
                    !"android".equals(callerPackage)) {
                throw new SecurityException("Given caller package " + callerPackage
                        + " is not running in process " + callerApp);
            }
            //获取uid,pid
            callingUid = callerApp.info.uid;
            callingPid = callerApp.pid;
        } else {
            callerPackage = null;
            callingUid = Binder.getCallingUid();
            callingPid = Binder.getCallingPid();
        }

        instantApp = isInstantApp(callerApp, callerPackage, callingUid);
        userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                ALLOW_FULL_ONLY, "registerReceiver", callerPackage);

        //获取所有设置的action,如果没有,则添加一个null进去
        Iterator<String> actions = filter.actionsIterator();
        if (actions == null) {
            ArrayList<String> noAction = new ArrayList<String>(1);
            noAction.add(null);
            actions = noAction.iterator();
        }

        // Collect stickies of users
        int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
        //遍历所有action
        while (actions.hasNext()) {
            String action = actions.next();
            for (int id : userIds) {
                //获取该id对的到所有黏性广播,id为应用程序id
                ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
                if (stickies != null) {
                    ArrayList<Intent> intents = stickies.get(action);
                    if (intents != null) {
                        if (stickyIntents == null) {
                            stickyIntents = new ArrayList<Intent>();
                        }
                        //将对应的黏性广播加入到stickyIntents中
                        stickyIntents.addAll(intents);
                    }
                }
            }
        }
    }

    ArrayList<Intent> allSticky = null;
    if (stickyIntents != null) {
        final ContentResolver resolver = mContext.getContentResolver();
        //遍历所有粘性广播的Intent
        for (int i = 0, N = stickyIntents.size(); i < N; i++) {
            Intent intent = stickyIntents.get(i);
            // 免安装应用直接跳过
            if (instantApp &&
                    (intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
                continue;
            }

            if (filter.match(resolver, intent, true, TAG) >= 0) {
                if (allSticky == null) {
                    allSticky = new ArrayList<Intent>();
                }
                //将所有的intent加入到allSticky中
                allSticky.add(intent);
            }
        }
    }

    //如果传过来的IIntentReceiver为null,则会直接把第一个黏性广播的Intent传给客户端。
    //这里应该是静态注册的情况,动态注册IIntentReceiver不为null
    Intent sticky = allSticky != null ? allSticky.get(0) : null;
    if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Register receiver " + filter + ": " + sticky);
    if (receiver == null) {
        return sticky;
    }

    synchronized (this) {
        //判断一下注册广播的Activity是否还存在,如果已经不存在,直接返回null。
        if (callerApp != null && (callerApp.thread == null
                || callerApp.thread.asBinder() != caller.asBinder())) {
            // Original caller already died
            return null;
        }
        //获取广播接收者列表,ReceiverList是继承于ArrayList的集合
        ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
        //如果列表为null,则直接创建一个
        if (rl == null) {
            rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                    userId, receiver);
            //如果前面获取的ProcessRecord不为null,则将新创建的ReceiverList
            //添加到ProcessRecord的receivers当中
            if (rl.app != null) {
                rl.app.receivers.add(rl);
            } else {
                try {
                    receiver.asBinder().linkToDeath(rl, 0);
                } catch (RemoteException e) {
                    return sticky;
                }
                rl.linkedToDeath = true;
            }
            //将新创建的ReceiverList也加入到mRegisteredReceivers中
            //mRegisteredReceivers是一个map,key的类型是IBinder,这里传入的是IIntentReceiver
            //这个IIntentReceiver是注册广播的时候客户端传过来的InnerReceiver
            mRegisteredReceivers.put(receiver.asBinder(), rl);
        } 
        ...
        //将传过来的IntentFilter和获取到的ReceiverList等参数用来创建BroadcastFilter
        BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                permission, callingUid, userId, instantApp, visibleToInstantApps);
        将新创建的BroadcastFilter添加到ReceiverList中
        rl.add(bf);
        if (!bf.debugCheck()) {
            Slog.w(TAG, "==> For Dynamic broadcast");
        }
        //将BroadcastFilter添加到IntentResolver类型的mReceiverResolver中
        //当AMS收到广播的时候就可以从mReceiverResolver中找到对应的广播接收者。
        //到这里注册广播就完成了
        mReceiverResolver.addFilter(bf);

        //将和BroadcastFilter匹配的所有粘性广播加入到队列
        if (allSticky != null) {
            ArrayList receivers = new ArrayList();
            receivers.add(bf);

            final int stickyCount = allSticky.size();
            for (int i = 0; i < stickyCount; i++) {
                Intent intent = allSticky.get(i);
                BroadcastQueue queue = broadcastQueueForIntent(intent);
                BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                        null, -1, -1, false, null, null, AppOpsManager.OP_NONE, null, receivers,
                        null, 0, null, null, false, true, true, -1);
                queue.enqueueParallelBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
        }

        return sticky;
    }
}
Copy the code

At this point the registration for dynamic broadcast is complete.