Android Broadcast原理分析之sendBroadcast(二)

目录

  • 广播发送与派发整体流程简介
  • sendBroadcast时序图
  • 源码解析
  • 总结

1. 广播发送与派发整体流程简介

从上一节广播的注册,可以知道广播机制是典型的观察者模式,那么通知所有receiver的时机具体是什么时候呢,答案就是在发送广播的时候,广播一发送,此时就应该通知所有已经注册的观察者,也就是已经注册的receiver。整个广播的派发的流程其实就是逐个通知观察者的过程。而这整体的流程主要都在BroadcastQueue中经过调度之后派发给各个注册的receiver,最终回调到APP进程中已注册的receiver的onReceive方法。

:本文基于Android 8.1。

2. sendBroadcast时序图

sendBroadcast

  1. 上面的流程中,主要涉及到的进程有发送APP的进程,systemserver进程,以及接收广播的进程
  2. 图中11~18的过程是动态注册的广播的派发(包括有序和无序)
  3. 图中19~24的过程是静态注册的派发,静态注册的广播默认都以有序广播形式派发
  4. BroadcastHandler调度线程是用的ActivityManager线程

3. 源码解析

3.1 ContextImpl.sendBroadcast

客户端通过context发送广播,都会调用到ContextImpl.sendBroadcast去实现广播的发送,而且不管是发送有序广播还是无序广播,最终发起binder call的方法都是一致的。
sendBroadcast

    @Override
    public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        String[] receiverPermissions = receiverPermission == null ? null
                : new String[] {receiverPermission};
        try {
            intent.prepareToLeaveProcess(this);
            ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false,
                    getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

sendOrderedBroadcast

    void sendOrderedBroadcast(Intent intent,
            String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
            Handler scheduler, int initialCode, String initialData,
            Bundle initialExtras, Bundle options) {
        warnIfCallingFromSystemProcess();
        IIntentReceiver rd = null;
        // 相比于发送无序广播,有序广播最重要区别就在
        // 有序广播可以有一个resultRceiver,也就是可以指定这个广播的最后一个接收者
        // 有序广播是逐个派发的,因此通过最后一个接收者可以知道广播派发完毕了,做一些收尾工作
        if (resultReceiver != null) {
            if (mPackageInfo != null) {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                rd = mPackageInfo.getReceiverDispatcher(
                    resultReceiver, getOuterContext(), scheduler,
                    mMainThread.getInstrumentation(), false);
            } else {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                rd = new LoadedApk.ReceiverDispatcher(
                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
            }
        }
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        String[] receiverPermissions = receiverPermission == null ? null
                : new String[] {receiverPermission};
        try {
            intent.prepareToLeaveProcess(this);
            ActivityManager.getService().broadcastIntent(
                mMainThread.getApplicationThread(), intent, resolvedType, rd,
                initialCode, initialData, initialExtras, receiverPermissions, appOp,
                    options, true, false, getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

上面resultReceiver跟receiver的注册有些类似,这也正是有序广播相对与无序广播多出来的部分,多了最后的InnerReceiver,保证本次发送的所有广播执行结束之后,调用这个广播。

3.2 ActivityManagerService.broadcastIntent

    public final int broadcastIntent(IApplicationThread caller,
            Intent intent, String resolvedType, IIntentReceiver resultTo,
            int resultCode, String resultData, Bundle resultExtras,
            String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean serialized, boolean sticky, int userId) {
        enforceNotIsolatedCaller("broadcastIntent");
        synchronized(this) {
            intent = verifyBroadcastLocked(intent);

            final ProcessRecord callerApp = getRecordForAppLocked(caller);
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            int res = broadcastIntentLocked(callerApp,
                    callerApp != null ? callerApp.info.packageName : null,
                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                    requiredPermissions, appOp, bOptions, serialized, sticky,
                    callingPid, callingUid, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

参数解析:
caller:发送方的applicationThread对象
intent:本次发送的广播所带的intent
resolvedType:根绝intent schema判断类型
resultTo:最终接受的receiver
resultCode:有序广播在一个receiver处理之后可以设置值,这样下一个receiver就可以拿到这个数据
resultData:作用同上面的code,是string类型的数据
resultExtras:作用同上面的code,是Bundle类型数据
requiredPermissions:接收这个广播需要的权限
appOp:接受这个广播需要的AppopsManager权限
bOptions:设置在这个广播发送的时候将某个package放入到deviceIdle白名单中,有时长限制
serialized:是否为有序广播
sticky:是否为sticky广播
userId:这个广播将要发送到的user

3.3 ActivityManagerService.broadcastIntentLocked

    final int broadcastIntentLocked(ProcessRecord callerApp,
            String callerPackage, Intent intent, String resolvedType,
            IIntentReceiver resultTo, int resultCode, String resultData,
            Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
        // Intent支持跨进程传输,保证互不干扰,此处创建新的Intent对象
        intent = new Intent(intent);

        final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
        if (callerInstantApp) {
            // 如果caller是instant app,则不能使用FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS
            // 即instant app不能发送给instant app可见的广播
            intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
        }

        // 默认情况下,广播不会发送给处于stop状态下的package
        // 应用在安装后从来没有启动过,或者已经被用户强制停止了,那么这个应用就处于停止状态
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

        // 如果开机还没有完成,且没有带升级状态可接受的flag,那么添加FLAG_RECEIVER_REGISTERED_ONLY
        if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
        }

        ...
        // user校验

        // 参数中的bOptions会改变deviceidle的临时白名单
        // 因此需要查看caller是否有改变deviceidle名单的权限
        BroadcastOptions brOptions = null;
        if (bOptions != null) {
            brOptions = new BroadcastOptions(bOptions);
            if (brOptions.getTemporaryAppWhitelistDuration() > 0) {
                if (checkComponentPermission(
                        android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
                        Binder.getCallingPid(), Binder.getCallingUid(), -1, true)
                        != PackageManager.PERMISSION_GRANTED) {
                    String msg = "Permission Denial: " + intent.getAction()
                            + " broadcast from " + callerPackage + " (pid=" + callingPid
                            + ", uid=" + callingUid + ")"
                            + " requires "
                            + android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
                    Slog.w(TAG, msg);
                    throw new SecurityException(msg);
                }
            }
        }

        // 确保protectBroadcast广播只能由某些特定的发送者发送
        // 主要是root/system/phone/bluetooth/nfc这些uid
        // 以及persist应用可以发送
        final String action = intent.getAction();
        final boolean isProtectedBroadcast;
        try {
            isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
        } catch (RemoteException e) {
            return ActivityManager.BROADCAST_SUCCESS;
        }

        final boolean isCallerSystem;
        switch (UserHandle.getAppId(callingUid)) {
            case ROOT_UID:
            case SYSTEM_UID:
            case PHONE_UID:
            case BLUETOOTH_UID:
            case NFC_UID:
                isCallerSystem = true;
                break;
            default:
                isCallerSystem = (callerApp != null) && callerApp.persistent;
                break;
        }

        if (!isCallerSystem) {
            // protectBroadcast只能由系统发送
            if (isProtectedBroadcast) {
                String msg = "Permission Denial: not allowed to send broadcast "
                        + action + " from pid="
                        + callingPid + ", uid=" + callingUid;
                Slog.w(TAG, msg);
                throw new SecurityException(msg);

            } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
                    || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
                // 对于这些比较特殊的广播,不允许caller为null
                if (callerPackage == null) {
                    String msg = "Permission Denial: not allowed to send broadcast "
                            + action + " from unknown caller.";
                    Slog.w(TAG, msg);
                    throw new SecurityException(msg);
                } else if (intent.getComponent() != null) {
                    // 如果component不为空,则必须要求所设置的component的package和caller一致
                    if (!intent.getComponent().getPackageName().equals(
                            callerPackage)) {
                        String msg = "Permission Denial: not allowed to send broadcast "
                                + action + " to "
                                + intent.getComponent().getPackageName() + " from "
                                + callerPackage;
                        Slog.w(TAG, msg);
                        throw new SecurityException(msg);
                    }
                } else {
                    // 如果component为空则只能发送给自己
                    intent.setPackage(callerPackage);
                }
            }
        }

        if (action != null) {
            if (getBackgroundLaunchBroadcasts().contains(action)) {
                // 判断允许在后台应用可以接受的广播的action列表中有没有这个action
                // 如果有,即允许这个广播被后台应用接收,则添加flag
                // 默认的action都是不带这个flag的,所以默认不允许后台应用接收广播
                intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            }

            // 此处对某些的action进行特殊处理
            switch (action) {
                ...
                // 主要是针对package相关的广播做了特殊处理,这里不再罗列,有兴趣可以自己翻看源码
            }
        }

        // 处理sticky广播
        if (sticky) {
            // sticky广播需要在manifest中声明BROADCAST_STICKY权限
            if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
                    callingPid, callingUid)
                    != PackageManager.PERMISSION_GRANTED) {
                String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
                        + callingPid + ", uid=" + callingUid
                        + " requires " + android.Manifest.permission.BROADCAST_STICKY;
                Slog.w(TAG, msg);
                throw new SecurityException(msg);
            }
            // Sticky广播不能有权限要求
            if (requiredPermissions != null && requiredPermissions.length > 0) {
                Slog.w(TAG, "Can't broadcast sticky intent " + intent
                        + " and enforce permissions " + Arrays.toString(requiredPermissions));
                return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
            }
            // Sticky广播必须有component
            if (intent.getComponent() != null) {
                throw new SecurityException(
                        "Sticky broadcasts can't target a specific component");
            }
            if (userId != UserHandle.USER_ALL) {
                // 校验对于当前的这个对单个user的广播 和现有的针对所有user的广播不冲突
                // 也就是说一个sticky广播不能同时针对单个user又针对user_all
                ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
                        UserHandle.USER_ALL);
                if (stickies != null) {
                    ArrayList<Intent> list = stickies.get(intent.getAction());
                    if (list != null) {
                        int N = list.size();
                        int i;
                        for (i=0; i<N; i++) {
                            if (intent.filterEquals(list.get(i))) {
                                throw new IllegalArgumentException(
                                        "Sticky broadcast " + intent + " for user "
                                        + userId + " conflicts with existing global broadcast");
                            }
                        }
                    }
                }
            }
            // 将sticky广播放入mStickyBroadcasts
            ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
            if (stickies == null) {
                stickies = new ArrayMap<>();
                mStickyBroadcasts.put(userId, stickies);
            }
            ArrayList<Intent> list = stickies.get(intent.getAction());
            if (list == null) {
                list = new ArrayList<>();
                stickies.put(intent.getAction(), list);
            }
            final int stickiesCount = list.size();
            int i;
            for (i = 0; i < stickiesCount; i++) {
                if (intent.filterEquals(list.get(i))) {
                    // 如果能找到对应的sticky广播,则进行替换
                    // 因为sticky广播是在注册者一注册就把最近的u一个发出去了
                    // 所以对于同一个sticky广播需要记录下,如果有重复,则替换
                    list.set(i, new Intent(intent));
                    break;
                }
            }
            if (i >= stickiesCount) {
                // 没有找到则添加
                list.add(new Intent(intent));
            }
        }

        int[] users;
        if (userId == UserHandle.USER_ALL) {
            // Caller wants broadcast to go to all started users.
            users = mUserController.getStartedUserArrayLocked();
        } else {
            // Caller wants broadcast to go to one specific user.
            users = new int[] {userId};
        }

        // 开始查找注册了这个广播的receiver
        List receivers = null;
        List<BroadcastFilter> registeredReceivers = null;
        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                 == 0) {
            // 查找静态注册的receiver,resolvedType在此查询时处生效
            receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
        }
        if (intent.getComponent() == null) {
            if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
                // 对于shell发送的user_all的广播
                for (int i = 0; i < users.length; i++) {
                    if (mUserController.hasUserRestriction(
                            UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
                        continue;
                    }
                    List<BroadcastFilter> registeredReceiversForUser =
                            mReceiverResolver.queryIntent(intent,
                                    resolvedType, false /*defaultOnly*/, users[i]);
                    if (registeredReceivers == null) {
                        registeredReceivers = registeredReceiversForUser;
                    } else if (registeredReceiversForUser != null) {
                        registeredReceivers.addAll(registeredReceiversForUser);
                    }
                }
            } else {
                // 默认情况下,只针对当前user注册的广播生效
                // 查找动态注册的广播
                registeredReceivers = mReceiverResolver.queryIntent(intent,
                        resolvedType, false /*defaultOnly*/, userId);
            }
        }

        // 如果带有FLAG_RECEIVER_REPLACE_PENDING
        // 表示如果这个广播还没有派发,则替换掉之前的广播
        final boolean replacePending =
                (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
        // 处理并行广播
        if (!ordered && NR > 0) {
            if (isCallerSystem) {
                // 对于系统发送的广播进行校验
                checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                        isProtectedBroadcast, registeredReceivers);
            }
            // 创建BroadcastRecord并入队
            final BroadcastQueue queue = broadcastQueueForIntent(intent);
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                    resultCode, resultData, resultExtras, ordered, sticky, false, userId);
            final boolean replaced = replacePending
                    && (queue.replaceParallelBroadcastLocked(r) != null);
            // 不需要替换的情况下,入队并派发
            if (!replaced) {
                queue.enqueueParallelBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
            registeredReceivers = null;
            NR = 0;
        }

        // Merge into one list.
        int ir = 0;
        if (receivers != null) {
            // 对特殊的广播,检查条件,不满足条件的从receiver的列表中移除
            String skipPackages[] = null;
            // ACTION_PACKAGE_ADDED广播
            if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
                    || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
                    || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
                Uri data = intent.getData();
                if (data != null) {
                    String pkgName = data.getSchemeSpecificPart();
                    if (pkgName != null) {
                        skipPackages = new String[] { pkgName };
                    }
                }
            } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
                skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
            }
            if (skipPackages != null && (skipPackages.length > 0)) {
                for (String skipPackage : skipPackages) {
                    if (skipPackage != null) {
                        int NT = receivers.size();
                        for (int it=0; it<NT; it++) {
                            ResolveInfo curt = (ResolveInfo)receivers.get(it);
                            if (curt.activityInfo.packageName.equals(skipPackage)) {
                                receivers.remove(it);
                                it--;
                                NT--;
                            }
                        }
                    }
                }
            }

            // 静态注册的广播可以在manifest中指定优先级
            // 根据priority进行排序,优先级高的排在前面
            int NT = receivers != null ? receivers.size() : 0;
            int it = 0;
            ResolveInfo curt = null;
            BroadcastFilter curr = null;
            // 如果是并行广播,经过前面处理,那此处NR就已经等于0了,等于只对静态注册的排序
            // 如果是串行广播,此处经过排序后合并
            while (it < NT && ir < NR) {
                if (curt == null) {
                    curt = (ResolveInfo)receivers.get(it);
                }
                if (curr == null) {
                    curr = registeredReceivers.get(ir);
                }
                if (curr.getPriority() >= curt.priority) {
                    receivers.add(it, curr);
                    ir++;
                    curr = null;
                    it++;
                    NT++;
                } else {
                    it++;
                    curt = null;
                }
            }
        }
        // 合并之后,如果动态注册的receiver中还有,则全部依次添加在后面
        while (ir < NR) {
            if (receivers == null) {
                receivers = new ArrayList();
            }
            receivers.add(registeredReceivers.get(ir));
            ir++;
        }

        if (isCallerSystem) {
            checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                    isProtectedBroadcast, receivers);
        }

        // 开始入队
        if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            // 根据广播是否带有fg的flag决定是要入前台广播队列还是后台广播队列
            BroadcastQueue queue = broadcastQueueForIntent(intent);
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId);
            // 如果需要替换之前的广播则进行查找并替换
            final BroadcastRecord oldRecord =
                    replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
            if (oldRecord != null) {
                // 如果替换了之前的广播,那么要执行之前广播的resultToReceiver
                if (oldRecord.resultTo != null) {
                    final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
                    try {
                        oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
                                oldRecord.intent,
                                Activity.RESULT_CANCELED, null, null,
                                false, false, oldRecord.userId);
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Failure ["
                                + queue.mQueueName + "] sending broadcast result of "
                                + intent, e);

                    }
                }
            } else {
                // 如果没有替换,则添加到有序队列,并开始调度
                queue.enqueueOrderedBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
        } else {
            // 没有找到receiver,仅仅记录
            if (intent.getComponent() == null && intent.getPackage() == null
                    && (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
            }
        }
        return ActivityManager.BROADCAST_SUCCESS;
    }

这段代码看起来很长,但是仔细捋一遍其中的大致流程其实也是很容易理解的

  1. 添加一些默认的flag
  2. user状态校验
  3. 如果要改变temp deviceidle名单,进行权限校验
  4. protectBroadcast的caller校验
  5. 特殊action广播特殊处理
  6. sticky广播处理
  7. 动态注册的并行广播处理入队
  8. 静态注册广播以及动态注册有序广播根据优先级排序后入队
  9. 开始调度
  1. 在AMS初始化的时候默认创建了两个队列,一个是前台广播队列,一个是后台广播队列
  2. 在每个队列中又有并行广播队列以及串行广播队列
  3. 有序广播队列的超时:前台广播队列10s,后台广播队列60s

3.4 BroadcastQueue.scheduleBroadcastsLocked

    // 广播调度开始
    public void scheduleBroadcastsLocked() {
        // 如果已经开始了就先return等待
        if (mBroadcastsScheduled) {
            return;
        }
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

3.5 BroadcastHandler.handleMessage

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BROADCAST_INTENT_MSG: {
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }

此处的handler的线程用的是ActivityManager线程

3.6 BroadcastQueue.processNextBroadcast

这个是广播调度派发的核心方法

    // 开始派发
    final void processNextBroadcast(boolean fromMsg) {
        synchronized(mService) {
            BroadcastRecord r;
            mService.updateCpuStats();
            if (fromMsg) {
                mBroadcastsScheduled = false;
            }
            // 首先派发并行广播
            while (mParallelBroadcasts.size() > 0) {
                r = mParallelBroadcasts.remove(0);
                r.dispatchTime = SystemClock.uptimeMillis();
                r.dispatchClockTime = System.currentTimeMillis();

                final int N = r.receivers.size();
                // 可以看到,并行广播的派发非常简单,直接一个for循环
                // deliverToRegisteredReceiverLocked中的处理还是比较简单的
                // 主要是进行了一系列权限的校验,之后调度到app进程
                for (int i=0; i<N; i++) {
                    Object target = r.receivers.get(i);
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
                }
                // 添加到广播历史记录
                addBroadcastToHistoryLocked(r);
            }

            // 这个是一个记录,如果在派发广播时需要启动进程的话,会用这个先记录下来
            // 等到进程启动之后再处理
            if (mPendingBroadcast != null) {
                boolean isDead;
                synchronized (mService.mPidsSelfLocked) {
                    ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
                    isDead = proc == null || proc.crashing;
                }
                // 如果进程不存在,retrun,继续等待
                // 在进程启动之后的attachApplication中会进行处理此广播
                // 后面的章节中会有Android进程管理部分,也会讲述此部分的处理
                if (!isDead) {
                    return;
                } else {
                    Slog.w(TAG, "pending app  ["
                            + mQueueName + "]" + mPendingBroadcast.curApp
                            + " died before responding to broadcast");
                    mPendingBroadcast.state = BroadcastRecord.IDLE;
                    mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
                    mPendingBroadcast = null;
                }
            }

            boolean looped = false;
            do {
                // 如果有序广播队列中已经没有需要派发的广播了
                // 说明所有广播已经派发完毕
                if (mOrderedBroadcasts.size() == 0) {
                    mService.scheduleAppGcsLocked();
                    if (looped) {
                        mService.updateOomAdjLocked();
                    }
                    return;
                }
                // 从有序广播队列中取出第一个
                r = mOrderedBroadcasts.get(0);
                boolean forceReceive = false;
                // 此处是判断这个广播的超时
                // 一个有序广播,所有的receiver的派发时间加起来
                // 不能大于2 * mTimeoutPeriod * numReceivers
                // mTimeoutPeriod是本广播队列的超时,前台广播队列10s,后台广播队列60s
                int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
                if (mService.mProcessesReady && r.dispatchTime > 0) {
                    long now = SystemClock.uptimeMillis();
                    if ((numReceivers > 0) &&
                            (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
                        Slog.w(TAG, "Hung broadcast ["
                                + mQueueName + "] discarded after timeout failure:"
                                + " now=" + now
                                + " dispatchTime=" + r.dispatchTime
                                + " startTime=" + r.receiverTime
                                + " intent=" + r.intent
                                + " numReceivers=" + numReceivers
                                + " nextReceiver=" + r.nextReceiver
                                + " state=" + r.state);
                        broadcastTimeoutLocked(false);
                        // 如果已经超时,那标志forceReceive
                        forceReceive = true;
                        r.state = BroadcastRecord.IDLE;
                    }
                }

                if (r.state != BroadcastRecord.IDLE) {
                    return;
                }
                // 这个广播没有更多的receiver了,或者被打断了
                // 或者被上面因为超时强制停止了
                // 此时需要直接执行resultReceiver(发送有序广播时指定的最后一个receiver)
                if (r.receivers == null || r.nextReceiver >= numReceivers
                        || r.resultAbort || forceReceive) {
                    if (r.resultTo != null) {
                        try {
                            performReceiveLocked(r.callerApp, r.resultTo,
                                new Intent(r.intent), r.resultCode,
                                r.resultData, r.resultExtras, false, false, r.userId);
                            r.resultTo = null;
                        } catch (RemoteException e) {
                            r.resultTo = null;
                            Slog.w(TAG, "Failure ["
                                    + mQueueName + "] sending broadcast result of "
                                    + r.intent, e);

                        }
                    }
                    // 已经在执行最后一个receiver了,取消超时的计时
                    cancelBroadcastTimeoutLocked();
                    // 记录到history
                    addBroadcastToHistoryLocked(r);
                    if (r.intent.getComponent() == null && r.intent.getPackage() == null
                            && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                        mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
                                r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
                    }
                    // 从有序广播队列中移除
                    mOrderedBroadcasts.remove(0);
                    r = null;
                    looped = true;
                    continue;
                }
            } while (r == null);
            // 经过了上面的do-while循环,取出来的就是马上要派发的广播了

            // 一个广播会有多个receiver,这个是用来记录当前派发的数量的
            int recIdx = r.nextReceiver++;
            r.receiverTime = SystemClock.uptimeMillis();
            // 这个广播第一次派发,记录时间
            if (recIdx == 0) {
                r.dispatchTime = r.receiverTime;
                r.dispatchClockTime = System.currentTimeMillis();
            }
            // 记录超时,超时后会触发ANR
            if (! mPendingBroadcastTimeoutMessage) {
                long timeoutTime = r.receiverTime + mTimeoutPeriod;
                setBroadcastTimeoutLocked(timeoutTime);
            }

            final BroadcastOptions brOptions = r.options;
            final Object nextReceiver = r.receivers.get(recIdx);
            // 说明这个receiver是一个动态注册的receiver
            // 进行派发,binder call到app进程
            if (nextReceiver instanceof BroadcastFilter) {
                BroadcastFilter filter = (BroadcastFilter)nextReceiver;
                deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
                if (r.receiver == null || !r.ordered) {
                    r.state = BroadcastRecord.IDLE;
                    scheduleBroadcastsLocked();
                } else {
                    // 需要设置deviceidle白名单就在此处设置
                    if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
                        scheduleTempWhitelistLocked(filter.owningUid,
                                brOptions.getTemporaryAppWhitelistDuration(), r);
                    }
                }
                return;
            }
            // 代码走到这里就说明这个receiver是静态注册的

            ResolveInfo info =
                (ResolveInfo)nextReceiver;
            ComponentName component = new ComponentName(
                    info.activityInfo.applicationInfo.packageName,
                    info.activityInfo.name);

            boolean skip = false;
            
            ...
            //这中间是一些权限的校验,此处不再罗列
            
            String targetProcess = info.activityInfo.processName;
            ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
                    info.activityInfo.applicationInfo.uid, false);
            // 这里也是权限的校验,但是这里比较重要,因为Android新版本的限制越来越多在此处判断
            // getAppStartModeLocked中会根据idle白名单,tmp名单,targetSdkVersion,appops权限等一些列校验
            // 后面会有专门章节介绍这块新增的权限校验,随着Android版本变化,此处的校验也越来越严格
            if (!skip) {
                final int allowed = mService.getAppStartModeLocked(
                        info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
                        info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false);
                if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                    if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
                        Slog.w(TAG, "Background execution disabled: receiving "
                                + r.intent + " to "
                                + component.flattenToShortString());
                        skip = true;
                        // // 在Android O上对后台app不允许接收广播的管控
                    } else if (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
                            || (r.intent.getComponent() == null
                                && r.intent.getPackage() == null
                                && ((r.intent.getFlags()
                                        & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
                                && !isSignaturePerm(r.requiredPermissions))) {
                        mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
                                component.getPackageName());
                        Slog.w(TAG, "Background execution not allowed: receiving "
                                + r.intent + " to "
                                + component.flattenToShortString());
                        skip = true;
                    }
                }
            }

            if (skip) {
            // 经过前面的校验,如果skip,则进行调度下一个
                r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
                r.receiver = null;
                r.curFilter = null;
                r.state = BroadcastRecord.IDLE;
                scheduleBroadcastsLocked();
                return;
            }

            r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
            r.state = BroadcastRecord.APP_RECEIVE;
            r.curComponent = component;
            r.curReceiver = info.activityInfo;
            if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
                scheduleTempWhitelistLocked(receiverUid,
                        brOptions.getTemporaryAppWhitelistDuration(), r);
            }

            // 因为广播在派发,设置package不能被stop
            try {
                AppGlobals.getPackageManager().setPackageStoppedState(
                        r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
            } catch (RemoteException e) {
            } catch (IllegalArgumentException e) {
                Slog.w(TAG, "Failed trying to unstop package "
                        + r.curComponent.getPackageName() + ": " + e);
            }

            // 此处判断这个receiver的进程是否存在,如果存在,那么在processCurBroadcastLocked派发
            if (app != null && app.thread != null && !app.killed) {
                try {
                    app.addPackage(info.activityInfo.packageName,
                            info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
                    processCurBroadcastLocked(r, app);
                    return;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when sending broadcast to "
                          + r.curComponent, e);
                } catch (RuntimeException e) {
                    Slog.wtf(TAG, "Failed sending broadcast to "
                            + r.curComponent + " with " + r.intent, e);
                    logBroadcastReceiverDiscardLocked(r);
                    finishReceiverLocked(r, r.resultCode, r.resultData,
                            r.resultExtras, r.resultAbort, false);
                    scheduleBroadcastsLocked();
                    // We need to reset the state if we failed to start the receiver.
                    r.state = BroadcastRecord.IDLE;
                    return;
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }

            // 如果进程不在,启动新的进程
            if ((r.curApp=mService.startProcessLocked(targetProcess,
                    info.activityInfo.applicationInfo, true,
                    r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
                    "broadcast", r.curComponent,
                    (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                            == null) {
                logBroadcastReceiverDiscardLocked(r);
                finishReceiverLocked(r, r.resultCode, r.resultData,
                        r.resultExtras, r.resultAbort, false);
                scheduleBroadcastsLocked();
                r.state = BroadcastRecord.IDLE;
                return;
            }

            // 记录需要处理的广播,在进程启动之后,进程attach到system server的时候处理
            mPendingBroadcast = r;
            mPendingBroadcastRecvIndex = recIdx;
        }
    }

这里是广播调度与派发的和讯流程,中间省略了一部分代码,但还是很长,总结一下流程如下:

  1. 派发并行广播
  2. 处理广播整体超时
  3. 处理resultReceiver
  4. 派发动态注册的串行广播(有序广播)
  5. 处理静态注册的串行广播(有序广播)
  6. 权限校验
  7. 进程在的情况下processCurBroadcastLocked
  8. 进程不在则启动进程,记录要处理的广播mPendingBroadcast

3.7 BroadcastQueue.deliverToRegisteredReceiverLocked

    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
        ...
        //权限校验,不做过多罗列
        if (mService.mPermissionReviewRequired) {
            if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName,
                    filter.owningUserId)) {
                r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
                return;
            }
        }

        r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;

        if (ordered) {
            r.receiver = filter.receiverList.receiver.asBinder();
            r.curFilter = filter;
            filter.receiverList.curBroadcast = r;
            r.state = BroadcastRecord.CALL_IN_RECEIVE;
            if (filter.receiverList.app != null) {
                r.curApp = filter.receiverList.app;
                filter.receiverList.app.curReceivers.add(r);
                mService.updateOomAdjLocked(r.curApp, true);
            }
        }
        try {
            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                if (ordered) {
                    skipReceiverLocked(r);
                }
            } else {
                // 执行receiver的派发
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
            }
            if (ordered) {
                r.state = BroadcastRecord.CALL_DONE_RECEIVE;
            }
        } catch (RemoteException e) {
            Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
            if (ordered) {
                r.receiver = null;
                r.curFilter = null;
                filter.receiverList.curBroadcast = null;
                if (filter.receiverList.app != null) {
                    filter.receiverList.app.curReceivers.remove(r);
                }
            }
        }
    }

这个方法中主要做了权限校验,然后派发

3.8 BroadcastQueue.performReceiveLocked

    void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
            Intent intent, int resultCode, String data, Bundle extras,
            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
        if (app != null) {
            if (app.thread != null) {
                try {
                    // 终于看到了binder call
                    // 此处经过binder call到了receiver所在进程
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);
                } catch (RemoteException ex) {
                    synchronized (mService) {
                        Slog.w(TAG, "Can't deliver broadcast to " + app.processName
                                + " (pid " + app.pid + "). Crashing it.");
                        app.scheduleCrash("can't deliver broadcast");
                    }
                    throw ex;
                }
            } else {
                throw new RemoteException("app.thread must not be null");
            }
        } else {
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
        }
    }

这个方法终于进行了binder call,到了app进程。

3.9 BroadcastQueue.processCurBroadcastLocked

    private final void processCurBroadcastLocked(BroadcastRecord r,
            ProcessRecord app) throws RemoteException {
        // app进程必须存在才可以派发
        if (app.thread == null) {
            throw new RemoteException();
        }
        if (app.inFullBackup) {
            skipReceiverLocked(r);
            return;
        }

        // 要派发之前,调整这个进程的优先级
        // 所以app在receiver执行的过程中优先级是很高的
        r.receiver = app.thread.asBinder();
        r.curApp = app;
        app.curReceivers.add(r);
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
        mService.updateLruProcessLocked(app, false, null);
        mService.updateOomAdjLocked();
        r.intent.setComponent(r.curComponent);

        boolean started = false;
        try {
            mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
                                      PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
            // binder call到app进程
            app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
                    mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
                    r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
                    app.repProcState);
            started = true;
        } finally {
            if (!started) {
                if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                        "Process cur broadcast " + r + ": NOT STARTED!");
                r.receiver = null;
                r.curApp = null;
                app.curReceivers.remove(r);
            }
        }
    }

上面这个方法是针对静态注册的广播,调度到其进程执行receiver。

3.10 ApplicationThread.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);
}

终于到了app的进程
从前面的处理流程可以知道,动态注册的receiver无论是并行还是串行最终调度都会到这里。
在注册的时候可以指定receiver的处理handler,如果没有指定才会用主线程。
这里就用到了之前注册时携带的binder对象innerReceiver.

3.11 InnerReceiver.performReceive

public void performReceive(Intent intent, int resultCode, String data,
        Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    final LoadedApk.ReceiverDispatcher rd;
    if (intent == null) {
        Log.wtf(TAG, "Null intent received");
        rd = null;
    } else {
        // innerReceiver是ReceiverDispatcher的内部类
        // innerReceiver保存了对dispatcher的弱饮用,在创建的时候就记录了receiverDisoatcher,此处取出
        rd = mDispatcher.get();
    }
    if (rd != null) {
        // receiverDisoatcher.performReceive
        rd.performReceive(intent, resultCode, data, extras,
                ordered, sticky, sendingUser);
    } else {
        IActivityManager mgr = ActivityManager.getService();
        try {
            if (extras != null) {
                extras.setAllowFds(false);
            }
            mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
        } catch (RemoteExceptin e) {
            throw e.rethrowFromSystemServer();
        }
    }
}

3.12 ReceiverDispatcher.performReceive

public void performReceive(Intent intent, int resultCode, String data,
        Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    final Args args = new Args(intent, resultCode, data, extras, ordered,
            sticky, sendingUser);
    ...
    if (intent == null || !mActivityThread.post(args.getRunnable())) {
        if (mRegistered && ordered) {
            IActivityManager mgr = ActivityManager.getService();
            args.sendFinished(mgr);
        }
    }

这个方法的重点在于mActivityThread.post(args.getRunnable())
不要被mActivityThread的名字迷惑,其实这是一个Handler,正是在广播动态注册的时候设置的那个handler
通过这个post,切换了线程,开始执行receiver。

3.13 Args.run

public final Runnable getRunnable() {
    return () -> {
        final BroadcastReceiver receiver = mReceiver;
        final boolean ordered = mOrdered;

        final IActivityManager mgr = ActivityManager.getService();
        final Intent intent = mCurIntent;

        mCurIntent = null;
        mDispatched = true;
        mPreviousRunStacktrace = new Throwable("Previous stacktrace");
        if (receiver == null || intent == null || mForgotten) {
            if (mRegistered && ordered) {
                // receiver为空直接发送finish
                sendFinished(mgr);
            }
            return;
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
        try {
            ClassLoader cl = mReceiver.getClass().getClassLoader();
            intent.setExtrasClassLoader(cl);
            intent.prepareToEnterProcess();
            setExtrasClassLoader(cl);
            receiver.setPendingResult(this);
            // 终于看到了熟悉的onReceive回调了
            receiver.onReceive(mContext, intent);
        } 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);
    };
}

到这里,终于看到了BroadcastReceiver的回调。
不过这只是动态注册的receiver,而且在动态注册的receiver执行完毕之后,如果是有序广播则还需要发送finish。
在处理有序广播的时候,前一个receiver处理完之后,可以留下一些信息,后面一个receiver在处理的时候可以根据这些信息做进一步的操作,而这些信息的传递正是通过getPendingResult

3.14 Args.finish

public final void finish() {
    if (mType == TYPE_COMPONENT) {
        final IActivityManager mgr = ActivityManager.getService();
        // 这个queuedwork前面讲sharedpreference的时候有重点提到
        // 这里就是在等待sp的写入完成
        if (QueuedWork.hasPendingWork()) {
            QueuedWork.queue(new Runnable() {
                @Override public void run() {
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing broadcast after work to component " + mToken);
                    sendFinished(mgr);
                }
            }, false);
        } else {
            sendFinished(mgr);
        }
    } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                "Finishing broadcast to " + mToken);
        final IActivityManager mgr = ActivityManager.getService();
        sendFinished(mgr);
    }

通过这里我们可以知道,在有序广播的执行流程中,还会去等待sp的写入文件完成,如果sp数据过大造成此处等待时间过长,是有可能造成广播anr的

3.15 ActivityThread.scheduleReceiver

public final void scheduleReceiver(Intent intent, ActivityInfo info,
        CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
        boolean sync, int sendingUser, int processState) {
    updateProcessState(processState, false);
    ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
            sync, false, mAppThread.asBinder(), sendingUser);
    r.info = info;
    r.compatInfo = compatInfo;
    sendMessage(H.RECEIVER, r);
}
H.handleMessage(Message msg){
    ...
    case RECEIVER:
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
        handleReceiver((ReceiverData)msg.obj);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        break;   
    ...
}

这里是Android app的基本机制了,几乎大多数从systemserver来的binder call都是通过applicationthread过来,然后经过切换线程到主线程中执行,此处正是这样。

3.15 ActivityThread.handleReceiver

    private void handleReceiver(ReceiverData data) {
        unscheduleGcIdler();

        String component = data.intent.getComponent().getClassName();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);

        IActivityManager mgr = ActivityManager.getService();

        Application app;
        BroadcastReceiver receiver;
        ContextImpl context;
        try {
            app = packageInfo.makeApplication(false, mInstrumentation);
            context = (ContextImpl) app.getBaseContext();
            if (data.info.splitName != null) {
                context = (ContextImpl) context.createContextForSplit(data.info.splitName);
            }
            java.lang.ClassLoader cl = context.getClassLoader();
            data.intent.setExtrasClassLoader(cl);
            data.intent.prepareToEnterProcess();
            data.setExtrasClassLoader(cl);
            receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
        } catch (Exception e) {
            data.sendFinished(mgr);
            throw new RuntimeException(
                "Unable to instantiate receiver " + component
                + ": " + e.toString(), e);
        }

        try {
            sCurrentBroadcastIntent.set(data.intent);
            receiver.setPendingResult(data);
            // 执行receiver的onReceive方法
            receiver.onReceive(context.getReceiverRestrictedContext(),
                    data.intent);
        } catch (Exception e) {
            if (DEBUG_BROADCAST) Slog.i(TAG,
                    "Finishing failed broadcast to " + data.intent.getComponent());
            data.sendFinished(mgr);
            if (!mInstrumentation.onException(receiver, e)) {
                throw new RuntimeException(
                    "Unable to start receiver " + component
                    + ": " + e.toString(), e);
            }
        } finally {
            sCurrentBroadcastIntent.set(null);
        }
        if (receiver.getPendingResult() != null) {
            data.finish();
        }
    }

这里就是静态注册的receiver在app这边的处理了,
从代码流程上看差距并不大,为什么静态注册要跟动态注册有区别呢?
重点在于动态注册的时候可以指定处理receiver的handler,而静态注册无法指定,因此只能用主线程处理

3.16 BroadcastReceiver.sendFinished

public void sendFinished(IActivityManager am) {
    synchronized (this) {
        if (mFinished) {
            throw new IllegalStateException("Broadcast already finished");
        }
        mFinished = true;
        try {
            if (mResultExtras != null) {
                mResultExtras.setAllowFds(false);
            }
            if (mOrderedHint) {
                am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
                        mAbortBroadcast, mFlags);
            } else {
                am.finishReceiver(mToken, 0, null, null, false, mFlags);
            }
        } catch (RemoteException ex) {
        }
    }

这里就比较简单了,一些简单的状态判断之后,发送消息到AMS,我这个receiver已经执行完毕了

3.17 BroadcastReceiver.sendFinished

public void finishReceiver(IBinder who, int resultCode, String resultData,
        Bundle resultExtras, boolean resultAbort, int flags) {
    if (resultExtras != null && resultExtras.hasFileDescriptors()) {
        throw new IllegalArgumentException("File descriptors passed in Bundle");
    }
    final long origId = Binder.clearCallingIdentity();
    try {
        boolean doNext = false;
        BroadcastRecord r;
        synchronized(this) {
            // 匹配相应的广播队列之后取出广播
            BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                    ? mFgBroadcastQueue : mBgBroadcastQueue;
            r = queue.getMatchingOrderedReceiver(who);
            if (r != null) {
                // finishReceiverLocked中置一些状态
                doNext = r.queue.finishReceiverLocked(r, resultCode,
                    resultData, resultExtras, resultAbort, true);
            }
        }
        // 进行下一轮的调度
        if (doNext) {
            r.queue.processNextBroadcast(false);
        }
        trimApplications();
    } finally {
        Binder.restoreCallingIdentity(origId);
    }

因为有序广播是逐个执行,所以前一个执行完之后,通过finish告诉AMS,我执行完了,可以进行下一轮的调度了,这样对于一个有序广播,可能会有多个接收者,就这样挨个执行下去。
广播的ANR也是针对有序广播才有的,为了避免前面有一个receiver执行的时间太久而耽误后面的receiver,所以广播超时机制也是很有必要的。

总结

整体上讲,广播从发送流程到派发搭配各个客户端的流程相对还是比较复杂的,重点在于其中多了很多特殊的校验和判断,但其实如果从大纲上来看主要流程如下:

  1. 发送广播
  2. 处理sticky广播(重点是替换以及存储)
  3. 如果是并行广播,收集receiver后,入队
  4. 如果是串行广播,收集静态注册的receiver,和动态注册的receiver一起根据优先级排序后,入队
  5. 开始派发
  6. 如果是并行广播,直接for循环逐个派发出去,且是异步binder call,可以认为基本所有receiver会同时收到
  7. 如果是串行广播,先派发动态注册的receiver
  8. 静态注册广播需要先看进程是否存在,存在则派发,不存在则启动进程
  9. 广播派发到客户端后,动态注册的receiver通过inndeRreceiver找到ReceiverDispatcher后找到相应handler执行
  10. 静态注册广播派发到客户端后主线程执行
  11. 如果是有序广播,则派发后还需要告诉ams,执行完毕,让ams开始这个广播下一个receiver的派发

版权声明:本文为u011733869原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。