Android广播发送流程(广播3)

Android广播发送流程

  • 1. 广播发送流程
  • 2. 广播发送
  • 3. 系统处理广播发送
    • 3.1 AMS接收广播的请求
    • 3.2 修改增加默认flag解析可选广播参数BroadcastOptions
    • 3.4 保护广播isProtectedBroadcast、特定action的处理
    • 3.5 发送粘性广播的处理
    • 3.6 筛选出静态广播接受者
    • 3.7 筛选出动态广播接受者
    • 3.8 非oder的平行广播的入队与分发
    • 3.8 order广播接收者的过滤
  • 4. 广播队列的处理
    • 4.1 新建广播队列
    • 4.2 广播接收者入队列
    • 4.3 广播队列的分发
    • 4.4 处理分发下一个广播
      • 4.4.1 mParallelBroadcasts平行广播的分发
      • 4.4.2 mPendingBroadcast挂起广播的处理
      • 4.4.3 取出下一个有序队列中的广播
      • 4.4.4 处理下一个接收者nextReceiver
      • 4.4.5 发送给动态注册的order注册者
      • 4.4.6 静态注册者跳过的逻辑
      • 4.4.7 发送给已经启动了的静态注册者
      • 4.4.8 启动静态注册接收者的进程
    • 4.5 广播接收者处理完成
      • 4.5.1 广播完成,开始下一个广播的调度
      • 4.5.2 广播完成finishReceiverLocked
  • 5. 广播的拓展使用

1. 广播发送流程

这次我们讲一下广播发送的流程,老规矩先上大概的流程图
Android广播发送流程(广播3)_第1张图片

2. 广播发送

  1. 常见的通过ContextImpl.java发送广播的方法有下面几种
    => sendBroadcast/sendBroadcastAsUser :普通的广播发送,默认是当前userId,带有“AsUser”的是发送给特定的user
    => sendBroadcastMultiplePermissions/sendBroadcastAsUserMultiplePermissions :带有多个权限的广播发送
    => sendOrderedBroadcast/sendOrderedBroadcastAsUser :发送order有序的广播(order广播是一个接收完成下一个才能接收,接收者一个个按顺序接收)
    => sendStickyBroadcast/sendStickyBroadcastAsUser :发送粘性广播,粘性广播的意思是注册者注册了就马上能收到该类型(之前已经发送的粘性广播)的广播,
    接收者的注册不需要在发送者的前面
    => sendStickyOrderedBroadcast/sendStickyOrderedBroadcastAsUser :发送粘性而且是顺序order的广播

它们都是调用AMS的broadcastIntentWithFeature来发送广播

如下面是最简单的只有一个Intent的广播发送

//ContextImpl.java
    @Override
    public void sendBroadcast(Intent intent) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        try {
            intent.prepareToLeaveProcess(this);
            //调用的是AMS的broadcastIntentWithFeature来发送广播
            ActivityManager.getService().broadcastIntentWithFeature(
                    mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                    null, Activity.RESULT_OK, null, null, null, null /*excludedPermissions=*/,
                    AppOpsManager.OP_NONE, null, false, false, getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
  1. 还是以亮屏SCREEN_ON的广播继续讲解其发送流程
    其调用方法是sendOrderedBroadcastAsUser(ContextImpl.java)->broadcastIntentWithFeature(ActivityManagerService.java)
//Notifier.java
    private final Intent mScreenOnIntent;
	//新建一个Intent,它的action是ACTION_SCREEN_ON,
	//注意此处增加了
	//FLAG_RECEIVER_REGISTERED_ONLY: 只允许动态注册的接收者接受
	//FLAG_RECEIVER_FOREGROUND: 前台接收,也就是前台广播(10s超时)的队列
	//FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS: 可以被即时app接收
	mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
	mScreenOnIntent.addFlags(
			Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
			| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);

    //亮屏广播发送完成后才调用的
    private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            //开始发送广播之前会打印类似“power_screen_broadcast_send: 1”的日志
            //这里会在event log中打印类似“power_screen_broadcast_done: [1,125,1]“的日志
			//里面包含了发送亮屏广播的时间,此处是“125 ms”
            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
                    SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
            sendNextBroadcast();
        }
    };

   private void sendWakeUpBroadcast() {
        if (DEBUG) {
            Slog.d(TAG, "Sending wake up broadcast.");
        }

        if (mActivityManagerInternal.isSystemReady()) {
            //调用的是ContextImpl的sendOrderedBroadcastAsUser去发送广播
			//mScreenOnIntent是发送的亮屏广播
			//mHandler是PowerManagerService.java的主线程,用来运行mWakeUpBroadcastDone
			//mWakeUpBroadcastDone是亮屏广播发送完成后
            mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,
                    mWakeUpBroadcastDone, mHandler, 0, null, null);
        } else {
            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
            sendNextBroadcast();
        }
    }

//ContextImpl.java
    public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
            String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
            int initialCode, String initialData, Bundle initialExtras) {
		//多带了appOp=OP_NONE、options=null的参数
        sendOrderedBroadcastAsUser(intent, user, receiverPermission, AppOpsManager.OP_NONE,
                null, resultReceiver, scheduler, initialCode, initialData, initialExtras);
    }

    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;
        if (resultReceiver != null) {
            if (mPackageInfo != null) {
                if (scheduler == null) {
                    //由于传入了scheduler(mHandler),所以这里是不会进来的
                    scheduler = mMainThread.getHandler();
                }
				//进入的是这里获取IIntentReceiver rd(通过mPackageInfo、resultReceiver、scheduler构建)
                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);
			//实际是调用的AMS的broadcastIntentWithFeature方法
            ActivityManager.getService().broadcastIntentWithFeature(
                    mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                    rd, initialCode, initialData, initialExtras, receiverPermissions,
                    null /*excludedPermissions=*/, appOp, options, true, false,
                    user.getIdentifier());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

3. 系统处理广播发送

3.1 AMS接收广播的请求

系统AMS通过broadcastIntentWithFeature接收广播的请求

//ActivityManagerService.java
    //从context过来的都走的这个broadcastIntentWithFeature方法,带特性的发送广播
    public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
            Intent intent, String resolvedType, IIntentReceiver resultTo,
            int resultCode, String resultData, Bundle resultExtras,
            String[] requiredPermissions, String[] excludedPermissions, int appOp, Bundle bOptions,
            boolean serialized, boolean sticky, int userId) {
        enforceNotIsolatedCaller("broadcastIntent");
        synchronized(this) {
            intent = verifyBroadcastLocked(intent);

			//通过IApplicationThread获取调用者ProcessRecord callerApp
            final ProcessRecord callerApp = getRecordForAppLOSP(caller);
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();

            final long origId = Binder.clearCallingIdentity();
            try {
                //获取callerApp、callingPid、callingUid用于广播发送参数传入
                return broadcastIntentLocked(callerApp,
                        callerApp != null ? callerApp.info.packageName : null, callingFeatureId,
                        intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                        requiredPermissions, excludedPermissions, appOp, bOptions, serialized,
                        sticky, callingPid, callingUid, callingUid, callingPid, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    }

    final int broadcastIntentLocked(ProcessRecord callerApp,
            String callerPackage, String callerFeatureId, Intent intent, String resolvedType,
            IIntentReceiver resultTo, int resultCode, String resultData,
            Bundle resultExtras, String[] requiredPermissions, String[] excludedPermissions,
            int appOp, Bundle bOptions, boolean ordered, boolean sticky, int callingPid,
            int callingUid, int realCallingUid, int realCallingPid, int userId) {
        //这里再次增加了3个参数allowBackgroundActivityStarts=false,tokenNeededForBackgroundActivityStarts=false
		//broadcastAllowList=null
        return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent,
                resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions,
                excludedPermissions, appOp, bOptions, ordered, sticky, callingPid, callingUid,
                realCallingUid, realCallingPid, userId, false /* allowBackgroundActivityStarts */,
                null /* tokenNeededForBackgroundActivityStarts */, null /* broadcastAllowList */);
    }

3.2 修改增加默认flag解析可选广播参数BroadcastOptions

  1. 如默认会增加 FLAG_EXCLUDE_STOPPED_PACKAGES ,不让stop(如通过forcestop会设置)的三方app接收静态广播
  2. 根据是否粘性广播输出类似的日志:Broadcast (sticky) intent ordered=(true/false) userid=(userId)
  3. 解析BroadcastOptions brOptions广播可选参数
    @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,
                                    String[] excludedPermissions, int appOp, Bundle bOptions,
                                    boolean ordered, boolean sticky, int callingPid, int callingUid,
                                    int realCallingUid, int realCallingPid, int userId,
                                    boolean allowBackgroundActivityStarts,
                                    @Nullable IBinder backgroundActivityStartsToken,
                                    @Nullable int[] broadcastAllowList) {
        intent = new Intent(intent);
        //调用者是否即时app
        final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
        // Instant Apps cannot use FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS
        //如果调用者是即时app,不能添加FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS,可以让即时app接收的flag
        if (callerInstantApp) {
            intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
        }

        // broadcastAllowList: 允许接收该广播uid的列表;一般包信息改变的时候才会传入,通过ContextImpl发送广播是不带这个参数的
        // broadcastAllowList目前只在PMS的doSendBroadcast发送package相关广播的时候才可能使用到
        // PackageManagerService.sendPackageBroadcast/sendMyPackageSuspendedOrUnsuspended->doSendBroadcast->
        // ActivityManagerService.LocalService.broadcastIntent
        if (userId == UserHandle.USER_ALL && broadcastAllowList != null) {
            Slog.e(TAG, "broadcastAllowList only applies when sending to individual users. "
                    + "Assuming restrictive whitelist.");
            broadcastAllowList = new int[]{};
        }

        // By default broadcasts do not go to stopped apps.
        //默认广播是不发送给stop的应用的,类似于安装后进程从未启动过,或者给强行停止的应用,
        //是无法通过接收静态注册的广播来启动的(具体在IntentResolver.java的buildResolveList会使用)
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

        // If we have not finished booting, don't allow this to launch new processes.
        //mProcessesReady在systemReady的时候会设置为true
        //在系统没有启动完成的时候,而且广播发送没有带FLAG_RECEIVER_BOOT_UPGRADE的flag
        if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
            //则默认只能发送到动态注册的接收者中,静态注册的全部无法接收
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
        }

        //DEBUG_BROADCAST_LIGHT这个是调试日志的开关,这里输出是否order有序广播
        if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
                        + " ordered=" + ordered + " userid=" + userId);

        //如果是非ordered的广播,而且有resultTo则输出warning的信息
        //一般情况下orderd的广播才会设置resultTo(发送完成后返回完成的结果到发送者)
        if ((resultTo != null) && !ordered) {
            Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
        }

        //多用户判断,如果是callingUid、userId同一个用户组,则直接返回userId
        userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                ALLOW_NON_FULL, "broadcast", callerPackage);

        // Make sure that the user who is receiving this broadcast or its parent is running.
        // If not, we will just skip it. Make an exception for shutdown broadcasts, upgrade steps.
        //如果userId不是发送到所有用户USER_ALL(-1),而且当前userId和它的父亲userId都没有在运行
        if (userId != UserHandle.USER_ALL && !mUserController.isUserOrItsParentRunning(userId)) {
            //如果调用者不是系统或者没有设置FLAG_RECEIVER_BOOT_UPGRADE,而且不是关机广播,
            //则跳过本次广播发送,不允许stop的userId发送广播,原因是user已经stop了
            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;
            }
        }

        //获取其意图的action
        final String action = intent.getAction();
        BroadcastOptions brOptions = null;
        //是否有传入BroadcastOptions的Bundle,开机广播有传入bOptions,亮屏幕广播没有bOptions
        if (bOptions != null) {
            //将Bundle转换成BroadcastOptions brOptions
            brOptions = new BroadcastOptions(bOptions);
            //如果mTemporaryAppAllowlistDuration的值大于0
            if (brOptions.getTemporaryAppAllowlistDuration() > 0) {
                // 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.
                // 检查一下realCallingPid/realCallingUid是否拥有CHANGE_DEVICE_IDLE_TEMP_WHITELIST(修改临时白名单)、
                // START_ACTIVITIES_FROM_BACKGROUND(后台启动activity)、
                // START_FOREGROUND_SERVICES_FROM_BACKGROUND(后台启动前台服务)的权限,
                // 如果一个都没有,则不允许发送该广播,并抛出安全异常
                // (在部分情况下callingPid/callingUid调用该发送广播的调用者,
                // 于realCallingPid/realCallingUid真实调用者不是一样的)
                if (checkComponentPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
                        realCallingPid, realCallingUid, -1, true)
                        != PackageManager.PERMISSION_GRANTED
                        && checkComponentPermission(START_ACTIVITIES_FROM_BACKGROUND,
                        realCallingPid, realCallingUid, -1, true)
                        != PackageManager.PERMISSION_GRANTED
                        && checkComponentPermission(START_FOREGROUND_SERVICES_FROM_BACKGROUND,
                        realCallingPid, realCallingUid, -1, true)
                        != PackageManager.PERMISSION_GRANTED) {
                    String msg = "Permission Denial: " + intent.getAction()
                            + " broadcast from " + callerPackage + " (pid=" + callingPid
                            + ", uid=" + callingUid + ")"
                            + " requires "
                            + CHANGE_DEVICE_IDLE_TEMP_WHITELIST + " or "
                            + START_ACTIVITIES_FROM_BACKGROUND + " or "
                            + START_FOREGROUND_SERVICES_FROM_BACKGROUND;
                    Slog.w(TAG, msg);
                    throw new SecurityException(msg);
                }
            }

            //如果带有mDontSendToRestrictedApps不发送给受限制的app
            // callingUid不在mActiveUids中,而且callingUid/callerPackage后台限制操作
            // 则由于“background restrictions”不允许发送广播
            if (brOptions.isDontSendToRestrictedApps()
                    && !isUidActiveLOSP(callingUid)
                    && isBackgroundRestrictedNoCheck(callingUid, callerPackage)) {
                Slog.i(TAG, "Not sending broadcast " + action + " - app " + callerPackage
                        + " has background restrictions");
                return ActivityManager.START_CANCELED;
            }
            //是否允许mAllowBackgroundActivityStarts后台启动activity
            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.
                //如果没有START_ACTIVITIES_FROM_BACKGROUND则抛出权限异常
                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,允许后台启动activity
                    allowBackgroundActivityStarts = true;
                    // We set the token to null since if it wasn't for it we'd allow anyway here
                    backgroundActivityStartsToken = null;
                }
            }
        }

3.4 保护广播isProtectedBroadcast、特定action的处理

  1. 识别是否保护广播,这类广播不能给系统之外的app调用;而系统尽量发送保护广播,不然也会发出警告
  2. 后台是否可以接收广播的识别(如果在system/etc、/product/etc等地方加入“allow-implicit-broadcast”的广播则可以让后台接收,
    会加上FLAG_RECEIVER_INCLUDE_BACKGROUND的flag)
  3. 特定action如包状态改变等的广播的处理
        // Verify that protected broadcasts are only being sent by system code,
        // and that system code is only sending protected broadcasts.
        //保护广播的判断逻辑isProtectedBroadcast,这类广播只有系统才能发送
        final boolean isProtectedBroadcast;
        try {
            //查询该广播是否包含在mProtectedBroadcasts,在isProtectedBroadcast也可以增加字符串过滤条件
            //例如在frameworks/base/core/res/AndroidManifest.xml等定义的带有“protected-broadcast”的广播
            // 
            isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
        } catch (RemoteException e) {
            Slog.w(TAG, "Remote exception", 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:
            case SE_UID:
            case NETWORK_STACK_UID:
                //root用户、系统、phone、蓝牙、nfc、安全、网络等相关调用则被认为是系统
                isCallerSystem = true;
                break;
            default:
                //其它就看是否常驻内存,如果是常驻内存调用,也被认为是系统
                isCallerSystem = (callerApp != null) && callerApp.isPersistent();
                break;
        }

        // First line security check before anything else: stop non-system apps from
        // sending protected broadcasts.
        //如果不是系统调用,会进行安全检查
        if (!isCallerSystem) {
            //如果是保护的广播,则不是系统进程,不允许发送,抛出权限异常
            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)) {
                // Special case for compatibility: we don't want apps to send this,
                // but historically it has not been protected and apps may be using it
                // to poke their own app widget.  So, instead of making it protected,
                // just limit it to the caller.
                //如果是widget配置(ACTION_APPWIDGET_CONFIGURE)和更新(ACTION_APPWIDGET_UPDATE)
                //则调用callerPackage不能是空
                if (callerPackage == null) {
                    String msg = "Permission Denial: not allowed to send broadcast "
                            + action + " from unknown caller.";
                    Slog.w(TAG, msg);
                    throw new SecurityException(msg);
                //如果调用组件不等于null
                } else if (intent.getComponent() != null) {
                    // They are good enough to send to an explicit component...  verify
                    // it is being sent to the calling app.
                    //这种情况只能自己发送给自己,不然抛出权限异常
                    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 {
                    // Limit broadcast to their own package.
                    //这类广播只能发给它自己,用于自身widget的更新
                    intent.setPackage(callerPackage);
                }
            }
        }

        //这个是广播超时豁免只有ACTION_PRE_BOOT_COMPLETED才会设置
        //设置了之后这个广播不会超时,谨慎使用
        boolean timeoutExempt = false;

        if (action != null) {
            //查看是否background的进程也可以接收该广播,具体列表在SystemConfig.java的mAllowImplicitBroadcasts
            //这个列表是扫描**/etc(如system/etc/sysconfig/framework-sysconfig.xml、
            // /product/etc/sysconfig/google.xml)带有“
            // 如:google的云推送”com.google.android.c2dm.intent.RECEIVE“、simcard状态改变
            // android.intent.action.SIM_STATE_CHANGED就是这类广播
            if (getBackgroundLaunchBroadcasts().contains(action)) {
                if (DEBUG_BACKGROUND_CHECK) {
                    Slog.i(TAG, "Broadcast action " + action + " forcing include-background");
                }
                //直接增加可以被后台进程接收的flag FLAG_RECEIVER_INCLUDE_BACKGROUND
                // (如何使用在讲解BroadcastQueue的processNextBroadcastLocked时会说明)
                intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            }

            switch (action) {
                case Intent.ACTION_UID_REMOVED:
                case Intent.ACTION_PACKAGE_REMOVED:
                case Intent.ACTION_PACKAGE_CHANGED:
                case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
                case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
                case Intent.ACTION_PACKAGES_SUSPENDED:
                case Intent.ACTION_PACKAGES_UNSUSPENDED:
                    // Handle special intents: if this broadcast is from the package
                    // manager about a package being removed, we need to remove all of
                    // its activities from the history stack.
                    // 如果是ACTION_UID_REMOVED/ACTION_PACKAGE_REMOVED/ACTION_PACKAGE_CHANGED/
                    // ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE/ACTION_EXTERNAL_APPLICATIONS_AVAILABLE/
                    // ACTION_PACKAGES_SUSPENDED/ACTION_PACKAGES_UNSUSPENDED这类广播,
                    // 则发送广播需要BROADCAST_PACKAGE_REMOVED的权限,不然是没法发送的
                    if (checkComponentPermission(
                            android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
                            callingPid, callingUid, -1, true)
                            != PackageManager.PERMISSION_GRANTED) {
                        String msg = "Permission Denial: " + intent.getAction()
                                + " broadcast from " + callerPackage + " (pid=" + callingPid
                                + ", uid=" + callingUid + ")"
                                + " requires "
                                + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
                        Slog.w(TAG, msg);
                        throw new SecurityException(msg);
                    }
                    switch (action) {
                        case Intent.ACTION_UID_REMOVED:
                            final int uid = getUidFromIntent(intent);
                            //如果发送的是ACTION_UID_REMOVED的广播
                            if (uid >= 0) {
                                //电池状态服务的removeUid
                                mBatteryStatsService.removeUid(uid);
                                //mAppOpsService app操作相关管理的处理
                                if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                                    mAppOpsService.resetAllModes(UserHandle.getUserId(uid),
                                            intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME));
                                } else {
                                    mAppOpsService.uidRemoved(uid);
                                }
                            }
                            break;
                        case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
                            // If resources are unavailable just force stop all those packages
                            // and flush the attribute cache as well.
                            String list[] =
                                    intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                            if (list != null && list.length > 0) {
                                for (int i = 0; i < list.length; i++) {
                                    forceStopPackageLocked(list[i], -1, false, true, true,
                                            false, false, userId, "storage unmount");
                                }
                                mAtmInternal.cleanupRecentTasksForUser(UserHandle.USER_ALL);
                                sendPackageBroadcastLocked(
                                        ApplicationThreadConstants.EXTERNAL_STORAGE_UNAVAILABLE,
                                        list, userId);
                            }
                            break;
                        case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
                            mAtmInternal.cleanupRecentTasksForUser(UserHandle.USER_ALL);
                            break;
                        case Intent.ACTION_PACKAGE_REMOVED:
                        case Intent.ACTION_PACKAGE_CHANGED:
                            //应用移除或者改变
                            Uri data = intent.getData();
                            String ssp;
                            if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
                                boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
                                final boolean replacing =
                                        intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
                                final boolean killProcess =
                                        !intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
                                final boolean fullUninstall = removed && !replacing;
                                if (removed) {
                                    if (killProcess) {
                                        forceStopPackageLocked(ssp, UserHandle.getAppId(
                                                intent.getIntExtra(Intent.EXTRA_UID, -1)),
                                                false, true, true, false, fullUninstall, userId,
                                                removed ? "pkg removed" : "pkg changed");
                                    } else {
                                        // Kill any app zygotes always, since they can't fork new
                                        // processes with references to the old code
                                        forceStopAppZygoteLocked(ssp, UserHandle.getAppId(
                                                intent.getIntExtra(Intent.EXTRA_UID, -1)),
                                                userId);
                                    }
                                    final int cmd = killProcess
                                            ? ApplicationThreadConstants.PACKAGE_REMOVED
                                            : ApplicationThreadConstants.PACKAGE_REMOVED_DONT_KILL;
                                    sendPackageBroadcastLocked(cmd,
                                            new String[] {ssp}, userId);
                                    if (fullUninstall) {
                                        mAppOpsService.packageRemoved(
                                                intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);

                                        // Remove all permissions granted from/to this package
                                        mUgmInternal.removeUriPermissionsForPackage(ssp, userId,
                                                true, false);

                                        mAtmInternal.removeRecentTasksByPackageName(ssp, userId);

                                        mServices.forceStopPackageLocked(ssp, userId);
                                        mAtmInternal.onPackageUninstalled(ssp);
                                        mBatteryStatsService.notePackageUninstalled(ssp);
                                    }
                                } else {
                                    if (killProcess) {
                                        final int extraUid = intent.getIntExtra(Intent.EXTRA_UID,
                                                -1);
                                        synchronized (mProcLock) {
                                            mProcessList.killPackageProcessesLSP(ssp,
                                                    UserHandle.getAppId(extraUid),
                                                    userId, ProcessList.INVALID_ADJ,
                                                    ApplicationExitInfo.REASON_USER_REQUESTED,
                                                    ApplicationExitInfo.SUBREASON_UNKNOWN,
                                                    "change " + ssp);
                                        }
                                    }
                                    cleanupDisabledPackageComponentsLocked(ssp, userId,
                                            intent.getStringArrayExtra(
                                                    Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
                                    mServices.schedulePendingServiceStartLocked(ssp, userId);
                                }                            }
                            break;
                        case Intent.ACTION_PACKAGES_SUSPENDED:
                        case Intent.ACTION_PACKAGES_UNSUSPENDED:
                            final boolean suspended = Intent.ACTION_PACKAGES_SUSPENDED.equals(
                                    intent.getAction());
                            final String[] packageNames = intent.getStringArrayExtra(
                                    Intent.EXTRA_CHANGED_PACKAGE_LIST);
                            final int userIdExtra = intent.getIntExtra(
                                    Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);

                            mAtmInternal.onPackagesSuspendedChanged(packageNames, suspended,
                                    userIdExtra);
                            break;
                    }
                    break;
                case Intent.ACTION_PACKAGE_REPLACED:
                {
                    final Uri data = intent.getData();
                    final String ssp;
                    if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
                        ApplicationInfo aInfo = null;
                        try {
                            aInfo = AppGlobals.getPackageManager()
                                    .getApplicationInfo(ssp, STOCK_PM_FLAGS, userId);
                        } catch (RemoteException ignore) {}
                        if (aInfo == null) {
                            Slog.w(TAG, "Dropping ACTION_PACKAGE_REPLACED for non-existent pkg:"
                                    + " ssp=" + ssp + " data=" + data);
                            return ActivityManager.BROADCAST_SUCCESS;
                        }
                        updateAssociationForApp(aInfo);
                        mAtmInternal.onPackageReplaced(aInfo);
                        mServices.updateServiceApplicationInfoLocked(aInfo);
                        sendPackageBroadcastLocked(ApplicationThreadConstants.PACKAGE_REPLACED,
                                new String[] {ssp}, userId);
                    }
                    break;
                }
                case Intent.ACTION_PACKAGE_ADDED:
                {
                    //应用安装
                    // Special case for adding a package: by default turn on compatibility mode.
                    Uri data = intent.getData();
                    String ssp;
                    if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
                        final boolean replacing =
                                intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
                        mAtmInternal.onPackageAdded(ssp, replacing);
                        try {
                            ApplicationInfo ai = AppGlobals.getPackageManager().
                                    getApplicationInfo(ssp, STOCK_PM_FLAGS, 0);
                            mBatteryStatsService.notePackageInstalled(ssp,
                                    ai != null ? ai.longVersionCode : 0);
                        } catch (RemoteException e) {
                        }
                    }
                    break;
                }
                case Intent.ACTION_PACKAGE_DATA_CLEARED:
                {
                    //应用数据清除
                    Uri data = intent.getData();
                    String ssp;
                    if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
                        mAtmInternal.onPackageDataCleared(ssp);
                    }
                    break;
                }
                case Intent.ACTION_TIMEZONE_CHANGED:
                    // If this is the time zone changed action, queue up a message that will reset
                    // the timezone of all currently running processes. This message will get
                    // queued up before the broadcast happens.
                    //时区改变
                    mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
                    break;
                case Intent.ACTION_TIME_CHANGED:
                    // EXTRA_TIME_PREF_24_HOUR_FORMAT is optional so we must distinguish between
                    // the tri-state value it may contain and "unknown".
                    // For convenience we re-use the Intent extra values.
                    //系统时间改变
                    final int NO_EXTRA_VALUE_FOUND = -1;
                    final int timeFormatPreferenceMsgValue = intent.getIntExtra(
                            Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT,
                            NO_EXTRA_VALUE_FOUND /* defaultValue */);
                    // Only send a message if the time preference is available.
                    if (timeFormatPreferenceMsgValue != NO_EXTRA_VALUE_FOUND) {
                        Message updateTimePreferenceMsg =
                                mHandler.obtainMessage(UPDATE_TIME_PREFERENCE_MSG,
                                        timeFormatPreferenceMsgValue, 0);
                        mHandler.sendMessage(updateTimePreferenceMsg);
                    }
                    mBatteryStatsService.noteCurrentTimeChanged();
                    break;
                case ConnectivityManager.ACTION_CLEAR_DNS_CACHE:
                    mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
                    break;
                case Proxy.PROXY_CHANGE_ACTION:
                    mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG));
                    break;
                case android.hardware.Camera.ACTION_NEW_PICTURE:
                case android.hardware.Camera.ACTION_NEW_VIDEO:
                    // In N we just turned these off; in O we are turing them back on partly,
                    // only for registered receivers.  This will still address the main problem
                    // (a spam of apps waking up when a picture is taken putting significant
                    // memory pressure on the system at a bad point), while still allowing apps
                    // that are already actively running to know about this happening.
                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                    break;
                case android.security.KeyChain.ACTION_TRUST_STORE_CHANGED:
                    mHandler.sendEmptyMessage(HANDLE_TRUST_STORAGE_UPDATE_MSG);
                    break;
                case "com.android.launcher.action.INSTALL_SHORTCUT":
                    // As of O, we no longer support this broadcasts, even for pre-O apps.
                    // Apps should now be using ShortcutManager.pinRequestShortcut().
                    Log.w(TAG, "Broadcast " + action
                            + " no longer supported. It will not be delivered.");
                    return ActivityManager.BROADCAST_SUCCESS;
                case Intent.ACTION_PRE_BOOT_COMPLETED:
                    //如果是ACTION_PRE_BOOT_COMPLETED广播则设置超时豁免timeoutExempt = true
                    timeoutExempt = true;
                    break;
                case Intent.ACTION_CLOSE_SYSTEM_DIALOGS:
                    //需要有BROADCAST_CLOSE_SYSTEM_DIALOGS的权限,不然直接返回
                    if (!mAtmInternal.checkCanCloseSystemDialogs(callingPid, callingUid,
                            callerPackage)) {
                        // Returning success seems to be the pattern here
                        return ActivityManager.BROADCAST_SUCCESS;
                    }
                    break;
            }

            if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
                    Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
                    Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
                final int uid = getUidFromIntent(intent);
                if (uid != -1) {
                    final UidRecord uidRec = mProcessList.getUidRecordLOSP(uid);
                    if (uidRec != null) {
                        uidRec.updateHasInternetPermission();
                    }
                }
            }
        }

3.5 发送粘性广播的处理

将粘性广播添加到AMS的mStickyBroadcasts(key是用户组,value是粘性广播列表stickies)中,
单个用户组的粘性广播列表stickies(key是action,value是intent)

已经发送的粘性广播会放入AMS的mStickyBroadcasts中,后面动态注册的接收者就可以在注册的时候就接收这类粘性广播, 因为系统有保存这类广播

        // Add to the sticky list if requested.
        // 是否粘性广播,可以通过ContextImpl.java的sendStickyBroadcast/sendStickyBroadcastAsUser/
        // sendStickyOrderedBroadcast/sendStickyOrderedBroadcastAsUser来进行发送
        if (sticky) {
            //粘性广播需要拥有"android.permission.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);
            }
            //这类广播不能带有requiredPermissions,否则直接返回
            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;
            }
            //粘性广播不能指定发送到相关组件,否则发出安全异常
            if (intent.getComponent() != null) {
                throw new SecurityException(
                        "Sticky broadcasts can't target a specific component");
            }
            // We use userId directly here, since the "all" target is maintained
            // as a separate set of sticky broadcasts.
            //如果userId不是发送给所有用户USER_ALL(-1)
            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.
                //则取出保存粘性广播的列表mStickyBroadcasts里面相同action的Intent
                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++) {
                            //粘性广播2个Intent不能完全相同,相同的话会抛出非法参数异常
                            //mAction/mData/mType/mIdentifier/mPackage/mComponent/mCategories都一致filterEquals才会返回true
                            if (intent.filterEquals(list.get(i))) {
                                throw new IllegalArgumentException(
                                        "Sticky broadcast " + intent + " for user "
                                                + userId + " conflicts with existing global broadcast");
                            }
                        }
                    }
                }
            }

            //获取该用户组的粘性广播列表stickies
            ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
            if (stickies == null) {
                //如果stickies是null,则新建一个
                stickies = new ArrayMap<>();
                //并添加到mStickyBroadcasts中key为userId中去
                mStickyBroadcasts.put(userId, stickies);
            }

            //通过粘性广播列表stickies(key是action,value是intent)
            ArrayList<Intent> list = stickies.get(intent.getAction());
            if (list == null) {
                //如果list为空,则新建一个ArrayList,并放入stickies
                list = new ArrayList<>();
                stickies.put(intent.getAction(), list);
            }
            final int stickiesCount = list.size();
            int i;
            for (i = 0; i < stickiesCount; i++) {
                //mAction/mData/mType/mIdentifier/mPackage/mComponent/mCategories都一致filterEquals才会返回true
                if (intent.filterEquals(list.get(i))) {
                    // This sticky already exists, replace it.
                    //如果之前存在一样的intent,则直接替换掉旧的,并且退出循环
                    list.set(i, new Intent(intent));
                    break;
                }
            }
            //如果上面中途替换过list的intent,则i < stickiesCount
            //而i >= stickiesCount则代表没有替换过
            if (i >= stickiesCount) {
                //没有替换过则加入list中去
                list.add(new Intent(intent));
            }
        }

3.6 筛选出静态广播接受者

  1. 这里主要是通过collectReceiverComponents来筛选出静态广播接受者
        int[] users;
        //通过userId,获取多用户的users
        if (userId == UserHandle.USER_ALL) {
            // Caller wants broadcast to go to all started users.
            users = mUserController.getStartedUserArray();
        } else {
            // Caller wants broadcast to go to one specific user.
            users = new int[] {userId};
        }

        // Figure out who all will receive this broadcast.
		// 静态广播接受者或者order的动态广播接受者的列表
        List receivers = null;
		// 动态广播接受者列表
        List<BroadcastFilter> registeredReceivers = null;
        // Need to resolve the intent to interested receivers...
        //静态广播的接收,只要没有设置FLAG_RECEIVER_REGISTERED_ONLY,都会查询发送到静态广播中,
        //不过如常见的Intent.ACTION_SCREEN_ON则发送时则有设置这个flag,于是Intent.ACTION_SCREEN_ON不会发送给静态广播
        //不要注册Intent.ACTION_SCREEN_ON的静态广播,这个注册了你也收不到
        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                == 0) {
            //这里就是查询静态广播的地方,通过PMS的mComponentResolver查询得到该intent静态注册的广播接受者
            //同时传入broadcastAllowList过滤是否允许接受者接收
            receivers = collectReceiverComponents(
                    intent, resolvedType, callingUid, users, broadcastAllowList);
        }
  1. collectReceiverComponents函数

collectReceiverComponents:收集静态接收者的函数,其调用的是PMS的queryIntentReceivers进行查询,然后进行相应过滤。
=> 调用的是PMS的queryIntentReceivers进行查询
=> 判断是否只发送到单个用户FLAG_SYSTEM_USER_ONLY(多用户场景使用),如果是则进行过滤,只发送给单个用户
=> 如果带有broadcastAllowList(允许接收该广播uid的列表),则只让特定uid列表的静态接收者接收

    private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
                                                        int callingUid, int[] users, int[] broadcastAllowList) {
        // TODO: come back and remove this assumption to triage all broadcasts
        int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;

        List<ResolveInfo> receivers = null;
        try {
            HashSet<ComponentName> singleUserReceivers = null;
            boolean scannedFirstReceivers = false;
            for (int user : users) {
                // Skip users that have Shell restrictions
                //如果调用者是shell,而且该user不允许shell调试,则跳过
                if (callingUid == SHELL_UID
                        && mUserController.hasUserRestriction(
                        UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
                    continue;
                }
                //静态广播通过PMS去查询接收者
                List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
                        .queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
                if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
                    // If this is not the system user, we need to check for
                    // any receivers that should be filtered out.
                    for (int i=0; i<newReceivers.size(); i++) {
                        ResolveInfo ri = newReceivers.get(i);
                        //如果取出来的ResolveInfo包含了只允许系统接收的flag(FLAG_SYSTEM_USER_ONLY),
                        //则从筛选出来的列表中移除这个接收者
                        if ((ri.activityInfo.flags&ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
                            newReceivers.remove(i);
                            i--;
                        }
                    }
                }
                //如果到目前为止newReceivers(ResolveInfo列表)为null或者空的
                if (newReceivers != null && newReceivers.size() == 0) {
                    newReceivers = null;
                }
                if (receivers == null) {
                    //如果receivers(最后返回的结果)为null,则先将newReceivers赋值给receivers
                    receivers = newReceivers;
                } else if (newReceivers != null) {
                    // We need to concatenate the additional receivers
                    // found with what we have do far.  This would be easy,
                    // but we also need to de-dup any receivers that are
                    // singleUser.
                    //scannedFirstReceivers默认是fasle,也就是第一次跑到这段代码会进来,只进来一次
                    //receivers此时已经赋值过一次,这里是users第二次和以上循环才可能会进来
                    if (!scannedFirstReceivers) {
                        // Collect any single user receivers we had already retrieved.
                        scannedFirstReceivers = true;
                        // 遍历之前的receivers(这里receivers没有判空逻辑,只看这段逻辑不太严谨,
                        // 没有出错是由于newReceivers有判空)
                        for (int i=0; i<receivers.size(); i++) {
                            ResolveInfo ri = receivers.get(i);
                            //如果接收者包含FLAG_SINGLE_USER的flag
                            if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
                                ComponentName cn = new ComponentName(
                                        ri.activityInfo.packageName, ri.activityInfo.name);
                                if (singleUserReceivers == null) {
                                    singleUserReceivers = new HashSet<ComponentName>();
                                }
                                //则把这类组件add到singleUserReceivers中
                                singleUserReceivers.add(cn);
                            }
                        }
                    }
                    // Add the new results to the existing results, tracking
                    // and de-dupping single user receivers.
                    // 遍历新的users中获取的newReceivers
                    for (int i=0; i<newReceivers.size(); i++) {
                        ResolveInfo ri = newReceivers.get(i);
                        //如果也是带有FLAG_SINGLE_USER的flag,只发送给单个user
                        if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
                            ComponentName cn = new ComponentName(
                                    ri.activityInfo.packageName, ri.activityInfo.name);
                            if (singleUserReceivers == null) {
                                singleUserReceivers = new HashSet<ComponentName>();
                            }
                            //如果之前还没有添加过,才进行receivers添加
                            if (!singleUserReceivers.contains(cn)) {
                                //而且将单个用户接受者ComponentName cn添加到ComponentName中
                                singleUserReceivers.add(cn);
                                receivers.add(ri);
                            }
                        } else {
                            //其它情况则直接加入该接收者到receivers
                            receivers.add(ri);
                        }
                    }
                }
            }
        } catch (RemoteException ex) {
            // pm is in same process, this will never happen.
        }
        //如果带有broadcastAllowList,允许接收该广播uid的列表
        if (receivers != null && broadcastAllowList != null) {
            for (int i = receivers.size() - 1; i >= 0; i--) {
                final int receiverAppId = UserHandle.getAppId(
                        receivers.get(i).activityInfo.applicationInfo.uid);
                //接受者的uid如果是app进程,而且不在允许接收该广播uid的列表,则移除查询到的接收者
                if (receiverAppId >= Process.FIRST_APPLICATION_UID
                        && Arrays.binarySearch(broadcastAllowList, receiverAppId) < 0) {
                    receivers.remove(i);
                }
            }
        }
        //返回接受者
        return receivers;
    }
  1. PMS通过包安装信息获得静态接收者

=> 如果包发送给特定组件,则通过mComponentResolver的mReceivers.mActivities获取ParsedActivity,并最终得到对应的ActivityInfo
=> 如果没有指定特定组件和特定包,则通过mComponentResolver查询recevier,
调用的是IntentResolver的queryIntent,根据各类Filter去查询,如mActionToFilter,
查询到结果后在通过buildResolveList构建返回的结果List result
=> 如果是发送给特定包,则通过mPackages(安装的时候保存的,key是包名,
value是AndroidPackage/ParsingPackageImpl/PackageImpl)获取AndroidPackage(ParsingPackageImpl),
通过ParsingPackageImpl得到这个包的receivers(pkg.getReceivers()),
然后通过mComponentResolver的queryReceivers(ComponentResolver.java)->mReceivers.queryIntentForPackage
queryIntentFromList(IntentResolver.java)->buildResolveList
此处queryIntentFromList只查询这个包的receivers(构建Pair来查询)

在这里可以看到之前“Android S静态广播注册流程”中提到的用来保存静态注册广播组件的mComponentResolver、mReceivers.mActivities、receivers

//PackageManagerService.java
    public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent,
            String resolvedType, int flags, int userId) {
        //内部方法查询该intent的接受者queryIntentReceiversInternal
        return new ParceledListSlice<>(
                queryIntentReceiversInternal(intent, resolvedType, flags, userId,
                        false /*allowDynamicSplits*/));
    }

    private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
            String resolvedType, int flags, int userId, boolean allowDynamicSplits) {
        //userId不存在则返回空
        if (!mUserManager.exists(userId)) return Collections.emptyList();
        final int callingUid = Binder.getCallingUid();
        //callingUid是否拥有INTERACT_ACROSS_USERS_FULL或者INTERACT_ACROSS_USERS的权限
        enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
                false /*checkShell*/, "query intent receivers");
        //看一下callingUid是否即时app,如果是则返回包名,如果不是则返回null
        final String instantAppPkgName = getInstantAppPackageName(callingUid);
        //更新一下flags
        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
                isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
                        flags));
        //获取intent意图的ComponentName
        ComponentName comp = intent.getComponent();
        if (comp == null) {
            //如果为空,再从intent的selector中查询组件
            if (intent.getSelector() != null) {
                intent = intent.getSelector();
                comp = intent.getComponent();
            }
        }
        if (comp != null) {
            //如果ComponentName组件不为null,则代表发送给特定的组件
            final List<ResolveInfo> list = new ArrayList<>(1);
            //通过组件获取ActivityInfo
            final ActivityInfo ai = getReceiverInfo(comp, flags, userId);
            if (ai != null) {
                // When specifying an explicit component, we prevent the activity from being
                // used when either 1) the calling package is normal and the activity is within
                // an instant application or 2) the calling package is ephemeral and the
                // activity is not visible to instant applications.
                final boolean matchInstantApp =
                        (flags & PackageManager.MATCH_INSTANT) != 0;
                final boolean matchVisibleToInstantAppOnly =
                        (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
                final boolean matchExplicitlyVisibleOnly =
                        (flags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
                final boolean isCallerInstantApp =
                        instantAppPkgName != null;
                final boolean isTargetSameInstantApp =
                        comp.getPackageName().equals(instantAppPkgName);
                final boolean isTargetInstantApp =
                        (ai.applicationInfo.privateFlags
                                & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
                final boolean isTargetVisibleToInstantApp =
                        (ai.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
                final boolean isTargetExplicitlyVisibleToInstantApp =
                        isTargetVisibleToInstantApp
                        && (ai.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
                final boolean isTargetHiddenFromInstantApp =
                        !isTargetVisibleToInstantApp
                        || (matchExplicitlyVisibleOnly && !isTargetExplicitlyVisibleToInstantApp);
                final boolean blockResolution =
                        !isTargetSameInstantApp
                        && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
                                || (matchVisibleToInstantAppOnly && isCallerInstantApp
                                        && isTargetHiddenFromInstantApp));
                //如果blockResolution为fasle(一般情况除了InstantApp,其它为fasle)
                if (!blockResolution) {
                    ResolveInfo ri = new ResolveInfo();
                    ri.activityInfo = ai;
                    //添加到List list中
                    list.add(ri);
                }
            }
            //将查询到的List list再次做一些判断,看是否需要移除
            return applyPostResolutionFilter(
                    list, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
                    intent);
        }

        // reader
        synchronized (mLock) {
            //看一下是否有发送给特定的包
            String pkgName = intent.getPackage();
            if (pkgName == null) {
                //如果pkgName为空,则通过mComponentResolver查询recevier
                //调用的是IntentResolver的queryIntent,根据各类Filter去查询,如mActionToFilter
                //查询到结果后在通过buildResolveList构建返回的结果List result
                final List<ResolveInfo> result =
                        mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
                if (result == null) {
                    return Collections.emptyList();
                }
                //过滤后返回结果
                return applyPostResolutionFilter(
                        result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
                        intent);
            }
            //如果有发送给特定的包
            final AndroidPackage pkg = mPackages.get(pkgName);
            if (pkg != null) {
                // 则queryReceivers(ComponentResolver.java)->mReceivers.queryIntentForPackage
                // queryIntentFromList(IntentResolver.java)->buildResolveList
                // 只查询这个包的receivers(构建Pair来查询)
                final List<ResolveInfo> result = mComponentResolver.queryReceivers(
                        intent, resolvedType, flags, pkg.getReceivers(), userId);
                if (result == null) {
                    return Collections.emptyList();
                }
                //过滤后返回结果
                return applyPostResolutionFilter(
                        result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
                        intent);
            }
            return Collections.emptyList();
        }
    }

	//查询单个组件的ActivityInfo:通过组件名,可以获得相应的ParsedActivity,最终返回的是ActivityInfo信息
    public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
        if (!mUserManager.exists(userId)) return null;
        final int callingUid = Binder.getCallingUid();
        flags = updateFlagsForComponent(flags, userId);
        enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */,
                false /* checkShell */, "get receiver info");
        synchronized (mLock) {
            //通过mComponentResolver(mReceivers.mActivities取)查询该组件的ParsedActivity
            ParsedActivity a = mComponentResolver.getReceiver(component);
            if (DEBUG_PACKAGE_INFO) Log.v(
                TAG, "getReceiverInfo " + component + ": " + a);

            if (a == null) {
                //如果没有取出来,则返回null
                return null;
            }

            //mPackages变量是保存了所有安装的应用,查看一下这个package是否能从安装应用中查出来
            AndroidPackage pkg = mPackages.get(a.getPackageName());
            if (pkg == null) {
                return null;
            }

            // 是否包enable(这个是ParsingPackageImpl的ENABLED,不是PackageSettingBase的enabledComponents/disabledComponents)
            // 和匹配
            if (mSettings.isEnabledAndMatchLPr(pkg, a, flags, userId)) {
                //从mSettings中获取包信息PackageSetting ps
                PackageSetting ps = mSettings.getPackageLPr(component.getPackageName());
                if (ps == null) return null;
                //查看一下是否需要根据callingUid过滤是否可见其它目标的package
                //系统调用的话返回false
                if (shouldFilterApplicationLocked(
                        ps, callingUid, component, TYPE_RECEIVER, userId)) {
                    return null;
                }
                //根据pkg和ParsedActivity生成相应的ActivityInfo信息
                return PackageInfoUtils.generateActivityInfo(pkg,
                        a, flags, ps.readUserState(userId), userId, ps);
            }
        }
        return null;
    }

3.7 筛选出动态广播接受者

“Android S动态广播注册流程”中有讲到:动态广播注册其实最终构建的是BroadcastFilter bf,并放入mReceiverResolver中去
而放入mReceiverResolver使用的方法是IntentResolver的addFilter在“Android S静态广播注册流程”也有提到。

  1. 动态广播接受者主要是通过mReceiverResolver的queryIntent来查询得到
        if (intent.getComponent() == null) {
            //如果intent不是单独发给某个组件的话
            //如果userId == UserHandle.USER_ALL(发给所有用户)而且callingUid == SHELL_UID(从shell过来)
            //一般app或者系统发送不是用过这个场景来发送的
            if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
                // Query one target user at a time, excluding shell-restricted users
                for (int i = 0; i < users.length; i++) {
                    if (mUserController.hasUserRestriction(
                            UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
                        continue;
                    }
                    //通过动态注册广播的解析器mReceiverResolver,查询动态注册的接受者
                    //也是通过IntentResolver.java的queryIntent来查询的
                    List<BroadcastFilter> registeredReceiversForUser =
                            mReceiverResolver.queryIntent(intent,
                                    resolvedType, false /*defaultOnly*/, users[i]);

                    //将查询到的接受者添加到registeredReceivers中去
                    if (registeredReceivers == null) {
                        registeredReceivers = registeredReceiversForUser;
                    } else if (registeredReceiversForUser != null) {
                        registeredReceivers.addAll(registeredReceiversForUser);
                    }
                }
            } else {
                //一般情况我们走的这里,直接从mReceiverResolver查询动态接受者赋值给registeredReceivers
                registeredReceivers = mReceiverResolver.queryIntent(intent,
                        resolvedType, false /*defaultOnly*/, userId);
            }
        }
  1. IntentResolver的queryIntent函数
    (动态接收者查询的使用mReceiverResolver的queryIntent来查询得到,
    而静态注册查询的使用也是通过mComponentResolver.mReceivers.queryIntent,都是使用一个方法)

=> 通过***Filter(如mActionToFilter)找出匹配的fliter
=> 通过buildResolveList构建可以被接收的结果
=> 通过优先级排序返回查询结果

//IntentResolver.java
    public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
                               int userId) {
        String scheme = intent.getScheme();

        ArrayList<R> finalList = new ArrayList<R>();

        final boolean debug = localLOGV ||
                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);

        if (debug) Slog.v(
                TAG, "Resolving type=" + resolvedType + " scheme=" + scheme
                        + " defaultOnly=" + defaultOnly + " userId=" + userId + " of " + intent);

        F[] firstTypeCut = null;
        F[] secondTypeCut = null;
        F[] thirdTypeCut = null;
        F[] schemeCut = null;

        // If the intent includes a MIME type, then we want to collect all of
        // the filters that match that MIME type.
        if (resolvedType != null) {
            int slashpos = resolvedType.indexOf('/');
            if (slashpos > 0) {
                final String baseType = resolvedType.substring(0, slashpos);
                if (!baseType.equals("*")) {
                    if (resolvedType.length() != slashpos+2
                            || resolvedType.charAt(slashpos+1) != '*') {
                        // Not a wild card, so we can just look for all filters that
                        // completely match or wildcards whose base type matches.
                        firstTypeCut = mTypeToFilter.get(resolvedType);
                        if (debug) Slog.v(TAG, "First type cut: " + Arrays.toString(firstTypeCut));
                        secondTypeCut = mWildTypeToFilter.get(baseType);
                        if (debug) Slog.v(TAG, "Second type cut: "
                                + Arrays.toString(secondTypeCut));
                    } else {
                        // We can match anything with our base type.
                        firstTypeCut = mBaseTypeToFilter.get(baseType);
                        if (debug) Slog.v(TAG, "First type cut: " + Arrays.toString(firstTypeCut));
                        secondTypeCut = mWildTypeToFilter.get(baseType);
                        if (debug) Slog.v(TAG, "Second type cut: "
                                + Arrays.toString(secondTypeCut));
                    }
                    // Any */* types always apply, but we only need to do this
                    // if the intent type was not already */*.
                    thirdTypeCut = mWildTypeToFilter.get("*");
                    if (debug) Slog.v(TAG, "Third type cut: " + Arrays.toString(thirdTypeCut));
                } else if (intent.getAction() != null) {
                    // The intent specified any type ({@literal *}/*).  This
                    // can be a whole heck of a lot of things, so as a first
                    // cut let's use the action instead.
                    firstTypeCut = mTypedActionToFilter.get(intent.getAction());
                    if (debug) Slog.v(TAG, "Typed Action list: " + Arrays.toString(firstTypeCut));
                }
            }
        }

        // If the intent includes a data URI, then we want to collect all of
        // the filters that match its scheme (we will further refine matches
        // on the authority and path by directly matching each resulting filter).
        if (scheme != null) {
            schemeCut = mSchemeToFilter.get(scheme);
            if (debug) Slog.v(TAG, "Scheme list: " + Arrays.toString(schemeCut));
        }

        // If the intent does not specify any data -- either a MIME type or
        // a URI -- then we will only be looking for matches against empty
        // data.
        if (resolvedType == null && scheme == null && intent.getAction() != null) {
            //这里就把所有的ParsedIntentInfo从mActionToFilter取出来了, key是action, value是Pair(ParsedActivity, ParsedIntentInfo)
            //如我们之前动态注册的亮屏广播mDynamicReceiver,静态注册的开机广播MyReceiver

/*
//动态注册的亮屏广播mReceiverResolver.queryIntent时
firstTypeCut = {BroadcastFilter[42]@39131} 
40 = {BroadcastFilter@39150} "BroadcastFilter{8f17ce8 10214/u0 ReceiverList{50ee60b 9948 com.example.myapplication/10214/u0 remote:7781da}}"

//静态注册的开机广播mComponentResolver.mReceivers.queryIntent时
firstTypeCut = {Pair[316]@38034}
107 = {Pair@38369} "Pair{Activity{7d26902 com.example.myapplication/.MyReceiver2} ParsedIntentInfo{a218213}}"
108 = {Pair@38370} "Pair{Activity{3985c50 com.example.myapplication/.MyReceiver} ParsedIntentInfo{9dfde49}}"
*/
            firstTypeCut = mActionToFilter.get(intent.getAction());
            if (debug) Slog.v(TAG, "Action list: " + Arrays.toString(firstTypeCut));
        }

        FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
        if (firstTypeCut != null) {
            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
                    scheme, firstTypeCut, finalList, userId);
        }
        if (secondTypeCut != null) {
            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
                    scheme, secondTypeCut, finalList, userId);
        }
        if (thirdTypeCut != null) {
            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
                    scheme, thirdTypeCut, finalList, userId);
        }
        if (schemeCut != null) {
            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
                    scheme, schemeCut, finalList, userId);
        }
        //这里对于即时应用才有过滤效果,普通的是直接返回
        filterResults(finalList);
        //通过getPriority优先级排序
        sortResults(finalList);

        if (debug) {
            Slog.v(TAG, "Final result list:");
            for (int i=0; i<finalList.size(); i++) {
                Slog.v(TAG, "  " + finalList.get(i));
            }
        }
        return finalList;
    }

    private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
                                  boolean debug, boolean defaultOnly, String resolvedType, String scheme,
                                  F[] src, List<R> dest, int userId) {
        //获取action
        final String action = intent.getAction();
        //获取data
        final Uri data = intent.getData();
        //获取包名
        final String packageName = intent.getPackage();

        //是否flag包含了FLAG_INCLUDE_STOPPED_PACKAGES(发送给停止的包)
        final boolean excludingStopped = intent.isExcludingStopped();

        final Printer logPrinter;
        final PrintWriter logPrintWriter;
        //调试使用的debug开关,localLOGV或者设置了FLAG_DEBUG_LOG_RESOLUTION时debug会是true
        if (debug) {
            logPrinter = new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM);
            logPrintWriter = new FastPrintWriter(logPrinter);
        } else {
            logPrinter = null;
            logPrintWriter = null;
        }

        final int N = src != null ? src.length : 0;
        boolean hasNonDefaults = false;
        int i;
        F filter;
        //遍历需要筛选的src,动态广播是BroadcastFilter,静态广播是Pair
        for (i=0; i<N && (filter=src[i]) != null; i++) {
            int match;
            if (debug) Slog.v(TAG, "Matching against filter " + filter);
            if (excludingStopped) {
                //1. 静态广播的mComponentResolver.mReceivers是继承于ActivityIntentResolver的
                // 其调用ComponentResolver.isFilterStopped会针对非系统应用判断是否stop停止的应用
                // 主要代码是!ps.isSystem() && ps.getStopped(userId);,这里就不扩展讲了
                //2. 非静态广播mReceiverResolver是new IntentResolver,直接返回false
                if (isFilterStopped(filter, userId)) {
                    if (debug) {
                        Slog.v(TAG, "  Filter's target is stopped; skipping");
                    }
                    continue;
                }
            }
            // Is delivery being limited to filters owned by a particular package?
            //这里是当intent发送给特定包的时候,判断是否当前filter
            if (packageName != null && !isPackageForFilter(packageName, filter)) {
                if (debug) {
                    Slog.v(TAG, "  Filter is not from package " + packageName + "; skipping");
                }
                continue;
            }

            // Are we verified ?
            //获取filter,动态的是BroadcastFilter,静态的是ParsedIntentInfo
            IntentFilter intentFilter = getIntentFilter(filter);
            //查看是否带有STATE_VERIFY_AUTO,这里只是打印日志
            if (intentFilter.getAutoVerify()) {
                if (localVerificationLOGV || debug) {
                    Slog.v(TAG, "  Filter verified: " + isFilterVerified(filter));
                    int authorities = intentFilter.countDataAuthorities();
                    for (int z = 0; z < authorities; z++) {
                        Slog.v(TAG, "   " + intentFilter.getDataAuthority(z)
                                .getHost());
                    }
                }
            }

            // Do we already have this one?
            //如果在dest中添加过一样的,则不在添加,跳过
            if (!allowFilterResult(filter, dest)) {
                if (debug) {
                    Slog.v(TAG, "  Filter's target already added");
                }
                continue;
            }

            //判断过滤器是否匹配
            match = intentFilter.match(action, resolvedType, scheme, data, categories, TAG);
            if (match >= 0) {
                if (debug) Slog.v(TAG, "  Filter matched!  match=0x" +
                        Integer.toHexString(match) + " hasDefault="
                        + intentFilter.hasCategory(Intent.CATEGORY_DEFAULT));
                // 对于接收者receiver来说:
                // 动态注册者mReceiverResolver.queryIntent的时候传入的defaultOnly=false
                // 静态注册者查询时需要设置了MATCH_DEFAULT_ONLY才会将defaultOnly设置成true,
                // 默认AMS收集静态注册者的时候是没有设置这个flag的,于是defaultOnly都是false
                if (!defaultOnly || intentFilter.hasCategory(Intent.CATEGORY_DEFAULT)) {
                    final R oneResult = newResult(filter, match, userId);
                    if (debug) Slog.v(TAG, "    Created result: " + oneResult);
                    if (oneResult != null) {
                        //将匹配的filter生成的结果放入dest中
                        dest.add(oneResult);
                        if (debug) {
                            dumpFilter(logPrintWriter, "    ", filter);
                            logPrintWriter.flush();
                            intentFilter.dump(logPrinter, "    ");
                        }
                    }
                } else {
                    hasNonDefaults = true;
                }
            }
        //...
    }

3.8 非oder的平行广播的入队与分发

如果没有设置ordered(也称之为serialized)按顺序,则针对动态注册类型的广播会一次性全部发送出去,
于是我们可以看到类似这样的日志:“Enqueueing parallel broadcas ***”,
这种无需等待APP的执行,很快系统就处理完了

        //是否拥FLAG_RECEIVER_REPLACE_PENDING,这类广播会将旧的广播给覆盖替换掉
        final boolean replacePending =
                (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;

        //replacePending也在调试开关下输出一下日志
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction()
                + " replacePending=" + replacePending);
        //动态注册查询的时候没有传入broadcastAllowList(允许接收的uid列表)
        //此处会根据broadcastAllowList(不为null才会过滤)来进行动态注册接收者的过滤
        if (registeredReceivers != null && broadcastAllowList != null) {
            // if a uid whitelist was provided, remove anything in the application space that wasn't
            // in it.
            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(broadcastAllowList, owningAppId) < 0) {
                    registeredReceivers.remove(i);
                }
            }
        }

        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
        //先处理动态注册接收者的逻辑,如果该广播是非ordered(也就是无序广播),则进入里面
        if (!ordered && NR > 0) {
            // If we are not serializing this broadcast, then send the
            // registered receivers separately so they don't wait for the
            // components to be launched.
            if (isCallerSystem) {
                checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                        isProtectedBroadcast, registeredReceivers);
            }
            //根据意图的flag是否有FLAG_RECEIVER_FOREGROUND来选择前台还是后台广播
            final BroadcastQueue queue = broadcastQueueForIntent(intent);

            //只有ACTION_PRE_BOOT_COMPLETED timeoutExempt才会为true
            //这里新建的BroadcastRecord r是动态广播注册者的广播记录对象
            //这里将registeredReceivers动态接受者全部传入
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                    callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, excludedPermissions, appOp, brOptions, registeredReceivers,
                    resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId,
                    allowBackgroundActivityStarts, backgroundActivityStartsToken,
                    timeoutExempt);
            // 由于是非order的,将这个广播的平行接收者放入队列中(动态注册的广播registeredReceivers)
            // 这就是所谓的平行广播的发送,发送后无需等待,一次性全部发完
            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
            //设置了flag FLAG_RECEIVER_REPLACE_PENDING的广播,会替换掉BroadcastQueue旧的广播
            final boolean replaced = replacePending
                    && (queue.replaceParallelBroadcastLocked(r) != null);
            // Note: We assume resultTo is null for non-ordered broadcasts.
            //如果是普通的广播,非替换的的情况
            if (!replaced) {
                //则将该BroadcastRecord放入BroadcastQueue的mParallelBroadcasts平行广播列表中
                queue.enqueueParallelBroadcastLocked(r);
                //BroadcastQueue进行广播的正常分发
                queue.scheduleBroadcastsLocked();
            }
            //清空动态接收者,已经处理过了
            registeredReceivers = null;
            NR = 0;
        }

3.8 order广播接收者的过滤

=> 如果设置ordered(也称之为serialized)按顺序,不管是动态还是静态的注册者都是放入order的广播里面发送
=> 如果没有设置ordered,则只放入静态接收者。(普通的广播会有2个队列发送,一个是parallel broadcast,一个是ordered broadcast)
=> 最终不管是静态还是动态注册的广播,只要是需要order发送的都会合并到receivers中,排序是按照优先级(android:order/IntentFilter.setPriority设置的优先级)

广播发送时看到类似这样的日志:“Enqueueing ordered broadcast ***”,
需要按顺序执行,前面一个接收者执行完成后才能让后面的继续执行,同时前面的可以中断后面接收者的执行

        // Merge into one list.
        int ir = 0;
        //处理静态接收者
        if (receivers != null) {
            // A special case for PACKAGE_ADDED: do not allow the package
            // being added to see this broadcast.  This prevents them from
            // using this as a back door to get run as soon as they are
            // installed.  Maybe in the future we want to have a special install
            // broadcast or such for apps, but we'd like to deliberately make
            // this decision.
            String skipPackages[] = null;
            //针对ACTION_PACKAGE_ADDED/ACTION_PACKAGE_RESTARTED/ACTION_PACKAGE_DATA_CLEARED
            //这类广播不允许被安装的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 };
                    }
                }
            } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
                skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
            }

            //将跳过的packageName从receivers中移除
            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--;
                            }
                        }
                    }
                }
            }

            //NT是静态接收者的个数,NR是动态接收者的个数
            int NT = receivers != null ? receivers.size() : 0;
            int it = 0;
            ResolveInfo curt = null;
            BroadcastFilter curr = null;
            // 遍历静态接收者receivers和动态接收者registeredReceivers
            // ir < NR代表还是存在动态接收者,由于非order的动态接收者上面已经发送完成,
            // 那么这里只会是order的广播的动态接收者
            while (it < NT && ir < NR) {
                //取出第it个静态接收者curt
                if (curt == null) {
                    curt = (ResolveInfo)receivers.get(it);
                }
                //取出ir个动态接收者curr
                if (curr == null) {
                    curr = registeredReceivers.get(ir);
                }

                //动态接收者的优先级是存放在IntentFilter的mPriority, 通过IntentFilter的setPriority设置
                //静态接收者的优先级是存放在ResolveInfo的priority,通过android:priority设置
                if (curr.getPriority() >= curt.priority) {
                    // Insert this broadcast record into the final list.
                    // 如果动态接收者curr的优先级大于静态接收者curt的优先级,
                    // 则将动态接收者curr放入原来静态接收者(curt)it的位置,
                    // 在这之前静态接收者(curt)it已经取出来了,这里只是用动态接收者curr来填充it的位置
                    receivers.add(it, curr);
                    //动态接收者用过了则ir++, 而且将curr = null置为空,再次取下一个动态接收者
                    //当前receivers it的位置存放动态接收者curr
                    ir++;
                    curr = null;
                    //同时这里使用了list add的特性,当一个元素增加到it时,其从it到NT的元素自动+1
                    //于是下一个元素就是it++
                    it++;
                    //receivers新增了一个元素,于是总大小NT++
                    NT++;
                } else {
                    // Skip to the next ResolveInfo in the final list.
                    //否则静态接收者curt的it++,同时curt = null,再次取下一个静态接收者
                    //当前receivers it的位置存放静态接收者curt
                    it++;
                    curt = null;
                }
            }
        }

        // 如果动态接收者还没有遍历完,说明最新的ir动态接收者curr的
        // 优先级小于receivers最后一个静态接收者curt的优先级,
        // 则将剩下的registeredReceivers全部加入到receivers的尾部
        while (ir < NR) {
            if (receivers == null) {
                receivers = new ArrayList();
            }
            receivers.add(registeredReceivers.get(ir));
            ir++;
        }

        //isCallerSystem(前面有解释)是否系统调用发送广播
        if (isCallerSystem) {
            //查看一下发送的是否保护的广播
            checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                    isProtectedBroadcast, receivers);
        }

        if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            //根据意图的flag是否有FLAG_RECEIVER_FOREGROUND来选择前台还是后台广播
            BroadcastQueue queue = broadcastQueueForIntent(intent);

            // 构建有序的BroadcastRecord,如果ordered = true则包含静态和动态接收者,
            // 如果ordered = false则只包含静态接收者,由于静态接收者都是有序发送的,
            // 故其实这个receivers全部都是有序接收的接收者
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                    callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, excludedPermissions, appOp, brOptions,
                    receivers, resultTo, resultCode, resultData, resultExtras,
                    ordered, sticky, false, userId, allowBackgroundActivityStarts,
                    backgroundActivityStartsToken, timeoutExempt);

            //静态注册的广播在receivers中,发送ordered 按顺序接收广播
            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);

            //设置了flag FLAG_RECEIVER_REPLACE_PENDING的广播,会替换掉BroadcastQueue旧的广播
            final BroadcastRecord oldRecord =
                    replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;

            if (oldRecord != null) {
                // Replaced, fire the result-to receiver.
                //存在旧的oldRecord(有序的),而且resultTo不为null
                if (oldRecord.resultTo != null) {
                    final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
                    try {
                        //则告诉原来的调用者oldRecord.callerApp,这个广播已经给cancel掉了
                        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 {
                //将order的广播放入mDispatcher的mOrderedBroadcasts中去
                queue.enqueueOrderedBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
        } else {
            // There was nobody interested in the broadcast, but we still want to record
            // that it happened.
            // 如果接收者receivers为null,而且resultTo也是null,则到这里已经没有人关注
            // 如果不是发送给特定的包或者组件,而且不是只发送给动态注册的广播
            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;
    }

4. 广播队列的处理

前面讲的是过滤接收者,然后将信息放入广播队列中,那么广播队列是如何处理这类信息的呢?

这一节我们接下去讲解广播队列处理流程

4.1 新建广播队列

目前有3个广播队列,一个是前台、一个是后台、一个是Offload的广播队列
其中前台广播超时时间是10s,后台是60s,Offload的广播也是60s

//ActivityManagerService.java
    //前台广播队列
    final BroadcastQueue mFgBroadcastQueue;
    //后台广播队列
    final BroadcastQueue mBgBroadcastQueue;
    //Offload的广播队列(默认这个没有使用)
    final BroadcastQueue mOffloadBroadcastQueue;
    // Convenient for easy iteration over the queues. Foreground is first
    // so that dispatch of foreground broadcasts gets precedence.
	//总的广播队列
    final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[3];


    public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) {
        //...
        // Broadcast policy parameters
        final BroadcastConstants foreConstants = new BroadcastConstants(
                Settings.Global.BROADCAST_FG_CONSTANTS);
        //前台广播超时时间是10s
        foreConstants.TIMEOUT = BROADCAST_FG_TIMEOUT;

        final BroadcastConstants backConstants = new BroadcastConstants(
                Settings.Global.BROADCAST_BG_CONSTANTS);
        //后台广播超时时间是60s
        backConstants.TIMEOUT = BROADCAST_BG_TIMEOUT;

        final BroadcastConstants offloadConstants = new BroadcastConstants(
                Settings.Global.BROADCAST_OFFLOAD_CONSTANTS);
        offloadConstants.TIMEOUT = BROADCAST_BG_TIMEOUT;
        // by default, no "slow" policy in this queue
		//没有SLOW_TIME,不使用延迟策略广播
        offloadConstants.SLOW_TIME = Integer.MAX_VALUE;

		//默认是没有使用Offload的广播的
        mEnableOffloadQueue = SystemProperties.getBoolean(
                "persist.device_config.activity_manager_native_boot.offload_queue_enabled", false);

		//这里的mHandler是AMS的MainHandler,优先级是THREAD_PRIORITY_FOREGROUND前台
        mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "foreground", foreConstants, false);
        mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "background", backConstants, true);
        mOffloadBroadcastQueue = new BroadcastQueue(this, mHandler,
                "offload", offloadConstants, true);
        mBroadcastQueues[0] = mFgBroadcastQueue;
        mBroadcastQueues[1] = mBgBroadcastQueue;
        mBroadcastQueues[2] = mOffloadBroadcastQueue;

		//...
    }

4.2 广播接收者入队列

  1. 平行广播接收者enqueueParallelBroadcastLocked入队列

这里入队列就是全部丢入广播队列BroadcastQueue的mParallelBroadcasts中

//BroadcastQueue.java
    public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
        mParallelBroadcasts.add(r);
        enqueueBroadcastHelper(r);
    }
  1. order广播接收者enqueueOrderedBroadcastLocked入队列

这里多了一个中转mDispatcher(BroadcastDispatcher),放入的其实是BroadcastDispatcher的mOrderedBroadcasts中

//BroadcastQueue.java
    public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
        mDispatcher.enqueueOrderedBroadcastLocked(r);
        enqueueBroadcastHelper(r);
    }

//BroadcastDispatcher.java
    void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
        mOrderedBroadcasts.add(r);
    }

4.3 广播队列的分发

一般外部调用(非BroadcastQueue中)分发有2种
1、scheduleBroadcastsLocked 让广播队列开始调度分发广播。如:发送广播的时候,平行广播分发、order广播分发使用的方式;注册的时候发送粘性广播也是使用这个方式
2、processNextBroadcastLocked 直接处理下一个广播。如:order广播中上一个广播处理完成后(这个比较常见,一会也会讲)、unregister的时候

  1. scheduleBroadcastsLocked让广播队列开始调度分发广播
    调用这个函数需要加入AMS的锁,也就是Thread.holdsLock(mService)需要返回true(原生调用都是包含这个锁的,注意新增的调用)

scheduleBroadcastsLocked通过mHandler发送BROADCAST_INTENT_MSG -> processNextBroadcast(true)开始处理下一个广播分发

//BroadcastQueue.java
    public void scheduleBroadcastsLocked() {
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
                + mQueueName + "]: current="
                + mBroadcastsScheduled);
		//是否mBroadcastsScheduled正在调度中,调度中则先返回,如果出现广播堆积优先查看这个值是否一直等于true
        if (mBroadcastsScheduled) {
            return;
        }
		//通过mHandler(其looper和AMS的MainHandler是一个looper)发送BROADCAST_INTENT_MSG
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

    private final class BroadcastHandler extends Handler {
        public BroadcastHandler(Looper looper) {
            super(looper, null, true);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BROADCAST_INTENT_MSG: {
                    if (DEBUG_BROADCAST) Slog.v(
                            TAG_BROADCAST, "Received BROADCAST_INTENT_MSG ["
                                    + mQueueName + "]");
					//开始下一个广播的处理,传入的fromMsg是true
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        //广播超时的处理
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
    }

	//注意从handler的持有mService的锁
    private void processNextBroadcast(boolean fromMsg) {
        synchronized (mService) {
            //此处skipOomAdj是false,也就是需要调整OomAdj
            processNextBroadcastLocked(fromMsg, false);
        }
    }

4.4 处理分发下一个广播

processNextBroadcastLocked下一个广播分发

4.4.1 mParallelBroadcasts平行广播的分发

  1. mParallelBroadcasts平行广播是一次性全部丢出去的,通过deliverToRegisteredReceiverLocked来分发到动态接收者
    //分发下一个广播
    //fromMsg:是否从handleMessage(BROADCAST_INTENT_MSG)而来
    //skipOomAdj:是否需要跳过adj调整,AMS的unregisterReceiver、finishReceiver过来是true,
    //BroadcastQueue过来是false
    final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
        //BroadcastRecord广播的记录者,需要分发的广播
        BroadcastRecord r;

        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "processNextBroadcast ["
                + mQueueName + "]: "
                + mParallelBroadcasts.size() + " parallel broadcasts; "
                + mDispatcher.describeStateLocked());

        //更新mProcessCpuMutexFree,可以继续执行updateCpuStatsNow
        mService.updateCpuStats();

        //如果fromMsg == ture,则设置mBroadcastsScheduled为true,允许scheduleBroadcastsLocked下一个BROADCAST_INTENT_MSG
        //注意原生逻辑scheduleBroadcastsLocked和processNextBroadcastLocked都持有AMS的锁,不然mBroadcastsScheduled会出现线程冲突导致广播堆积
        if (fromMsg) {
            mBroadcastsScheduled = false;
        }

        // First, deliver any non-serialized broadcasts right away.
        //第一步:先分发mParallelBroadcasts平行的广播队列
        while (mParallelBroadcasts.size() > 0) {
            //取出平行广播队列里面的第一个BroadcastRecord
            r = mParallelBroadcasts.remove(0);
            //设置BroadcastRecord r广播分发时间dispatchTime
            r.dispatchTime = SystemClock.uptimeMillis();
            //System.currentTimeMillis()获取的是系统时钟的时间,修改系统时间这个时间会变化
            r.dispatchClockTime = System.currentTimeMillis();

            //如果打开了"am"的tag会记录trace的日志
            //"am",         "Activity Manager",         ATRACE_TAG_ACTIVITY_MANAGER,
            if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                //结束DELIVERY_PENDING的trace
                Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
                        System.identityHashCode(r));
                //开始DELIVERY_DELIVERED的trace
                Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
                        System.identityHashCode(r));
            }

            final int N = r.receivers.size();
            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
                    + mQueueName + "] " + r);
            //遍历构建 BroadcastRecord 的所有receivers
            for (int i=0; i<N; i++) {
                Object target = r.receivers.get(i);
                if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                        "Delivering non-ordered on [" + mQueueName + "] to registered "
                                + target + ": " + r);
                deliverToRegisteredReceiverLocked(r,
                        (BroadcastFilter) target, false, i);
            }
            addBroadcastToHistoryLocked(r);
            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
                    + mQueueName + "] " + r);
        }
```java

2) deliverToRegisteredReceiverLocked分发到动态接收者

deliverToRegisteredReceiverLocked -> performReceiveLocked


```java
    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
                                                   BroadcastFilter filter, boolean ordered, int index) {
        //...
		//前面是各类跳过skip的场景

        r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;

        // If this is not being sent as an ordered broadcast, then we
        // don't want to touch the fields that keep track of the current
        // state of ordered broadcasts.
        if (ordered) {
            //order分发的时候,会有r.receiver的设置
            r.receiver = filter.receiverList.receiver.asBinder();
            r.curFilter = filter;
            filter.receiverList.curBroadcast = r;
            r.state = BroadcastRecord.CALL_IN_RECEIVE;
            if (filter.receiverList.app != null) {
                // Bump hosting application to no longer be in background
                // scheduling class.  Note that we can't do that if there
                // isn't an app...  but we can only be in that case for
                // things that directly call the IActivityManager API, which
                // are already core system stuff so don't matter for this.
                r.curApp = filter.receiverList.app;
                filter.receiverList.app.mReceivers.addCurReceiver(r);
                mService.enqueueOomAdjTargetLocked(r.curApp);
                mService.updateOomAdjPendingTargetsLocked(
                        OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
            }
        } else if (filter.receiverList.app != null) {
            mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(filter.receiverList.app);
        }

        try {
            if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
                    "Delivering to " + filter + " : " + r);
            if (filter.receiverList.app != null && filter.receiverList.app.isInFullBackup()) {
                // Skip delivery if full backup in progress
                // If it's an ordered broadcast, we need to continue to the next receiver.
                //全备份的app接收这才会到这里
                if (ordered) {
                    skipReceiverLocked(r);
                }
            } else {
                //一般跑的这里
                r.receiverTime = SystemClock.uptimeMillis();
                maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
                maybeScheduleTempAllowlistLocked(filter.owningUid, r, r.options);
                //接下去运行的是performReceiveLocked
                //filter.receiverList.app是动态注册的callerApp, filter.receiverList.receiver是动态注册是传入的IIntentReceiver
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
                // parallel broadcasts are fire-and-forget, not bookended by a call to
                // finishReceiverLocked(), so we manage their activity-start token here
                if (filter.receiverList.app != null
                        && r.allowBackgroundActivityStarts && !r.ordered) {
                    postActivityStartTokenRemoval(filter.receiverList.app, r);
                }
            }
            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.mReceivers.removeCurReceiver(r);
                    // Something wrong, its oom adj could be downgraded, but not in a hurry.
                    mService.enqueueOomAdjTargetLocked(r.curApp);
                }
            }
            // And BroadcastRecord state related to ordered delivery, if appropriate
            if (ordered) {
                //异常还原
                r.receiver = null;
                r.curFilter = null;
                filter.receiverList.curBroadcast = null;
            }
        }
    }

  1. performReceiveLocked返回结果给动态接收者

performReceiveLocked返回结果给动态接收者(该函数还在广播发送时用于结果返回)


    void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
                              Intent intent, int resultCode, String data, Bundle extras,
                              boolean ordered, boolean sticky, int sendingUser)
            throws RemoteException {
        // Send the intent to the receiver asynchronously using one-way binder calls.
        if (app != null) {
            final IApplicationThread thread = app.getThread();
            if (thread != null) {
                // If we have an app thread, do the call through that so it is
                // correctly ordered with other one-way calls.
                try {
                    //调用app进程的scheduleRegisteredReceiver,分发到app进程
                    //scheduleRegisteredReceiver包括: updateProcessState进程状态更新/receiver.performReceive执行
                    //receiver调用的是LoadedApk.ReceiverDispatcher的performReceive -> mActivityThread.post一般是主线成去分发广播
                    thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser,
                            app.mState.getReportedProcState());
                    // TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
                    // DeadObjectException when the process isn't actually dead.
                    //} catch (DeadObjectException ex) {
                    // Failed to call into the process.  It's dying so just let it die and move on.
                    //    throw ex;
                } catch (RemoteException ex) {
                    // Failed to call into the process. It's either dying or wedged. Kill it gently.
                    synchronized (mService) {
                        Slog.w(TAG, "Can't deliver broadcast to " + app.processName
                                + " (pid " + app.getPid() + "). Crashing it.");
                        app.scheduleCrashLocked("can't deliver broadcast");
                    }
                    throw ex;
                }
            } else {
                // Application has died. Receiver doesn't exist.
                throw new RemoteException("app.thread must not be null");
            }
        } else {
            //否者直接给到receiver的performReceive
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
        }
    }
  1. ActivityThread.java的scheduleRegisteredReceiver(这里已经是app线程了)

IIntentReceiver在之前的文章“Android S动态广播注册流程”里面已经提到是:LoadedApk.ReceiverDispatcher得到mIIntentReceiver

//ActivityThread.java
        public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
                int resultCode, String dataStr, Bundle extras, boolean ordered,
                boolean sticky, int sendingUser, int processState) throws RemoteException {
            //更新app的进程状态processState
            updateProcessState(processState, false);
			//调用IIntentReceiver的performReceive发送广播
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
        }

//LoadedApk.java
//LoadedApk.ReceiverDispatcher.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 {
                    //mDispatcher是ReceiverDispatcher
                    rd = mDispatcher.get();
                }
                if (ActivityThread.DEBUG_BROADCAST) {
                    int seq = intent.getIntExtra("seq", -1);
                    Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
                            + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
                }
                if (rd != null) {
                    //一般执行的是这里LoadedApk.ReceiverDispatcher的performReceive
                    rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
                } else {
                    // The activity manager dispatched a broadcast to a registered
                    // receiver in this process, but before it could be delivered the
                    // receiver was unregistered.  Acknowledge the broadcast on its
                    // behalf so that the system's broadcast sequence can continue.
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing broadcast to unregistered receiver");
                    IActivityManager mgr = ActivityManager.getService();
                    try {
                        if (extras != null) {
                            extras.setAllowFds(false);
                        }
                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
            }

		//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) {
                Log.wtf(TAG, "Null intent received");
            } else {
                if (ActivityThread.DEBUG_BROADCAST) {
                    int seq = intent.getIntExtra("seq", -1);
                    Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
                            + " seq=" + seq + " to " + mReceiver);
                }
            }
			
			//这里是通过mActivityThread线程(一般是app主线程,也可以自己传入Handler scheduler当做调度线程)
			//实际是在调度线程中运行new Args的run方法
            if (intent == null || !mActivityThread.post(args.getRunnable())) {
                if (mRegistered && ordered) {
                    IActivityManager mgr = ActivityManager.getService();
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing sync broadcast to " + mReceiver);
                    args.sendFinished(mgr);
                }
            }
        }
  1. app动态注册的BroadcastReceiver接收与返回结果

=> BroadcastReceiver的onReceive执行
=> 处理完成后,调用AMS的finishReceiver,告诉系统该接受者已经处理完了

//LoadedApk.java
        final class Args extends BroadcastReceiver.PendingResult {
            private Intent mCurIntent;
            private final boolean mOrdered;
            private boolean mDispatched;
            private boolean mRunCalled;

            public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
                    boolean ordered, boolean sticky, int sendingUser) {
                super(resultCode, resultData, resultExtras,
                        mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
                        sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
                mCurIntent = intent;
                mOrdered = ordered;
            }

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

                    if (ActivityThread.DEBUG_BROADCAST) {
                        int seq = mCurIntent.getIntExtra("seq", -1);
                        Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
                                + " seq=" + seq + " to " + mReceiver);
                        Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
                                + " mOrderedHint=" + ordered);
                    }

                    final IActivityManager mgr = ActivityManager.getService();
                    final Intent intent = mCurIntent;
                    if (intent == null) {
                        Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
                                + (mRunCalled ? ", run() has already been called" : ""));
                    }

                    mCurIntent = null;
                    mDispatched = true;
                    mRunCalled = true;
                    if (receiver == null || intent == null || mForgotten) {
                        if (mRegistered && ordered) {
                            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                                    "Finishing null broadcast to " + mReceiver);
                            sendFinished(mgr);
                        }
                        return;
                    }

                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
                    try {
                        ClassLoader cl = mReceiver.getClass().getClassLoader();
                        intent.setExtrasClassLoader(cl);
                        // TODO: determine at registration time if caller is
                        // protecting themselves with signature permission
                        intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent),
                                mContext.getAttributionSource());
                        setExtrasClassLoader(cl);
                        receiver.setPendingResult(this);
						//这里就是调用BroadcastReceiver的onReceive方法了
						//如之前例子中,此时会输出"MyReceiver dynamic intent = android.intent.action.SCREEN_ON"
                        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(BroadcastReceiver.java)->
                        finish();
                    }
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                };
            }
        }

//BroadcastReceiver.java
        public final void finish() {
            if (mType == TYPE_COMPONENT) {
                final IActivityManager mgr = ActivityManager.getService();
                if (QueuedWork.hasPendingWork()) {
                    // If this is a broadcast component, we need to make sure any
                    // queued work is complete before telling AM we are done, so
                    // we don't have our process killed before that.  We now know
                    // there is pending work; put another piece of work at the end
                    // of the list to finish the broadcast, so we don't block this
                    // thread (which may be the main thread) to have it finished.
                    //
                    // Note that we don't need to use QueuedWork.addFinisher() with the
                    // runnable, since we know the AM is waiting for us until the
                    // executor gets to it.
                    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 {
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing broadcast to component " + mToken);
					//发送给静态组件后返回AMS的情况
                    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();
				//发送给动态接收者后返回AMS的情况,非order的是没有结果返回的
                sendFinished(mgr);
            }
        }

       //完成接收处理后app返回AMS
       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) {
                        //order的调用的多了mResultCode、mResultData、mResultExtras、
						//mAbortBroadcast(是否中断后续接收者,app使用abortBroadcast设置)
						//包含静态和动态接收者
                        am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
                                mAbortBroadcast, mFlags);
                    } else {
                        // This broadcast was sent to a component; it is not ordered,
                        // but we still need to tell the activity manager we are done.
						//非order的情况,这里只会是组件接收的时候返回
                        am.finishReceiver(mToken, 0, null, null, false, mFlags);
                    }
                } catch (RemoteException ex) {
                }
            }
        }

4.4.2 mPendingBroadcast挂起广播的处理

mPendingBroadcast是正在处理的有序队列中的广播,由于进程没有启动,先挂起了。
Need to start app 的时候会设置mPendingBroadcast = r

需要先把mPendingBroadcast处理完成才能处理下一个有序队列中的广播

        // Now take care of the next serialized one...

        // If we are waiting for a process to come up to handle the next
        // broadcast, then do nothing at this point.  Just in case, we
        // check that the process we're waiting for still exists.
        // 分析是建议打开日志 DEBUG_BROADCAST DEBUG_BROADCAST_BACKGROUND DEBUG_BROADCAST_DEFERRAL DEBUG_BROADCAST_LIGHT
        // 至于DEBUG_ALL也可以考虑打开
        // Need to start app 的时候会设置mPendingBroadcast = r;
        // 1. 如果进程没有启动,则首先启动进程startProcessLocked(am_proc_start)
        // 2. 并将这个广播放入mPendingBroadcast中去,同时mPendingBroadcast.curApp = 下一个处理广播的进程
        // 3. 当进程启动而且进行attachApplicationLocked(AMS)(am_proc_bound)/bindApplication的时候
        // 调用attachApplicationLocked(AMS)->sendPendingBroadcastsLocked->processCurBroadcastLocked将该广播传递给curApp-> scheduleReceiver(ActivityThread)
        // 此时也会清除mPendingBroadcast = null,代表已经处理过了
        // 4. 当广播处理完成后会从app回传AMS
        // 动态注册完成广播LoadedApk.ReceiverDispatcher.Args -> mActivityThread.post(args.getRunnable()) -> finish(BroadcastReceiver.java)
        // deliverToRegisteredReceiverLocked/performReceiveLocked -> app.thread.scheduleRegisteredReceiver -> receiver.performReceive
        // -> mActivityThread.post(args.getRunnable()) -> finish(BroadcastReceiver.java)
        // 静态注册完成广播 scheduleReceiver(ActivityThread) -> RECEIVER
        // -> handleReceiver(ActivityThread.java) -> finish(BroadcastReceiver.java)
        // => finish/sendFinished(BroadcastReceiver.java) -> am.finishReceiver
        // 5. ams收到curApp将广播处理完成,则调用r.queue.processNextBroadcastLocked继续处理下一个广播
        // finishReceiver(AMS) -> r.queue.processNextBroadcastLocked(BroadcastQueue)
        if (mPendingBroadcast != null) {
            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                    "processNextBroadcast [" + mQueueName + "]: waiting for "
                            + mPendingBroadcast.curApp);

            boolean isDead;
            //是否存在这个进程的pid
            if (mPendingBroadcast.curApp.getPid() > 0) {
                synchronized (mService.mPidsSelfLocked) {
                    //如果存在pid,则从mPidsSelfLocked中获取这个进程的ProcessRecord proc
                    ProcessRecord proc = mService.mPidsSelfLocked.get(
                            mPendingBroadcast.curApp.getPid());
                    //如果proc存在,而且没有发生crash,则isDead = false
                    isDead = proc == null || proc.mErrorState.isCrashing();
                }
            } else {
                //否则从mProcessList通过名字获取该进程的ProcessRecord proc
                final ProcessRecord proc = mService.mProcessList.getProcessNamesLOSP().get(
                        mPendingBroadcast.curApp.processName, mPendingBroadcast.curApp.uid);
                //如果proc存在,而且该进程正在启动中isPendingStart,则isDead = false
                isDead = proc == null || !proc.isPendingStart();
            }
            if (!isDead) {
                // It's still alive, so keep waiting
                //如果mPendingBroadcast还存在,则直接返回,等待其先处理
                //注意,这里等待mPendingBroadcast处理了才会有下一个广播的处理,不然一直再此等待
                return;
            } else {
                //如果app死掉了
                Slog.w(TAG, "pending app  ["
                        + mQueueName + "]" + mPendingBroadcast.curApp
                        + " died before responding to broadcast");
                mPendingBroadcast.state = BroadcastRecord.IDLE;
                //下一次处理这个BroadcastRecord的nextReceiver还是这个recIdx
                mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
                //app死掉了清除mPendingBroadcast = null, 跳过这个mPendingBroadcast
                mPendingBroadcast = null;
            }
        }

4.4.3 取出下一个有序队列中的广播

  1. 主要是通过mDispatcher的getNextBroadcastLocked来取出有序广播队列的广播(这里就只讲解其中的mOrderedBroadcasts,如我们上面有序广播放入的地方)

  2. 总的分发时间大于210s/60snumReceivers的时间,则发出总得广播超时,并且将这个广播给finish掉

  3. 如果已经完成了广播发送,而且发送时有设置IIntentReceiver resultTo(结果返回的地方),则调用performReceiveLocked,返回结果给到resultTo

  4. 如果已经完成了广播发送,则取消该order的超时设定,输出“Finished with ordered broadcast”类似日志

        boolean looped = false;

        do {
            final long now = SystemClock.uptimeMillis();
            //取得mAlarmBroadcasts(alarm挂起的广播)、mDeferredBroadcasts(如果存在order的广播在处理,这类延迟广播会按照deferUntil进行延迟)、
            // mOrderedBroadcasts 有序广播队列,依次取出来
            r = mDispatcher.getNextBroadcastLocked(now);

            if (r == null) {
                // No more broadcasts are deliverable right now, so all done!
                //如果存在延迟的广播mDeferredBroadcasts,则重新下一次调度scheduleBroadcastsLocked
                //不过一般上面BroadcastRecord r都取得出来(存在延迟的广播mDeferredBroadcasts, getNextBroadcastLocked得出来),
                // 也就是这里相当于没啥作用
                mDispatcher.scheduleDeferralCheckLocked(false);

                synchronized (mService.mAppProfiler.mProfilerLock) {
                    //将AMS所有挂起的gc进程mProcessesToGc进行按顺序的gc
                    mService.mAppProfiler.scheduleAppGcsLPf();
                }
                if (looped && !skipOomAdj) {
                    // If we had finished the last ordered broadcast, then
                    // make sure all processes have correct oom and sched
                    // adjustments.
                    //adj调整,原因是启动了receiver
                    mService.updateOomAdjPendingTargetsLocked(
                            OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
                }

                // when we have no more ordered broadcast on this queue, stop logging
                //现在已经没有mOrderedBroadcasts 有序广播队列, 则停止log的输出mLogLatencyMetrics = false
                if (mService.mUserController.mBootCompleted && mLogLatencyMetrics) {
                    mLogLatencyMetrics = false;
                }

                //结束本次processNextBroadcastLocked
                return;
            }

            //是否需要强制结束recevie
            boolean forceReceive = false;

            // Ensure that even if something goes awry with the timeout
            // detection, we catch "hung" broadcasts here, discard them,
            // and continue to make progress.
            //
            // This is only done if the system is ready so that early-stage receivers
            // don't get executed with timeouts; and of course other timeout-
            // exempt broadcasts are ignored.
            //numReceivers接收者的个数
            int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
            //systemReady之后mService.mProcessesReady = true
            //timeoutExempt只有ACTION_PRE_BOOT_COMPLETED才会设置为true
            //r.dispatchTime是开始分发该BroadcastRecord r的时间
            if (mService.mProcessesReady && !r.timeoutExempt && r.dispatchTime > 0) {
                //如果当前时间now > r.dispatchTime + (2 * mConstants.TIMEOUT(10s/60s) * numReceivers)
                //也就是总的分发时间大于2*10s/60s*numReceivers的时间,则告知这个广播出现anr
                //isAnrDeferrable是mtk加入的是否需要跳过anr的逻辑
                if ((numReceivers > 0) &&
                        (now > r.dispatchTime + (2 * mConstants.TIMEOUT * numReceivers)) &&
                        /// M: ANR Debug Mechanism
                        !mService.mAnrManager.isAnrDeferrable()) {
                    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
                    //设置强制结束recevie (forceReceive = true)
                    forceReceive = true;
                    r.state = BroadcastRecord.IDLE;
                }
            }

            if (r.state != BroadcastRecord.IDLE) {
                if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
                        "processNextBroadcast("
                                + mQueueName + ") called when not idle (state="
                                + r.state + ")");
                return;
            }

            // Is the current broadcast is done for any reason?
            // 如果没有r.receivers 或者 r.nextReceiver已经遍历完成最后一个了
            // 或者强制结束forceReceive,
            // 或者resultAbort为true(bortBroadcast(应用进程) -> finishReceiver(AMS)-> r.queue.finishReceiverLocked(BroadcastQueue))
            if (r.receivers == null || r.nextReceiver >= numReceivers
                    || r.resultAbort || forceReceive) {
                // Send the final result if requested
                //是否有resultTo,如果有将结果回传resultTo
                if (r.resultTo != null) {
                    boolean sendResult = true;

                    // if this was part of a split/deferral complex, update the refcount and only
                    // send the completion when we clear all of them
                    if (r.splitToken != 0) {
                        int newCount = mSplitRefcounts.get(r.splitToken) - 1;
                        if (newCount == 0) {
                            // done!  clear out this record's bookkeeping and deliver
                            if (DEBUG_BROADCAST_DEFERRAL) {
                                Slog.i(TAG_BROADCAST,
                                        "Sending broadcast completion for split token "
                                                + r.splitToken + " : " + r.intent.getAction());
                            }
                            mSplitRefcounts.delete(r.splitToken);
                        } else {
                            // still have some split broadcast records in flight; update refcount
                            // and hold off on the callback
                            if (DEBUG_BROADCAST_DEFERRAL) {
                                Slog.i(TAG_BROADCAST,
                                        "Result refcount now " + newCount + " for split token "
                                                + r.splitToken + " : " + r.intent.getAction()
                                                + " - not sending completion yet");
                            }
                            sendResult = false;
                            mSplitRefcounts.put(r.splitToken, newCount);
                        }
                    }
                    if (sendResult) {
                        if (r.callerApp != null) {
                            mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(
                                    r.callerApp);
                        }
                        try {
                            if (DEBUG_BROADCAST) {
                                Slog.i(TAG_BROADCAST, "Finishing broadcast [" + mQueueName + "] "
                                        + r.intent.getAction() + " app=" + r.callerApp);
                            }
                            //将结果返回给app
                            performReceiveLocked(r.callerApp, r.resultTo,
                                    new Intent(r.intent), r.resultCode,
                                    r.resultData, r.resultExtras, false, false, r.userId);
                            // Set this to null so that the reference
                            // (local and remote) isn't kept in the mBroadcastHistory.
                            r.resultTo = null;
                        } catch (RemoteException e) {
                            r.resultTo = null;
                            Slog.w(TAG, "Failure ["
                                    + mQueueName + "] sending broadcast result of "
                                    + r.intent, e);
                        }
                    }
                }

                if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");
                //取消广播超时
                cancelBroadcastTimeoutLocked();

                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                        "Finished with ordered broadcast " + r);

                // ... and on to the next...
                //添加到广播历史中去,代表完成了
                addBroadcastToHistoryLocked(r);
                if (r.intent.getComponent() == null && r.intent.getPackage() == null
                        && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                    // This was an implicit broadcast... let's record it for posterity.
                    mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
                            r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
                }

                //完成odered的广播后,在retireBroadcastLocked中设置mCurrentBroadcast = null(一般在r == mCurrentBroadcast时)
                mDispatcher.retireBroadcastLocked(r);
                //r == null继续while循环,取出下一个广播
                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.
            // addDeferredBroadcast的时候会将deferred设置成ture,
            // 如果这个广播没有进行延迟,则判断一下是否需要延迟
            if (!r.deferred) {
                //获取下一个nextReceiver的uid
                final int receiverUid = r.getReceiverUid(r.receivers.get(r.nextReceiver));
                //如果
                if (mDispatcher.isDeferringLocked(receiverUid)) {
                    if (DEBUG_BROADCAST_DEFERRAL) {
                        Slog.i(TAG_BROADCAST, "Next receiver in " + r + " uid " + receiverUid
                                + " at " + r.nextReceiver + " is under deferral");
                    }
                    // 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;
                    // 下一个Receiver将延迟,再下一个Receiver已经没有了
                    if (r.nextReceiver + 1 == numReceivers) {
                        if (DEBUG_BROADCAST_DEFERRAL) {
                            Slog.i(TAG_BROADCAST, "Sole receiver of " + r
                                    + " is under deferral; setting aside and proceeding");
                        }
                        defer = r;
                        // 下一个Receiver将延迟,再下一个Receiver已经没有了,
                        // 则在retireBroadcastLocked中设置mCurrentBroadcast = null(一般在r == mCurrentBroadcast时)
                        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);
                        if (DEBUG_BROADCAST_DEFERRAL) {
                            Slog.i(TAG_BROADCAST, "Post split:");
                            Slog.i(TAG_BROADCAST, "Original broadcast receivers:");
                            for (int i = 0; i < r.receivers.size(); i++) {
                                Slog.i(TAG_BROADCAST, "  " + r.receivers.get(i));
                            }
                            Slog.i(TAG_BROADCAST, "Split receivers:");
                            for (int i = 0; i < defer.receivers.size(); i++) {
                                Slog.i(TAG_BROADCAST, "  " + defer.receivers.get(i));
                            }
                        }
                        // 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);
                                if (DEBUG_BROADCAST_DEFERRAL) {
                                    Slog.i(TAG_BROADCAST,
                                            "Broadcast needs split refcount; using new token "
                                                    + r.splitToken);
                                }
                            } else {
                                // new split from an already-refcounted situation; increment count
                                final int curCount = mSplitRefcounts.get(token);
                                if (DEBUG_BROADCAST_DEFERRAL) {
                                    if (curCount == 0) {
                                        Slog.wtf(TAG_BROADCAST,
                                                "Split refcount is zero with token for " + r);
                                    }
                                }
                                mSplitRefcounts.put(token, curCount + 1);
                                if (DEBUG_BROADCAST_DEFERRAL) {
                                    Slog.i(TAG_BROADCAST, "New split count for token " + token
                                            + " is " + (curCount + 1));
                                }
                            }
                        }
                    }
                    //将defer添加到延迟广播中,按照uid放入
                    mDispatcher.addDeferredBroadcast(receiverUid, defer);
                    //r == null会继续while循环
                    r = null;
                    looped = true;
                    continue;
                }
            }
        } while (r == null);

//BroadcastDispatcher.java
    //获取下一个处理的广播BroadcastRecord next,上面mDispatcher.getNextBroadcastLocked调用
	//这里除了mOrderedBroadcasts有序广播队列,还多了mAlarmBroadcasts(alarm设置的)、mDeferredBroadcasts(延迟广播)的概念
    public BroadcastRecord getNextBroadcastLocked(final long now) {
        //如果当前mCurrentBroadcast还在处理,则直接返回mCurrentBroadcast
        if (mCurrentBroadcast != null) {
            return mCurrentBroadcast;
        }

        //是否有oder的广播,如果有,则someQueued = true
        final boolean someQueued = !mOrderedBroadcasts.isEmpty();

        BroadcastRecord next = null;

        //mAlarmBroadcasts不为空的时候
        if (!mAlarmBroadcasts.isEmpty()) {
            // 首先取出的就是mAlarmBroadcasts中的Deferrals d
            // 然后取出BroadcastRecord next = d.broadcasts.remove(0)
            next = popLocked(mAlarmBroadcasts);
            if (DEBUG_BROADCAST_DEFERRAL && next != null) {
                Slog.i(TAG, "Next broadcast from alarm targets: " + next);
            }
        }

        //如果next为null,而且mDeferredBroadcasts还有内容
        if (next == null && !mDeferredBroadcasts.isEmpty()) {
            // We're going to deliver either:
            // 1. the next "overdue" deferral; or
            // 2. the next ordinary ordered broadcast; *or*
            // 3. the next not-yet-overdue deferral.

            for (int i = 0; i < mDeferredBroadcasts.size(); i++) {
                Deferrals d = mDeferredBroadcasts.get(i);

                //查看一下当前now是否小于d.deferUntil(延迟分发时间,默认是延迟5s)
                //而且someQueued为true,就是有order的时候才break?(跳过这个延迟广播)
                if (now < d.deferUntil && someQueued) {
                    // stop looking when we haven't hit the next time-out boundary
                    // but only if we have un-deferred broadcasts waiting,
                    // otherwise we can deliver whatever deferred broadcast
                    // is next available.
                    break;
                }

                if (d.broadcasts.size() > 0) {
                    //取出next
                    next = d.broadcasts.remove(0);
                    // apply deferral-interval decay policy and move this uid's
                    // deferred broadcasts down in the delivery queue accordingly
                    //将这个Deferrals d从mDeferredBroadcasts移除,代表已经处理了
                    mDeferredBroadcasts.remove(i); // already 'd'

                    //deferredBy*0.75在赋值给deferredBy(第一次deferredBy是5s)
                    d.deferredBy = calculateDeferral(d.deferredBy);

                    //延迟时间deferUntil + deferredBy*0.75,再给新的Deferrals d
                    d.deferUntil += d.deferredBy;
                    //重新根据deferUntil排序放入mDeferredBroadcasts

                    //貌似d.broadcasts如果此时为null,不需要再次将d加入mDeferredBroadcasts了吧?
                    insertLocked(mDeferredBroadcasts, d);
                    if (DEBUG_BROADCAST_DEFERRAL) {
                        Slog.i(TAG, "Next broadcast from deferrals " + next
                                + ", deferUntil now " + d.deferUntil);
                    }
                    break;
                }
            }
        }

        //如果next还是null,而且someQueued=true(有oder的广播)
        if (next == null && someQueued) {
            //则取出order的广播
            next = mOrderedBroadcasts.remove(0);
            if (DEBUG_BROADCAST_DEFERRAL) {
                Slog.i(TAG, "Next broadcast from main queue: " + next);
            }
        }

        //当前正在处理的广播
        mCurrentBroadcast = next;
        return next;
    }

4.4.4 处理下一个接收者nextReceiver

  1. 第一个接收者会设置r.dispatchTime广播分发时间(SystemClock.uptimeMillis当前时间,不受系统时间修改影响)、
    r.dispatchClockTime分发的系统时间(System.currentTimeMillis,该时间会随系统时间变化而变化)
  2. 设置超时时间setBroadcastTimeoutLocked(前台是10s超时,后台是60s超时,针对是单个注册者的时间),
    每个有序的接受者,都是从取出开始算时间r.receiverTime = SystemClock.uptimeMillis();
  3. 开始处理时输出如:"Processing ordered broadcast"类似的日志
        // Get the next receiver...
        // 正常取出一个广播r != null
        //先将nextReceiver赋值给recIdx,然后nextReceiver++,下一次进来nextReceiver就不会时当前这个了
        int recIdx = r.nextReceiver++;

        // Keep track of when this receiver started, and make sure there
        // is a timeout message pending to kill it if need be.
        //设置receiver接受时间receiverTime
        r.receiverTime = SystemClock.uptimeMillis();
        if (recIdx == 0) {
            //如果recIdx是第一个,这将receiverTime设置给dispatchTime(这个广播的分发时间)
            r.dispatchTime = r.receiverTime;
            //设置分发的系统时间(修改系统时间这个时间会变化)
            r.dispatchClockTime = System.currentTimeMillis();

            if (mLogLatencyMetrics) {
                //输出日志到FrameworkStatsLog中
                FrameworkStatsLog.write(
                        FrameworkStatsLog.BROADCAST_DISPATCH_LATENCY_REPORTED,
                        r.dispatchClockTime - r.enqueueClockTime);
            }

            //trace相关
            if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
                        System.identityHashCode(r));
                Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
                        System.identityHashCode(r));
            }
            //输出开始发送order的广播
            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
                    + mQueueName + "] " + r);
        }

        //如果还没有设置超时时间,此处设置超时时间
        if (! mPendingBroadcastTimeoutMessage) {
            //单个广播超时时间是10s(前台)或者60s(后台广播)
            long timeoutTime = r.receiverTime + mConstants.TIMEOUT;
            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
                    "Submitting BROADCAST_TIMEOUT_MSG ["
                            + mQueueName + "] for " + r + " at " + timeoutTime);
            setBroadcastTimeoutLocked(timeoutTime);
        }

4.4.5 发送给动态注册的order注册者

  1. 使用的方法是deliverToRegisteredReceiverLocked,和平行广播类似,都是处理动态注册的接受者,
    只是这里是按顺序,一个个处理
  2. 输出日志如:“Delivering ordered [foreground/background] to registered ***”
        final BroadcastOptions brOptions = r.options;

        //获取下一个接受者
        final Object nextReceiver = r.receivers.get(recIdx);

        //如果这个nextReceiver为BroadcastFilter类型(动态注册广播接收者)
        // BroadcastRecord的receivers还有另一种类型ResolveInfo,是从PMS中查询得到的静态注册广播类型
        if (nextReceiver instanceof BroadcastFilter) {
            // Simple case: this is a registered receiver who gets
            // a direct call.
            BroadcastFilter filter = (BroadcastFilter)nextReceiver;
            if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                    "Delivering ordered ["
                            + mQueueName + "] to registered "
                            + filter + ": " + r);
            //发送给动态注册的广播
            deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
            //如果r.receiver == null(没有正在执行的广播)
            //而且该广播是非order的
            if (r.receiver == null || !r.ordered) {
                // The receiver has already finished, so schedule to
                // process the next one.
                if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Quick finishing ["
                        + mQueueName + "]: ordered="
                        + r.ordered + " receiver=" + r.receiver);
                r.state = BroadcastRecord.IDLE;
                //已经发出去执行了,无需等待,直接处理下一个
                scheduleBroadcastsLocked();
            } else {
                if (filter.receiverList != null) {
                    maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
                    // r is guaranteed ordered at this point, so we know finishReceiverLocked()
                    // will get a callback and handle the activity start token lifecycle.
                }
            }
            //直接返回,代表本次完成,一次处理一个广播中的nextReceiver
            return;
        }

4.4.6 静态注册者跳过的逻辑

跳过的逻辑较多,
这里注意一下“Background execution not allowed”,如果flag设置了FLAG_RECEIVER_EXCLUDE_BACKGROUND则无法让后台接收,
或者getComponent/getPackage都为null,而且没有设置FLAG_RECEIVER_INCLUDE_BACKGROUND,而且没有requiredPermissions,
则无法发送给后台的进程(进程状态procState>=PROCESS_STATE_TRANSIENT_BACKGROUND(8)属于广播的后台进程)

        // Hard case: need to instantiate the receiver, possibly
        // starting its application process to host it.

        //静态广播的处理
        ResolveInfo info =
                (ResolveInfo)nextReceiver;
        ComponentName component = new ComponentName(
                info.activityInfo.applicationInfo.packageName,
                info.activityInfo.name);

        //注意这里是静态广播接收跳过的逻辑,动态注册跳过的逻辑是在deliverToRegisteredReceiverLocked中
        boolean skip = false;
        //判断是否需要跳过
		//sdk的一些判断
        if (brOptions != null &&
                (info.activityInfo.applicationInfo.targetSdkVersion
                        < brOptions.getMinManifestReceiverApiLevel() ||
                        info.activityInfo.applicationInfo.targetSdkVersion
                                > brOptions.getMaxManifestReceiverApiLevel())) {
            Slog.w(TAG, "Target SDK mismatch: receiver " + info.activityInfo
                    + " targets " + info.activityInfo.applicationInfo.targetSdkVersion
                    + " but delivery restricted to ["
                    + brOptions.getMinManifestReceiverApiLevel() + ", "
                    + brOptions.getMaxManifestReceiverApiLevel()
                    + "] broadcasting " + broadcastDescription(r, component));
            skip = true;
        }
		
		//查看发送者的uid和接受者的uid是否一样,或者是否系统uid,确定一些是否两者有设定关联关系association
		//默认返回是true
        if (!skip && !mService.validateAssociationAllowedLocked(r.callerPackage, r.callingUid,
                component.getPackageName(), info.activityInfo.applicationInfo.uid)) {
            Slog.w(TAG, "Association not allowed: broadcasting "
                    + broadcastDescription(r, component));
            skip = true;
        }
        if (!skip) {
            //看一下意图防火墙mIntentFirewall是否有block该发送行为
            skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
                    r.callingPid, r.resolvedType, info.activityInfo.applicationInfo.uid);
            if (skip) {
                Slog.w(TAG, "Firewall blocked: broadcasting "
                        + broadcastDescription(r, component));
            }
        }
		
		//权限相关的的检查
        int perm = mService.checkComponentPermission(info.activityInfo.permission,
                r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
                info.activityInfo.exported);
        if (!skip && perm != PackageManager.PERMISSION_GRANTED) {
            if (!info.activityInfo.exported) {
                Slog.w(TAG, "Permission Denial: broadcasting "
                        + broadcastDescription(r, component)
                        + " is not exported from uid " + info.activityInfo.applicationInfo.uid);
            } else {
                Slog.w(TAG, "Permission Denial: broadcasting "
                        + broadcastDescription(r, component)
                        + " requires " + info.activityInfo.permission);
            }
            skip = true;
        } else if (!skip && info.activityInfo.permission != null) {
            final int opCode = AppOpsManager.permissionToOpCode(info.activityInfo.permission);
            if (opCode != AppOpsManager.OP_NONE && mService.getAppOpsManager().noteOpNoThrow(opCode,
                    r.callingUid, r.callerPackage, r.callerFeatureId,
                    "Broadcast delivered to " + info.activityInfo.name)
                    != AppOpsManager.MODE_ALLOWED) {
                Slog.w(TAG, "Appop Denial: broadcasting "
                        + broadcastDescription(r, component)
                        + " requires appop " + AppOpsManager.permissionToOp(
                        info.activityInfo.permission));
                skip = true;
            }
        }

        boolean isSingleton = false;
        try {
            isSingleton = mService.isSingleton(info.activityInfo.processName,
                    info.activityInfo.applicationInfo,
                    info.activityInfo.name, info.activityInfo.flags);
        } catch (SecurityException e) {
            Slog.w(TAG, e.getMessage());
            skip = true;
        }
        if ((info.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
            if (ActivityManager.checkUidPermission(
                    android.Manifest.permission.INTERACT_ACROSS_USERS,
                    info.activityInfo.applicationInfo.uid)
                    != PackageManager.PERMISSION_GRANTED) {
                Slog.w(TAG, "Permission Denial: Receiver " + component.flattenToShortString()
                        + " requests FLAG_SINGLE_USER, but app does not hold "
                        + android.Manifest.permission.INTERACT_ACROSS_USERS);
                skip = true;
            }
        }
        if (!skip && info.activityInfo.applicationInfo.isInstantApp()
                && r.callingUid != info.activityInfo.applicationInfo.uid) {
            Slog.w(TAG, "Instant App Denial: receiving "
                    + r.intent
                    + " to " + component.flattenToShortString()
                    + " due to sender " + r.callerPackage
                    + " (uid " + r.callingUid + ")"
                    + " Instant Apps do not support manifest receivers");
            skip = true;
        }
        if (!skip && r.callerInstantApp
                && (info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0
                && r.callingUid != info.activityInfo.applicationInfo.uid) {
            Slog.w(TAG, "Instant App Denial: receiving "
                    + r.intent
                    + " to " + component.flattenToShortString()
                    + " requires receiver have visibleToInstantApps set"
                    + " due to sender " + r.callerPackage
                    + " (uid " + r.callingUid + ")");
            skip = true;
        }
		
		//crash的app则直接跳过
        if (r.curApp != null && r.curApp.mErrorState.isCrashing()) {
            // If the target process is crashing, just skip it.
            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) {
                Slog.w(TAG_BROADCAST,
                        "Skipping delivery to " + info.activityInfo.packageName + " / "
                                + info.activityInfo.applicationInfo.uid
                                + " : package no longer available");
                skip = true;
            }
        }

        // If permissions need a review before any of the app components can run, we drop
        // the broadcast and if the calling app is in the foreground and the broadcast is
        // explicit we launch the review UI passing it a pending intent to send the skipped
        // broadcast.
        if (!skip) {
            //判断是否需要权限来启动,如果需要则跳过(如果调用者是前台,而且发送到特定组件,则启动权限申请的ui界面)
            if (!requestStartTargetPermissionsReviewIfNeededLocked(r,
                    info.activityInfo.packageName, UserHandle.getUserId(
                            info.activityInfo.applicationInfo.uid))) {
                Slog.w(TAG_BROADCAST,
                        "Skipping delivery: permission review required for "
                                + broadcastDescription(r, component));
                skip = true;
            }
        }

        // This is safe to do even if we are skipping the broadcast, and we need
        // this information now to evaluate whether it is going to be allowed to run.
        //接收者的uid
        final int receiverUid = info.activityInfo.applicationInfo.uid;
        // If it's a singleton, it needs to be the same app or a special app
        if (r.callingUid != Process.SYSTEM_UID && isSingleton
                && mService.isValidSingletonCall(r.callingUid, receiverUid)) {
            info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0);
        }
        //接受者的进程名字
        String targetProcess = info.activityInfo.processName;

        //接受者的进程ProcessRecord app,这个可能为null,也就是进程未启动
        ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
                info.activityInfo.applicationInfo.uid);

        if (!skip) {
            final int allowed = mService.getAppStartModeLOSP(
                    info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
                    info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false, false);

/*
//进程状态,只有小于8才会被认为可以接收广播(不带getComponent、getPackage)
    public static final boolean isProcStateBackground(int procState) {
        return procState >= PROCESS_STATE_TRANSIENT_BACKGROUND;
    }
    //PROCESS_STATE_TRANSIENT_BACKGROUND后台临时的一个状态(一般的含义,如toasts)
    //1.如果设置了getForcingToImportant不为null(调用AMS的setProcessImportant设置),会设置该状态,
    //而且adj是用户可感知的PERCEPTIBLE_APP_ADJ,例如toasts是这种情况(NotificationManagerService中调用setProcessImportant)
    //2.AMS的mBackupTargets是该app,且其adj大于BACKUP_APP_ADJ,会设置该值
    //3.service服务依赖:如果设置了BIND_NOT_FOREGROUND(非前台绑定)而且没有设置BIND_IMPORTANT_BACKGROUND(绑定重要后台)的时候,
    //且客户端状态优先级小于该值时,会设置该值
    TRANSIENT_BACKGROUND = 8,
*/

            if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                // We won't allow this receiver to be launched if the app has been
                // completely disabled from launches, or it was not explicitly sent
                // to it and the app is in a state that should not receive it
                // (depending on how getAppStartModeLOSP has determined that).
                if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
                    Slog.w(TAG, "Background execution disabled: receiving "
                            + r.intent + " to "
                            + component.flattenToShortString());
                    skip = true;
                    //如果flag设置了FLAG_RECEIVER_EXCLUDE_BACKGROUND则无法让后台接收
                    //或者getComponent/getPackage都为null,而且没有设置FLAG_RECEIVER_INCLUDE_BACKGROUND,而且没有requiredPermissions
                    //如ACTION_BOOT_COMPLETED是有设置FLAG_RECEIVER_INCLUDE_BACKGROUND,所以静态广播无需权限就可以直接接收
                } 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");
        }

		//处理不包含的权限excludedPermissions
        if (!skip && r.excludedPermissions != null && r.excludedPermissions.length > 0) {
            for (int i = 0; i < r.excludedPermissions.length; i++) {
                String excludedPermission = r.excludedPermissions[i];
                try {
                    perm = AppGlobals.getPackageManager()
                            .checkPermission(excludedPermission,
                                    info.activityInfo.applicationInfo.packageName,
                                    UserHandle
                                            .getUserId(info.activityInfo.applicationInfo.uid));
                } catch (RemoteException e) {
                    perm = PackageManager.PERMISSION_DENIED;
                }

                int appOp = AppOpsManager.permissionToOpCode(excludedPermission);
                if (appOp != AppOpsManager.OP_NONE) {
                    // When there is an app op associated with the permission,
                    // skip when both the permission and the app op are
                    // granted.
                    if ((perm == PackageManager.PERMISSION_GRANTED) && (
                            mService.getAppOpsManager().checkOpNoThrow(appOp,
                                    info.activityInfo.applicationInfo.uid,
                                    info.activityInfo.packageName)
                                    == AppOpsManager.MODE_ALLOWED)) {
                        skip = true;
                        break;
                    }
                } else {
                    // When there is no app op associated with the permission,
                    // skip when permission is granted.
                    if (perm == PackageManager.PERMISSION_GRANTED) {
                        skip = true;
                        break;
                    }
                }
            }
        }

		//处理需要包含的权限requiredPermission
        if (!skip && info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
                r.requiredPermissions != null && r.requiredPermissions.length > 0) {
            for (int i = 0; i < r.requiredPermissions.length; i++) {
                String requiredPermission = r.requiredPermissions[i];
                try {
                    perm = AppGlobals.getPackageManager().
                            checkPermission(requiredPermission,
                                    info.activityInfo.applicationInfo.packageName,
                                    UserHandle
                                            .getUserId(info.activityInfo.applicationInfo.uid));
                } catch (RemoteException e) {
                    perm = PackageManager.PERMISSION_DENIED;
                }
                if (perm != PackageManager.PERMISSION_GRANTED) {
                    Slog.w(TAG, "Permission Denial: receiving "
                            + r.intent + " to "
                            + component.flattenToShortString()
                            + " requires " + requiredPermission
                            + " due to sender " + r.callerPackage
                            + " (uid " + r.callingUid + ")");
                    skip = true;
                    break;
                }
                int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
                if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp) {
                    if (!noteOpForManifestReceiver(appOp, r, info, component)) {
                        skip = true;
                        break;
                    }
                }
            }
        }
        if (!skip && r.appOp != AppOpsManager.OP_NONE) {
            //AppOps相关判断
            if (!noteOpForManifestReceiver(r.appOp, r, info, component)) {
                skip = true;
            }
        }

        //上面都是各类判断是否需要跳过的逻辑skip
        if (skip) {
            if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                    "Skipping delivery of ordered [" + mQueueName + "] "
                            + r + " for reason described above");

            //如果需要跳过,标定当前r.delivery[recIdx]为skipped
            r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
            //跳过的时候清空r.receiver = null
            r.receiver = null;
            r.curFilter = null;
            r.state = BroadcastRecord.IDLE;
            //静态广播跳过++
            r.manifestSkipCount++;
            //继续下一个分发
            scheduleBroadcastsLocked();
            return;
        }

4.4.7 发送给已经启动了的静态注册者

  1. 对于已经启动了的静态注册者,则直接调用processCurBroadcastLocked去发送给静态注册者
  2. 静态接收者都是在APP主线程中分发
  3. APP线程handleReceiver会新建BroadcastReceiver实例,执行onReceive方法,然后调用AMS的finishReceiver方法

ps: 注意一下,此处广播记录的状态设置成app接收“r.state = BroadcastRecord.APP_RECEIVE”,
设置当前接收的组件r.curComponent = component

        //静态广播Count执行++
        r.manifestCount++;

        //标定当前r.delivery[recIdx]为分发DELIVERED
        r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
        //状态修改成app接收APP_RECEIVE,后面该receive finishReceiver返回的时候APP_RECEIVE或BroadcastRecord.CALL_DONE_RECEIVE才会继续处理下一个
        r.state = BroadcastRecord.APP_RECEIVE;
        //当前接收组件curComponent
        r.curComponent = component;
        //当前的receiver
        r.curReceiver = info.activityInfo;
        if (DEBUG_MU && r.callingUid > UserHandle.PER_USER_RANGE) {
            Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, "
                    + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = "
                    + receiverUid);
        }
        final boolean isActivityCapable =
                (brOptions != null && brOptions.getTemporaryAppAllowlistDuration() > 0);
        maybeScheduleTempAllowlistLocked(receiverUid, r, brOptions);

        // Report that a component is used for explicit broadcasts.
        if (r.intent.getComponent() != null && r.curComponent != null
                && !TextUtils.equals(r.curComponent.getPackageName(), r.callerPackage)) {
            mService.mUsageStatsService.reportEvent(
                    r.curComponent.getPackageName(), r.userId, Event.APP_COMPONENT_USED);
        }

        // Broadcast is being executed, its package can't be stopped.
        try {
            //设置包的stop状态是false(需要启动改应用了,包不再是stop了)
            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);
        }

        // Is this receiver's application already running?
        //如果app之前已经启动
        if (app != null && app.getThread() != null && !app.isKilled()) {
            try {
                app.addPackage(info.activityInfo.packageName,
                        info.activityInfo.applicationInfo.longVersionCode, mService.mProcessStats);
                maybeAddAllowBackgroundActivityStartsToken(app, r);
                //则直接发送该广播到app中
                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);
                // If some unexpected exception happened, just skip
                // this broadcast.  At this point we are not in the call
                // from a client, so throwing an exception out from here
                // will crash the entire system instead of just whoever
                // sent the broadcast.
                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.
        }

//发送给静态注册者的函数processCurBroadcastLocked
    private final void processCurBroadcastLocked(BroadcastRecord r,
                                                 ProcessRecord app) throws RemoteException {
        if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                "Process cur broadcast " + r + " for app " + app);
        final IApplicationThread thread = app.getThread();
        if (thread == null) {
            throw new RemoteException();
        }
        if (app.isInFullBackup()) {
            skipReceiverLocked(r);
            return;
        }

        //processCurBroadcastLocked的时候,会有r.receiver的设置
        r.receiver = thread.asBinder();
        r.curApp = app;
        final ProcessReceiverRecord prr = app.mReceivers;
        prr.addCurReceiver(r);
        app.mState.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
        mService.updateLruProcessLocked(app, false, null);
        // Make sure the oom adj score is updated before delivering the broadcast.
        // Force an update, even if there are other pending requests, overall it still saves time,
        // because time(updateOomAdj(N apps)) <= N * time(updateOomAdj(1 app)).
        mService.enqueueOomAdjTargetLocked(app);
        mService.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);

        // Tell the application to launch this receiver.
		//r.curComponent是发送给静态接收者的时候设置的组件名字
        r.intent.setComponent(r.curComponent);

        boolean started = false;
        try {
            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                    "Delivering to component " + r.curComponent
                            + ": " + r);
            mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
                    PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
            //发送给app主线程的scheduleReceiver
            thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
                    mService.compatibilityInfoForPackage(r.curReceiver.applicationInfo),
                    r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
                    app.mState.getReportedProcState());
            if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                    "Process cur broadcast " + r + " DELIVERED for app " + app);
            started = true;
        } finally {
            if (!started) {
                if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                        "Process cur broadcast " + r + ": NOT STARTED!");
                //没有启动成功,还原状态
                r.receiver = null;
                r.curApp = null;
                prr.removeCurReceiver(r);
            }
        }
    }

//ActivityThread.java
        //APP的接受者,在主线程中运行
        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);
        }

        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
			//...
                case RECEIVER:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
					//处理广播接收者
                    handleReceiver((ReceiverData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
			//...
        }

    private void handleReceiver(ReceiverData data) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        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;
		//新建一个静态接收者的实例BroadcastReceiver
        try {
            app = packageInfo.makeApplication(false, mInstrumentation);
            context = (ContextImpl) app.getBaseContext();
            if (data.info.splitName != null) {
                context = (ContextImpl) context.createContextForSplit(data.info.splitName);
            }
            if (data.info.attributionTags != null && data.info.attributionTags.length > 0) {
                final String attributionTag = data.info.attributionTags[0];
                context = (ContextImpl) context.createAttributionContext(attributionTag);
            }
            java.lang.ClassLoader cl = context.getClassLoader();
            data.intent.setExtrasClassLoader(cl);
            data.intent.prepareToEnterProcess(
                    isProtectedComponent(data.info) || isProtectedBroadcast(data.intent),
                    context.getAttributionSource());
            data.setExtrasClassLoader(cl);
			//通过class loader,新建一个接收者的实例,(BroadcastReceiver) cl.loadClass(className).newInstance()
			//如实例化MyReceiver
            receiver = packageInfo.getAppFactory()
                    .instantiateReceiver(cl, data.info.name, data.intent);
        } catch (Exception e) {
            if (DEBUG_BROADCAST) Slog.i(TAG,
                    "Finishing failed broadcast to " + data.intent.getComponent());
            data.sendFinished(mgr);
            throw new RuntimeException(
                "Unable to instantiate receiver " + component
                + ": " + e.toString(), e);
        }

        try {
            if (localLOGV) Slog.v(
                TAG, "Performing receive of " + data.intent
                + ": app=" + app
                + ", appName=" + app.getPackageName()
                + ", pkg=" + packageInfo.getPackageName()
                + ", comp=" + data.intent.getComponent().toShortString()
                + ", dir=" + packageInfo.getAppDir());

            sCurrentBroadcastIntent.set(data.intent);
            receiver.setPendingResult(data);
			//执行app定义的onReceive方法,如执行MyReceiver的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) {
            //BroadcastReceiver.PendingResul(ReceiverData继承PendingResul)的finish
			//具体过程和“4.4.1 mParallelBroadcasts平行广播的分发”是类似的
            data.finish();
        }
    }

4.4.8 启动静态注册接收者的进程

  1. 如果静态注册的接受者进程没有启动,则需要启动,并且挂起该广播mPendingBroadcast分发
        // Not running -- get it started, to be executed when the app comes up.
        //否则第一步,我们需要先启动该进程
        if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                "Need to start app ["
                        + mQueueName + "] " + targetProcess + " for broadcast " + r);
        //启动进程ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE(延迟敏感的)标签用于确定fork进程时是否需要使用usap
        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);
        if (r.curApp == null) {
            // Ah, this recipient is unavailable.  Finish it if necessary,
            // and mark the broadcast record as ready for the next.
            //当无法启动app的时候,完成这个广播BroadcastRecord r的分发finishReceiverLocked
            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;
        }

        maybeAddAllowBackgroundActivityStartsToken(r.curApp, r);

        // Need to start app 需要先启动该进程会设置mPendingBroadcast = r;
        //启动进程后会调用attachApplicationLocked(AMS)、bindApplication(IApplicationThread)
        //attachApplicationLocked(AMS)-> sendPendingBroadcastsLocked 会处理mPendingBroadcast
        mPendingBroadcast = r;
        //mPendingBroadcastRecvIndex是当前需要处理recevie的recIdx
        mPendingBroadcastRecvIndex = recIdx;
    }
  1. 从APP进程启动到回传AMS

=> mService.startProcessLocked启动进程后,
会调用ActivityThread的main方法:创建main loop,调用thread.attach,Looper.loop开始消息队列的循环

//ActivityThread.java
    public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        // Install selective syscall interception
        AndroidOs.install();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        // Call per-process mainline module initialization.
		//google main line的模块初始化
        initializeMainlineModules();

		//设置该进程刚刚创建,名字是""
		//在handleBindApplication之后app才会设置成对应的进程名字processName
        Process.setArgV0("");

		//准备主线程,此处H mH = new H();才能从Looper.myLooper()获取主线程的sMainLooper
        Looper.prepareMainLooper();

        // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
        // It will be in the format "seq=114"
        long startSeq = 0;
        if (args != null) {
            for (int i = args.length - 1; i >= 0; --i) {
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
		
		//这里是接下去的流程
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
		//开始loop的循环,此时ActivityThread主线程mH的消息队列才开始分发
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

	//附着方法attach
    private void attach(boolean system, long startSeq) {
        sCurrentActivityThread = this;
        mConfigurationController = new ConfigurationController(this);
        mSystemThread = system;
        if (!system) {
            //app进程的逻辑
            android.ddm.DdmHandleAppName.setAppName("",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try {
                //调用的是AMS的attachApplication
                mgr.attachApplication(mAppThread, startSeq);
            //...
        } else {
            // Don't set application object here -- if the system crashes,
            // we can't display an alert, we just want to die die die.
			//系统进程的逻辑
            android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());
            try {
                mInstrumentation = new Instrumentation();
                mInstrumentation.basicInit(this);
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }

        //...
    }
  1. AMS开始处理挂起的广播

=> AMS收到app的attachApplication,查看是否有挂起的广播isPendingBroadcastProcessLocked,
如果有则让广播队列处理该app挂起的广播sendPendingBroadcastsLocked

//ActivityManagerService.java
    //从app调用的attachApplication(附着在应用)方法
    public final void attachApplication(IApplicationThread thread, long startSeq) {
        if (thread == null) {
            throw new SecurityException("Invalid application interface");
        }
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
			//attachApplicationLocked,加个Locked,这类方法代表需要上锁才能调用
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            Binder.restoreCallingIdentity(origId);
        }
    }

    private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
        //...
		//绑定pid到ProcessRecord,用于死亡回调AppDeathRecipient
        if (DEBUG_ALL) Slog.v(
                TAG, "Binding process pid " + pid + " to record " + app);

        final String processName = app.processName;
        try {
            AppDeathRecipient adr = new AppDeathRecipient(
                    app, pid, thread);
            thread.asBinder().linkToDeath(adr, 0);
            app.setDeathRecipient(adr);
        } catch (RemoteException e) {
            app.resetPackageList(mProcessStats);
            mProcessList.startProcessLocked(app,
                    new HostingRecord("link fail", processName),
                    ZYGOTE_POLICY_FLAG_EMPTY);
            return false;
        }

		//这个就是event log中经常出现的"am_proc_bound",代表进程创建后,app进程回调AMS绑定了该app进程
        EventLogTags.writeAmProcBound(app.userId, pid, app.processName);

		//进程信息记录ProcessRecord app的初始化
        
            //...
			//同时这里还会从system_server回传APP进程,去绑定应用bindApplication
                thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.getCompat(), getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions,
                        app.getDisabledCompatChanges(), serializedSystemFontMap);
            //...

        // 调用ActivityTaskManagerService的attachApplication(activity是否需要运行)
        if (normalMode) {
            try {
                didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }

        // 调用ActiveServices的attachApplication(services是否需要运行)
        if (!badApp) {
            try {
                didSomething |= mServices.attachApplicationLocked(app, processName);
                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            }
        }

        // 看一下是否有挂起的广播需要运行
        if (!badApp && isPendingBroadcastProcessLocked(pid)) {
            try {
                //向广播队列告知,有挂起的进程启动
                didSomething |= sendPendingBroadcastsLocked(app);
                checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");
            } catch (Exception e) {
                // If the app died trying to launch the receiver we declare it 'bad'
                Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
                badApp = true;
            }
        }

        //...
        return true;
    }

//BroadcastQueue.java
    //遍历所有的广播队列,看一下是否有挂起的广播
    boolean isPendingBroadcastProcessLocked(int pid) {
        return mFgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
                || mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
                || mOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid);
    }

    //查看该pid是否有挂起的广播
    public boolean isPendingBroadcastProcessLocked(int pid) {
        return mPendingBroadcast != null && mPendingBroadcast.curApp.getPid() == pid;
    }
	
	//向广播队列告知,有挂起的进程启动
    // The app just attached; send any pending broadcasts that it should receive
    boolean sendPendingBroadcastsLocked(ProcessRecord app) {
        boolean didSomething = false;
        for (BroadcastQueue queue : mBroadcastQueues) {
            didSomething |= queue.sendPendingBroadcastsLocked(app);
        }
        return didSomething;
    }
  1. 广播队列处理挂起的进程

=> 广播队列处理挂起的进程sendPendingBroadcastsLocked -> processCurBroadcastLocked,
并清除mPendingBroadcast = null,广播分发可以继续下去
=> processCurBroadcastLocked将广播发送给该app的curComponent
=> processCurBroadcastLocked(系统进程BroadcastQueue.java)将该广播传递给curApp-> scheduleReceiver(app进程ActivityThread)
-> RECEIVER -> handleReceiver(ActivityThread.java) -> finish(BroadcastReceiver.java) -> finish/sendFinished(BroadcastReceiver.java)
-> am.finishReceiver(再次回到系统进程AMS)

//BroadcastQueue.java
   // attachApplicationLocked(AMS) -> sendPendingBroadcastsLocked(AMS/BroadcastQueue)
    // 进程启动的时候会清除 mPendingBroadcast
    public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
        boolean didSomething = false;
        final BroadcastRecord br = mPendingBroadcast;
        if (br != null && br.curApp.getPid() > 0 && br.curApp.getPid() == app.getPid()) {
            if (br.curApp != app) {
                Slog.e(TAG, "App mismatch when sending pending broadcast to "
                        + app.processName + ", intended target is " + br.curApp.processName);
                return false;
            }
            try {
                //发送给pending的广播时候会清除 mPendingBroadcast = nul
                mPendingBroadcast = null;
				//"章节4.4.7"中已经讲过这个函数,就是发送给该app的curComponent(静态接收者组件名字)
                processCurBroadcastLocked(br, app);
                didSomething = true;
            } catch (Exception e) {
                Slog.w(TAG, "Exception in new application when starting receiver "
                        + br.curComponent.flattenToShortString(), e);
                logBroadcastReceiverDiscardLocked(br);
                finishReceiverLocked(br, br.resultCode, br.resultData,
                        br.resultExtras, br.resultAbort, false);
                scheduleBroadcastsLocked();
                // We need to reset the state if we failed to start the receiver.
                br.state = BroadcastRecord.IDLE;
                throw new RuntimeException(e.getMessage());
            }
        }
        return didSomething;
    }

4.5 广播接收者处理完成

我们接着讲AMS的finishReceiver,这个是广播接受者接收完成后,回传AMS的方法

4.5.1 广播完成,开始下一个广播的调度

  1. 该广播接收者已经完成了BroadcastRecord.finishReceiverLocked
  2. 开始下一个广播接受者的调度(这里就是order的按顺序的核心)processNextBroadcastLocked(调用这个函数,相当于下一个重复的逻辑,直到全部广播发送完成)
//ActivityManagerService.java
    public void finishReceiver(IBinder who, int resultCode, String resultData,
                               Bundle resultExtras, boolean resultAbort, int flags) {
		//打印该广播接受者完成处理的日志
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Finish receiver: " + who);

        //...
        final long origId = Binder.clearCallingIdentity();
        try {
            boolean doNext = false;
            BroadcastRecord r;
            BroadcastQueue queue;

            synchronized(this) {
                //查看广播队列属于前台还是后台
                if (isOnOffloadQueue(flags)) {
                    queue = mOffloadBroadcastQueue;
                } else {
                    queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                            ? mFgBroadcastQueue : mBgBroadcastQueue;
                }

				//看一下对应的BroadcastRecord是谁
                r = queue.getMatchingOrderedReceiver(who);
                if (r != null) {
                    //如果BroadcastRecord r存在,则告知广播队列BroadcastQueue,该广播接收者已经完成了finishReceiverLocked
                    doNext = r.queue.finishReceiverLocked(r, resultCode,
                            resultData, resultExtras, resultAbort, true);
                }
				
				//如果doNext正常返回true(上一个正常处理完成返回的就是true)
                if (doNext) {
                    //开始下一个广播接受者的调度,这里就是order的按顺序的核心
                    r.queue.processNextBroadcastLocked(/*fromMsg=*/ false, /*skipOomAdj=*/ true);
                }
                // updateOomAdjLocked() will be done here
                trimApplicationsLocked(false, OomAdjuster.OOM_ADJ_REASON_FINISH_RECEIVER);
            }

        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

4.5.2 广播完成finishReceiverLocked

finishReceiverLocked是广播完成时调用,到这里广播的流程基本上就讲完了

//BroadcastQueue.java
    public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
                                        String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
        final int state = r.state;
        final ActivityInfo receiver = r.curReceiver;
        final long finishTime = SystemClock.uptimeMillis();
        final long elapsed = finishTime - r.receiverTime;
		//app状态变成IDLE
        r.state = BroadcastRecord.IDLE;
		//如果是执行静态注册广播接收的逻辑,这里一般情况是BroadcastRecord.APP_RECEIVE(无超时/无异常情况时)
        if (state == BroadcastRecord.IDLE) {
            Slog.w(TAG_BROADCAST, "finishReceiver [" + mQueueName + "] called but state is IDLE");
        }
        if (r.allowBackgroundActivityStarts && r.curApp != null) {
            if (elapsed > mConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT) {
                // if the receiver has run for more than allowed bg activity start timeout,
                // just remove the token for this process now and we're done
                r.curApp.removeAllowBackgroundActivityStartsToken(r);
            } else {
                // It gets more time; post the removal to happen at the appropriate moment
                postActivityStartTokenRemoval(r.curApp, r);
            }
        }
        // If we're abandoning this broadcast before any receivers were actually spun up,
        // nextReceiver is zero; in which case time-to-process bookkeeping doesn't apply.
        if (r.nextReceiver > 0) {
            r.duration[r.nextReceiver - 1] = elapsed;
        }

        // if this receiver was slow, impose deferral policy on the app.  This will kick in
        // when processNextBroadcastLocked() next finds this uid as a receiver identity.
		//timeoutExempt只有ACTION_PRE_BOOT_COMPLETED才会设置为true,也就是一般会进来
        if (!r.timeoutExempt) {
            // r.curApp can be null if finish has raced with process death - benign
            // edge case, and we just ignore it because we're already cleaning up
            // as expected.
            if (r.curApp != null
                    && mConstants.SLOW_TIME > 0 && elapsed > mConstants.SLOW_TIME) {
                // Core system packages are exempt from deferral policy
				//看一下是否需要加入延迟广播里面
                if (!UserHandle.isCore(r.curApp.uid)) {
                    if (DEBUG_BROADCAST_DEFERRAL) {
                        Slog.i(TAG_BROADCAST, "Broadcast receiver " + (r.nextReceiver - 1)
                                + " was slow: " + receiver + " br=" + r);
                    }
                    mDispatcher.startDeferring(r.curApp.uid);
                } else {
                    if (DEBUG_BROADCAST_DEFERRAL) {
                        Slog.i(TAG_BROADCAST, "Core uid " + r.curApp.uid
                                + " receiver was slow but not deferring: "
                                + receiver + " br=" + r);
                    }
                }
            }
        } else {
            if (DEBUG_BROADCAST_DEFERRAL) {
                Slog.i(TAG_BROADCAST, "Finished broadcast " + r.intent.getAction()
                        + " is exempt from deferral policy");
            }
        }

        //结束的时候r.receiver = null
        r.receiver = null;
        r.intent.setComponent(null);
        if (r.curApp != null && r.curApp.mReceivers.hasCurReceiver(r)) {
            r.curApp.mReceivers.removeCurReceiver(r);
            mService.enqueueOomAdjTargetLocked(r.curApp);
        }
        if (r.curFilter != null) {
            r.curFilter.receiverList.curBroadcast = null;
        }
        r.curFilter = null;
        r.curReceiver = null;
        r.curApp = null;
        //正常的完成广播接收的时候会清除mPendingBroadcast = nul
        mPendingBroadcast = null;

        r.resultCode = resultCode;
        r.resultData = resultData;
        r.resultExtras = resultExtras;

        // bortBroadcast(应用进程) -> finishReceiver(AMS)-> r.queue.finishReceiverLocked(BroadcastQueue)
        // 只要这个广播没有设置不能中断,则order的广播,优先级在前面的可以中断后续的广播接收
        if (resultAbort && (r.intent.getFlags()&Intent.FLAG_RECEIVER_NO_ABORT) == 0) {
            r.resultAbort = resultAbort;
        } else {
            r.resultAbort = false;
        }

        // If we want to wait behind services *AND* we're finishing the head/
        // active broadcast on its queue
        if (waitForServices && r.curComponent != null && r.queue.mDelayBehindServices
                && r.queue.mDispatcher.getActiveBroadcastLocked() == r) {
            ActivityInfo nextReceiver;
            if (r.nextReceiver < r.receivers.size()) {
                Object obj = r.receivers.get(r.nextReceiver);
                nextReceiver = (obj instanceof ActivityInfo) ? (ActivityInfo)obj : null;
            } else {
                nextReceiver = null;
            }
            // Don't do this if the next receive is in the same process as the current one.
            if (receiver == null || nextReceiver == null
                    || receiver.applicationInfo.uid != nextReceiver.applicationInfo.uid
                    || !receiver.processName.equals(nextReceiver.processName)) {
                // In this case, we are ready to process the next receiver for the current broadcast,
                //?but are on a queue that would like to wait for services to finish before moving
                // on.  If there are background services currently starting, then we will go into a
                // special state where we hold off on continuing this broadcast until they are done.
                //如果该uid的进程有正在启动的后台服务mStartingBackground,则等待后台服务启动完成再继续
                if (mService.mServices.hasBackgroundServicesLocked(r.userId)) {
                    Slog.i(TAG, "Delay finish: " + r.curComponent.flattenToShortString());
                    r.state = BroadcastRecord.WAITING_SERVICES;
                    return false;
                }
            }
        }

        r.curComponent = null;

        // We will process the next receiver right now if this is finishing
        // an app receiver (which is always asynchronous) or after we have
        // come back from calling a receiver.
		//发送给静态注册者的时候一般是APP_RECEIVE,发送给动态注册者的时候一般是CALL_DONE_RECEIVE
        return state == BroadcastRecord.APP_RECEIVE
                || state == BroadcastRecord.CALL_DONE_RECEIVE;
    }

5. 广播的拓展使用

从上面的文章基本上可以知道广播是干什么的,广播的流程是怎么样的。
一般广播的应用有3类:
1、针对高配置的设备:VIP广播,给一些关键的进程,关键的广播,放入特定的队列,不会由于本身广播队列阻塞了其广播分发,
达到比较高效的分发
2、针对低配置的设备:
=> 延迟广播,间隔分发广播等。主要是广播如平行广播一次性发给所有进程,会导致系统负担;
或者是发送给静态注册者需要启动应用,启动多个应用的时候会导致系统负载过重,可以将类似广播延迟分发。
(这个总负载还是一样的,只是分散开来,降低持续卡顿情况,至于偶发的峰值卡顿还是存在,需要别的方法配合)
场景如开机、切换语言等
=> 限制广播:如在特定场景限制启动,限制接收等行为,降低系统负载。
(这类方法效果立竿见影,不过场景需要非常慎重,不然导致功能使用可能出现异常)
=> 其它应用:特定场景修改超时时间,让用户感知的anr减少;针对用户不可见的anr,看一下是否需要用户感知等;接受者优先级调整等。
3、各类广播无法接收问题的解决等(可以考虑动态打开一些基本的调试广播开关DEBUG_BROADCAST DEBUG_BROADCAST_BACKGROUND DEBUG_BROADCAST_DEFERRAL DEBUG_BROADCAST_LIGHT DEBUG_BACKGROUND_CHECK)

了解广播的流程,实现上述内容一般都大概心里有底,会比较快速的做出相应的方案。

你可能感兴趣的:(性能相关,android,java)