Android广播机制二

接着分析广播的发送过程

Activity中的sendBroadcast最后是调用了   

ContextWrapper.sendBroadcast:


 public void sendBroadcast(Intent intent) {
        mBase.sendBroadcast(intent);
    }


前面说过,这里的mBase是一个ContextImpl的实例。所以直接看ContextImpl.sendBroadcast:

    @Override
    public void sendBroadcast(Intent intent) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        try {
            intent.prepareToLeaveProcess();
            ActivityManagerNative.getDefault().broadcastIntent(
                mMainThread.getApplicationThread(), intent, resolvedType, null,
                Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, false,
                getUserId());
        } catch (RemoteException e) {
        }
    }

ActivityManagerNative是通过IBinder驱动与ActivityManagerService通信而已。

直接到ActivityManagerService中去看看:

public final int broadcastIntent(IApplicationThread caller,
            Intent intent, String resolvedType, IIntentReceiver resultTo,
            int resultCode, String resultData, Bundle map,
            String requiredPermission, int appOp, 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 = ActivityManager.BROADCAST_SUCCESS;
            /// M: IPO feature @{
            if ("android.intent.action.ACTION_BOOT_IPO".equals(intent.getAction()) && userId == UserHandle.USER_ALL) {
                finishIPOBootingLocked(intent, resultTo);
            }
            /// @}
            else {
                res = broadcastIntentLocked(callerApp,
                    callerApp != null ? callerApp.info.packageName : null,
                    intent, resolvedType, resultTo,
                    resultCode, resultData, map, requiredPermission, appOp, serialized, sticky,
                    callingPid, callingUid, userId);
            }
            Binder.restoreCallingIdentity(origId);
            return res;
        }

    }

转到broadcastIntentLocked函数中:

 private final int broadcastIntentLocked(ProcessRecord callerApp,
            String callerPackage, Intent intent, String resolvedType,
            IIntentReceiver resultTo, int resultCode, String resultData,
            Bundle map, String requiredPermission, int appOp,
            boolean ordered, boolean sticky, int callingPid, int callingUid,
            int userId) {

....前面是检查用户及权限的动作

int[] users;
        if (userId == UserHandle.USER_ALL) {
            // Caller wants broadcast to go to all started users.
            users = mStartedUserArray;
        } else {
            // Caller wants broadcast to go to one specific user.
            users = new int[] {userId};
        }


        // Figure out who all will receive this broadcast.
        List receivers = null;
        List<BroadcastFilter> registeredReceivers = null;
        // Need to resolve the intent to interested receivers...
        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
                 == 0) {
            receivers = collectReceiverComponents(intent, resolvedType, users);
        }
        if (intent.getComponent() == null) {
            registeredReceivers = mReceiverResolver.queryIntent(intent,
                    resolvedType, false, userId);
            /// M: IPO feature:
            /// if the intent is ACTION_SHUTDOWN, don't broadcast to the receivers resided in system server. @{
            if ( mAmPlus != null ) {
                mAmPlus.updateRegisterReceivers(registeredReceivers, intent);
        }
            /// @}
        }


这部分代码,首先用collectReceiverComponents函数收集所有静态注册的,即在AndroidMainfest.xml中声明了的对应的Receiver,接着在mReceiverResolver中查找对应的Receiver,前面在广播注册的分析中,我们已经知道广播的注册信息最终保存在mReceiverResolver变量中了。


final boolean replacePending =
                (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
        
        if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
                + " replacePending=" + replacePending);
        
        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.
            final BroadcastQueue queue = broadcastQueueForIntent(intent);
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, resolvedType, requiredPermission,
                    appOp, registeredReceivers, resultTo, resultCode, resultData, map,
                    ordered, sticky, false, userId);
            if (DEBUG_BROADCAST) Slog.v(
                    TAG, "Enqueueing parallel broadcast " + r);
            final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
            if (!replaced) {
                queue.enqueueParallelBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
            registeredReceivers = null;
            NR = 0;
        }

看这句代码 final BroadcastQueue queue = broadcastQueueForIntent(intent);

BroadcastQueue broadcastQueueForIntent(Intent intent) {
        final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
        if (DEBUG_BACKGROUND_BROADCAST) {
            Slog.i(TAG, "Broadcast intent " + intent + " on "
                    + (isFg ? "foreground" : "background")
                    + " queue");
        }
        return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
    }
       

看来系统维护了两个广播队列,一个是前台广播的,另一个是后台广播(普通广播)。

然后构建一个BroadcastRecord。然后queue.enqueueParallelBroadcastLocked(r);加入到mParallelBroadcasts数组中去。

 queue.scheduleBroadcastsLocked():

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


        if (mBroadcastsScheduled) {
            return;
        }
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

最后发送一个BROADCAST_INTENT_MSG的消息出去,就不管了。

所以接下来的工作由这个消息来驱动了:

 final Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BROADCAST_INTENT_MSG: {
                    if (DEBUG_BROADCAST) Slog.v(
                            TAG, "Received BROADCAST_INTENT_MSG");
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
    };


接着看processNextBroadcast(true):

final void processNextBroadcast(boolean fromMsg) {
        synchronized(mService) {
            BroadcastRecord r;


            if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast ["
                    + mQueueName + "]: "
                    + mParallelBroadcasts.size() + " broadcasts, "
                    + mOrderedBroadcasts.size() + " ordered broadcasts");


            mService.updateCpuStats();


            if (fromMsg) {
                mBroadcastsScheduled = false;
            }


这里的mService就是ActivityManagerService.

 // First, deliver any non-serialized broadcasts right away.
            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, "Processing parallel broadcast ["
                        + mQueueName + "] " + r);
                for (int i=0; i<N; i++) {
                    Object target = r.receivers.get(i);
                    if (DEBUG_BROADCAST)  Slog.v(TAG,
                            "Delivering non-ordered on [" + mQueueName + "] to registered "
                            + target + ": " + r);
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
                }
                addBroadcastToHistoryLocked(r);
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast ["
                        + mQueueName + "] " + r);
            }

前面已经把相关信息加入到mParallelBroadcasts中来了,现在逐个的提取出来,逐个处理。

    private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered) {

....

 try {
                if (DEBUG_BROADCAST_LIGHT) {
                    /// M: Fix ALPS00453579 thread safe issue, avoid Bundle's parcel data to be unparceled
                    //int seq = r.intent.getIntExtra("seq", -1);
                    int seq = -1;
                    Slog.i(TAG, "Delivering to " + filter
                            + " (seq=" + seq + "): " + r);
                }
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                    new Intent(r.intent), r.resultCode, r.resultData,
                    r.resultExtras, r.ordered, r.initialSticky, r.userId);
                /// M: AMS log enhancement @{
                if ((!ActivityManagerService.IS_USER_BUILD || DEBUG_BROADCAST) && ordered) {
                    Slog.d(TAG, "BDC-Delivered broadcast: " + r.intent
                        + ", ordered=true"
                        + ", filter=" + filter
                        + ", receiver=" + r.receiver);
                }

....

交给ActivityManagerService.performReceiveLocked处理

    private static 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 && app.thread != null) {
            // If we have an app thread, do the call through that so it is
            // correctly ordered with other one-way calls.
            app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                    data, extras, ordered, sticky, sendingUser, app.repProcState);
        } else if (app != null && app.thread == null) {
            /// M: Fix ALPS00457952, when AP's thread is dead, we throw the exception directly.
            throw new RemoteException("app thread has died");
        } else {
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
        }
    }


这里的 app.thread是一个Binder远程对象,最终 app.thread.scheduleRegisteredReceiver调用到ActivityThread.ApplicationThread.scheduleRegisteredReceiver函数中去了。

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

这里其实就已经回到了调用者所在进程中去了。

receiver.performReceive实际执行是LoadedApk.ReceiverDispatcher.performReceive函数

 public void performReceive(Intent intent, int resultCode, String data,
                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
                if (ActivityThread.DEBUG_BROADCAST) {
                    int seq = intent.getIntExtra("seq", -1);
                    Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
                            + " to " + (rd != null ? rd.mReceiver : null));
                }
                if (rd != null) {
                    rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
                }

它又调用到ReceiverDispatcher.performReceive函数:

public void performReceive(Intent intent, int resultCode, String data,
                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
            if (ActivityThread.DEBUG_BROADCAST) {
                int seq = intent.getIntExtra("seq", -1);
                Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
                        + " to " + mReceiver);
            }
            Args args = new Args(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
            if (!mActivityThread.post(args)) {
                if (mRegistered && ordered) {
                    IActivityManager mgr = ActivityManagerNative.getDefault();
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing sync broadcast to " + mReceiver);
                    args.sendFinished(mgr);
                }
            }
        }

这里(!mActivityThread.post(args),所以执行Args这个Runnable。

找到Args的run函数:

 final class Args extends BroadcastReceiver.PendingResult implements Runnable {
            private Intent mCurIntent;
            private final boolean mOrdered;


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

....

 try {
                    ClassLoader cl =  mReceiver.getClass().getClassLoader();
                    intent.setExtrasClassLoader(cl);
                    setExtrasClassLoader(cl);
                    receiver.setPendingResult(this);
                    /// M: ActivityThread log enhancement @{
                    if (!ActivityThread.mIsUserBuild && (mRegistered && ordered)) {
                        final boolean isOrdered = mRegistered && ordered;
                        Slog.d(ActivityThread.TAG, "BDC-Calling onReceive"
                            + ": intent=" + intent
                            + ", ordered=true"
                            + ", receiver=" + receiver
                            + ", IIntentReceiver="
                            + Integer.toHexString(System.identityHashCode(
                                mIIntentReceiver.asBinder())));
                    }
                    /// @}
                    receiver.onReceive(mContext, intent);
                } catch (Exception e) {

这个receiver.onReceive(mContext, intent);里的receiver是BroadcastReceiver,就是我们在注册时的BroadcastReceiver。

所以最终调用MainActivity的BroadcastReceiver.onReceive


到这里,整个广播的发送及分发过程就完成了。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值