zoukankan      html  css  js  c++  java
  • 发送广播(sendBroadcast)的过程源码分析

    发送广播(sendBroadcast)的过程源码分析

    一、简介

    这篇文章我们来分析sendBroadcast的过程。

    二、源码分析

    一般我们通过以下代码来发送一个广播

    Intent intent = new Intent(XXX_ACTION);  
    sendBroadcast(intent);  
    

    sendBroadcast的具体实现是在 ContextImpl类中

    class ContextImpl extends Context {
    
    public void sendBroadcast(Intent intent) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        try {
            intent.prepareToLeaveProcess(this);
            ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                    getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    
    }
    

    其中调用了AMS的broadcastIntent方法

    public class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    
    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);
    
            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;
        }
    }
    
    
    final int broadcastIntentLocked(ProcessRecord callerApp,
            String callerPackage, Intent intent, String resolvedType,
            IIntentReceiver resultTo, int resultCode, String resultData,
            Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
        intent = new Intent(intent);
    //...
    // Figure out who all will receive this broadcast.
    List receivers = null;
    List<BroadcastFilter> registeredReceivers = null;
    if (intent.getComponent() == null) {//1 因为我们传入的intent Component为空,所以此处符合条件
        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]);//2 通过mReceiverResolver.queryIntent找出相应的广播接收器,你是否还记得在之前的广播注册过程中我们把BroadcastFilter存到了mReceiverResolver,
                // 此处是取出我们存入的BroadcastFilter,BroadcastFilter,因为有可能有多个广播接收器注册了同一个广播所以此处返回的是一个list,该list包含了注册了当前广播的所有receiver
                if (registeredReceivers == null) {
                    registeredReceivers = registeredReceiversForUser;
                } else if (registeredReceiversForUser != null) {
                    registeredReceivers.addAll(registeredReceiversForUser);
                }
            }
        } else {
            registeredReceivers = mReceiverResolver.queryIntent(intent,
                    resolvedType, false /*defaultOnly*/, userId);
        }
    }
    //...
    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);
    
        //3 构造一个BroadcastRecord 里面记录了这个广播是由谁发出的以及要发给谁等相关信息
        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                resultCode, resultData, resultExtras, ordered, sticky, false, userId);
        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);//4 存储BroadcastRecord到mParallelBroadcasts中
            queue.scheduleBroadcastsLocked();//5 处理广播
        }
        registeredReceivers = null;
        NR = 0;
    }
    //...
    }
    

    在broadcastIntentLocked中会通过mReceiverResolver.queryIntent找出相应的广播接收器,然后在注释3处构造一个BroadcastRecord 因为传入callerApp、registeredReceivers等参数所以BroadcastRecord里面记录了这个广播是由谁发出的以及要发给谁等相关信息。在注释4处把上面构造的BroadcastRecord存到了mParallelBroadcasts变量中,mParallelBroadcasts是一个存储即将执行的广播的list,之后便是调用BroadcastQueue.scheduleBroadcastsLocked()对广播进行处理。

    到这里广播的发送实际上就已经完成了,下面的操作是对广播的处理,广播的处理是在BroadcastQueue类中,这个类存储了已经发送且尚未处理的广播。

    public final class BroadcastQueue {
    
    public void scheduleBroadcastsLocked() {
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
                + mQueueName + "]: current="
                + mBroadcastsScheduled);
    
        if (mBroadcastsScheduled) {//1 mBroadcastsScheduled为true表示当前AMS正在处理某个广播
            return;
        }
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));//2 用handler发送message
        mBroadcastsScheduled = true;
    }
    }
    

    scheduleBroadcastsLocked实现很简单首先判断当前AMS是否正在处理某个广播如果是返回,如果没有则发送message并把mBroadcastsScheduled置为true。这样就可以保证所有广播都是串行处理的。

    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);//调用processNextBroadcast
            } break;
            case BROADCAST_TIMEOUT_MSG: {
                synchronized (mService) {
                    broadcastTimeoutLocked(true);
                }
            } break;
        }
    }
    
    public final class BroadcastQueue {
    
    final void processNextBroadcast(boolean fromMsg) {
    if (fromMsg) {//mBroadcastsScheduled置为false
        mBroadcastsScheduled = false;
    }
    while (mParallelBroadcasts.size() > 0) {//1 你是否还记得在AMS中我们把发送的广播所对应BroadcastRecord存入到了mParallelBroadcasts中,在这里会循环取出存入的BroadcastRecord
        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(); //2 receivers存储了注册当前广播的接收器
        if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
                + mQueueName + "] " + r);
        for (int i=0; i<N; i++) {//3 循环取出注册当前广播的接收器
            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);//4 把当前广播发送给每一个订阅了该广播的接收器
        }
        addBroadcastToHistoryLocked(r);
        if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
                + mQueueName + "] " + r);
    }
    }
    }
    

    processNextBroadcast会把mBroadcastsScheduled置为false这样下一个广播到来就可以进行处理了。之后就是在注释1循环取出存入mParallelBroadcasts的BroadcastRecord,然后循环取出注册当前广播的接收器,最后通过deliverToRegisteredReceiverLocked把当前广播发送给每一个订阅了该广播的接收器。

    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
        boolean skip = false;
        if (filter.requiredPermission != null) {
            int perm = mService.checkComponentPermission(filter.requiredPermission,
                    r.callingPid, r.callingUid, -1, true);
            if (perm != PackageManager.PERMISSION_GRANTED) {//1 首先检查一下广播发送和接收的权限
                Slog.w(TAG, "Permission Denial: broadcasting "
                        + r.intent.toString()
                        + " from " + r.callerPackage + " (pid="
                        + r.callingPid + ", uid=" + r.callingUid + ")"
                        + " requires " + filter.requiredPermission
                        + " due to registered receiver " + filter);
                skip = true;
            } else {
                final int opCode = AppOpsManager.permissionToOpCode(filter.requiredPermission);
                if (opCode != AppOpsManager.OP_NONE
                        && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
                                r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
                    Slog.w(TAG, "Appop Denial: broadcasting "
                            + r.intent.toString()
                            + " from " + r.callerPackage + " (pid="
                            + r.callingPid + ", uid=" + r.callingUid + ")"
                            + " requires appop " + AppOpsManager.permissionToOp(
                                    filter.requiredPermission)
                            + " due to registered receiver " + filter);
                    skip = true;
                }
            }
        }
    //...
    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 {
    //2 发送广播
            performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                    new Intent(r.intent), r.resultCode, r.resultData,
                    r.resultExtras, r.ordered, r.initialSticky, r.userId);
        }
        if (ordered) {
            r.state = BroadcastRecord.CALL_DONE_RECEIVE;
        }
    }
    }
    

    deliverToRegisteredReceiverLocked做的主要是两件事,检查权限然后发送广播。

    void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
            Intent intent, int resultCode, String data, Bundle extras,
            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
    if (app != null) {
        if (app.thread != null) {
            // 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.repProcState);//1 分发广播
            // 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);
    }
    }
    

    performReceiveLocked调用app.thread.scheduleRegisteredReceiver函数来把这个广播分发出去,此处的app.thread一个Binder远程对象,最终调用的是ActivityThread的scheduleRegisteredReceiver。

    public final class ActivityThread {
    
    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);//1 
    }
    }
    

    scheduleRegisteredReceiver中的receiver具体类型是LoadedApk.ReceiverDispatcher.InnerReceiver

    @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 (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);//1 
        } else {
            // The activity manager dispatched a broadcast to a registered
            // receiver in this process, but before it could be delivered the
            // receiver was unregistered.  Acknowledge the broadcast on its
            // behalf so that the system's broadcast sequence can continue.
            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                    "Finishing broadcast to unregistered receiver");
            IActivityManager mgr = ActivityManager.getService();
            try {
                if (extras != null) {
                    extras.setAllowFds(false);
                }
                mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }
    

    performReceive调用了LoadedApk.ReceiverDispatcher的performReceive

    public void performReceive(Intent intent, int resultCode, String data,
            Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
        final Args args = new Args(intent, resultCode, data, extras, ordered,
                sticky, sendingUser);//1 构造Args
        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())) {//2 调用handler post发送args
            if (mRegistered && ordered) {
                IActivityManager mgr = ActivityManager.getService();
                if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                        "Finishing sync broadcast to " + mReceiver);
                args.sendFinished(mgr);
            }
        }
    }
    

    我们看到首先构造了一个Args 实例,然后在注释2处调用了args.getRunnable(),这个方法会返回一个Runnable实例。然后通过mActivityThread发送出去,此处的mActivityThread实际是一个Handler并且是ReceiverDispatcher的一个内部变量。mActivityThread是在ReceiverDispatcher的构造函数中进行赋值的。

    static final class ReceiverDispatcher {
    
    final Handler mActivityThread;
    
    ReceiverDispatcher(BroadcastReceiver receiver, Context context,
            Handler activityThread, Instrumentation instrumentation,
            boolean registered) {
        if (activityThread == null) {
            throw new NullPointerException("Handler must not be null");
        }
    
        mIIntentReceiver = new InnerReceiver(this, !registered);
        mReceiver = receiver;
        mContext = context;
        mActivityThread = activityThread;//为mActivityThread赋值
        mInstrumentation = instrumentation;
        mRegistered = registered;
        mLocation = new IntentReceiverLeaked(null);
        mLocation.fillInStackTrace();
    }
    }
    

    那么此处的mActivityThread实际是从哪里传入的呢。不知道你是否还记得广播注册流程分析中在ContextImpl.registerReceiverInternal函数中我们曾获取过ReceiverDispatcher,handler就是在那时传入并赋值的。而当时传入的handler是通过mMainThread.getHandler()获取的这个handler是ActivityThread的H也就是注册广播接收器的主线程的handler。

    private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission,
            Handler scheduler, Context context, int flags) {
    
    IIntentReceiver rd = null;
    
    if (scheduler == null) {
        scheduler = mMainThread.getHandler();//传入的handler
    }
    
    rd = mPackageInfo.getReceiverDispatcher(
        receiver, context, scheduler,
        mMainThread.getInstrumentation(), true);//获取ReceiverDispatcher
    
    }
    

    mActivityThread是注册广播接收器所在进程主线程的handler,那我们通过post操作就向其发送一条消息。注册广播接收器所在进程主线程收到后会进行处理,此处就是执行post中的runnable。runnable是通过args.getRunnable()获取的。

    final class Args extends BroadcastReceiver.PendingResult {
    
    public final Runnable getRunnable() {
        return () -> {
    final BroadcastReceiver receiver = mReceiver;
    final boolean ordered = mOrdered;
    
    //...
    try {
        ClassLoader cl = mReceiver.getClass().getClassLoader();
        intent.setExtrasClassLoader(cl);
        intent.prepareToEnterProcess();
        setExtrasClassLoader(cl);
        receiver.setPendingResult(this);
        receiver.onReceive(mContext, intent);//调用onReceive
    } 
    }
    

    我们看到在 getRunnable()返回的runnable的run方法中调用了receiver.onReceive,此处的receiver就是注册广播接收器是传入的广播接收器。至此广播接收器就接收到发送的广播了。

    最后,我们总结一下这个Android应用程序发送广播的过程:

    1、通过sendBroadcast把一个广播通过Binder进程间通信机制发送给ActivityManagerService,ActivityManagerService根据这个广播的Action类型找到相应的广播接收器,然后把这个广播放进自己的消息队列中去,就完成第一阶段对这个广播的异步分发了;

    2、ActivityManagerService在消息循环中处理这个广播,并通过Binder进程间通信机制把这个广播分发给注册的广播接收分发器ReceiverDispatcher,ReceiverDispatcher把这个广播放进广播接收器所在的线程的消息队列中去,就完成第二阶段对这个广播的异步分发了;

    3、ReceiverDispatcher的内部类Args在广播接收器所在的线程消息循环中处理这个广播,最终是将这个广播分发给所注册的BroadcastReceiver实例的onReceive函数进行处理。

    发送广播就是发送端把广播intent通过IPC发送给AMS,AMS在收到广播intent后会根据广播intent在已注册的广播接收器中查找匹配的接收器。然后把广播intent封装成BroadcastRecord存入BroadcastQueue到这一步广播的发送就完成了,接下来就是广播的分发,上一步我们已经把广播存入BroadcastQueue,广播分发就是取出BroadcastQueue中的广播通过IPC分发至对应的广播接收器。

    下面我们来看下整个流程部分核心操作是如何完成的:

    1、发送广播就是发送端把广播intent通过IPC发送给AMS,AMS在收到广播intent后会根据广播intent在已注册的广播接收器中查找匹配的接收器,AMS查找匹配的接收器是通过mReceiverResolver.queryIntent,我们之前分析过广播的注册过程,在AMS端注册最后阶段我们会把注册器所对应的BroadcastFilter存入mReceiverResolver。mReceiverResolver通过解析广播的intent找到匹配的BroadcastFilter,这一步操作可以这样理解:广播是基于订阅/发布模型的,该模型需要一个数据中心,数据中心需要一张记录订阅广播的记录表,这样广播A到达后数据中心可以通过查表找到订阅广播A的接收者,AMS充当数据中心的角色,mReceiverResolver可以看做是数据中心那张记录表,而BroadcastFilter可以看做是表中的一条记录,该记录表明自己感兴趣的广播。所以当AMS收到广播时会查询mReceiverResolver。

     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) {
             ...
    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 {
                 registeredReceivers = mReceiverResolver.queryIntent(intent,
                         resolvedType, false /*defaultOnly*/, userId);
             }
         }
    

    2、当发现有接收该广播的接收器时,AMS会进行记录即创建BroadcastRecord对象,BroadcastRecord是AMS端用来详细记录一个广播相关信息的类,比如广播所在queue、广播发送者、接受者等等信息。

    BroadcastQueue queue = broadcastQueueForIntent(intent);
    //创建BroadcastRecord记录一个广播相关信息
    BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                     callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                     requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                     resultData, resultExtras, ordered, sticky, false, userId);
    
    

    3、下一步就是广播的分发了。广播的分发会根据广播类型的不同而有所不同这里只关注普通广播的分发过程。普通广播会先存入mParallelBroadcasts中,mParallelBroadcasts是一个存放即将执行的list集合,然后就是调用BroadcastQueue分发广播

    final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
    
    //把之前创建的BroadcastRecord存入mParallelBroadcasts
    queue.enqueueParallelBroadcastLocked(r);
    //分发广播
     queue.scheduleBroadcastsLocked();
    

    4、大致分发流程

    final void processNextBroadcast(boolean fromMsg) {
    while (mParallelBroadcasts.size() > 0) {
                 r = mParallelBroadcasts.remove(0);
                 final int N = r.receivers.size();
                 for (int i=0; i<N; i++) {
                   deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
                 }
           
    
     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 {
                  app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,data, extras, ordered, sticky, sendingUser, app.repProcState);
                 }
    

    可以到先是从mParallelBroadcasts依次取出待分发的广播,然后经过调用最终通过广播接收器所在进程的ApplicationThread进行分发。

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

    广播接收端收到AMS的消息后调用了IIntentReceiver.performReceive进行处理,此处的IIntentReceiver对象是我们在注册广播接收器时穿给AMS的。在IIntentReceiver.performReceive方法中取获取了LoadedApk.ReceiverDispatcher然后调用其performReceive函数

    public void performReceive(Intent intent, int resultCode, String data,
                     Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                 final LoadedApk.ReceiverDispatcher rd;
                 rd = mDispatcher.get();
                 if (rd != null) {
                     rd.performReceive(intent, resultCode, data, extras,
                             ordered, sticky, sendingUser);
                 }
    
    

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

    构造Args实例然后通过该实例获取一个Runnable实例,并通过mActivityThread.post(args.getRunnable())执行,此处mActivityThread就是主线程的Handler

    当主线程收到消息处理时会调用Args实例获取的Runnable对象,Args获取的Runnable如下所示

    public final Runnable getRunnable() {
                        final BroadcastReceiver receiver = mReceiver;
                        ....
                         ClassLoader cl = mReceiver.getClass().getClassLoader();
                         intent.setExtrasClassLoader(cl);
                         intent.prepareToEnterProcess();
                         setExtrasClassLoader(cl);
                         receiver.setPendingResult(this);
                         receiver.onReceive(mContext, intent);
    

    我们看到它会通过ClassLoader构造一个BroadcastReceiver,然后调用其onReceive函数,至此我们的广播接收器就收到广播了。

    参考链接:
    https://blog.csdn.net/luoshengyang/article/details/6744448

  • 相关阅读:
    ECSHOP 2.5.1 二次开发文档【文件结构说明和数据库表分析】
    ECSHOP后台左侧添加菜单栏
    PHPstudy 2018 集成环境项目配置虚拟域名访问
    微擎左侧模块业务菜单修改
    ThinkPHP5使用阿里云OSS图片上传
    ThinkPHP5使用PHPExcel实现数据导出功能
    ThinkPHP5生成二维码图片与另一张背景图片进行合成
    原生PHP连接MySQL数据库
    数组的冒泡排序
    【原创诗歌】读仓央嘉措(下)
  • 原文地址:https://www.cnblogs.com/Robin132929/p/13804724.html
Copyright © 2011-2022 走看看