从系统看Broadcast入队与分发流程

发送广播

app端发送广播最终都是调用ContentImpl中的sendBroadcast相关方法实现,最终binder调用AMS的broadcastIntentWithFeature方法实现。

发送普通广播

    @Override
    public void sendBroadcastAsUser(Intent intent, UserHandle user,
            String receiverPermission, int appOp) {
		// 解析MIME type
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
		// 将权限封装成数组
        String[] receiverPermissions = receiverPermission == null ? null
                : new String[] {receiverPermission};
        try {
            intent.prepareToLeaveProcess(this);
			// 调用AMS的接口
            ActivityManager.getService().broadcastIntentWithFeature(
                    mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                    null, Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false,
                    false, user.getIdentifier());
        } catch (RemoteException e) {
			// 抛出异常
            throw e.rethrowFromSystemServer();
        }
    }

发送有序广播

有序广播和无序广播主要区别在于可以指定广播的最后一个接收者resultReceiver,通过最后一个receiver可以知道广播派发完了,做一些收尾工作。

    @Override
    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
            String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
            Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
        IIntentReceiver rd = null;
		// 通过传入的resultReceiver获取IIntentReceiver 实例
        if (resultReceiver != null) {
            if (mPackageInfo != null) {
                if (scheduler == null) {
					// 获取主线程的handler
                    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();
            }
        }
		// 解析type,封装权限
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        String[] receiverPermissions = receiverPermission == null ? null
                : new String[] {receiverPermission};
        try {
            intent.prepareToLeaveProcess(this);
            ActivityManager.getService().broadcastIntentWithFeature(
                    mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                    rd, initialCode, initialData, initialExtras, receiverPermissions, appOp,
                    options, true, false, user.getIdentifier());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

入队广播

入队相关逻辑主要都在AMS的broadcastIntentLocked方法中。

参数解析

caller: 发送方的application thread对象
callingFeatureId: feature id
intent: 广播所带的intent
resolvedType: MIME type
resultTo: 最终接收的receiver
resultCode: 有序广播在一个receiver处理之后可以设置值,下一个receiver可以拿到这个值
resultData: 有序广播在一个receiver处理之后可以设置值,下一个receiver可以拿到这个值
resultExtras:有序广播在一个receiver处理之后可以设置值,下一个receiver可以拿到这个值
serialized:是否为有序广播
sticky:是否为sticky广播
userId:这个广播要发送到的user

  • 校验是否是隔离进程,是就抛出异常
  • 验证广播是否合理,不合理抛出异常
  • 清除calling uid,避免权限校验失败
  • 调用broadcastIntentLocked执行入队逻辑
  • 恢复calling uid
    public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
            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);
			// 通过caller获取调用端进程
            final ProcessRecord callerApp = getRecordForAppLocked(caller);
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
			// 清除calling uid,避免权限校验失败
            final long origId = Binder.clearCallingIdentity();
            try {
                return broadcastIntentLocked(callerApp,
                        callerApp != null ? callerApp.info.packageName : null, callingFeatureId,
                        intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                        requiredPermissions, appOp, bOptions, serialized, sticky,
                        callingPid, callingUid, callingUid, callingPid, userId);
            } finally {
				// 恢复calling uid
                Binder.restoreCallingIdentity(origId);
            }
        }
    }

特殊情况处理

需要添加特殊flag
  1. caller是即时app,不允许当前广播派发给即时app,~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS
  2. 默认任何广播不会派发给stop状态的app(安装后未被启动过,或者被force stop过处于stop状态),FLAG_EXCLUDE_STOPPED_PACKAGES
  3. 系统未启动完,不允许拉起静态注册app的进程,需要添加FLAG_RECEIVER_REGISTERED_ONLY,只允许动态注册的receier接收
发送广播app所处user不在运行状态,终止广播入队

以下情况除外

  • 调用者uid为system uid且没有添加FLAG_RECEIVER_BOOT_UPGRADE
  • 关机广播
非系统特殊uid不允许发送受保护的广播

主要是root/system/phone/bluetooth/nfc这些uid 可以发送

组件相关的ACTION_APPWIDGET_CONFIGURE和ACTION_APPWIDGET_UPDATE广播
  • caller不能为null
  • 如果是显示广播,发送者和接收者的package需要保持一致
  • 如果是隐式广播,接收者package跟发送者package一致
尝试添加FLAG_RECEIVER_INCLUDE_BACKGROUND

allow-implicit-broadcast 列表内的action会添加flag FLAG_RECEIVER_INCLUDE_BACKGROUND,允许这些隐式广播被后台进程接收,后拉起进程。

一些特殊的系统广播处理(package相关等)
sticky广播的处理
  • 发送stikcy广播的caller需要拥有BROADCAST_STICKY权限,否则抛出异常
  • stiky广播不能拥有权限
  • sticky广播不能为显示广播
  • sticky广播不能同时针对单个user又针对user_all

入队分发

收集广播接收者
  1. 收集静态注册者(flag中无FLAG_RECEIVER_REGISTERED_ONLY)
  2. 收集动态注册者(隐式广播)
  3. 不在广播百名单的uid列表且uid > 10000的receiver,从动态注册者中移除
动态注册的无序广播入队分发
  1. 系统广播校验
  2. 不需要替换的情况入队分发
静态注册无序广播和有序广播入队分发

静态注册的无序广播当作有序广播入队分发,避免一次拉起太多进程。

  1. 按优先级整合动态注册和静态注册的接收者receivers
  2. 校验系统发送的广播
  3. 替换之前的广播,且为有序广播,分发广播到resultTo
  4. 不需要替换则入队并分发
没有对应的receivers且为隐式广播,则仅仅记录
    @GuardedBy("this")
    final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,
            @Nullable String callerFeatureId, 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 realCallingUid,
            int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
            @Nullable int[] broadcastWhitelist) {
        intent = new Intent(intent);
		//caller 是即时app的处理
        final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
        if (callerInstantApp) {
            intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
        }
		// 非系统发送的广播,broadcastWhitelist一般为null
        if (userId == UserHandle.USER_ALL && broadcastWhitelist != null) {
                Slog.e(TAG, "broadcastWhitelist only applies when sending to individual users. "
                        + "Assuming restrictive whitelist.");
                broadcastWhitelist = new int[]{};
        }

        // By default broadcasts do not go to stopped apps.
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

        // 系统未启动完成,一般不允许拉起新的进程,所以只允许动态注册的接收该广播
        if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
        }
		// 非有序广播不能指定分发者IIntentReceiver
        if ((resultTo != null) && !ordered) {
            Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
        }

        userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                ALLOW_NON_FULL, "broadcast", callerPackage);

        //  当前user不在运行中,终止入队
        if (userId != UserHandle.USER_ALL && !mUserController.isUserOrItsParentRunning(userId)) {
            if ((callingUid != SYSTEM_UID
                    || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
                    && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
                Slog.w(TAG, "Skipping broadcast of " + intent
                        + ": user " + userId + " and its parent (if any) are stopped");
                return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
            }
        }

        final String action = intent.getAction();
        BroadcastOptions brOptions = null;
		// bOptions一般为null,会改变device idle的临时白名单,需要检查caller是否有改变临时白名单的权限
        if (bOptions != null) {
            brOptions = new BroadcastOptions(bOptions);
            if (brOptions.getTemporaryAppWhitelistDuration() > 0) {
                if (checkComponentPermission(
                        android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
                        realCallingPid, realCallingUid, -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);
                }
            }
            if (brOptions.isDontSendToRestrictedApps()
                    && !isUidActiveLocked(callingUid)
                    && isBackgroundRestrictedNoCheck(callingUid, callerPackage)) {
                Slog.i(TAG, "Not sending broadcast " + action + " - app " + callerPackage
                        + " has background restrictions");
                return ActivityManager.START_CANCELED;
            }
            if (brOptions.allowsBackgroundActivityStarts()) {
                // See if the caller is allowed to do this.  Note we are checking against
                // the actual real caller (not whoever provided the operation as say a
                // PendingIntent), because that who is actually supplied the arguments.
                if (checkComponentPermission(
                        android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
                        realCallingPid, realCallingUid, -1, true)
                        != PackageManager.PERMISSION_GRANTED) {
                    String msg = "Permission Denial: " + intent.getAction()
                            + " broadcast from " + callerPackage + " (pid=" + callingPid
                            + ", uid=" + callingUid + ")"
                            + " requires "
                            + android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
                    Slog.w(TAG, msg);
                    throw new SecurityException(msg);
                } else {
                    allowBackgroundActivityStarts = true;
                }
            }
        }

       // 判断是否是保护广播
        final boolean isProtectedBroadcast;
        try {
            isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
        } catch (RemoteException e) {
            Slog.w(TAG, "Remote exception", e);
            return ActivityManager.BROADCAST_SUCCESS;
        }

        final boolean isCallerSystem;
        // 判断广播是否来自system
        switch (UserHandle.getAppId(callingUid)) {
            case ROOT_UID:
            case SYSTEM_UID:
            case PHONE_UID:
            case BLUETOOTH_UID:
            case NFC_UID:
            case SE_UID:
            case NETWORK_STACK_UID:
                isCallerSystem = true;
                break;
            default:
                // MIUI MOD
                // isCallerSystem = (callerApp != null) && callerApp.isPersistent();
                isCallerSystem = false;
                break;
        }

        // First line security check before anything else: stop non-system apps from
        // sending protected broadcasts.
       
        if (!isCallerSystem) {
			// 非系统特殊uid不允许发送保护广播
            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) {
                   // 显示广播要求发送者和接收者的package一致
                    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);
                }
            }
        }

        boolean timeoutExempt = false;

        if (action != null) {
			// allow-implicit-broadcast 列表内的action会添加flagFLAG_RECEIVER_INCLUDE_BACKGROUND
            if (getBackgroundLaunchBroadcasts().contains(action)) {
                intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            }
			// 一些特殊的系统广播处理
		}

        // 处理sticky广播
        if (sticky) {
			// 发送stikcy广播的app需要声明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;
            }
			// stikcy广播不能为显式广播
            if (intent.getComponent() != null) {
                throw new SecurityException(
                        "Sticky broadcasts can't target a specific component");
            }
           // sticky广播不能针对单个user又针对所有user
            if (userId != UserHandle.USER_ALL) {
                // But first, if this is not a broadcast to all users, then
                // make sure it doesn't conflict with an existing broadcast to
                // all users.
                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))) {
                    // 替换
                    list.set(i, new Intent(intent));
                    break;
                }
            }
            if (i >= stickiesCount) {
				//没替换则新增
                list.add(new Intent(intent));
            }
        }

        int[] users;
        if (userId == UserHandle.USER_ALL) {
            users = mUserController.getStartedUserArray();
        } else {
            users = new int[] {userId};
        }

        // Figure out who all will receive this broadcast.
        List receivers = null;
        List<BroadcastFilter> registeredReceivers = null;
        // 收集静态注册的receivers,resolvedType 在此处生效
        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                 == 0) {
            receivers = collectReceiverComponents(
                    intent, resolvedType, callingUid, users, broadcastWhitelist);
        }
		// 隐式广播
        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 {
				// 查找动态注册的广播
                registeredReceivers = mReceiverResolver.queryIntent(intent,
                        resolvedType, false /*defaultOnly*/, userId);
            }
        }
		// 表示这个广播还没有派发,则替换掉之前的广播
        final boolean replacePending =
                (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;

        if (registeredReceivers != null && broadcastWhitelist != null) {
            // 不在广播百名单的uid列表且uid > 10000的receiver,从动态注册者中移除
            for (int i = registeredReceivers.size() - 1; i >= 0; i--) {
                final int owningAppId = UserHandle.getAppId(registeredReceivers.get(i).owningUid);
                if (owningAppId >= Process.FIRST_APPLICATION_UID
                        && Arrays.binarySearch(broadcastWhitelist, owningAppId) < 0) {
                    registeredReceivers.remove(i);
                }
            }
        }
		// 动态注册的广播
        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
		// 处理并行广播
        if (!ordered && NR > 0) {
            if (isCallerSystem) {
				// 对系统发送的广播进行校验
                checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                        isProtectedBroadcast, registeredReceivers);
            }
			// 根据intent的flag获取广播队列,负载队列或前台队列或后台队列
            final BroadcastQueue queue = broadcastQueueForIntent(intent);
			// 创建广播对象
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                    callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                    resultCode, resultData, resultExtras, ordered, sticky, false, userId,
                    allowBackgroundActivityStarts, timeoutExempt);
			// 根据需要替换无序广播
            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) {
            // 移除一些静态注册的广播接收者
            String skipPackages[] = null;
			// package相关广播
            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 };
                    }
                }
			// ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
            } 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;
			// 有序广播的动态注册receivers和静态注册的receivers
			// 无序广播的静态注册receivers
			// 下面这个循环就是一个动态,静态receiver排序后插入的过程,最终都在receivers中
            while (it < NT && ir < NR) {
				// 静态注册获取resolver info
                if (curt == null) {
                    curt = (ResolveInfo)receivers.get(it);
                }
				// 动态注册获取broadcast filter
                if (curr == null) {
                    curr = registeredReceivers.get(ir);
                }
				// 动态优先级大于静态优先级,插入到receivers中,继续循环
                if (curr.getPriority() >= curt.priority) {
                    receivers.add(it, curr);
                    ir++;
                    curr = null;
                    it++;
                    NT++;
                } else {
                    // 将当前动态跟下一个静态相比,就是一个插入排序的过程
                    it++;
                    curt = null;
                }
            }
        }
		// 合并之后。如果动态注册的receivers还有,全部添加到receivers后面
        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) {
			// 获取广播队列,前台后后台队列
            BroadcastQueue queue = broadcastQueueForIntent(intent);
			// 创建广播对象
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                    callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId,
                    allowBackgroundActivityStarts, timeoutExempt);
			// 如果需要替换之前的广播则查找并替换
            final BroadcastRecord oldRecord =
                    replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
            if (oldRecord != null) {
                // 如果替换了之前的广播,且是有序广播,则需要执行之前广播的result to receiver
                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) {
                // This was an implicit broadcast... let's record it for posterity.
                addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
            }
        }

        return ActivityManager.BROADCAST_SUCCESS;
    }


分发广播

广播调度分发逻辑主要在BroadcastQueue中且是异步的,由binder线程转到main线程中执行

	// 广播调度开始
    public void scheduleBroadcastsLocked() {
		// 如果已经开始就返回
        if (mBroadcastsScheduled) {
            return;
        }
		// 发送BROADCAST_INTENT_MSG消息
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }
	// main线程
    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: {
				    // 处理广播
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
						// 处理广播超时
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
    }

广播分发调度的核心方法如下:

无序广播的派发

  1. 设置派发时间
  2. for循环派发,几乎同时派发到各个app进程
  3. 添加到广播历史记录
mPendingBroadcat广播的处理

一般是派发静态注册的receiver时,app进程不存在,会先去拉起进程,等进程拉起后调用sendPendingBroadcastsLocked去处理pending的广播
这里判断进程是否死亡,未死亡直接返回;
死亡则将

  • 当前广播状态置为idle状态
  • pending广播的索引向后移
  • 重置mPendingBroadcat为null

有序广播派发

循环获取需要处理的有序广播

1.若没有需要处理的有序广播,直接返回
2.处理广播的整体超时
有序广播派发中,若当前时间距离派发时间超过 2 * mConstants.TIMEOUT * numReceivers,则标记forceReceive为true,强制结束这个广播
3. 获取到的广播状态不为idle,直接返回
4. 当前广播派发完或终止或2中的forceReceive为true
- 尝试派发有序广播的最后一个接收者
- 取消超时计算
- 添加到广播的历史记录中
- 重新循环
5. 延时广播的处理,重新循环
取到要处理的广播后,通过receiverTime发送超时消息,10s或60s内未取消触发anr

分发到动态注册的receiver

通过deliverToRegisteredReceiverLocked派发动态注册的广播,权限相关校验等也在这个方法中。

分发到静态注册的receiver
  1. 是否跳过本次分发的判断
    分发广播到静态接收者,会有一系列权限校验或特殊情况的处理。
    比较典型的是android o不允许后台app不允许接收隐式广播。
    如果skip为true,跳过分发到app,则重置一些状态:
    • delivery[recIdx]设为DELIVERY_SKIPPED 表示当前跳过当前receiver的分发
    • receiver 设为null,表示广播当前没有要派发的receiver
    • manifestSkipCount++,表示跳过静态接收者的数量+1
    • 重置广播状态为idle,便于下一次分发
  2. 派发之前,设置一些状态:
    • manifestCount++,表示派发到静态接收者数量+1
    • delivery[recIdx] 设为DELIVERY_DELIVERED,表示当前receiver正常派发到
    • state设为APP_RECEIVE,表示当前正在派发到静态接收者,完成之前不允许下一次派发
    • curReceiver 设为对应的activityInfo
    • 设置receiver的package不允许stop
  3. 进程存在,通过processCurBroadcastLocked派发静态注册的广播
  4. 进程不存在,先启动进程,将当前广播赋值给mPendingBroadcast,等待进程启动后继续派发
    final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
        BroadcastRecord r;
		// 更新cpu统计
        mService.updateCpuStats();
		// 重置mBroadcastsScheduled
        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循环派发到app进程
            for (int i=0; i<N; i++) {
                Object target = r.receivers.get(i);
                deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
            }
			// 添加到广播历史记录
            addBroadcastToHistoryLocked(r);
        }

        // mPendingBroadcast表示派发广播时需要启动进程,会先用这个记录下来,等进程启动后处理
		// 静态注册可能需要拉起进程
        if (mPendingBroadcast != null) {
            boolean isDead;
			// 判断mPendingBroadcast广播的当前进程是否死亡
            if (mPendingBroadcast.curApp.pid > 0) {
                synchronized (mService.mPidsSelfLocked) {
                    ProcessRecord proc = mService.mPidsSelfLocked.get(
                            mPendingBroadcast.curApp.pid);
                    isDead = proc == null || proc.isCrashing();
                }
            } else {
                final ProcessRecord proc = mService.mProcessList.mProcessNames.get(
                        mPendingBroadcast.curApp.processName, mPendingBroadcast.curApp.uid);
                isDead = proc == null || !proc.pendingStart;
            }
			// 当前进程未死亡,继续等待
            if (!isDead) {
                return;
            } else {
            	// 否则将广播状态置为idle,receiver索引移到下一位
                mPendingBroadcast.state = BroadcastRecord.IDLE;
                mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
                mPendingBroadcast = null;
            }
        }

        boolean looped = false;

        do {
            final long now = SystemClock.uptimeMillis();
			// 获取当前需要处理的有序广播
            r = mDispatcher.getNextBroadcastLocked(now);
			// 若无需要处理的有序广播,
            if (r == null) {
                mDispatcher.scheduleDeferralCheckLocked(false);
                mService.scheduleAppGcsLocked();
                if (looped) {
                    mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
                }

                if (mService.mUserController.mBootCompleted && mLogLatencyMetrics) {
                    mLogLatencyMetrics = false;
                }

                return;
            }

            boolean forceReceive = false;

            //获取接收者
            int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
			// timeoutExempt表示当前广播不受接收器超时的限制,如开机广播等
			// 系统已经就绪,广播已经分发过
            if (mService.mProcessesReady && !r.timeoutExempt && r.dispatchTime > 0) {
				// 一个有序广播,所有的receivers派发时间加起来不得大于 2倍的单个派发超时时间(前台10s,后台60s)*receiver的数量
                if ((numReceivers > 0) && (now > r.dispatchTime + (2 * mConstants.TIMEOUT * 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); // forcibly finish this broadcast
					// 标记forceReceive为true,当前广播状态标记为idle
                    forceReceive = true;
                    r.state = BroadcastRecord.IDLE;
                }
            }
			
			// 如果当前广播状态不是idle,退出这个循环
            if (r.state != BroadcastRecord.IDLE) {
                return;
            }

            // 当前广播已经派发完,被终止,或者上面的超时停止了
            if (r.receivers == null || r.nextReceiver >= numReceivers
                    || r.resultAbort || forceReceive) {
                // 有序广播的最终接收者
                if (r.resultTo != null) {
                    boolean sendResult = true;

                    // 如果当前广播拆分/延迟广播,更新引用计数
                    if (r.splitToken != 0) {
                        int newCount = mSplitRefcounts.get(r.splitToken) - 1;
						// 移除计数
                        if (newCount == 0) {
                            mSplitRefcounts.delete(r.splitToken);
                        } else {
                            // 若还有一些拆分的广播,更新引用计数,并延迟回调
                            sendResult = false;
                            mSplitRefcounts.put(r.splitToken, newCount);
                        }
                    }
					// 派发有序广播的最后一个receiver
                    if (sendResult) {
                        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);
                        }
                    }
                }
				// 广播派发完了,取消超时计算
				cancelBroadcastTimeoutLocked();
                // 将当前广播添加到历史记录中
                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);
                }
				// 处理完当前广播,重新循环
                mDispatcher.retireBroadcastLocked(r);
                r = null;
                looped = true;
                continue;
            }

            // Check whether the next receiver is under deferral policy, and handle that
            // accordingly.  If the current broadcast was already part of deferred-delivery
            // tracking, we know that it must now be deliverable as-is without re-deferral.
            if (!r.deferred) {
                final int receiverUid = r.getReceiverUid(r.receivers.get(r.nextReceiver));
                if (mDispatcher.isDeferringLocked(receiverUid)) {
                
                    // If this is the only (remaining) receiver in the broadcast, "splitting"
                    // doesn't make sense -- just defer it as-is and retire it as the
                    // currently active outgoing broadcast.
                    BroadcastRecord defer;
                    if (r.nextReceiver + 1 == numReceivers) {
                      
                        defer = r;
                        mDispatcher.retireBroadcastLocked(r);
                    } else {
                        // Nontrivial case; split out 'uid's receivers to a new broadcast record
                        // and defer that, then loop and pick up continuing delivery of the current
                        // record (now absent those receivers).

                        // The split operation is guaranteed to match at least at 'nextReceiver'
                        defer = r.splitRecipientsLocked(receiverUid, r.nextReceiver);
                      
                        // Track completion refcount as well if relevant
                        if (r.resultTo != null) {
                            int token = r.splitToken;
                            if (token == 0) {
                                // first split of this record; refcount for 'r' and 'deferred'
                                r.splitToken = defer.splitToken = nextSplitTokenLocked();
                                mSplitRefcounts.put(r.splitToken, 2);
                                
                            } else {
                                // new split from an already-refcounted situation; increment count
                                final int curCount = mSplitRefcounts.get(token);
                             
                                mSplitRefcounts.put(token, curCount + 1);
                               
                            }
                        }
                    }
                    mDispatcher.addDeferredBroadcast(receiverUid, defer);
                    r = null;
                    looped = true;
                    continue;
                }
            }
        } while (r == null);

        //经过上面的循环,取到了一个需要派发的广播
		// 广播的receiver索引赋值给recIdx,随后自增1
        int recIdx = r.nextReceiver++;

        // 赋值receiverTime,计算超时需要
        r.receiverTime = SystemClock.uptimeMillis();
		// 如果第一次分发,赋值广播的派发时间
        if (recIdx == 0) {
            r.dispatchTime = r.receiverTime;
            r.dispatchClockTime = System.currentTimeMillis();
        }
		// 发送超时消息,10s或60s后未取消则触发anr
        if (! mPendingBroadcastTimeoutMessage) {
            long timeoutTime = r.receiverTime + mConstants.TIMEOUT;
            setBroadcastTimeoutLocked(timeoutTime);
        }

        final BroadcastOptions brOptions = r.options;
		// 获取下一个需要派发的receiver
        final Object nextReceiver = r.receivers.get(recIdx);
		// 如果是动态注册的receiver
        if (nextReceiver instanceof BroadcastFilter) {
            BroadcastFilter filter = (BroadcastFilter)nextReceiver;
        	// 进行分发,binder到app进程执行
            deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
			//广播的receiver为null代表当前分发完成则继续分发下一轮
            if (r.receiver == null || !r.ordered) {
				//重置广播状态,开始下一轮
                r.state = BroadcastRecord.IDLE;
                scheduleBroadcastsLocked();
            } else {
                if (filter.receiverList != null) {
                    maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
                }
				// 需要设置device idle百名单在此设置
                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;
     
		.......
       // 一些特殊情况会跳过分发
        if (r.curApp != null && r.curApp.isCrashing()) {
            Slog.w(TAG, "Skipping deliver ordered [" + mQueueName + "] " + r
                    + " to " + r.curApp + ": process crashing");
            skip = true;
        }
        if (!skip) {
            boolean isAvailable = false;
            try {
                isAvailable = AppGlobals.getPackageManager().isPackageAvailable(
                        info.activityInfo.packageName,
                        UserHandle.getUserId(info.activityInfo.applicationInfo.uid));
            } catch (Exception e) {
                // all such failures mean we skip this receiver
                Slog.w(TAG, "Exception getting recipient info for "
                        + info.activityInfo.packageName, e);
            }
            if (!isAvailable) {
                skip = true;
            }
        }

        if (!skip) {
            if (!requestStartTargetPermissionsReviewIfNeededLocked(r,
                    info.activityInfo.packageName, UserHandle.getUserId(
                            info.activityInfo.applicationInfo.uid))) {
                skip = true;
            }
        }

     .......
        if (!skip) {
            final int allowed = mService.getAppStartModeLocked(
                    info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
                  info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false, false);
            if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
               // android O 上对后台app不允许接收广播的管控
                if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
                    Slog.w(TAG, "Background execution disabled: receiving "
                            + r.intent + " to "
                            + component.flattenToShortString());
                    skip = true;
                } 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 && !Intent.ACTION_SHUTDOWN.equals(r.intent.getAction())
                && !mService.mUserController
                .isUserRunning(UserHandle.getUserId(info.activityInfo.applicationInfo.uid),
                        0 /* flags */)) {
            skip = true;
            Slog.w(TAG,
                    "Skipping delivery to " + info.activityInfo.packageName + " / "
                            + info.activityInfo.applicationInfo.uid + " : user is not running");
        }
		// 如果跳过,继续下一轮的派发
        if (skip) {
            r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
            r.receiver = null;
            r.curFilter = null;
            r.state = BroadcastRecord.IDLE;
            r.manifestSkipCount++;
            scheduleBroadcastsLocked();
            return;
        }
        r.manifestCount++;

        r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
		// 设置当前广播的状态
        r.state = BroadcastRecord.APP_RECEIVE;
        r.curComponent = component;
        r.curReceiver = info.activityInfo;
      
        final boolean isActivityCapable =
                (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0);
        if (isActivityCapable) {
            scheduleTempWhitelistLocked(receiverUid,
                    brOptions.getTemporaryAppWhitelistDuration(), r);
        }

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

        // 如果当前进程存在,则在processCurBroadcastLocked中派发
        if (app != null && app.thread != null && !app.killed) {
            try {
                app.addPackage(info.activityInfo.packageName,
                        info.activityInfo.applicationInfo.longVersionCode, mService.mProcessStats);
                maybeAddAllowBackgroundActivityStartsToken(app, r);
                processCurBroadcastLocked(r, app, skipOomAdj);
                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();
                r.state = BroadcastRecord.IDLE;
                return;
            }    
        }
		// 如果进程不存在,启动新的进程
        if ((r.curApp=mService.startProcessLocked(targetProcess,
                info.activityInfo.applicationInfo, true,
                r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
                new HostingRecord("broadcast", r.curComponent),
                isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY,
                (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                        == null) {
           // app 短时间crash多次会导致进程启动失败
			// 结束派发,继续下一轮派发
            Slog.w(TAG, "Unable to launch app "
                    + info.activityInfo.applicationInfo.packageName + "/"
                    + receiverUid + " for broadcast "
                    + r.intent + ": process is bad");
            logBroadcastReceiverDiscardLocked(r);
            finishReceiverLocked(r, r.resultCode, r.resultData,
                    r.resultExtras, r.resultAbort, false);
            scheduleBroadcastsLocked();
            r.state = BroadcastRecord.IDLE;
            return;
        }
		// 启动新的进程,将当前广播赋值给mPendingBroadcast,等进程启动后继续派发
        maybeAddAllowBackgroundActivityStartsToken(r.curApp, r);
        mPendingBroadcast = r;
        mPendingBroadcastRecvIndex = recIdx;
    }

分发广播到app进程

分发到动态注册的接收者

    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
        boolean skip = false;
		......
        // 一些权限的校验

        if (!skip && (filter.receiverList.app == null || filter.receiverList.app.killed
                || filter.receiverList.app.isCrashing())) {
            Slog.w(TAG, "Skipping deliver [" + mQueueName + "] " + r
                    + " to " + filter.receiverList + ": process gone or crashing");
            skip = true;
        }

        .......
		// 跳过,将当前动态接收者分发状态标为DELIVERY_SKIPPED
        if (skip) {
            r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
            return;
        }

       .......
		
		//设置当前receiver的处理状态,表示已经分发到app进程
        r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;
		// 如果是有序广播,相关属性赋值
        if (ordered) {
			// 记录当前正在处理的receiver
            r.receiver = filter.receiverList.receiver.asBinder();
			// 记录当前处理的那个IntentFilter,(因为一个客户端有可能有多个IntentFilter)
            r.curFilter = filter;
            filter.receiverList.curBroadcast = r;
			// 当前广播有正在派发的app
            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,
                        OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
            }
        }
    
        try {
          	// 接收端进程正在被份
            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                // 且是有序广播,则结束当前派发,并开始下一轮派发
                if (ordered) {
                    skipReceiverLocked(r);
                }
            } else {
				// 赋值receiverTime,用于计算超时时间,触发anr等
                r.receiverTime = SystemClock.uptimeMillis();
                maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
				// 派发到app进程
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
             
                if (r.allowBackgroundActivityStarts && !r.ordered) {
                    postActivityStartTokenRemoval(filter.receiverList.app, r);
                }
            }
			// 有序广播,表示当前已经派发到app端
            if (ordered) {
                r.state = BroadcastRecord.CALL_DONE_RECEIVE;
            }
        } catch (RemoteException e) {
            Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
            // Clean up ProcessRecord state related to this broadcast attempt
            if (filter.receiverList.app != null) {
                filter.receiverList.app.removeAllowBackgroundActivityStartsToken(r);
                if (ordered) {
                    filter.receiverList.app.curReceivers.remove(r);
                }
            }
            // And BroadcastRecord state related to ordered delivery, if appropriate
            if (ordered) {
                r.receiver = null;
                r.curFilter = null;
                filter.receiverList.curBroadcast = null;
            }
        }
    }
    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) {
               // 进程存在,binder到app端去执行
                try {
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
                } 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);
        }
    }

分发到静态注册的接收者

    private final void processCurBroadcastLocked(BroadcastRecord r,
            ProcessRecord app, boolean skipOomAdj) throws RemoteException {
        // 进程不存在,抛出异常
        if (app.thread == null) {
            throw new RemoteException();
        }
		// app进程在备份,则结束派发,并开始下一轮派发
        if (app.inFullBackup) {
            skipReceiverLocked(r);
            return;
        }
		// 这个只有在有序广播和静态注册时才赋值
        r.receiver = app.thread.asBinder();
        r.curApp = app;
        app.curReceivers.add(r);
      	// 将app的进程提升到PROCESS_STATE_RECEIVER(11),一般执行完后优先级就可能会掉下去
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
        mService.mProcessList.updateLruProcessLocked(app, false, null);
        if (!skipOomAdj) {
            mService.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
        }

        // Tell the application to launch this receiver.
        r.intent.setComponent(r.curComponent);

        boolean started = false;
        try {
          
            mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
                                      PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
			// binder到app端去执行
            app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
                    mService.compatibilityInfoForPackage(r.curReceiver.applicationInfo),
                    r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
                    app.getReportedProcState());
            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);
            }
        }
    }

无序广播的动态注册入队平行广播队列,所以分发也只针对动态注册的方式分发
在这里插入图片描述

无序广播的静态注册入队有序广播队列

在这里插入图片描述
动态注册的广播的派发
在这里插入图片描述

静态注册的广播默认都以有序广播的形式派发

在这里插入图片描述
有序广播才有10-12的过程,有序队列的静态注册的无序广播没有这个过程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
BroadcastReceiver 可以分为两类:普通广播(Normal Broadcast)和有序广播(Ordered Broadcast)。 1. 普通广播(Normal Broadcast): 普通广播是一种完全异步的广播方式,BroadcastReceiver 接收到广播后,会以并发的方式将广播消息发送给所有匹配的 BroadcastReceiver,各个接收者之间没有先后顺序,无法拦截或修改广播。这种广播方式适用于不需要有序处理的场景,比如向多个组件发送通知等。 2. 有序广播(Ordered Broadcast): 有序广播是一种按照优先级顺序依次传递的广播方式,BroadcastReceiver 接收到广播后,可以中断广播或者修改广播内容,然后将广播继续传递给下一个接收者。有序广播通过 setPriority() 方法设置接收者的优先级,优先级高的接收者会先接收到广播。这种广播方式适用于需要有序处理的场景,比如短信拦截、系统事件处理等。 BroadcastReceiver 的工作原理如下: 1. 当发送一个广播时,系统会将广播消息封装为 Intent 对象。 2. 系统会根据 Intent 的 action 和 category 来匹配符合条件的 BroadcastReceiver。 3. 对于普通广播,系统会并发地将广播消息发送给所有匹配的 BroadcastReceiver,各个接收者之间没有先后顺序。 4. 对于有序广播,系统会按照优先级顺序依次传递广播消息给 BroadcastReceiver,每个接收者都可以中断广播或者修改广播内容,然后将广播继续传递给下一个接收者。 5. 广播的最终接收者可以通过 setResult() 方法设置结果代码,并通过 getResultExtras() 方法获取结果数据。 6. 广播接收完成后,系统会自动回收不再需要的资源。 需要注意的是,BroadcastReceiver 的处理时间应尽量控制在几秒钟以内,避免影响用户体验。同时,为了保护用户隐私和安全,Android 8.0(API 级别 26)以上的版本对隐式广播进行了限制,只能通过动态注册的方式接收隐式广播。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值