美文网首页
broadcast 学习

broadcast 学习

作者: android小奉先 | 来源:发表于2021-04-17 22:41 被阅读0次

    本篇介绍

    android的广播在应用开发中使用的场景很多,本篇就介绍下广播的基本内容,然后侧重介绍广播的几个关键流程,包含广播的注册,注销,还有广播的发送,本篇侧重的是流程的学习,希望通过学习该流程可以对Android的广播有一个清晰的过程了解,这块知识在分析anr问题的时候很有帮助。

    基础知识介绍

    android中的broadcast包含动态注册, 静态注册, 有序广播,本地广播。

    名词 介绍
    静态注册 直接在manifest文件中之名注册广播,不支持注销广播,在广播接受的时候优先级不如动态注册,后续代码会看到
    动态注册 在代码中显示调用registerReceiver注册广播,支持注册与注销,灵活性比较高
    无序广播 并行通知的就是无序广播
    有序广播 通过sendOrderedBroadcast发送,接受者按优先级排序,一个处理完后传递给下一个,同时也可以在本应用中设置数据,这样数据就可以传递给下一个接受者
    本地广播 只在应用内部有效的广播,安全性高
    粘性广播 注册广播的时候如果系统中有广播,那么马上就能收到,而非粘性广播是需要注册完,系统再次接收到广播,应用才可以接收到

    这儿只是介绍下基础概念,重点看下代码流程,分三个,广播的注册,注销,发送。接下来挨个看下。

    广播的注册

    广播的注册要从registerReceiver开始:

        @Override
        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
            return registerReceiver(receiver, filter, null, null);
        }
    
        @Override
        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
                int flags) {
            return registerReceiver(receiver, filter, null, null, flags);
        }
    
        @Override
        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
                String broadcastPermission, Handler scheduler) {
            return registerReceiverInternal(receiver, getUserId(),
                    filter, broadcastPermission, scheduler, getOuterContext(), 0);
        }
    
        @Override
        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
                String broadcastPermission, Handler scheduler, int flags) {
            return registerReceiverInternal(receiver, getUserId(),
                    filter, broadcastPermission, scheduler, getOuterContext(), flags);
        }
    

    可以看到有多种形式的registerReceiver,不过内部都是调用了registerReceiverInternal, 其他的几个参数是全新,handler,flags,看下registerReceiverInternal的实现:

        private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
                IntentFilter filter, String broadcastPermission,
                Handler scheduler, Context context, int flags) {
            IIntentReceiver rd = null;
            if (receiver != null) {
                if (mPackageInfo != null && context != null) {
                    if (scheduler == null) {
                        scheduler = mMainThread.getHandler();
                    } // 广播的默认handler是主线程handler
                    rd = mPackageInfo.getReceiverDispatcher(
                        receiver, context, scheduler,
                        mMainThread.getInstrumentation(), true); 
    // 获取intentreceiver,如果看过bindService流程,这块应该就会觉得比较熟悉了吧?
    //套路就是搞一个匿名binder,然后将匿名binder和当前的receiver绑定起来
                } else {
                    if (scheduler == null) {
                        scheduler = mMainThread.getHandler();
                    }
                    rd = new LoadedApk.ReceiverDispatcher(
                            receiver, context, scheduler, null, true).getIIntentReceiver();
                }
            }
            try {
                final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
                        mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd,
                        filter, broadcastPermission, userId, flags); // 走ams 注册
                if (intent != null) {
                    intent.setExtrasClassLoader(getClassLoader());
                    intent.prepareToEnterProcess();
                }
                return intent;
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    

    这块流程和bindService基本是一致的,搞一个内部对象,然后和一个匿名binder绑定到一个封装对象里面,然后把这个匿名binder的proxy传递到ams中。
    在进入AMS之前再简单看下IIntentReceiver的过程:

        public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
                Context context, Handler handler,
                Instrumentation instrumentation, boolean registered) {
            synchronized (mReceivers) {
                LoadedApk.ReceiverDispatcher rd = null;
                ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
                if (registered) {
                    map = mReceivers.get(context);
                    if (map != null) {
                        rd = map.get(r);
                    }
                } 
    // 还是以context为key管理receivers,每个receiver对应一个receiverdispater
                if (rd == null) {
                    rd = new ReceiverDispatcher(r, context, handler,
                            instrumentation, registered);
                    if (registered) {
                        if (map == null) {
                            map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                            mReceivers.put(context, map);
                        }
                        map.put(r, rd);
                    }
                } else {
                    rd.validate(context, handler);
                }
                rd.mForgotten = false;
                return rd.getIIntentReceiver();
            }
        }
    

    现在也能猜出来ReceiverDispatcher的实现,基本就是内部搞一个匿名binder做一下关联,通过代码证实一下:

        static final class ReceiverDispatcher {
            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) {
                        Log.wtf(TAG, "Null intent received");
                        rd = null;
                    } else {
                        rd = mDispatcher.get();
                    }
                  
                    if (rd != null) {
                        rd.performReceive(intent, resultCode, data, extras,
                                ordered, sticky, sendingUser); 
    //如果非空就通知对应的receiver,可以看到这儿的dispatcher用的是弱应用,这儿是因为匿名binder 记录到ams后,
    //receiver对象是不需要或者没必要保证一定存活的,这样如果应用已经把这个对象释放了,那么就不调用了,直接向ams回一个消息就可以了
                    } 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());
     // 直接向ams 回一个完成消息,具体逻辑在消息通知那部分细看
                        } catch (RemoteException e) {
                            throw e.rethrowFromSystemServer();
                        }
                    }
                }
            }
    
    
    

    接下来就开始进入ams看ams里面是如何注册receiver的,入口函数就是registerReceiverWithFeature,在此之前先看下传递了哪些参数:

    参数 含义
    mMainThread.getApplicationThread() 当前应用的binder
    mBasePackageName 包名
    getAttributionTag 属性tag
    rd IIntentReceiver的binder
    filter 过滤广播的Intent
    broadcastPermission 权限相关
    userId 用户id
    flags 标识符

    代码比较多,还是分开阅读:

        public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
                String callerFeatureId, IIntentReceiver receiver, IntentFilter filter,
                String permission, int userId, int flags) {
            enforceNotIsolatedCaller("registerReceiver");
            ArrayList<Intent> stickyIntents = null;
            ProcessRecord callerApp = null;
            final boolean visibleToInstantApps
                    = (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
            int callingUid;
            int callingPid;
            boolean instantApp;
            synchronized(this) {
                if (caller != null) {
                    callerApp = getRecordForAppLocked(caller); //获取调用方进程信息
                    if (callerApp == null) {
                        throw new SecurityException(
                                "Unable to find app for caller " + caller
                                + " (pid=" + Binder.getCallingPid()
                                + ") when registering receiver " + receiver);
                    }
                    if (callerApp.info.uid != SYSTEM_UID &&
                            !callerApp.pkgList.containsKey(callerPackage) &&
                            !"android".equals(callerPackage)) {
                        throw new SecurityException("Given caller package " + callerPackage
                                + " is not running in process " + callerApp);
                    }
                    callingUid = callerApp.info.uid;
                    callingPid = callerApp.pid;
                } else {
                    callerPackage = null;
                    callingUid = Binder.getCallingUid();
                    callingPid = Binder.getCallingPid();
                }
               instantApp = isInstantApp(callerApp, callerPackage, callingUid);
                userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                        ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
    
                Iterator<String> actions = filter.actionsIterator();
                if (actions == null) {
                    ArrayList<String> noAction = new ArrayList<String>(1);
                    noAction.add(null);
                    actions = noAction.iterator();
                }
    
                // Collect stickies of users
                int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
                while (actions.hasNext()) {
                    String action = actions.next();
                    for (int id : userIds) {
                        ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id); //查询粘性广播
                        if (stickies != null) {
                            ArrayList<Intent> intents = stickies.get(action);
                            if (intents != null) {
                                if (stickyIntents == null) {
                                    stickyIntents = new ArrayList<Intent>();
                                }
                                stickyIntents.addAll(intents);
                            }
                        }
                    }
                }
            }
    
           ArrayList<Intent> allSticky = null;
            if (stickyIntents != null) {
                final ContentResolver resolver = mContext.getContentResolver();
                // Look for any matching sticky broadcasts...
                for (int i = 0, N = stickyIntents.size(); i < N; i++) {
                    Intent intent = stickyIntents.get(i);
                    // Don't provided intents that aren't available to instant apps.
                    if (instantApp &&
                            (intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
                        continue;
                    }
                    // If intent has scheme "content", it will need to acccess
                    // provider that needs to lock mProviderMap in ActivityThread
                    // and also it may need to wait application response, so we
                    // cannot lock ActivityManagerService here.
                    if (filter.match(resolver, intent, true, TAG) >= 0) {
                        if (allSticky == null) {
                            allSticky = new ArrayList<Intent>();
                        }
                        allSticky.add(intent);
                    }
                }
            }
    
            // The first sticky in the list is returned directly back to the client.
            Intent sticky = allSticky != null ? allSticky.get(0) : null;
            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Register receiver " + filter + ": " + sticky);
            if (receiver == null) {
                return sticky;
            }
    
            synchronized (this) {
                if (callerApp != null && (callerApp.thread == null
                        || callerApp.thread.asBinder() != caller.asBinder())) {
                    // Original caller already died
                    return null;
                }
                ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); // 按binder 查找该receiver对应的ReceiverList
                if (rl == null) {
                    rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                            userId, receiver);
                    if (rl.app != null) {
                        final int totalReceiversForApp = rl.app.receivers.size();
                        if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
                            throw new IllegalStateException("Too many receivers, total of "
                                    + totalReceiversForApp + ", registered for pid: "
                                    + rl.pid + ", callerPackage: " + callerPackage);
                        }// 单个应用注册的广播不超过1000个
                        rl.app.receivers.add(rl);
                    } else {
                        try {
                            receiver.asBinder().linkToDeath(rl, 0);
                        } catch (RemoteException e) {
                            return sticky;
                        }
                        rl.linkedToDeath = true;
                    }
                    mRegisteredReceivers.put(receiver.asBinder(), rl);
                } 
    ...
                BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
                        permission, callingUid, userId, instantApp, visibleToInstantApps);
                if (rl.containsFilter(filter)) {
                    Slog.w(TAG, "Receiver with filter " + filter
                            + " already registered for pid " + rl.pid
                            + ", callerPackage is " + callerPackage);
                } else {
                    rl.add(bf); //为调用方应用添加filter
                    if (!bf.debugCheck()) {
                        Slog.w(TAG, "==> For Dynamic broadcast");
                    }
                    mReceiverResolver.addFilter(bf);
    //在ams中添加filter,到了这儿普通的广播注册流程已经结束了
    //再往下就是粘性广播了,如果是粘性广播,还需要通知下业务
                }
    
                // Enqueue broadcasts for all existing stickies that match
                // this filter.
                if (allSticky != null) {
                    ArrayList receivers = new ArrayList();
                    receivers.add(bf);
    
                    final int stickyCount = allSticky.size();
                    for (int i = 0; i < stickyCount; i++) {
                        Intent intent = allSticky.get(i);
                        BroadcastQueue queue = broadcastQueueForIntent(intent);
                        BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                                null, null, -1, -1, false, null, null, OP_NONE, null, receivers,
                                null, 0, null, null, false, true, true, -1, false,
                                false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */);
                        queue.enqueueParallelBroadcastLocked(r);//添加到并行广播队列中
                        queue.scheduleBroadcastsLocked(); // 投递广播,具体细节见通知部分
                    }
                }
    
                return sticky;
            }
        }
    

    到了这儿广播的注册就介绍完了,流程很清晰,就是应用把receiver对应的binder传递到ams中,并记录到ams的对应结构中就可以了,记录的时候,在应用对应的结构中记录一份,在ams的全局mReceiverResolver也记录一份,这个也是用内存换效率的例子了。如果是有粘性广播,则还需要立马通知下注册方。

    广播的注销

    看了广播的注册后,注销就差不多能猜到了,可以简单看下:

        public void unregisterReceiver(BroadcastReceiver receiver) {
            if (mPackageInfo != null) {
                IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
                        getOuterContext(), receiver);
                try {
                    ActivityManager.getService().unregisterReceiver(rd);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            } else {
                throw new RuntimeException("Not supported in system context");
            }
        }
    

    可以看到流程基本是先从本地应用记录的receiver 中删除掉记录,然后再发一个请求到AMS删除ams保存的记录。

        public IIntentReceiver forgetReceiverDispatcher(Context context,
                BroadcastReceiver r) {
            synchronized (mReceivers) {
                ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
                LoadedApk.ReceiverDispatcher rd = null;
                if (map != null) {
                    rd = map.get(r);
                    if (rd != null) {
                        map.remove(r); // 删除receiver 
                        if (map.size() == 0) {
                            mReceivers.remove(context);
                        }
                        if (r.getDebugUnregister()) {
                            ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
                                    = mUnregisteredReceivers.get(context);
                            if (holder == null) {
                                holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                                mUnregisteredReceivers.put(context, holder); //记录已删除的receiver
                            }
                            RuntimeException ex = new IllegalArgumentException(
                                    "Originally unregistered here:");
                            ex.fillInStackTrace();
                            rd.setUnregisterLocation(ex);
                            holder.put(r, rd);
                        }
                        rd.mForgotten = true;
                        return rd.getIIntentReceiver();
                    }
                }
                ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
                        = mUnregisteredReceivers.get(context);
                if (holder != null) {
                    rd = holder.get(r);
                    if (rd != null) {
                        RuntimeException ex = rd.getUnregisterLocation();
                        throw new IllegalArgumentException( //重复删除会抛异常
                                "Unregistering Receiver " + r
                                + " that was already unregistered", ex);
                    }
                }
                if (context == null) {
                    throw new IllegalStateException("Unbinding Receiver " + r
                            + " from Context that is no longer in use: " + context);
                } else {
                    throw new IllegalArgumentException("Receiver not registered: " + r);
                }
    
            }
        }
    

    接下来看下ams的实现

        public void unregisterReceiver(IIntentReceiver receiver) {
            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Unregister receiver: " + receiver);
    
            final long origId = Binder.clearCallingIdentity();
            try {
                boolean doTrim = false;
    
                synchronized(this) {
                    ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
                    if (rl != null) {
                        final BroadcastRecord r = rl.curBroadcast;
                        if (r != null && r == r.queue.getMatchingOrderedReceiver(r)) { // 获取当前正在处理的广播,并且接收者是发起的注销方
                            final boolean doNext = r.queue.finishReceiverLocked( //从通知队列里面删除当前receiver
                                    r, r.resultCode, r.resultData, r.resultExtras,
                                    r.resultAbort, false);
                            if (doNext) {
                                doTrim = true;
                                r.queue.processNextBroadcast(false); //如果broadcastrecord状态是APP_RECEIVE 或者WAITING_SERVICES,那就继续处理下一个接收者
                            }
                        }
    
                        if (rl.app != null) {
                            rl.app.receivers.remove(rl);
                        }
                        removeReceiverLocked(rl);
                        if (rl.linkedToDeath) {
                            rl.linkedToDeath = false;
                            rl.receiver.asBinder().unlinkToDeath(rl, 0);
                        }
                    }
                }
    
                // If we actually concluded any broadcasts, we might now be able
                // to trim the recipients' apps from our working set
                if (doTrim) {
                    trimApplications(OomAdjuster.OOM_ADJ_REASON_FINISH_RECEIVER);
                    return;
                }
    
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    

    接下来看下removeReceiverLocked的内容:

       void removeReceiverLocked(ReceiverList rl) {
           mRegisteredReceivers.remove(rl.receiver.asBinder()); //从ams的记录里面删除这个receiver
           for (int i = rl.size() - 1; i >= 0; i--) {
               mReceiverResolver.removeFilter(rl.get(i)); // 从ams里面删除该receiver对应的filter
           }
       }
    

    这时候注销广播也介绍完了,流程比较直接,就是请求方自己删除后,再调用到ams里面删除一把,不涉及发广播的应用。

    广播的发送

    这个应该是本篇最复杂的流程了,这块是应用方发送一个广播到ams,然后ams通知给订阅方,起点是sendBroadcast

        public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
            warnIfCallingFromSystemProcess();
            String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
            try {
                intent.prepareToLeaveProcess(this);
                ActivityManager.getService().broadcastIntentWithFeature(
                        mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                        null, Activity.RESULT_OK, null, null, receiverPermissions,
                        AppOpsManager.OP_NONE, null, false, false, getUserId());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    
        @Override
        public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
                String[] receiverPermissions) {
            String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
            try {
                intent.prepareToLeaveProcess(this);
                ActivityManager.getService().broadcastIntentWithFeature(
                        mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                        null, Activity.RESULT_OK, null, null, receiverPermissions,
                        AppOpsManager.OP_NONE, null, false, false, user.getIdentifier());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    
        @Override
        public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
            warnIfCallingFromSystemProcess();
            String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
            String[] receiverPermissions = receiverPermission == null ? null
                    : new String[] {receiverPermission};
            try {
                intent.prepareToLeaveProcess(this);
                ActivityManager.getService().broadcastIntentWithFeature(
                        mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                        null, Activity.RESULT_OK, null, null, receiverPermissions,
                        AppOpsManager.OP_NONE, options, false, false, getUserId());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    
        @Override
        public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
            warnIfCallingFromSystemProcess();
            String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
            String[] receiverPermissions = receiverPermission == null ? null
                    : new String[] {receiverPermission};
            try {
                intent.prepareToLeaveProcess(this);
                ActivityManager.getService().broadcastIntentWithFeature(
                        mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                        null, Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false,
                        false, getUserId()); // 注意下倒数第二个参数sticky,这儿发的是非粘性广播
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    

    可以看到sendBroadcast有多种形式,不过一样的是本地基本没做啥逻辑,都是一下子到了ams的broadcastIntentWithFeature,现在就进入ams看下:

        public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
                Intent intent, String resolvedType, IIntentReceiver resultTo,
                int resultCode, String resultData, Bundle resultExtras,
                String[] requiredPermissions, int appOp, Bundle bOptions,
                boolean serialized, boolean sticky, int userId) {
            enforceNotIsolatedCaller("broadcastIntent");
            synchronized(this) {
                intent = verifyBroadcastLocked(intent); //对intent进行合法性检查
    
                final ProcessRecord callerApp = getRecordForAppLocked(caller);
                final int callingPid = Binder.getCallingPid();
                final int callingUid = Binder.getCallingUid();
    
                final long origId = Binder.clearCallingIdentity();
                try {
                    return broadcastIntentLocked(callerApp,
                            callerApp != null ? callerApp.info.packageName : null, callingFeatureId,
                            intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                            requiredPermissions, appOp, bOptions, serialized, sticky,
                            callingPid, callingUid, callingUid, callingPid, userId);
                } finally {
                    Binder.restoreCallingIdentity(origId);
                }
            }
        }
    

    接下来看下broadcastIntentLocked,这个函数比较长,只能分阶段看了

      final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,
                @Nullable String callerFeatureId, Intent intent, String resolvedType,
                IIntentReceiver resultTo, int resultCode, String resultData,
                Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
                boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
                int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
                @Nullable int[] broadcastWhitelist) {
    // 可以看到入参里面有resultTo,放心调用的时候传入的是null
            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);
            }
    
            if (userId == UserHandle.USER_ALL && broadcastWhitelist != null) {
                    Slog.e(TAG, "broadcastWhitelist only applies when sending to individual users. "
                            + "Assuming restrictive whitelist.");
                    broadcastWhitelist = new int[]{};
            }
    
            // By default broadcasts do not go to stopped apps.
            intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); // 默认广播不发给已经停止的app
    
            // 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);
            }
    
            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                    (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
                    + " ordered=" + ordered + " userid=" + userId);
            if ((resultTo != null) && !ordered) {
                Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
            }
    
            userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                    ALLOW_NON_FULL, "broadcast", callerPackage);
           // 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())) {
                    Slog.w(TAG, "Skipping broadcast of " + intent
                            + ": user " + userId + " and its parent (if any) are stopped");
                    return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
                }
            }
    

    第一阶段修改了下intent,标注默认不发给已经结束运行的app,如果当前用户或父用户账号不在运行,则直接返回广播失败。接下来看第二阶段:

         final String action = intent.getAction();
            BroadcastOptions brOptions = null;
            if (bOptions != null) { 
     // 对于sendBroadcast,bOptions是null,因此下文可以忽略,感兴趣也可以简单看下
    //就是做权限检查,没权限发广播的,不可以发送给受管控广播的,会拉起后台广播的
    // 权限不通过都会抛异常
                brOptions = new BroadcastOptions(bOptions);
                if (brOptions.getTemporaryAppWhitelistDuration() > 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.
                    if (checkComponentPermission(
                            android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
                            realCallingPid, realCallingUid, -1, true)
                            != PackageManager.PERMISSION_GRANTED) {
                        String msg = "Permission Denial: " + intent.getAction()
                                + " broadcast from " + callerPackage + " (pid=" + callingPid
                                + ", uid=" + callingUid + ")"
                                + " requires "
                                + android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
                        Slog.w(TAG, msg);
                        throw new SecurityException(msg);
                    }
                }
                if (brOptions.isDontSendToRestrictedApps()
                        && !isUidActiveLocked(callingUid)
                        && isBackgroundRestrictedNoCheck(callingUid, callerPackage)) {
                    Slog.i(TAG, "Not sending broadcast " + action + " - app " + callerPackage
                            + " has background restrictions");
                    return ActivityManager.START_CANCELED;
                }
                if (brOptions.allowsBackgroundActivityStarts()) {
                    // See if the caller is allowed to do this.  Note we are checking against
                    // the actual real caller (not whoever provided the operation as say a
                    // PendingIntent), because that who is actually supplied the arguments.
                    if (checkComponentPermission(
                            android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
                            realCallingPid, realCallingUid, -1, true)
                            != PackageManager.PERMISSION_GRANTED) {
                        String msg = "Permission Denial: " + intent.getAction()
                                + " broadcast from " + callerPackage + " (pid=" + callingPid
                                + ", uid=" + callingUid + ")"
                                + " requires "
                                + android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
                        Slog.w(TAG, msg);
                        throw new SecurityException(msg);
                    } else {
                        allowBackgroundActivityStarts = true;
                    }
                }
            }
    

    第二阶段就是做了一个权限检查,并没有主要逻辑,看下第三阶段:

            // Verify that protected broadcasts are only being sent by system code,
            // and that system code is only sending protected broadcasts.
            final boolean isProtectedBroadcast;
            try {
                isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
            } catch (RemoteException e) {
                Slog.w(TAG, "Remote exception", e);
                return ActivityManager.BROADCAST_SUCCESS;
            }
    
            final boolean isCallerSystem;
            switch (UserHandle.getAppId(callingUid)) {
                case ROOT_UID:
                case SYSTEM_UID:
                case PHONE_UID:
                case BLUETOOTH_UID:
                case NFC_UID:
                case SE_UID:
                case NETWORK_STACK_UID:
                    isCallerSystem = true;
                    break;
                default:
                    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.
                    if (callerPackage == null) {
                        String msg = "Permission Denial: not allowed to send broadcast "
                                + action + " from unknown caller.";
                        Slog.w(TAG, msg);
                        throw new SecurityException(msg);
                    } else if (intent.getComponent() != null) {
                        // 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.
                        intent.setPackage(callerPackage);
                    }
                }
            }
    

    第三阶段还是检查,不知道以前是否有人想过,既然android好多行为都依赖于系统广播,那是否可以自己搞一个app专门假冒发这些系统广播,看到这块逻辑就死心了吧,这块就是保证系统广播是需要系统应用才可以发送的。接下来的第五阶段就是一些需要ams介入处理的广播逻辑,这块和主要流程关系不大,因此直接略过。再接着第六阶段就是粘性广播的逻辑了,sendBroadcast发送的是非粘性广播,因此也和该流程影响不大,不过这儿还是需要看下,了解下粘性广播的特殊之处

           // Add to the sticky list if requested.
            if (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);
                }
                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.
                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");
                                }
                            }
                        }
                    }
                }
                ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
                if (stickies == null) {
                    stickies = new ArrayMap<>();
                    mStickyBroadcasts.put(userId, stickies);
                }
                ArrayList<Intent> list = stickies.get(intent.getAction()); 
                if (list == null) {
                    list = new ArrayList<>();
                    stickies.put(intent.getAction(), list);
                }
                final int stickiesCount = list.size();
                int i;
                for (i = 0; i < stickiesCount; i++) {
                    if (intent.filterEquals(list.get(i))) {
                        // This sticky already exists, replace it.
                        list.set(i, new Intent(intent)); // 如果已经有,则取代之
                        break;
                    }
                }
                if (i >= stickiesCount) {
                    list.add(new Intent(intent)); // 这个就是关键的,将当前广播加入到粘性广播stickies中
                }
            }
    

    接下来还是一堆检查,没权限的,指定目标的,和现有粘性广播冲突的,都是不合法的。接下来看第七阶段的内容:

            // Figure out who all will receive this broadcast.
            List receivers = null;
            List<BroadcastFilter> registeredReceivers = null;
            // Need to resolve the intent to interested receivers...
            if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                     == 0) {
                receivers = collectReceiverComponents(
                        intent, resolvedType, callingUid, users, broadcastWhitelist); 
    // 从pms中查询receivers,主要是静态注册的应用
            }
            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]); // 查询多用户对应的receivers
                        if (registeredReceivers == null) {
                            registeredReceivers = registeredReceiversForUser;
                        } else if (registeredReceiversForUser != null) {
                            registeredReceivers.addAll(registeredReceiversForUser);  将两个receiver列表合并起来
                        }
                    }
                } else {
                    registeredReceivers = mReceiverResolver.queryIntent(intent,
                            resolvedType, false /*defaultOnly*/, userId); // 查询单用户的receivers
                }
            }
    
           final boolean replacePending =
                    (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
    
            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction()
                    + " replacePending=" + replacePending);
            if (registeredReceivers != null && broadcastWhitelist != 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(broadcastWhitelist, owningAppId) < 0) {
                        registeredReceivers.remove(i); //如果receiver是三方应用(uid > 10000),并且不在白名单中,则从接收方列表中移除
                    }
                }
            }
    

    看下第八阶段的流程,目前处理的是动态注册的广播,之前有人问过同一个广播,是动态注册还是静态注册先接收到,看到这儿答案就出来了吧,当然是动态注册的先接收到了。

            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);
                }
                final BroadcastQueue queue = broadcastQueueForIntent(intent);
                BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                        callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
                        requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                        resultCode, resultData, resultExtras, ordered, sticky, false, userId,
                        allowBackgroundActivityStarts, timeoutExempt);
                if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
                final boolean replaced = replacePending
                        && (queue.replaceParallelBroadcastLocked(r) != null);
                // Note: We assume resultTo is null for non-ordered broadcasts.
                if (!replaced) {
                    queue.enqueueParallelBroadcastLocked(r); // 加入到并行广播队列中,并且把当前时间记录到广播中
                    queue.scheduleBroadcastsLocked(); // 执行真正的发送广播操作,是异步的,后面详细介绍
                }
                registeredReceivers = null; // 这句很关键,清空动态注册的列表,这样就不会影响后续有序广播的逻辑了
                NR = 0;
            }
    

    这一段针对的是无序广播,无序广播不会拉起静态注册的应用,只会通知给动态注册的应用,这是为了防止一个广播过来了,然后把n个应用拉起来了,这儿比较关键。继续看第九阶段吧

       // 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;
                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--;
                                }
                            }
                        }
                    }
                }
    

    接下来看第十阶段:

                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);
                    }
                    if (curr == null) {
                        curr = registeredReceivers.get(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;
                    }
                }
            }
            while (ir < NR) {
                if (receivers == null) {
                    receivers = new ArrayList();
                }
                receivers.add(registeredReceivers.get(ir));
                ir++;
            }
    

    可以看到这时候就是动态注册和静态注册的receiver合并,需要注意的是如果是无序广播的话,动态注册的已经都通知过了,这儿就全是静态注册的receiver了。如果是有序广播的话,这儿就会按照优先级合并起来。接下来看下最后一个阶段:

            if ((receivers != null && receivers.size() > 0)
                    || resultTo != null) {
                BroadcastQueue queue = broadcastQueueForIntent(intent);
                BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                        callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
                        requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                        resultData, resultExtras, ordered, sticky, false, userId,
                        allowBackgroundActivityStarts, timeoutExempt);
    
                if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);
    
                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 {
                    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;
        }
    

    现在就需要看下scheduleBroadcastsLocked 的逻辑了,广播如何通知给订阅方的逻辑就在里面:

        public void scheduleBroadcastsLocked() {
            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
                    + mQueueName + "]: current="
                    + mBroadcastsScheduled);
    
            if (mBroadcastsScheduled) {
                return;
            }
            mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
            mBroadcastsScheduled = true;
        }
    

    发送了一个looper消息,是异步操作,对应的处理函数是processNextBroadcast, 看下实现逻辑:

        final void processNextBroadcast(boolean fromMsg) {
            synchronized (mService) {
                processNextBroadcastLocked(fromMsg, false);
            }
        }
    

    接着再看下processNextBroadcastLocked,注意这儿的fromMsg 是true, 这里面的逻辑也很多,我们只拿出关键的看看

     final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
            // First, deliver any non-serialized broadcasts right away.
            while (mParallelBroadcasts.size() > 0) {
                r = mParallelBroadcasts.remove(0);
                r.dispatchTime = SystemClock.uptimeMillis();
                r.dispatchClockTime = System.currentTimeMillis();
    
                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));
                }
    
                final int N = r.receivers.size();
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
                        + mQueueName + "] " + r);
                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);
            }
    ...
      do {
                final long now = SystemClock.uptimeMillis();
                r = mDispatcher.getNextBroadcastLocked(now);
    
                if (r == null) {
                    // No more broadcasts are deliverable right now, so all done!
                    mDispatcher.scheduleDeferralCheckLocked(false);
                    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(OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
                    }
    
                    // when we have no more ordered broadcast on this queue, stop logging
                    if (mService.mUserController.mBootCompleted && mLogLatencyMetrics) {
                        mLogLatencyMetrics = false;
                    }
    
                    return; // 接下来没有广播了,所以就退出去了
                }
    
                int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
                if (mService.mProcessesReady && !r.timeoutExempt && r.dispatchTime > 0) {
                    if ((numReceivers > 0) &&
                            (now > r.dispatchTime + (2 * mConstants.TIMEOUT * numReceivers))) {
                        Slog.w(TAG, "Hung broadcast ["
                                + mQueueName + "] discarded after timeout failure:"
                                + " now=" + now
                                + " dispatchTime=" + r.dispatchTime
                                + " startTime=" + r.receiverTime
                                + " intent=" + r.intent
                                + " numReceivers=" + numReceivers
                                + " nextReceiver=" + r.nextReceiver
                                + " state=" + r.state);
                        broadcastTimeoutLocked(false); // forcibly finish this broadcast //按照广播数量和时间计算,已经超时了,因此报一个anr问题
                        forceReceive = true;
                        r.state = BroadcastRecord.IDLE;
                    }
                }
    ...
                if (r.receivers == null || r.nextReceiver >= numReceivers
                        || r.resultAbort || forceReceive) {
    ...
                    if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");
                    cancelBroadcastTimeoutLocked(); // 能走到这里,说明广播都投递结束了,发一个广播超时取消消息,这样就不会anr了。
    
           // 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) {
                r.dispatchTime = r.receiverTime;
                r.dispatchClockTime = System.currentTimeMillis();
    
                if (mLogLatencyMetrics) {
                    FrameworkStatsLog.write(
                            FrameworkStatsLog.BROADCAST_DISPATCH_LATENCY_REPORTED,
                            r.dispatchClockTime - r.enqueueClockTime);
                }
    
                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));
                }
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
                        + mQueueName + "] " + r);
            }
            if (! mPendingBroadcastTimeoutMessage) {
                long timeoutTime = r.receiverTime + mConstants.TIMEOUT;
                if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
                        "Submitting BROADCAST_TIMEOUT_MSG ["
                        + mQueueName + "] for " + r + " at " + timeoutTime);
                setBroadcastTimeoutLocked(timeoutTime);  // 给下一个广播设置超时消息,如果在规定时间内没有移除,那么超时函数就会被调用
            }
    
    ...
           // 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);
            if ((r.curApp=mService.startProcessLocked(targetProcess, //最麻烦的一种是还需要把接收者进程给拉起来
    //有几种情况可以通过广播把应用拉起来,一种是指定了广播flags。一种是指定了广播接收者
                    info.activityInfo.applicationInfo, true,
                    r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
                    new HostingRecord("broadcast", r.curComponent),
                    isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY,
                    (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                            == null) {
                // Ah, this recipient is unavailable.  Finish it if necessary,
                // and mark the broadcast record as ready for the next.
                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);
            mPendingBroadcast = r;
            mPendingBroadcastRecvIndex = recIdx;
    

    第一个阶段先拿出并行广播,然后开始发送,对应的实现就是deliverToRegisteredReceiverLocked,这里面也会有很多检查,不满足条件的receiver就不会投递了,不过不影响主流程,就一块略去了,只看关键部分:

        private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
                BroadcastFilter filter, boolean ordered, int index) {
    ...
            if (ordered) {
                r.receiver = filter.receiverList.receiver.asBinder();
                r.curFilter = filter;
                filter.receiverList.curBroadcast = r;
                r.state = BroadcastRecord.CALL_IN_RECEIVE;
                if (filter.receiverList.app != null) {
                    // 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.curReceivers.add(r);
                    mService.updateOomAdjLocked(r.curApp, true,
                            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.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 {
                    r.receiverTime = SystemClock.uptimeMillis();
                    maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
                    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;
                }
    

    继续看下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) {
                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 {
                        app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                                data, extras, ordered, sticky, sendingUser, app.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.pid + "). Crashing it.");
                            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 {
                receiver.performReceive(intent, resultCode, data, extras, ordered,
                        sticky, sendingUser); // 通知广播
            }
        }
    

    可以看到这儿有两种投递广播的方法,一种是通过应用的主线程投递的,一种是直接走receiver的匿名binder投递的,先看下第一种:

            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);
            }
    

    可以看到第一种的实现到了订阅方进程中也是执行的performReceive,区别就是第一种可以是异步的形式,第二种就成同步了。现在就开始看下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 {
                        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) {
                        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()); // 如果对应的ReceiverDispatcher已经被注销了,那么就直接通知ams
                        } catch (RemoteException e) {
                            throw e.rethrowFromSystemServer();
                        }
                    }
                }
            }
    

    继续看下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);
                    }
                }
                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); // 如果是有序广播,则需要再回复下ams
                    }
                }
            }
    

    可以看到具体的广播通知是在Args里面,这个是类似Runnable的东西,看下实现:

      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);
                            intent.prepareToEnterProcess();
                            setExtrasClassLoader(cl);
                            receiver.setPendingResult(this);
                            receiver.onReceive(mContext, intent); // 调用业务重载的onReceive方法,这时候就通知到业务了
                        } 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(); // 调用的也是sendFinished通知ams
                        }
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    };
                }
            }
    

    这儿就看到广播终于可以通知给业务了,但还没有结束,还需要在通知后,再回复下ams,看下sendFinished:

            public void sendFinished(IActivityManager am) {
                synchronized (this) {
                    if (mFinished) {
                        throw new IllegalStateException("Broadcast already finished");
                    }
                    mFinished = true;
    
                    try {
                        if (mResultExtras != null) {
                            mResultExtras.setAllowFds(false);
                        }
                        if (mOrderedHint) {
                            am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
                                    mAbortBroadcast, mFlags);
                        } else {
                            // This broadcast was sent to a component; it is not ordered,
                            // but we still need to tell the activity manager we are done.
                            am.finishReceiver(mToken, 0, null, null, false, mFlags);
                        }
                    } catch (RemoteException ex) {
                    }
                }
            }
    

    可以看到是调用了finishReceiver来通知的,看下ams那边接收到后,做了哪些事情:

        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);
    
            // 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;
                BroadcastQueue queue;
    
                synchronized(this) {
                    if (isOnOffloadQueue(flags)) {
                        queue = mOffloadBroadcastQueue;
                    } else {
                        queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                                ? mFgBroadcastQueue : mBgBroadcastQueue;
                    }
    
                    r = queue.getMatchingOrderedReceiver(who); //获取当前的binder对应的BroadcastRecord
                    if (r != null) {
                        doNext = r.queue.finishReceiverLocked(r, resultCode,
                            resultData, resultExtras, resultAbort, true); // 通知广播通知结束
                    }
                    if (doNext) {
                        r.queue.processNextBroadcastLocked(/*fromMsg=*/ false, /*skipOomAdj=*/ true);
                    }
                    // updateOomAdjLocked() will be done here
                    trimApplicationsLocked(OomAdjuster.OOM_ADJ_REASON_FINISH_RECEIVER);
                }
    
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    

    看下finishReceiverLocked的逻辑:

       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;
            r.state = BroadcastRecord.IDLE;
            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.
            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.intent.setComponent(null);
            if (r.curApp != null && r.curApp.curReceivers.contains(r)) {
                r.curApp.curReceivers.remove(r);
            }
            if (r.curFilter != null) {
                r.curFilter.receiverList.curBroadcast = null;
            }
            r.curFilter = null;
            r.curReceiver = null;
            r.curApp = null;
            mPendingBroadcast = null;
    
            r.resultCode = resultCode;
            r.resultData = resultData;
            r.resultExtras = resultExtras;
            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.
                    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.
            return state == BroadcastRecord.APP_RECEIVE
                    || state == BroadcastRecord.CALL_DONE_RECEIVE;
        }
    

    这里就完成了广播记录的更新,并且返回了当前BroadcastRecord的状态。
    看到这里,应该是整个流程就梳理完了。
    最后的最后再补充下广播anr的处理,前面有介绍过在发送广播的时候就会检查广播有没有超时,同时也会给新的广播设置超时消息,处理完后删除超时消息,那么广播anr是如何报的呢,处理逻辑就在broadcastTimeoutLocked里:

     final void broadcastTimeoutLocked(boolean fromMsg) {
            if (fromMsg) {
                mPendingBroadcastTimeoutMessage = false;
            }
    
            if (mDispatcher.isEmpty() || mDispatcher.getActiveBroadcastLocked() == null) {
                return;
            }
    
            long now = SystemClock.uptimeMillis();
            BroadcastRecord r = mDispatcher.getActiveBroadcastLocked();
            if (fromMsg) {
                if (!mService.mProcessesReady) {
                    // Only process broadcast timeouts if the system is ready; some early
                    // broadcasts do heavy work setting up system facilities
                    return;
                }
    
                // If the broadcast is generally exempt from timeout tracking, we're done
                if (r.timeoutExempt) {
                    if (DEBUG_BROADCAST) {
                        Slog.i(TAG_BROADCAST, "Broadcast timeout but it's exempt: "
                                + r.intent.getAction());
                    }
                    return;
                }
    
                long timeoutTime = r.receiverTime + mConstants.TIMEOUT;
                if (timeoutTime > now) {
                    // We can observe premature timeouts because we do not cancel and reset the
                    // broadcast timeout message after each receiver finishes.  Instead, we set up
                    // an initial timeout then kick it down the road a little further as needed
                    // when it expires.
                    if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
                            "Premature timeout ["
                            + mQueueName + "] @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
                            + timeoutTime);
                    setBroadcastTimeoutLocked(timeoutTime);
                    return;
                }
            }
    
           if (r.state == BroadcastRecord.WAITING_SERVICES) { // 等待服务启动场景不算,直接传递下一个广播
                // In this case the broadcast had already finished, but we had decided to wait
                // for started services to finish as well before going on.  So if we have actually
                // waited long enough time timeout the broadcast, let's give up on the whole thing
                // and just move on to the next.
                Slog.i(TAG, "Waited long enough for: " + (r.curComponent != null
                        ? r.curComponent.flattenToShortString() : "(null)"));
                r.curComponent = null;
                r.state = BroadcastRecord.IDLE;
                processNextBroadcast(false);
                return;
            }
            // If the receiver app is being debugged we quietly ignore unresponsiveness, just
            // tidying up and moving on to the next broadcast without crashing or ANRing this
            // app just because it's stopped at a breakpoint.
            final boolean debugging = (r.curApp != null && r.curApp.isDebugging());
    
            Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
                    + ", started " + (now - r.receiverTime) + "ms ago"); // 这句log应该是很熟悉得了吧,看到广播anr,就是这儿搞的
            r.receiverTime = now;
            if (!debugging) {
                r.anrCount++;
            }
    
            ProcessRecord app = null;
            String anrMessage = null;
    
            Object curReceiver;
            if (r.nextReceiver > 0) {
                curReceiver = r.receivers.get(r.nextReceiver-1);
                r.delivery[r.nextReceiver-1] = BroadcastRecord.DELIVERY_TIMEOUT;
            } else {
                curReceiver = r.curReceiver;
            }
            Slog.w(TAG, "Receiver during timeout of " + r + " : " + curReceiver);
            logBroadcastReceiverDiscardLocked(r);
            if (curReceiver != null && curReceiver instanceof BroadcastFilter) {
                BroadcastFilter bf = (BroadcastFilter)curReceiver;
                if (bf.receiverList.pid != 0
                        && bf.receiverList.pid != ActivityManagerService.MY_PID) {
                    synchronized (mService.mPidsSelfLocked) {
                        app = mService.mPidsSelfLocked.get(
                                bf.receiverList.pid);
                    }
                }
            } else {
                app = r.curApp;
            }
    
            if (app != null) {
                anrMessage = "Broadcast of " + r.intent.toString();
            }
    
            if (mPendingBroadcast == r) {
                mPendingBroadcast = null;
            }
    
            // Move on to the next receiver.
            finishReceiverLocked(r, r.resultCode, r.resultData,
                    r.resultExtras, r.resultAbort, false); // 跳过当前receiver,直接给下一个receiver传递
            scheduleBroadcastsLocked();
    
            if (!debugging && anrMessage != null) {
                mService.mAnrHelper.appNotResponding(app, anrMessage); //让当前超时的receiver 发生anr
            }
        }
    
    

    这里面的逻辑主要就是找到当前超时的receiver和下一个receiver,然后安排给下一个receiver发送广播,并且把当前超时的receiver 搞一个anr。

    本篇总结

    broadcast的流程还是比较复杂的,本篇把广播的大致流程介绍了下,这样以后不管广播出什么问题,应该都有思路分析了吧。

    相关文章

      网友评论

          本文标题:broadcast 学习

          本文链接:https://www.haomeiwen.com/subject/crmplltx.html