Android 9.0系统源码_广播(三)广播的发送

上一篇分析了Android系统中广播的注册和注销,这一篇我们继续分析发送广播的源码流程,广播的发送相对来说比较复杂,所以需要比较长的时间来看,如果你看懂了流程相对来说再研究流程中的细节就比较简单了。

先看一张时序图,因为里面涉及到循环过程,代码中会提到,但是时序图没有绘制,所以需要注意一下。

在这里插入图片描述
在这里插入图片描述

一、调用ContextImpl.sendBroadcast发送广播

frameworks/base/core/java/android/app/ContextImpl.java

 /**
     * 发送广播
     * 步骤:
     * 1.广播发送者,即一个Activity组件或者一个Service组件,将一个特定类型的广播发送给AMS
     * <p>
     * 2.AMS接收到一个广播后,首先找到与这个广播对应的广播接收者,然后将它们添加到一个广播调度队列中,
     * 最后向AMS所运行在的线程的消息队列发送一个类型为BROADCAST_INTENT_MSG的消息,这时候对广播发送
     * 者来说,一个广播就发送完了。
     * <p>
     * 3.当发送到AMS所运行在的线程的消息队列中的BROADCAST_INTENT_MSG消息被处理时,AMS就会从广播调
     * 度队列中知道需要接受广播的接收者,并且将对应的广播发送给它们所运行在的应用进程。
     * <p>
     * 4.广播接收者所运行的应用程序接收到AMS发送过来的广播后,并不是直接将接收到的广播发送给广播接收
     * 者来处理,而是将接收到的广播封装成一个消息,并且发送到主线程的消息队列中。当这个消息被处理时,
     * 应用程序进程才会将它所描述的广播发给相应的广播接收者处理
     * <p>
     */
    @Override
    public void sendBroadcast(Intent intent) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        try {
            intent.prepareToLeaveProcess(this);
            //直接调用AMS的broadcastIntent方法
            ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                    getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

二、调用AMS的broadcastIntent方法:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    // 发送广播
    public final int broadcastIntent(IApplicationThread caller,
                                     Intent intent, String resolvedType, IIntentReceiver resultTo,
                                     int resultCode, String resultData, Bundle resultExtras,
                                     String[] requiredPermissions, int appOp, Bundle bOptions,
                                     boolean serialized, boolean sticky, int userId) {
        enforceNotIsolatedCaller("broadcastIntent");
        synchronized (this) {
            //验证广播的Intent是否合法
            // 如果这个时候系统正在启动,还会验证intent所描述的广播是否只发送给动态注册的广播接收者。
            // 在系统的启动过程中,PMS可能还未启动,这种情况下,AMS是无法获取静态注册广播接收者的,因此,就禁止发送广播给静态注册的广播接收者
            intent = verifyBroadcastLocked(intent);
            // 根据caller从缓存mLruProcesses中获取进程对象ProcessRecord
            final ProcessRecord callerApp = getRecordForAppLocked(caller);
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
			
            int res = broadcastIntentLocked(callerApp,
                    callerApp != null ? callerApp.info.packageName : null,
                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                    requiredPermissions, appOp, bOptions, serialized, sticky,
                    callingPid, callingUid, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

三、调用AMS的broadcastIntentLocked方法:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    final int broadcastIntentLocked(ProcessRecord callerApp,
                                    String callerPackage, Intent intent, String resolvedType,
                                    IIntentReceiver resultTo, int resultCode, String resultData,
                                    Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
                                    boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
        intent = new Intent(intent);
        
        final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
        // Instant Apps cannot use FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS
        if (callerInstantApp) {
            intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
        }
        // By default broadcasts do not go to stopped apps.
        // 增加下面flag,默认不发送广播到已经停止的app
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

        // If we have not finished booting, don't allow this to launch new processes.
        // 如果该进程还没有完成启动,并且不是发送给启动升级的广播,则添只发送给已注册的广播接收者标签
        if (!mProcessesReady && (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);// 只发给注册的receiver
        }
        // 获取当前发送广播应用所在用户的userId
        // 解释:
        // 7.1.1系统有多用户登录,就像电脑上的主用户和访客模式一样,可以设置多个用户,每个用户有一个id,
        // 有些广播需要多个用户都要接收,比如时区变化这些,是同步的,每个用户都要变化。这里一般是我们
        // 当前登录的用户id
        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.
        if (userId != UserHandle.USER_ALL && !mUserController.isUserOrItsParentRunning(userId)) {
            if ((callingUid != SYSTEM_UID
                    || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
                    && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
                return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
            }
        }
        final String action = intent.getAction();
        BroadcastOptions brOptions = null;
        ...
        final boolean isProtectedBroadcast;
        try {
            // 验证是不是受保护的广播(是不是系统广播)
            isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
        } catch (RemoteException e) {
            return ActivityManager.BROADCAST_SUCCESS;
        }

        // 检查是不是系统调用
        final boolean isCallerSystem;
        switch (UserHandle.getAppId(callingUid)) {
            case Process.ROOT_UID:
            case Process.SYSTEM_UID:
            case Process.PHONE_UID:
            case Process.BLUETOOTH_UID:
            case Process.NFC_UID:
                isCallerSystem = true;
                break;
            default:
                isCallerSystem = (callerApp != null) && callerApp.persistent;
                break;
        }

        // First line security check before anything else: stop non-system apps from
        // sending protected broadcasts.
        if (!isCallerSystem) {// 不是系统发送的广播
            if (isProtectedBroadcast) {// 非系统进程发送受保护广播抛出异常
                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.
                if (callerPackage == null) {
                    throw new SecurityException(msg);
                } 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)) {
                        throw new SecurityException(msg);
                    }
                } else {
                    // Limit broadcast to their own package.
                    // 限制发送广播给自己包里
                    intent.setPackage(callerPackage);
                }
            }
        }

        // 下面主要是针对系统广播的处理
        if (action != null) {
            switch (action) {
                case Intent.ACTION_UID_REMOVED:// 移除uid
                case Intent.ACTION_PACKAGE_REMOVED:// 卸载应用
                case Intent.ACTION_PACKAGE_CHANGED:// 应用更改,比如:停用,启动等
                case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:// 外部应用不可用,比如安装到sd卡的应用,卸载了sd卡
                case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:// 外部应用可用
                case Intent.ACTION_PACKAGES_SUSPENDED:// 暂停应用
                case Intent.ACTION_PACKAGES_UNSUSPENDED:// 应用可用
                    switch (action) {
                        case Intent.ACTION_UID_REMOVED:// 移除系统userId(删除一个用户)
                            ...
                            break;
                        case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:// 外部应用不可用,一般是卸载SD...
                            break;
                        case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:// 外部应用可用,一般是插入SD...
                            break;
                        case Intent.ACTION_PACKAGE_REMOVED:// 卸载
                        case Intent.ACTION_PACKAGE_CHANGED:// 更新
                            ...
                            break;
                        case Intent.ACTION_PACKAGES_SUSPENDED:
                        case Intent.ACTION_PACKAGES_UNSUSPENDED:
                            ...
                            break;
                    }
                    break;
                case Intent.ACTION_PACKAGE_REPLACED: {// 升级应用
                    ...
                    break;
                }
                case Intent.ACTION_PACKAGE_ADDED: {// 安装应用
                    ...
                    break;
                }
                case Intent.ACTION_PACKAGE_DATA_CLEARED: {// 清理应用数据
                    ...
                    break;
                }
                case Intent.ACTION_TIMEZONE_CHANGED:// 时区改变
                    ...
                    break;
                case Intent.ACTION_TIME_CHANGED:// 时间改变
                    ...
                    break;
                case Intent.ACTION_CLEAR_DNS_CACHE:// 清理DNS缓存
                    ...
                    break;
                case Proxy.PROXY_CHANGE_ACTION:// 代理改变
                    ...
                    break;
                case android.hardware.Camera.ACTION_NEW_PICTURE:// 新照片
                case android.hardware.Camera.ACTION_NEW_VIDEO:// 新视频
                    ...
                    break:
                case android.security.KeyChain.ACTION_TRUST_STORE_CHANGED:
                    ...
                    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().
                    return ActivityManager.BROADCAST_SUCCESS;
            }
        }
		...
        // Add to the sticky list if requested.
        // 判断是否是粘性广播,如果是,AMS就需要保存这个广播,以便后面注册要接收此类型广播的接收者可以获得这个广播
        if (sticky) {
            // 检查粘性广播是否申请了权限
            if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, callingPid, callingUid)
                    != PackageManager.PERMISSION_GRANTED) {
                throw new SecurityException(msg);
            }
            if (requiredPermissions != null && requiredPermissions.length > 0) {
                return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
            }
            // sticky广播不能指定目标组件
            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.
            //不是发送给所有用户的广播
            if (userId != UserHandle.USER_ALL) {
                // But first, if this is not a broadcast to all users, then
                // make sure it doesn't conflict with an existing broadcast to
                // all users.
                ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
                        UserHandle.USER_ALL);
                // 检查是否和存在的发给所有用户的粘性广播一样的广播
                if (stickies != null) {
                    ArrayList<Intent> list = stickies.get(intent.getAction());
                    if (list != null) {
                        int N = list.size();
                        int i;
                        for (i = 0; i < N; i++) {
                            if (intent.filterEquals(list.get(i))) {
                                throw new IllegalArgumentException(
                                        "Sticky broadcast " + intent + " for user "
                                                + userId + " conflicts with existing global broadcast");
                            }
                        }
                    }
                }
            }
            // 所有的粘性广播都保存在一个列表中,这些列表最终保存在AMS的成员变量mStickyBroadcasts所描述的一个HashMap中,
            // 并且以它们的广播类型为关键字
            // 首先检查mStickyBroadcasts是否有该用户的粘性广播列表
            ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
            // 该广播列表中没有该用户的stick广播列表
            if (stickies == null) {
                stickies = new ArrayMap<>();
                mStickyBroadcasts.put(userId, stickies);
            }
            // 获取注册广播的Action对应的粘性广播的Intent列表
            ArrayList<Intent> list = stickies.get(intent.getAction());

            if (list == null) {//如果为空
                list = new ArrayList<>();//创建一个列表
                stickies.put(intent.getAction(), list);//以action为键保存该列表
            }
            // 获取该action对应粘性广播Intent列表的个数
            final int stickiesCount = list.size();
            int i;
            // 检查在粘性广播列表中是否保存了一个与参数Intent一致的广播。如果存在直接替换,否则将参数
            // Intent描述的广播添加到粘性广播列表list中
            for (i = 0; i < stickiesCount; i++) {
                if (intent.filterEquals(list.get(i))) {
                    // This sticky already exists, replace it.
                    list.set(i, new Intent(intent));
                    break;
                }
            }
            if (i >= stickiesCount) {// 如果该列表中不存在该粘性广播的Intent加入进去
                list.add(new Intent(intent));
                // 我们看到粘性广播放在了list中,而list以action为键放置在了stickies中,而stickies
                // 又以userId为键放在了mStickyBroadcasts中,因此mStickyBroadcasts保存了设备中所有
                // 用户粘性广播的Intent
            }
        }

        int[] users;
        if (userId == UserHandle.USER_ALL) {// 发送广播给全部用户
            // Caller wants broadcast to go to all started users.
            // 获取所有已启动用户的列表
            users = mUserController.getStartedUserArrayLocked();
        } else {// 发送广播给指定用户
            // Caller wants broadcast to go to one specific user.
            users = new int[]{userId};
        }

 		// Figure out who all will receive this broadcast.
        List receivers = null;//静态注册接收者
        List<BroadcastFilter> registeredReceivers = null;//动态注册接收者
        // Need to resolve the intent to interested receivers...
        // 如果当前的广播Intent没有指定FLAG_RECEIVER_REGISTERED_ONLY标记,也就是允许静态注册
        if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
            // 允许静态注册的Intent,需要从PMS中去查询对应的广播接收者
            receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
        }
        // 如果参数intent没有指定广播接收者的组件名,说明是发送给所有已注册并且要接收该广播的接收者的
        if (intent.getComponent() == null) {
            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;
                    }
                    List<BroadcastFilter> registeredReceiversForUser =
                            mReceiverResolver.queryIntent(intent,
                                    resolvedType, false /*defaultOnly*/, users[i]);
                    if (registeredReceivers == null) {
                        registeredReceivers = registeredReceiversForUser;
                    } else if (registeredReceiversForUser != null) {
                        registeredReceivers.addAll(registeredReceiversForUser);
                    }
                }
            } else {
                // 查找当前用户的所有动态注册的广播接收者
                registeredReceivers = mReceiverResolver.queryIntent(intent,
                        resolvedType, false /*defaultOnly*/, userId);
            }
        }
  		// 由于AMS是通过消息机制将接收到的广播发送给目标广播接收者的,因此可能会出现一种情况:上次接收
        // 的广播还没有来得及发送给广播接收者,又马上接收到一个同样的广播,在这种情况下,如果现在接收的
        // 广播标志位FLAG_RECEIVER_REPLACE_PENDING等于1,那么AMS就会用新的广播代替旧的广播。
        final boolean replacePending = (intent.getFlags() & Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
        // 动态注册的广播接收者个数
        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
        // 当前发送的是有序广播,且存在动态注册的广播接收者
        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);
            }
            // 根据intent查找对应的广播队列
            final BroadcastQueue queue = broadcastQueueForIntent(intent);
            // 创建BroadcastRecord对象并将当前所有通过动态注册的广播接收者传进去
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                    resultCode, resultData, resultExtras, ordered, sticky, false, userId);
            // 在BroadcastQueue中等待发送广播中搜索是否有相同的BroadcastRecord并且是否替换
            final boolean replaced = replacePending && (queue.replaceParallelBroadcastLocked(r) != null);
            // Note: We assume resultTo is null for non-ordered broadcasts.
            if (!replaced) {
                // 如果不需要替换则插入到BroadcastQueue中
                // 也就是说动态广播接收者都放在了BroadcastQueue的mParallelBroadcasts中
                queue.enqueueParallelBroadcastLocked(r);
                //并推动一次广播发送
                queue.scheduleBroadcastsLocked();
            }
            registeredReceivers = null;
            NR = 0;
        }

         // Merge into one list.
        // 如果说【动态注册且接受无序广播的广播接收者】是并行操作,
        // 那么【动态注册接受有序广播的广播接收者】和【静态注册的广播接收者】接受广播的最大特点就是串行

        // 如果是有序广播,动态接收者和静态的接收者合并到一个队列里面进行处理,也就是说order广播下,
        // 所有的接收者(静态和动态)处理方式都是一样的(后面会分析到,都是串行化处理的)。
        // 还有就是对于静态注册的接收者而言,始终是和order广播的处理方式是一样的,也就是说静态的接收者
        // 只有order模式(串行化接收)。
        // 在合并过程中,如果一个动态注册的广播接收者和一个静态注册的目标广播接收者的优先级相同,那么
        // 动态注册的目标接收者会排在静态注册的目标广播接收者前面,即动态注册的目标广播接收者会优先于
        // 静态注册的广播接收者接受有序广播
        int ir = 0;
        if (receivers != null) {
            // 对于ACTION_PACKAGE_ADDED广播而言,如果是自己被add了,那么这个广播只能别人收到,
            // 自己即使注册了这个静态广播也接收不到,注释上说是担心有些应用一安装就接收自己的PACKAGE_ADDED
            // 广播,然后就启动了。简言之,应用永远接收不到自己的PACKAGE_ADDED广播。
            // 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;// 需要跳过的广播
            if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
                    || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
                    || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
                Uri data = intent.getData();
                if (data != null) {
                    String pkgName = data.getSchemeSpecificPart();
                    if (pkgName != null) {
                        skipPackages = new String[]{pkgName};
                    }
                }
            } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
                skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
            }
            if (skipPackages != null && (skipPackages.length > 0)) {
                for (String skipPackage : skipPackages) {
                    if (skipPackage != null) {
                        int NT = receivers.size();
                        for (int it = 0; it < NT; it++) {
                            ResolveInfo curt = (ResolveInfo) receivers.get(it);
                            if (curt.activityInfo.packageName.equals(skipPackage)) {
                                receivers.remove(it);
                                it--;
                                NT--;
                            }
                        }
                    }
                }
            }

            // 开始把动态注册的广播接收者列表registeredReceivers和静态注册的广播接收者列表receivers合并成一个列表

            // 下面这一段代码是典型的有序链表的合并操作,合并的依据是接收者的priority值,这里需要注意的一点
            // 是动态广播接收器注册的时候一般都没有指定priority,默认值是0,具体实现好像有点像归并排序的意思,
            // 而且是从后向前进行的归并,因此priority越小,在链表中的位置就越靠前,后面处理的时候也就越先处理。
            // 走完这里所有的静态接收者和order模式下的动态接收者都已经被合并到了receivers链表里面。
            // 合并以后在receivers链表里面静态接收者对应ResolveInfo对象,order模式下的动态接收者对应的
            // 是BroadcastFilter对象。
            int NT = receivers != null ? receivers.size() : 0;//静态注册的广播接收者数量
            int it = 0;
            ResolveInfo curt = null;//静态注册的广播接收者
            BroadcastFilter curr = null;//动态注册的广播接收者
            while (it < NT && ir < NR) {
                if (curt == null) {
                    curt = (ResolveInfo) receivers.get(it);//获取静态广播接收者列表第it个条目
                }
                if (curr == null) {
                    curr = registeredReceivers.get(ir);//获取动态广播接收者列表第ir个条目
                }
                if (curr.getPriority() >= curt.priority) {//如果动态注册广播接收者的优先级大于等于静态注册的
                    // Insert this broadcast record into the final list.
                    //把动态注册广播者插入静态注册的广播接收者列表中对应条目的前方
                    receivers.add(it, curr);
                    ir++;
                    curr = null;
                    it++;
                    NT++;
                } else {
                    // Skip to the next ResolveInfo in the final list.
                    it++;
                    curt = null;
                }
            }
        }
        // 将两个列表合并到一个列表中,这样静态注册广播接收者receivers列表就包含了所有的广播接收者(无序广播和有序广播)。
        while (ir < NR) {
            if (receivers == null) {
                receivers = new ArrayList();
            }
            receivers.add(registeredReceivers.get(ir));
            ir++;
        }

        if (isCallerSystem) {
            checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                    isProtectedBroadcast, receivers);
        }
        // 可以看出,是在合并入receiver后统一发送BroadcastQueue.scheduleBroadcastsLocked
        if ((receivers != null && receivers.size() > 0) || resultTo != null) {
            // 根据intent查找对应的广播队列
            final BroadcastQueue queue = broadcastQueueForIntent(intent);
            // 创建BroadcastRecord对象并将合并过的广播接收者列表receivers传进去
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId);

            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r
                    + ": prev had " + queue.mOrderedBroadcasts.size());
            if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
                    "Enqueueing broadcast " + r.intent.getAction());


            final BroadcastRecord oldRecord = replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
            if (oldRecord != null) {
                // Replaced, fire the result-to receiver.
                if (oldRecord.resultTo != null) {
                    final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
                    try {
                        oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
                                oldRecord.intent,
                                Activity.RESULT_CANCELED, null, null,
                                false, false, oldRecord.userId);
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Failure ["
                                + queue.mQueueName + "] sending broadcast result of "
                                + intent, e);

                    }
                }
            } else {
                //无序广播+有序广播合并之后放在了BroadcastQueue的mOrderedBroadcasts中
                queue.enqueueOrderedBroadcastLocked(r);
                //并推动一次广播发送
                queue.scheduleBroadcastsLocked();
            }
        } else {
            // There was nobody interested in the broadcast, but we still want to record
            // that it happened.
            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;
    }

代码比较多,这里简单解释一下:

  • 首先是判断是不是系统广播,也就是switch语句中的部分,这部分的广播是系统发出的,根据不同广播做出不同的处理,系统广播我们可以接收但是不能发送,只能由系统发出;
  • 接着是粘性广播的处理;
  • 然后是【动态注册且接受无序广播的广播接收者】的处理,把他们放入到BroadcastQueue的mParallelBroadcasts中,并调用scheduleBroadcastsLocked,BroadcastQueue对mParallelBroadcasts列表中条目的最终处理是通过并行操作来完成的;
  • 最后是【动态注册接受有序广播的广播接收者】和【静态注册的广播接收者】的处理,把他们放入到BroadcastQueue的mOrderedBroadcasts中,并调用scheduleBroadcastsLocked,BroadcastQueue对mOrderedBroadcasts列表中条目的最终处理是通过串行操作来完成的;

四、调用BroadcastQueue的enqueueParallelBroadcastLocked方法和enqueueOrderedBroadcastLocked方法:

frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java

    public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
        //把当前BroadcastRecord添加到无序广播接收者集合mParallelBroadcasts中
        mParallelBroadcasts.add(r);
        enqueueBroadcastHelper(r);
    }

    public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
        //把当前BroadcastRecord添加到有序广播接收者集合mOrderedBroadcasts中
        mOrderedBroadcasts.add(r);
        enqueueBroadcastHelper(r);
    }
    ...
   /**
     * Don't call this method directly; call enqueueParallelBroadcastLocked or
     * enqueueOrderedBroadcastLocked.
     * 不要直接调用这个方法;请调用enqueueParallelBroadcastLocked 或者enqueueOrderedBroadcastLocked
     */
    private void enqueueBroadcastHelper(BroadcastRecord r) {
        r.enqueueClockTime = System.currentTimeMillis();//保存当前的系统时间
    }

五、调用BroadcastQueue的scheduleBroadcastsLocked方法:

    // 执行广播发送,所有广播都会从这里走,然后会到processNextBroadcast
    public void scheduleBroadcastsLocked() {
        // 如果true说明消息队列已经存在一个类型为BROADCAST_INTENT_MSG的消息了,直接返回,因为该消息在执行完毕会自动调用下一条消息
        // AMS就是通过这个BROADCAST_INTENT_MSG消息类
        // 来调度保存在无序广播调度队列mParallelBroadcasts和有序广播调度队列mOrderedBroadcasts中的广播转发任务的
        if (mBroadcastsScheduled) {
            return;
        }
        // 虽然这里只发送了发送广播的消息,但是这一步执行完之后就已经标记广播发送了,因此可以看出广播发送和接
        // 受是异步的,即广播发送者将一个广播发送给AMS后,不会等待AMS将这个广播转发给广播接收者处理
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }
    
	//BroadcastQueue中的消息调度BroadcastHandler 
    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: {
                    processNextBroadcast(true);//开始处理下一个广播
                }
                break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                }
                break;
            }
        }
    }

广播中大多数内容的处理是在BroadcastQueue类中,上面有个mBroadcastsScheduled参数,如果为ture则阻止继续执行,我们可以看到下面发完消息后会将其设置为true。BROADCAST_INTENT_MSG被发送之后,最终会在BroadcastHandler的handleMessage方法中调用processNextBroadcast方法。

六、调用BroadcastQueue的processNextBroadcast方法,执行无序广播

	//参数fromMsg是用来描述processNextBroadcast是否是被handleMessage触发的
    final void processNextBroadcast(boolean fromMsg) {
        synchronized (mService) {
            processNextBroadcastLocked(fromMsg, false);
        }
    }
    // 广播发送的核心内容
    final void processNextBroadcastLocked(boolean fromMsg) {
        BroadcastRecord r;
        mService.updateCpuStats();
  		// 否是来自handleMessage的BROADCAST_INTENT_MSG类型消息
        if (fromMsg) {
            // 前面说到,如果消息队列里面有BROADCAST_INTENT_MSG消息,该标记为true,阻止新的消息加入队列,
            // 这里开始处理这个消息的时候,将mBroadcastsScheduled变量设置为false,开始允许新的消息加入。
            mBroadcastsScheduled = false;
        }
        // First, deliver any non-serialized broadcasts right away.
        // 无序广播之间不存在相互等待,这里处理的是保存在无序广播调度队列mParallelBroadcasts中的广播发送任务,
        // 即把保存在无序广播调度队列mParallelBroadcasts中的广播发送给它的目标广播接收者处理
        while (mParallelBroadcasts.size() > 0) {
            // 首先获取保存无序广播调度队列mParallelBroadcasts中的每一个BroadcastRecord对象
            r = mParallelBroadcasts.remove(0);
            r.dispatchTime = SystemClock.uptimeMillis();
            r.dispatchClockTime = System.currentTimeMillis();
            //获取BroadcastRecord中的所有广播接收者的数量
            final int N = r.receivers.size();
            for (int i = 0; i < N; i++) {
                Object target = r.receivers.get(i);
                // 调用deliverToRegisteredReceiverLocked向所有的receivers发送广播
                // 将它所描述的每一个无序广播发送给每一个广播接收者,异步处理广播
                // 通过deliverToRegisteredReceiverLocked调用ActivityThread.scheduleRegisteredReceiver处理广播
                deliverToRegisteredReceiverLocked(r, (BroadcastFilter) target, false, i);
            }
            addBroadcastToHistoryLocked(r);
        } 
        ...
        // 后面的有序广播的处理,第七步会具体分析有序广播的处理流程
    }

我们根据第4步的发送消息类型可以跟踪到,消息执行是在BroadcastHandler的handleMessage方法中调用的,这里出入一个参数fromMsg,也就是该广播是不是通过Handler发送消息的方式传递的,从上面知道我们这就是通过这种方式执行的,所以在代码中会将mBroadcastsScheduled参数设置为false,也就是这个消息开始执行了则开始运行下一个消息发送。还有就是通过直接调用的方式来执行的,那么就不会改变这个参数。

接着看,先执行无序广播,无序广播接收者不需要等待,所以直接for循环执行,调用deliverToRegisteredReceiverLocked方法发送广播。

6.1 调用BroadcastQueue的deliverToRegisteredReceiverLocked方法

	//执行动态注册的广播接收者的发送接受过程
    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
                                                   BroadcastFilter filter, boolean ordered, int index) {
        // 标记是否要跳过该广播接收者
        boolean skip = false;
        // 需要检查广播发送者的权限
        ...
        // r.requiredPermissions != null为true表示需要检查广播接收者的权限
        ...
        // 如果要跳过,则设置该广播结束
        if (skip) {
            r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
            return;
        }
        ...
        // order广播,所有的接收者需要依次以一种同步的方式发送广播,
        // 可以看到order广播在BroadcastRecord保存了几个状态
        if (ordered) {
            // IBinder类型,代表当前的接收者
            r.receiver = filter.receiverList.receiver.asBinder();
            // 当前正在处理的BroadcastFilter,和上面的receiver是对应好的
            r.curFilter = filter;
            filter.receiverList.curBroadcast = r;
            r.state = BroadcastRecord.CALL_IN_RECEIVE;
            if (filter.receiverList.app != null) {
                r.curApp = filter.receiverList.app;
                filter.receiverList.app.curReceiver = r;
                mService.updateOomAdjLocked(r.curApp);
            }
        }
        try {
            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                // Skip delivery if full backup in progress
                // If it's an ordered broadcast, we need to continue to the next receiver.
                // 如果正在备份或者恢复备份跳过,
                // 如果是一个有序广播,则执行下一个广播
                if (ordered) {
                    skipReceiverLocked(r);
                }
            } else {
                // 如果不需要进行权限检查或者通过权限检查,调用performReceiveLocked发送广播
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
            }
            if (ordered) {
                r.state = BroadcastRecord.CALL_DONE_RECEIVE;
            }
        } catch (RemoteException e) {
            if (ordered) {
                r.receiver = null;
                r.curFilter = null;
                filter.receiverList.curBroadcast = null;
                if (filter.receiverList.app != null) {
                    filter.receiverList.app.curReceivers.remove(r);
                }
            }
        }
    }

这里不是有序广播,正常也不会备份,所以会走else里面的方法performReceiveLocked。

6.2 调用BroadcastQueue的performReceiveLocked方法

        /**
     * 由前面可知,当一个Activity或者一个Service将一个广播接收者注册到AMS中时,它所在的应用程序进程会先将
     * 这个广播接收者封装成一个类型为InnerReceiver的Binder本地对象,然后再注册到AMS中。因此当AMS要将一个
     * 广播发给一个目标广播接收者处理时,实际上是将这个广播转发给封装了这个目标广播接收者的一个InnerReceiver
     * 对象来处理
     * <p>
     * AMS向一个应用程序进程发送一个广播时,采用的是异步进程间通信方式。前面提到,发送给一个Binder实体对象
     * 的所有异步事物都是保存在一个异步事物队列中的。由于保存在一个异步事物队列中的异步事物在同一时刻只有一
     * 个会得到处理,即只有队列头部的异步事物才会得到处理,因此AMS就可以保证它发送给同一个应用程序的所有广
     * 播都是按照这个发送顺序来串行的被接受和处理
     */
    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.
        // app不为空,表示进程已经启动,调用ActivityThread.scheduleRegisteredReceiver发送当前广播
        if (app != null) {
            if (app.thread != null) {// 因为是动态注册广播,所以不为空
                // If we have an app thread, do the call through that so it is
                // correctly ordered with other one-way calls.
                try {
                    // 这里scheduleRegisteredReceiver函数是一个Binder调用,注释上面说的很清楚,
                    // 调用ApplicationThread对象的Binder代理对象的函数来向它发送广播
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);
                } catch (RemoteException ex) {
                    // Failed to call into the process. It's either dying or wedged. Kill it gently.
                    synchronized (mService) {
                        app.scheduleCrash("can't deliver broadcast");
                    }
                    throw ex;
                }
            } else {
                // Application has died. Receiver doesn't exist.
                throw new RemoteException("app.thread must not be null");
            }
        } else {
            // 直接调用与它关联的一个InnerReceiver对象的Binder代理对象的成员函数performReceive来向它发送广播
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
        }
    }

如果进程存在,就会执行ActivityThread.scheduleRegisteredReceiver方法,否则直接调用receiver.performReceive方法发送广播。因为我们这里分析的是动态注册的广播接收者,所以会执行第一种情况。

6.3 调用ActivityThread的scheduleRegisteredReceiver方法

/frameworks/base/core/java/android/app/ActivityThread.java

 // This function exists to make sure all receiver dispatching is
        // correctly ordered, since these are one-way calls and the binder driver
        // applies transaction ordering per object for such calls.
        // 处理非串行化动态广播,非串化ordered是false
        // 这里的receiver对应的是LoadedApk.ReceiverDispatcher.InnerReceiver对象
        public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
                int resultCode, String dataStr, Bundle extras, boolean ordered,
                boolean sticky, int sendingUser, int processState) throws RemoteException {
            updateProcessState(processState, false);
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
        }

可以看到,这里和第8步的else分支一样,最终还是执行receiver.performReceive方法来发送广播。

6.4 调用LoadedApk#ReceiverDispatcher#InnerReceiver的performReceive方法

/frameworks/base/core/java/android/app/LoadedApk.java#ReceiverDispatcher#InnerReceiver

        final static class InnerReceiver extends IIntentReceiver.Stub {
            final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
            final LoadedApk.ReceiverDispatcher mStrongRef;

            InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
                mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                mStrongRef = strong ? rd : null;
            }

            @Override
            public void performReceive(Intent intent, int resultCode, String data,
                                       Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                final LoadedApk.ReceiverDispatcher rd;
                if (intent == null) {
                    rd = null;
                } else {
                	//获取rd的实例对象
                    rd = mDispatcher.get();
                }
   				//判断是否为空
                if (rd != null) {
                	//6.4.1 存在广播,rd 不为空,调用LoadedApk.ReceiverDispatcher对象的performReceive方法
                    rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
                } else {
                    IActivityManager mgr = ActivityManager.getService();
                    try {
                        if (extras != null) {
                            extras.setAllowFds(false);
                        }
                    	//6.4.3 不存在广播,rd为空,调用activityManagerService对象的finishReceiver结束广播的发送接受过程
                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
            }
        }

我们广播注册篇讲过LoadedApk.ReceiverDispatcher对象封装了广播接收者,如果该广播接收者注册了,那么该对象就会存在,这里就会调用LodedApk.ReceiverDispatcher.performReceive,否则就会调用AMS.finishReceiver方法,这里我们先看存在广播的情况。

6.4.1 调用LodedApk#ReceiverDispatcher的performReceive方法

/frameworks/base/core/java/android/app/LoadedApk.java#ReceiverDispatcher

        public void performReceive(Intent intent, int resultCode, String data,
                                   Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
            // 首先将参数Intent所描述的一个广播封装成一个Args对象,然后将这个Args对象封装成一个消息对象,
            // 然后将这个消息对象发送到应用程序主线程的消息队列中。
            final Args args = new Args(intent, resultCode, data, extras, ordered, sticky, sendingUser);
            // 将args对象post到主线程的消息队列里面,作为一个Runnable调度而不是在handleMessage中处理,
            // 因此这里不久后会调用Args.run函数
            if (intent == null || !mActivityThread.post(args.getRunnable())) {
                if (mRegistered && ordered) {
                    IActivityManager mgr = ActivityManager.getService();
                    args.sendFinished(mgr);
                }
            }
        }

上面初始化了一个Args对象,该对象实现了Runnable接口,在if语句中调用post方法,最终会调用Args中的run方法。

6.4.2 调用LodedApk#ReceiverDispatcher#Args的getRunnable方法
        final class Args extends BroadcastReceiver.PendingResult {
     		...
            public final Runnable getRunnable() {
                return () -> {
                    // mReceiver指向一个广播接收者
                    final BroadcastReceiver receiver = mReceiver;
                    final boolean ordered = mOrdered;
                    final IActivityManager mgr = ActivityManager.getService();
                    final Intent intent = mCurIntent;
                    mCurIntent = null;
                    mDispatched = true;
                    mPreviousRunStacktrace = new Throwable("Previous stacktrace");
                    if (receiver == null || intent == null || mForgotten) {
                        if (mRegistered && ordered) {
                            sendFinished(mgr);
                        }
                        return;
                    }
                    try {
                        // 这里处理的是动态广播接收者,默认认为接收者BroadcastReceiver已经存在
                        ClassLoader cl = mReceiver.getClass().getClassLoader();
                        intent.setExtrasClassLoader(cl);
                        intent.prepareToEnterProcess();
                        setExtrasClassLoader(cl);
                        receiver.setPendingResult(this);
                        // 接受广播
                        receiver.onReceive(mContext, intent);
                        // 然后调用BroadcastReceiver.PendingResult.finish函数,也就是下面的finish函数
                    } catch (Exception e) {
                        // 检查当前广播是否是有序广播,并且广播接收者是否已经注册到AMS中
                        if (mRegistered && ordered) {
                            // 通知AMS,它前面转发过来的有序广播已经处理完了,这时AMS就可以继续将这个有序广播
                            // 转发给下一个目标广播接收者了
                            sendFinished(mgr);
                        }
                        if (mInstrumentation == null || !mInstrumentation.onException(mReceiver, e)) {
                            throw new RuntimeException("Error receiving broadcast " + intent + " in " + mReceiver, e);
                        }
                    }
                    if (receiver.getPendingResult() != null) {
                        finish();
                    }
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                };
            }
        }

在这里调用BroadcastReceiver.onReceive方法,这样就会执行完一次无序广播的发送接受过程。
接下来我们重新再回到第6.4步,如果对象接收者不存在则调用AMS.finishReceiver。

6.5 调用activityManagerService的finishReceiver方法

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

   public void finishReceiver(IBinder who, int resultCode, String resultData,
                               Bundle resultExtras, boolean resultAbort, int flags) {
        // Refuse possible leaked file descriptors
        if (resultExtras != null && resultExtras.hasFileDescriptors()) {
            throw new IllegalArgumentException("File descriptors passed in Bundle");
        }
        final long origId = Binder.clearCallingIdentity();
        try {
            boolean doNext = false;
            BroadcastRecord r;
            // 首先辨别出当前receiver所在的BroadcastRecord属于前台广播还是后台广播,然后在对应的
            // BroadcastQueue中找出对应的BroadcastRecord,里面的finishReceiverLocked函数在前面介绍过,
            // 主要是重新设置BroadcastRecord里面一些状态变量,以便于BroadcastRecord将广播发送给下一个
            // 接收者。尤其的,如果前面的mAbortBroadcast设置为true,那么BroadcastRecord的成员resultAbort
            // 会设置成true
            synchronized (this) {
                BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                        ? mFgBroadcastQueue : mBgBroadcastQueue;
                r = queue.getMatchingOrderedReceiver(who);
                if (r != null) {
                    // 结束当前正在发送的广播
                    doNext = r.queue.finishReceiverLocked(r, resultCode,
                            resultData, resultExtras, resultAbort, true);
                }
                if (doNext) {
                    // 立马调度一次发送广播,发送下一次广播,但是processNextBroadcast是一个同步函数,
                    // 一次只能处理一个请求
                    r.queue.processNextBroadcastLocked(/*fromMsg=*/ false, /*skipOomAdj=*/ true);
                }
                // updateOomAdjLocked() will be done here
                trimApplicationsLocked();
            }

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

如果发送广播时接收者不存在,那么要完成该次广播,并且判断是否执行发送给下一个广播接收者,如果需要发送给下个广播接收者要再次调用BroadcastQueue.processNextBroadcast方法,这样就又回到了前面第六步。

七、调用BroadcastQueue的processNextBroadcast方法,执行无序广播

我们重新回到第六步的BroadcastQueue的processNextBroadcast方法中,该方法在执行完无序广播后开始执行有序广播。

	//参数fromMsg是用来描述processNextBroadcast是否是被handleMessage触发的
    final void processNextBroadcast(boolean fromMsg) {
        synchronized (mService) {
            processNextBroadcastLocked(fromMsg, false);
        }
    }
    // 广播发送的核心内容
    final void processNextBroadcastLocked(boolean fromMsg) {
        BroadcastRecord r;
        mService.updateCpuStats();
  		// 否是来自handleMessage的BROADCAST_INTENT_MSG类型消息
        if (fromMsg) {
            // 前面说到,如果消息队列里面有BROADCAST_INTENT_MSG消息,该标记为true,阻止新的消息加入队列,
            // 这里开始处理这个消息的时候,将mBroadcastsScheduled变量设置为false,开始允许新的消息加入。
            mBroadcastsScheduled = false;
        }
		// 无序广播的处理流程,具体请看前面的第六步
        ...
        //开始有序广播的处理流程
		 // 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.
        // 接下来处理保存在有序广播调度队列mPendingBroadcast中的广播转发任务。从前面可知,有序广播
        // 调度队列mOrderedBroadcast描述的目标广播接收者有可能是静态注册的,而这些静态注册的目标广
        // 播接收者可能还没有启动起来,因此AMS将一个广播发送给它们处理时,首先将它们启动起来。事实上,
        // AMS只需要将他们所运行在的进程启动起来就可以了,因为当这些进程接收到AMS发送的广播后,就会
        // 主动将目标广播接收者启动起来
        // mPendingBroadcast对象是用来描述一个正在等待静态注册的目标广播接收者启动起来的广播转发任务的
        if (mPendingBroadcast != null) {
            //记录目标广播接收者所在进程是否是死亡状态
            boolean isDead;
            if (mPendingBroadcast.curApp.pid > 0) {
                synchronized (mService.mPidsSelfLocked) {
                    ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
                    isDead = proc == null || proc.crashing;
                }
            } else {
                final ProcessRecord proc = mService.mProcessNames.get(
                        mPendingBroadcast.curApp.processName, mPendingBroadcast.curApp.uid);
                isDead = proc == null || !proc.pendingStart;
            }
            // 如果应用已经启动,会调用AMS的函数来处理静态广播,这里直接return
            if (!isDead) {
                // It's still alive, so keep waiting
                return;
            } else {
                mPendingBroadcast.state = BroadcastRecord.IDLE;
                mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
                mPendingBroadcast = null;
            }
        }

        boolean looped = false;
        // 这里的do-while只会从mOrderedBroadcasts中取出第一个BroadcastRecord进行后续的处理!
        do {
            // 判断有序广播调度队列mOrderedBroadcasts是否还有需要处理的广播
            // 如果长度为0,则说明调度队列mOrderedBroadcasts中的广播已经全部处理完成
            if (mOrderedBroadcasts.size() == 0) {
                // No more broadcasts pending, so all done!
                mService.scheduleAppGcsLocked();
                if (looped) {
                    // If we had finished the last ordered broadcast, then
                    // make sure all processes have correct oom and sched
                    // adjustments.
                    mService.updateOomAdjLocked();
                }
                return;
            }
            // 如果没有处理完成,则继续取出mOrderedBroadcasts中的第一个BroadcastRecord
            r = mOrderedBroadcasts.get(0);
            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 PRE_BOOT_COMPLETED
            // receivers don't get executed with timeouts. They're intended for
            // one time heavy lifting after system upgrades and can take
            // significant amounts of time.
            // 获取广播转发任务的目标广播接收者的个数
            int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
            // 检查前一个目标广播接收者是否在规定的时间内处理完成AMS给它发送的一个有序广播。AMS处理
            // BroadcastRecord对象r所描述的一个广播转发任务时,会将当前时间记录在这个BroadcastRecord
            // 对象中,如果这个广播任务不能在(2*BROADCAST_TIMEOUT*numReceivers)毫秒内完成,即它的目
            // 标广播接收者不能在(2*BROADCAST_TIMEOUT*numReceivers)毫秒内完成AMS给它们发送的一个有
            // 序广播,那么会调用broadcastTimeoutLocked函数来强制结束这个广播转发任务,
            if (mService.mProcessesReady && r.dispatchTime > 0) {
                long now = SystemClock.uptimeMillis();
                if ((numReceivers > 0) && (now > r.dispatchTime + (2 * mTimeoutPeriod * numReceivers))) {
                    //出现超时,强制结束
                    broadcastTimeoutLocked(false); // forcibly finish this broadcast
                    // 重置参数,继续处理有序广播调度队列mOrderedBroadcasts的下一个广播转发任务
                    forceReceive = true;
                    r.state = BroadcastRecord.IDLE;
                }
            }

            if (r.state != BroadcastRecord.IDLE) {
                return;
            }

            // 检测广播转发任务是否正在处理中,即AMS正在将一个有序广播转发给它的前一个目标广播接收处理者,
            // 如果是,AMS就会等待这个目标广播接收者处理完该有序广播,然后再转发给下一个广播接收者处理

            // r.resultAbort表示广播已经向所有的receiver发送结束或者中途被取消, 如果r.resultAbort为true,会停止处理
            // 当前正在发送的BroadcastRecord,这样优先级比较低的接收者也就收不到这个广播了
            // forceReceive检查BroadcastRecord对象r所描述的广播转发任务是否已经处理完成,或者是否已经被强制结束了。
            // 如果是,那么调用函数cancelBroadcastTimeoutLocked来删除前面发送到AMS所运行在的线程的消息
            // 队列中的一个BROADCAST_TIMEOUT_MSG消息,表示BroadcastRecord对象r所描述的广播转发任务已经
            // 在规定时间内处理完成了。接下来就讲改广播BroadcastRecord对象从队列中删除,然后赋值为null
            if (r.receivers == null || r.nextReceiver >= numReceivers
                    || r.resultAbort || forceReceive) {
                // No more receivers for this broadcast!  Send the final
                // result if requested...
                if (r.resultTo != null) {
                    try {
                        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;
                    }
                }
                cancelBroadcastTimeoutLocked();//取消即将导致ANR异常的消息
                // ... 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);
                }
                // BroadcastRecord处理完移除
                mOrderedBroadcasts.remove(0);
                r = null;
                looped = true;
                continue;
            }
        } while (r == null);// 如果第一次取出的r不为空,则退出循环

        // Get the next receiver...
        //获取下一个将要处理的广播接收者在其列表中的位置
        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.
        // 保存当前时间
        r.receiverTime = SystemClock.uptimeMillis();
        if (recIdx == 0) {// 表示第一个开始处理的接收者,也就是BroadcastRecord对象r所描述的广播任务刚被处理
            // 接收者开始处理的时间戳,也就是这个接收者开始处理了,要记录开始时间来计算是否超过超时时间
            // 也就是说这是BroadcastRecord中第一个接收者开始被处理的时间戳,也就是上面BroadcastRecord
            // 超时的起点,可以看到上面超时比较的时候用的就是r.dispatchTime
            r.dispatchTime = r.receiverTime;
            r.dispatchClockTime = System.currentTimeMillis();
        }
        if (!mPendingBroadcastTimeoutMessage) {
            long timeoutTime = r.receiverTime + mTimeoutPeriod;
            // 设置超时,传入参数是r.receiverTime + mTimeoutPeriod,也就是开始时间加上超时时间
            // mTimeoutPeriod,mTimeoutPeriod初始化是在BroadcastQueue初始化的时候传入的,
            // 也就是在AMS(AMS构造函数中)中初始化mFgBroadcastQueue和mBgBroadcastQueue时传入的
            // BROADCAST_FG_TIMEOUT = 10 * 1000和BROADCAST_BG_TIMEOUT = 60 * 1000,
            // 这里开始埋了ANR的雷
            setBroadcastTimeoutLocked(timeoutTime);
        }

        // 上面分析的时候对于BroadcastRecord.receivers里面包含两种receiver接收者:order广播下的
        // 动态注册接收者和静态接收者,这两种receiver处理的方式是不一样的,对于order广播下的动态注册
        // receiver而言,接收者进程一定是已经启动的,但是对于静态接收者receiver而言,当前的receiver进程
        // 可能还没有启动,因此动态和静态的receiver处理的逻辑不一样,需要分开处理,而静态接收者又分为进程
        // 已经启动和尚未启动两种情况。

        final BroadcastOptions brOptions = r.options;
        // 得到下一个广播接收者
        final Object nextReceiver = r.receivers.get(recIdx);
        // 如果当前nextReceiver是一个BroadcastFilter类型,说明是一个动态注册接收者,不需要启动一个进程,
        // 直接调用deliverToRegisteredReceiverLocked函数发送广播
        if (nextReceiver instanceof BroadcastFilter) {
            // Simple case: this is a registered receiver who gets
            // a direct call.
            BroadcastFilter filter = (BroadcastFilter) nextReceiver;
            // 调用deliverToRegisteredReceiverLocked向所有的receivers发送广播
            // 将它所描述的每一个无序广播发送给每一个广播接收者,异步处理广播
            // 通过deliverToRegisteredReceiverLocked调用ActivityThread.scheduleRegisteredReceiver处理广播
            deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
            // 检查BroadcastRecord对象r所描述的广播转发任务是否用来转发无序广播的。
            if (r.receiver == null || !r.ordered) {
                // 设置IDLE状态,表示AMS不需要等待它的前一个目标广播接收者处理完成一个广播就可以将该广播
                // 继续发送给它的下一个目标广播接收者处理
                r.state = BroadcastRecord.IDLE;
                // 调用下面函数就是为了将一个广播继续发送给BroadcastRecord对象r所描述的广播转发任务的
                // 下一个目标广播接收者处理的
                scheduleBroadcastsLocked();
            } else {
                if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
                    scheduleTempWhitelistLocked(filter.owningUid,
                            brOptions.getTemporaryAppWhitelistDuration(), r);
                }
            }
            return;
        }

        // Hard case: need to instantiate the receiver, possibly
        // starting its application process to host it.
        // 如果上面if没有进行拦截,说明不是广播接收者动态注册的,而应该是静态注册的
        // 此时进程可能没有启动
        ResolveInfo info = (ResolveInfo) nextReceiver;
        ComponentName component = new ComponentName(
                info.activityInfo.applicationInfo.packageName,
                info.activityInfo.name);

        // 是否跳过该广播接收者不处理
        ...
        // 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.
        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);
        }
        // 得到ResolveInfo对象info所描述的广播接收者的android:process属性值,
        // 即它需要运行在的应用程序进程的名称,并且保存在变量targetProcess中
        String targetProcess = info.activityInfo.processName;
        // 获取当前广播接收者的进程记录,也就是该静态广播接收者是否已经运行
        ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
                info.activityInfo.applicationInfo.uid, false);
     	// 是否跳过该广播接收者不处理
   		...
        // 如果跳过,直接恢复初始状态,开始下一个广播接收者的处理
        if (skip) {
            r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
            r.receiver = null;
            r.curFilter = null;
            r.state = BroadcastRecord.IDLE;
            r.manifestSkipCount++;
            scheduleBroadcastsLocked();
            return;
        }
        r.manifestCount++;

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

        // Broadcast is being executed, its package can't be stopped.
        try {
            AppGlobals.getPackageManager().setPackageStoppedState(
                    r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
        } catch (RemoteException e) {
        } catch (IllegalArgumentException e) {
        }

        // Is this receiver's application already running?
        // 如果当前进程已经运行,则直接发给该进程,然后返回
        if (app != null && app.thread != null && !app.killed) {
            try {
                app.addPackage(info.activityInfo.packageName,
                        info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
                // app进程存在,通过processCurBroadcastLocked -> ActivityThread.scheduleReceiver -> receiver.onReceive处理当前广播
                // 第九步有具体分析
                processCurBroadcastLocked(r, app, skipOomAdj);
                // order广播是一种同步处理方式,因此处理完可以直接return
                return;
            } catch (RemoteException e) {

            } catch (RuntimeException 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.
        }

     	// 如果app进程不存在,会先创建该进程,第十步有具体分析
        // 静态接收者进程尚未启动,调用AMS的startProcessLocked函数启动该接收者进程,并将当前正在等待进程
        // 启动的BroadcastRecord存储到mPendingBroadcast里面,这个就是静态广播拉起应用的原理,如果应用
        // 没有启动,注册一个静态广播(一般厂商会修改只能启动自己的应用)。到这里又开始进入等待进程启动的
        // 过程,进程启动完成后才能处理广播,流程如下
        // AMS >>> Process >>> Zygote
        // >>>> ActivityThread.main >>>> ActivityThread.attach >>>> AMS.attachApplication >>>> AMS.attachApplicationLocked
        // >>>> ActivityThread.bindApplication >>>> AMS.sendPendingBroadcastsLocked >>>> BroadcastQueue.sendPendingBroadcastsLocked
        // >>>> BroadcastQueue.processCurBroadcastLocked >>>> ActivityThread.scheduleReceiver >>>> ActivityThread.handleReceiver
        // >>>> BroadcastReceiver.onReceive(触发广播接收者的onReceive方法)
        // >>>> ReceiverData.finishReceiver >>>> AMS.finishReceiver
        if ((r.curApp = mService.startProcessLocked(targetProcess,
                info.activityInfo.applicationInfo, true,
                r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
                "broadcast", r.curComponent,
                (r.intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                == null) {// 如果启动失败
            logBroadcastReceiverDiscardLocked(r);
            // 结束广播发送任务
            finishReceiverLocked(r, r.resultCode, r.resultData,
                    r.resultExtras, r.resultAbort, false);
            scheduleBroadcastsLocked();
            r.state = BroadcastRecord.IDLE;
            return;
        }
        // 将BroadcastRecord赋值为mPendingBroadcast,等待应用启动完成后处理
        // 正在启动接收者进程,将正在启动的BroadcastRecord记录存储到mPendingBroadcast中,同时将当前正在
        // 启动的接收者进程在所有接收者中的索引存储到mPendingBroadcastRecvIndex,如果当前广播接收者处理
        // 完,需要继续从mPendingBroadcastRecvIndex计算到下一个接收者发送当前广播
        mPendingBroadcast = r;
        mPendingBroadcastRecvIndex = recIdx;
    }

因为有序广播是一个执行完再执行下一个所以必须设置超时,并且如果超时要立即结束广播:

八、调用BroadcastQueue的broadcastTimeoutLocked方法处理超时问题

    /**
     * AMS在处理order模式广播接收者时,会为每一个order模式广播处理设置超时时间,并且超时时间是各个接收者之间
     * 相互独立,前面分析超时通过setBroadcastTimeoutLocked函数建立超时时间点消息的,本以为每次处理完以后,
     * 调用cancelBroadcastTimeoutLocked函数取消当前接收者的超时消息,但是实际上用了一种更加高效的方法处理了
     * 超时机制,在每个order模式receiver开始处理的时候设置超时消息,BroadcastRecord.receiverTime记录了
     * 当前receiver开始处理的时间点
     * <p>
     * BroadcastRecord超时:注意这里的超时和我们常说的广播超时ANR不是一个概念,这个BroadcastRecord超时是针
     * 对当前BroadcastRecord. receivers里面剩余的所有的成员而言的,比如说当前receivers里面剩余4个广播接收者,
     * 那么这个超时的时间: 2*(4*mTimeoutPeriod) 至于这个mTimeoutPeriod,对于前台广播mFgBroadcastQueue
     * 和mBgBroadcastQueue后台广播时间:BROADCAST_FG_TIMEOUT = 10 * 1000
     * 和BROADCAST_BG_TIMEOUT = 60 * 1000(AMS中),也就是对于有4个成员的receivers 后台广播的
     * BroadcastRecord而言超时的时间为:2*(4*10*1000)=80 000ms=80s,当出现这种超时的时候,当前正在处理的
     * 广播接收者会出现ANR,并且导致后面尚未接收到广播的收不到当前的广播。broadcastTimeoutLocked函数会将
     * mOrderedBroadcasts中下标为0的应用进程ANR,下面forceReceive设置为true,走到下面的if判断里面会将当前
     * 正在处理的BroadcastRecord从mOrderedBroadcasts中remove掉,导致receivers后面的成员没有收到广播,
     * 并且将r设置为null,接着就处理broadcastTimeoutLocked里面的下一个广播记录BroadcastRecord。例如,
     * receivers里面包含4个成员,但是第1个接收者在80s内都没有处理完,那么这个接收者进程会收到ANR,
     * 并且后面的3个广播接收者都收不到当前的广播。
     * <p>
     *
     * @param fromMsg
     */
    final void broadcastTimeoutLocked(boolean fromMsg) {
        if (fromMsg) {
            mPendingBroadcastTimeoutMessage = false;
        }

        if (mOrderedBroadcasts.size() == 0) {
            return;
        }

        long now = SystemClock.uptimeMillis();
        BroadcastRecord r = mOrderedBroadcasts.get(0);
        if (fromMsg) {
            if (!mService.mProcessesReady) {
                // Only process broadcast timeouts if the system is ready. That way
                // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
                // to do heavy lifting for system up.
                return;
            }

            long timeoutTime = r.receiverTime + mTimeoutPeriod;
            // 举个例子:
            // 假设receiverA在100s的时候开始处理,超时时间为10s,那么receiverA的超时时间点就是110s,
            // 但是receiverA在105s的时候已经处理完了,于是在105s的时候开始receiverB,但是并没有取消
            // receiverA的超时消息,也就是在110s的时候仍然会走到这里的broadcastTimeoutLocked函数,
            // receiverB开始处理,这时候r.receiverTime就是105s,对于receiverB而言超时时间应该是115s,
            // 假设receiverB需要在112s才能处理完,在110s的时候broadcastTimeoutLocked函数处理的时候
            // timeoutTime=115s,now=110s,这时候不会进行实际的超时处理,因为还没有到真实的超时时间,
            // 所以重新设置超时时间点在115s。就这样根据当前BroadcastRecord.receiverTime的时间反复调整。
            if (timeoutTime > now) {// 判断超时时间点和现在时间的关系,此处还没有超时
                // 因为没有在每个广播处理完之后取消或者重置超时时间,从而导致提前检测到超时消息。取而代之,
                // 设置一个初始超时时间点,然后每次出现超时事件的时候根据需要进行处理或者调整超时机制。
                setBroadcastTimeoutLocked(timeoutTime);
                return;
            }
        }
  • 关于超时的处理,注释已经非常详细,我们在写广播接收到消息是最后采用Handler或者启动服务将消息处理的过程放到Handler中或者服务中,而不是直接在广播接收者中完成。

  • 关于setBroadcastTimeoutLocked方法,如果广播还没有超时就执行完了就从新设置下一个广播的起始时间,方便计算下一个广播的超时。这个消息处理就不分析了,自己看一下。再回到第六步BroadcastQueue.processNextBroadcast方法中,如果广播发送完成,或者被中断或者取消,则判断是否发送最后的广播,如果要发送,则执行performReceiveLocked方法,这个方法在第八步讲了,这里就不再重复分析。我们知道广播有静态广播接收者和动态广播接收者,动态广播接收者进程都是启动的,但是静态的就不一定了,可能进程还没有启动,就想第六步中代码注释分析的一样,我们上面处理的都是动态注册的,不需要判断进程是否已经启动,但是静态广播就需要判断该进程是否已经启动了。这里的ResolveInfo表示静态广播接收者对象。找到对象后判断是否要跳过该广播,如果跳过则通过执行scheduleBroadcastsLocked方法发送消息执行下一个广播。如果不需要跳过该广播时,判断该进程是否存在,如果该静态广播的进程已经存在了则执行processCurBroadcastLocked,将广播发送给该进程处理,如果不存在则启动进程,并且将广播对象BroadcastRecord放入等待广播列表中,如果启动失败则接受该广播并判断是否执行下一个广播,我们先将一下进程存在时广播的处理,最后再分析进程启动时的广播处理。

九、如果app进程存在

9.1 调用BroadcastQueue的processCurBroadcastLocked方法处理有序广播
    // 这里只是将广播发送到接收者进程,需要一直等待接收者进程处理完广播后返回,AMS才能处理当前BroadcastRecord
    // 里面的下一个receiver,所以直接返回就行了,反正需要等待的。
    // 这个方法会触发以下流程
    // ActivityThread->scheduleReceiver>>>>>ActivityThread->handleReceiver>>>>>Receiver->onReceive
    private final void processCurBroadcastLocked(BroadcastRecord r,
                                                 ProcessRecord app, boolean skipOomAdj) throws RemoteException {
        if (app.thread == null) {
            throw new RemoteException();
        }
        if (app.inFullBackup) {
            skipReceiverLocked(r);
            return;
        }
        // 将进程的相关信息写入当前BroadcastRecord中相关的接收者
        r.receiver = app.thread.asBinder();
        r.curApp = app;
        app.curReceivers.add(r);
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
        mService.updateLruProcessLocked(app, false, null);
        if (!skipOomAdj) {
            mService.updateOomAdjLocked();
        }

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

        boolean started = false;
        try {
            mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
                    PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
            // 处理广播,等待接收进程的返回
            app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
                    mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
                    r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
                    app.repProcState);
            started = true;
        } finally {
            if (!started) {
                r.receiver = null;
                r.curApp = null;
                app.curReceivers.remove(r);
            }
        }
    }
9.2 调用ApplicationThread的scheduleReceiver方法
       // 处理应用进程中接收到的静态广播消息,实际处理该广播的是ActivityThread.handleReceiver函数
        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);
        }
    class H extends Handler {
    	...
         public void handleMessage(Message msg) {
                 switch (msg.what) {
                 		...
		              case RECEIVER:
		              	  //该消息最终会触发handleReceiver方法
		                  handleReceiver((ReceiverData)msg.obj);
		                  break;    
		                ...   		
          }
    }
9.3调用ApplicationThread的handleReceiver方法
    // 主要包括三步:
    // 1) 创建BroadcastReceiver对象
    // 2) 执行onReceive函数
    // 3) 向AMS发送处理结束消息
    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();
        // 1) 创建BroadcastReceiver对象
        // 这里处理的是静态广播接收者,默认认为接收者BroadcastReceiver对象不存在
        // 每次接受都会创建一个新的BroadcastReceiver对象
        String component = data.intent.getComponent().getClassName();

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

        IActivityManager mgr = ActivityManager.getService();

        Application app;
        BroadcastReceiver receiver;
        ContextImpl context;
        try {
            // 首先从AMS传递的intent中获取当前处理该广播的组件名称,然后通过反射创建一个BroadcastReceiver
            // 对象,从这里可以看出来,静态广播处理的时候,每次都会创建一个新的BroadcastReceiver对象;

            // 创建Application对象,如果进程已经启动,Application对象已经创建
            app = packageInfo.makeApplication(false, mInstrumentation);
            context = (ContextImpl) app.getBaseContext();
            if (data.info.splitName != null) {
                context = (ContextImpl) context.createContextForSplit(data.info.splitName);
            }
            java.lang.ClassLoader cl = context.getClassLoader();
            data.intent.setExtrasClassLoader(cl);
            data.intent.prepareToEnterProcess();
            data.setExtrasClassLoader(cl);
            receiver = packageInfo.getAppFactory()
                    .instantiateReceiver(cl, data.info.name, data.intent);
        } catch (Exception e) {
            data.sendFinished(mgr);
            throw new RuntimeException(
                "Unable to instantiate receiver " + component
                + ": " + e.toString(), e);
        }

        // 2) 执行onReceive函数
        try {
            sCurrentBroadcastIntent.set(data.intent);
            // 调用接收者的onReceive方法,这里还调用了setPendingResult方法,详细内容请看BroadcastReceiver.goAsync方法。
            receiver.setPendingResult(data);
            receiver.onReceive(context.getReceiverRestrictedContext(),
                    data.intent);
        } catch (Exception e) {
            data.sendFinished(mgr);
            if (!mInstrumentation.onException(receiver, e)) {
                throw new RuntimeException(
                    "Unable to start receiver " + component
                    + ": " + e.toString(), e);
            }
        } finally {
            sCurrentBroadcastIntent.set(null);
        }
        // 3) 向AMS发送处理结束消息
        if (receiver.getPendingResult() != null) {
            data.finish();
        }
    }

十、app进程不存在,先创建该进程

如果静态广播接收者进程尚未启动,会直接调用AMS的startProcessLocked函数启动该接收者进程,并将当前正在等待进程
启动的BroadcastRecord存储到mPendingBroadcast里面,这个就是静态广播拉起应用的原理,如果应用
没有启动,注册一个静态广播(一般厂商会修改只能启动自己的应用)。到这里又开始进入等待进程启动的
过程,进程启动完成后才能处理广播,流程如下

AMS >>> Process >>> Zygote >>> ZygotInit
>>>> ActivityThread.main >>>> ActivityThread.attach >>>> AMS.attachApplication >>>> AMS.attachApplicationLocked
>>>> ActivityThread.bindApplication >>>> AMS.sendPendingBroadcastsLocked >>>> BroadcastQueue.sendPendingBroadcastsLocked
>>>> BroadcastQueue.processCurBroadcastLocked >>>> ActivityThread.scheduleReceiver >>>> ActivityThread.handleReceiver
>>>> BroadcastReceiver.onReceive(触发广播接收者的onReceive方法)
>>>> ReceiverData.finishReceiver >>>> AMS.finishReceiver
10.1 调用AMS的sendPendingBroadcastsLocked方法

关于应用进程的创建流程,并不是本篇文章讨论的范畴,这里不会细讲;总之在app进程启动之后,会先调用application的attach和onCreate方法,然后才会调用ActivityManagerService的sendPendingBroadcastsLocked方法。

    boolean sendPendingBroadcastsLocked(ProcessRecord app) {
        boolean didSomething = false;
        for (BroadcastQueue queue : mBroadcastQueues) {
        	//调用BroadcastQueue的sendPendingBroadcastsLocked方法
            didSomething |= queue.sendPendingBroadcastsLocked(app);
        }
        return didSomething;
    }

mBroadcastQueues是包含前台优先级和后台优先级的广播队列,这里分别调用前台和后台优先级广播的BroadcastQueue.sendPendingBroadcastsLocked方法。

10.1 调用BroadcastQueue的sendPendingBroadcastsLocked方法
    // 未启动进程的广播接收者需要先启动进程,最后到达这个函数
    public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
        boolean didSomething = false;
        // 前面分析mPendingBroadcast用于存储当前正在等待进程启动的BroadcastRecord
        final BroadcastRecord br = mPendingBroadcast;
        if (br != null && br.curApp.pid > 0 && br.curApp.pid == app.pid) {
            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 {
                // 启动完成设置为null
                mPendingBroadcast = null;
                // 调用processCurBroadcastLocked方法进行处理
                processCurBroadcastLocked(br, app, false);
                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;
    }

这里是找到等待处理的广播并且判断是否为空,以及是否和当前进程的pid相同,也就是是不是这个进程的等待广播,如果是就调用processCurBroadcastLocked方法进行处理,这个方法在上面第九步中已经很详细的分析过了,等于又回到了进程存在的情况下广播的处理。

至此,整个广播的发送接受流程就分析完了,代码量很大,但是逻辑很清楚,多画时序图,然后对着注释多看看应该就能明白了。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值