Broadcast原理解析

注册广播源码解析

调用registerReceiver最终进入context的实现类ContextImpl中:

public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        return this.registerReceiver(receiver, filter, (String)null, (Handler)null);
    }
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) {
        return this.registerReceiverInternal(receiver, this.getUserId(), filter, broadcastPermission, scheduler, this.getOuterContext(), 0);
    }

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context, int flags) {
        //getReceiverDispatcher静态内部类,作为当前应用广播的Binder,当有消息时通过此binder回调广播接收者的onReceive方法
        IIntentReceiver rd = null;
        if (receiver != null) {
            //广播接收者不为空
            if (this.mPackageInfo != null && context != null) {
                if (scheduler == null) {
                    //取ActivityThread的handler作为广播调度器
                    scheduler = this.mMainThread.getHandler();
                }
                //从LoadedApk中取广播分发器,,并从广播分发器获取广播IIntentReceiver Binder
                rd = this.mPackageInfo.getReceiverDispatcher(receiver, context, scheduler, this.mMainThread.getInstrumentation(), true);
            } else {
                if (scheduler == null) {
                  //取ActivityThread的handler作为广播调度器
                    scheduler = this.mMainThread.getHandler();
                }
                //创建广播分发器,并从广播分发器获取广播IIntentReceiver Binder
                rd = (new ReceiverDispatcher(receiver, context, scheduler, (Instrumentation)null, true)).getIIntentReceiver();
            }
        }

        try {
            //获取AMS代理进行binder通信,在AMS中进行广播注册
            Intent intent = ActivityManager.getService().registerReceiver(this.mMainThread.getApplicationThread(), this.mBasePackageName, rd, filter, broadcastPermission, userId, flags);
            if (intent != null) {
                intent.setExtrasClassLoader(this.getClassLoader());
                intent.prepareToEnterProcess();
            }

            return intent;
        } catch (RemoteException var10) {
            throw var10.rethrowFromSystemServer();
        }
    }

ContextImpl的注册广播,先获取/创建广播分发器,再通过广播分发器获取本应用广播的Binder,接着获取AMS代理,通过AMS代理进行进程间通信,进入AMS对广播进行注册。
我们先看看LoadedApk获取广播分发器的逻辑:

private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mReceivers = new ArrayMap();
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r, Context context, Handler handler, Instrumentation instrumentation, boolean registered) {
        synchronized(this.mReceivers) {
            LoadedApk.ReceiverDispatcher rd = null;
            ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
            if (registered) {
                //从内存中取当前context中的广播集合map
                map = (ArrayMap)this.mReceivers.get(context);
                if (map != null) {
                    //从广播集合map中取出与本次广播关联的广播分发器
                    rd = (LoadedApk.ReceiverDispatcher)map.get(r);
                }
            }

            if (rd == null) {
                //广播集合map没有本次广播关联的广播分发器,则
                //创建一个广播分发器,其内部关联本次广播、与本次广播关联的IntentReceive等
                rd = new LoadedApk.ReceiverDispatcher(r, context, handler, instrumentation, registered);
                if (registered) {
                    if (map == null) {
                        map = new ArrayMap();
                        //context关联广播集合
                        this.mReceivers.put(context, map);
                    }
                    //将广播分发器放入广播集合中
                    map.put(r, rd);
                }
            } else {
                rd.validate(context, handler);
            }

            rd.mForgotten = false;
            //返回广播分发器的Binder
            return rd.getIIntentReceiver();
        }
    }

LoadedApk中持有一个广播集合用于保存每个context及与context关联的广播集合,一个cotext可以注册多个广播,每个广播会存储在context的广播结合中,且每个广播都会有一个广播分发器关联,每个广播器都会持有广播及广播Binder等,我们看看new一个广播分发器发生了啥:

ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered) {
            if (activityThread == null) {
                throw new NullPointerException("Handler must not be null");
            } else {
                //创建一个IntentReceiver,它是一个Binder,作为广播的Binder
                this.mIIntentReceiver = new LoadedApk.ReceiverDispatcher.InnerReceiver(this, !registered);
                //关联的广播
                this.mReceiver = receiver;
                this.mContext = context;
                //所属的ActivityThread
                this.mActivityThread = activityThread;
                //所属的instrumentation
                this.mInstrumentation = instrumentation;
                this.mRegistered = registered;
                this.mLocation = new IntentReceiverLeaked((String)null);
                this.mLocation.fillInStackTrace();
            }
        }
static final class InnerReceiver extends android.content.IIntentReceiver.Stub {
            final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
            final LoadedApk.ReceiverDispatcher mStrongRef;

            InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
                //弱引用方式持有广播分发器
                this.mDispatcher = new WeakReference(rd);
                this.mStrongRef = strong ? rd : null;
            }
}

到这里我们大致明白:

  • 注册广播时,会使用一个广播分发器ReceiverDispatcher及IIntentReceiver与之关联(不存在则创建)
  • IntentReceiver引用ReceiverDispatcher,ReceiverDispatcher又引用IntentReceiver和真实的BroadcastReceiver
  • 将ReceiverDispatcher存储在LoadedApk的mReceiver中
  • IntentReceiver作为本应用广播接收Binder传递到AMS进行注册

我们继续分析AMS中的registerReceiver方法:

/**
     * Keeps track of all IIntentReceivers that have been registered for broadcasts.
     * Hash keys are the receiver IBinder, hash value is a ReceiverList.
     */
//保存广播接收者及消息过滤器列表,IBinder即上文中的IntentReceiver,ReceiverList是广播与消息过滤器列表
final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
/**
     * Resolver for broadcast intents to registered receivers.
     * Holds BroadcastFilter (subclass of IntentFilter).
     */
//广播消息过滤器列表
final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver

public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
            int flags) {
    //......
    //从注册列表中取出接收者列表
    ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
    if (rl == null) {
                //没有注册过,则创建接收者
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
                //rl.app即callerApp,是ProcessRecord对象
                if (rl.app != null) {
                    final int totalReceiversForApp = rl.app.receivers.size();
                    if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
                        //一个APP的广播注册数超过了阈值,则抛出异常
                        throw new IllegalStateException("Too many receivers, total of "
                                + totalReceiversForApp + ", registered for pid: "
                                + rl.pid + ", callerPackage: " + callerPackage);
                    }
                    //将在ProcessRecord的receivers注册广播
                    rl.app.receivers.add(rl);
                } else {
                    //表示已不存在,标记消息已消亡
                    try {
                        receiver.asBinder().linkToDeath(rl, 0);
                    } catch (RemoteException e) {
                        return sticky;
                    }
                    rl.linkedToDeath = true;
                }
                //注册广播到mRegisteredReceivers中
                mRegisteredReceivers.put(receiver.asBinder(), rl);
            }
    //......
   //根据过滤器filter和广播接收者ReceiverList创建BroadcastFilter 广播过滤
    BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    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);
                if (!bf.debugCheck()) {
                    Slog.w(TAG, "==> For Dynamic broadcast");
                }
                //保存过滤器
                mReceiverResolver.addFilter(bf);
            }
    //......
}

AMS中注册广播主要做:

  • 创建ReceiverList作为广播与过滤器的包装,广播可以关联多个过滤器
  • 将广播注册到AMS的成员变量mRegisteredReceivers中
  • 生成一个过滤BroadcastFilter,并加入ReceiverList中,作为ReceiverList的一个过滤,同时保持到AMS的成员变量mReceiverResolver中

广播注册总结:
现将广播包装为IntentReceiver——》再传递到AMS中进行注册,将广播和过滤器注册到成员变量mRegisteredReceivers中

广播的注册涉及Binder进程间通信,将广播注册到AMS,此广播是经过IntentReceiver进行包装,IntentReceiver是一个binder,方便AMS接收到消息之后,通过过滤匹配到相应广播IntentReceiver,在通过IntentReceiver进行进程间通信回调广播接收消息方法onReceiver

发送&接收广播源码解析

发送广播

发送广播同样是在ContextImpl中:

public void sendBroadcast(Intent intent) {
        this.warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(this.getContentResolver());

        try {
            intent.prepareToLeaveProcess(this);
            ActivityManager.getService().broadcastIntent(this.mMainThread.getApplicationThread(), intent, resolvedType, (IIntentReceiver)null, -1, (String)null, (Bundle)null, (String[])null, -1, (Bundle)null, false, false, this.getUserId());
        } catch (RemoteException var4) {
            throw var4.rethrowFromSystemServer();
        }
    }

发送广播直接获取AMS的代理,并调用broadcastIntent方法进行消息发送,这里使用了进程间通信
我们进入AMS的broadcastIntent方法继续查看其流程:

public final int broadcastIntent(IApplicationThread caller,
            Intent intent, String resolvedType, IIntentReceiver resultTo,
            int resultCode, String resultData, Bundle resultExtras,
            String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean serialized, boolean sticky, int userId) {
        enforceNotIsolatedCaller("broadcastIntent");
        synchronized(this) {
            //校验广播意图的正确性
            intent = verifyBroadcastLocked(intent);
            //从caller即IApplicationThread 获取进程记录信息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;
        }
    }

broadcastIntent接着调用broadcastIntentLocked方法:

@GuardedBy("this")
    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) {
    //......
   //静态广播,即在Manifest中注册的广播
   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);
   }
   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;
                    }
                    //从mReceiverResolver中找到匹配的动态广播列表
                    List<BroadcastFilter> registeredReceiversForUser =
                            mReceiverResolver.queryIntent(intent,
                                    resolvedType, false /*defaultOnly*/, users[i]);
                    if (registeredReceivers == null) {
                        registeredReceivers = registeredReceiversForUser;
                    } else if (registeredReceiversForUser != null) {
                        registeredReceivers.addAll(registeredReceiversForUser);
                    }
                }
            } else {
                //从mReceiverResolver中找到匹配的动态广播列表
                registeredReceivers = mReceiverResolver.queryIntent(intent,
                        resolvedType, false /*defaultOnly*/, userId);
            }
   }
   //......
  int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
  if (!ordered && NR > 0) {
      //非有序广播且有匹配的动态广播,则:
      //......
      //获取广播队列,前台或者后台广播队列
      final BroadcastQueue queue = broadcastQueueForIntent(intent);
      //创建广播记录对象
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                    resultCode, resultData, resultExtras, ordered, sticky, false, userId);
            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;
  }
  //......
  if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            //静态广播
            BroadcastQueue queue = broadcastQueueForIntent(intent);
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId);

            //......
            final BroadcastRecord oldRecord =
                    replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
            //......
                queue.enqueueOrderedBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            //......
        }
  //......
}

在发送广播前先从应用包取静态广播列表进行过滤找出匹配的静态广播列表,同时从动态广播列表过滤找出匹配的广播列表;接着根据广播是前台还是后台使用对应前台/后台广播队列,将广播及匹配的广播列表加入队列,并进行调度发生,我们继续看广播队列BroadcastQueue如何调度并发送广播:

public void scheduleBroadcastsLocked() {
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
                + mQueueName + "]: current="
                + mBroadcastsScheduled);

        if (mBroadcastsScheduled) {
            return;
        }
        //发送一个消息BROADCAST_INTENT_MSG
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

scheduleBroadcastsLocked中发生一个BROADCAST_INTENT_MSG消息,通过内部的mHandler来处理消息:

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

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BROADCAST_INTENT_MSG: {
                    //处理广播
                    if (DEBUG_BROADCAST) Slog.v(
                            TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    //处理广播超时消息
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
    }

mHandler在BROADCAST_INTENT_MSG分支中调用processNextBroadcast调度消息队列:

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

processNextBroadcast继续调用processNextBroadcastLocked调度消息队列:

final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
    //......
    while (mParallelBroadcasts.size() > 0) {
            //遍历并发下行队列
            //取出第一个消息
            r = mParallelBroadcasts.remove(0);
            //记录分发事件
            r.dispatchTime = SystemClock.uptimeMillis();
            r.dispatchClockTime = System.currentTimeMillis();

            //......
            
            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);
        }
    //......
    //记录消息接收时间
    r.receiverTime = SystemClock.uptimeMillis();
    //......
    if (! mPendingBroadcastTimeoutMessage) {
            long timeoutTime = r.receiverTime + mTimeoutPeriod;
            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
                    "Submitting BROADCAST_TIMEOUT_MSG ["
                    + mQueueName + "] for " + r + " at " + timeoutTime);
            //倒计时处理消息是否超时
            setBroadcastTimeoutLocked(timeoutTime);
        }
    //......
}
//分发消息
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
    //......
    performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
    //......
}

void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
            Intent intent, int resultCode, String data, Bundle extras,
            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
     //......
    try {
                  //thread为ApplicationThread,调用ApplicationThread的scheduleRegisteredReceiver进行分发消息
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);
                }
     //......
}
 

//ActivityThread.ApplicationThread
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky, int sendingUser, int processState) throws RemoteException {
            this.updateProcessState(processState, false);
            //调用IntentReceiver的performReceive接收处理消息
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky, sendingUser);
        }

AMS发送广播的流程大致为:

  • 根据广播从应用包中过滤找到匹配的静态广播列表
  • 从动态广播列表过滤匹配的动态广播列表
  • 将匹配的动态广播列表/静态广播列表与发送的广播包装为广播记录,并放入前台/后台广播队列
  • 前台/后台广播队列通过Handler机制调度分发广播,每次从队列中删除并得到队首的广播记录,遍历广播记录中的广播接收者列表并进行分发,最终调用广播注册是的IntentReceiver的performReceive接收并处理消息
  • 启动广播处理超时逻辑,如果超过时间未处理完,则触发anr
接收广播

上述分析到调用IntentReceiver的performReceive接收处理消息,我们回到LoadedApk的IntentReceiver中的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 {
                    //获取IntentReceiver从分发器弱引用获取分发器
                    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) {
                    //如果分发器不为空,则
                    //调用分发器的performReceive处理广播
                    rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
                } else {
                    // The activity manager dispatched a broadcast to a registered
                    // receiver in this process, but before it could be delivered the
                    // receiver was unregistered.  Acknowledge the broadcast on its
                    // behalf so that the system's broadcast sequence can continue.
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing broadcast to unregistered receiver");
                    //如果分发器为空,则:
                    IActivityManager mgr = ActivityManager.getService();
                    try {
                        if (extras != null) {
                            extras.setAllowFds(false);
                        }
                        //调用AMS的finishReceiver方法告知广播处理结束
                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
            }

我们接着看分发器ReceiverDispatcher的performReceive:

public void performReceive(Intent intent, int resultCode, String data,
                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
            //将广播包装为Args参数信息
            final Args args = new Args(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
            //......
            //ActivityThread的Handler发送args 消息
            if (intent == null || !mActivityThread.post(args.getRunnable())) {
                //......
            }
        }

我们进入Args的Runnable查看怎么处理消息:

public final Runnable getRunnable() {
                return () -> {
                    //分发器关联的真实广播接收对象
                    final BroadcastReceiver receiver = mReceiver;
                    final boolean ordered = mOrdered;

                    //......
                    //AMS
                    final IActivityManager mgr = ActivityManager.getService();
                    final Intent intent = mCurIntent;
                    //......
                    try {
                        ClassLoader cl = mReceiver.getClass().getClassLoader();
                        intent.setExtrasClassLoader(cl);
                        intent.prepareToEnterProcess();
                        setExtrasClassLoader(cl);
                        receiver.setPendingResult(this);
                        //调用广播接收对象的onReceive接收处理广播
                        receiver.onReceive(mContext, intent);
                    } catch (Exception e) {
                        //......
                    }

                    if (receiver.getPendingResult() != null) {
                        //调用finish方法处理消息结束的逻辑
                        finish();
                    }
                    //......
                };
            }

这里我们看到在Args的Runnable中调用了真实的广播接收者对象的onReceive方法接收处理intent消息,接着调用finish方法处理广播接收结束的逻辑:

public final void finish() {
            if (mType == TYPE_COMPONENT) {
                //AMS
                final IActivityManager mgr = ActivityManager.getService();
                if (QueuedWork.hasPendingWork()) {
                    //......
                    QueuedWork.queue(new Runnable() {
                        @Override public void run() {
                            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                                    "Finishing broadcast after work to component " + mToken);
                            sendFinished(mgr);
                        }
                    }, false);
                } else {
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing broadcast to component " + mToken);
                    sendFinished(mgr);
                }
            } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
                if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                        "Finishing broadcast to " + mToken);
                final IActivityManager mgr = ActivityManager.getService();
                sendFinished(mgr);
            }
        }

finish中调用sendFinished方法继续广播处理接收的流程:

public void sendFinished(IActivityManager am) {
            synchronized (this) {
               //......
                try {
                    //......
                    if (mOrderedHint) {
                        //有序广播,调用AMS的finishReceiver
                        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.  
                        //普通广播,调用AMS的finishReceiver
                        am.finishReceiver(mToken, 0, null, null, false, mFlags);
                    }
                } catch (RemoteException ex) {
                }
            }
        }

sendFinished接着又调用AMS的finishReceiver方法继续广播处理接收的流程:

public void finishReceiver(IBinder who, int resultCode, String resultData,
            Bundle resultExtras, boolean resultAbort, int flags) {
       //......
        final long origId = Binder.clearCallingIdentity();
        try {
            boolean doNext = false;
            BroadcastRecord r;

            synchronized(this) {
                BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                        ? mFgBroadcastQueue : mBgBroadcastQueue;
                r = queue.getMatchingOrderedReceiver(who);
                if (r != null) {
                    //调用广播队列的finishReceiverLocked
                    doNext = r.queue.finishReceiverLocked(r, resultCode,
                        resultData, resultExtras, resultAbort, true);
                }
                if (doNext) {
                    //有待处理的消息,继续调度处理下一个消息
                    r.queue.processNextBroadcastLocked(/*fromMsg=*/ false, /*skipOomAdj=*/ true);
                }
                //......
            }

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

AMS的finishReceiver继续调用广播队列的finishReceiverLocked方法:

public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
            String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
        //......
        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;
        }

        //......
        r.curComponent = null;

        //......
    }

广播队列的finishReceiverLocked方法主要是对广播进行资源的释放

广播超时处理

我们看下处理广播超时的逻辑setBroadcastTimeoutLocked:

//mTimeoutPeriod即广播超时时间,如果是前台广播则为10秒,后台则为60秒
//long timeoutTime = r.receiverTime + mTimeoutPeriod;
final void setBroadcastTimeoutLocked(long timeoutTime) {
        if (! mPendingBroadcastTimeoutMessage) {
            Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
            //Handler发送超时消息
            mHandler.sendMessageAtTime(msg, timeoutTime);
            mPendingBroadcastTimeoutMessage = true;
        }
    }

我们看下超时时间的定义:

//AMS
// How long we allow a receiver to run before giving up on it.
    //AMS中定义前台广播处理消息超时时间
    static final int BROADCAST_FG_TIMEOUT = 10*1000;
     //AMS中定义后台广播处理消息超时时间
    static final int BROADCAST_BG_TIMEOUT = 60*1000;
mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "foreground", BROADCAST_FG_TIMEOUT, false);
        mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "background", BROADCAST_BG_TIMEOUT, true);

//BroadcastQueue
BroadcastQueue(ActivityManagerService service, Handler handler,
            String name, long timeoutPeriod, boolean allowDelayBehindServices) {
        mService = service;
        mHandler = new BroadcastHandler(handler.getLooper());
        mQueueName = name;
        //接收并处理消息超时时间
        mTimeoutPeriod = timeoutPeriod;
        mDelayBehindServices = allowDelayBehindServices;
    }

BroadcastQueue中处理广播超时的分支:

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_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
    }

调用broadcastTimeoutLocked函数处理超时逻辑:

final void broadcastTimeoutLocked(boolean fromMsg) {
    //......
    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);
        scheduleBroadcastsLocked();

        if (!debugging && anrMessage != null) {
            // Post the ANR to the handler since we do not want to process ANRs while
            // potentially holding our lock.
            mHandler.post(new AppNotResponding(app, anrMessage));
        }
    //......
}

private final class AppNotResponding implements Runnable {
        private final ProcessRecord mApp;
        private final String mAnnotation;

        public AppNotResponding(ProcessRecord app, String annotation) {
            mApp = app;
            mAnnotation = annotation;
        }

        @Override
        public void run() {
            mService.mAppErrors.appNotResponding(mApp, null, null, false, mAnnotation);
        }
    }

broadcastTimeoutLocked最终调用mHandler发送AppNotResponding消息,AppNotResponding中调用AMS触发ANR

总结:

  • 注册广播会先包装为IntentReceiver,调用AMS将IntentReceiver与过滤器注册到AMS的广播集合中
  • 发送广播进入AMS从Manifest中过滤找到匹配的静态广播,同时从动态广播列表过滤匹配动态广播列表
    • 将广播及其匹配的广播列表包装为广播记录,加入广播队列
    • 广播队列调度广播接收者,最终调用IntentReceiver接收并处理广播
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容