美文网首页Android学习
Android broadcast处理流程分析

Android broadcast处理流程分析

作者: 晴天12345 | 来源:发表于2017-10-21 20:04 被阅读778次

    1.1 动态广播注册后的数据结构图

    Broadcast相关数据结构类图
    BroadcastFilter

    继承自IntentFilter,它记录了当前需注册的ReceiverIntentFilter信息;
    描述广播接收者;

    ReceiverList
    final class ReceiverList extends ArrayList<BroadcastFilter>implements IBinder.DeathRecipient
    

    保存使用相同InnerReceiver对象来注册的广播接收者,并以InnerReceiver.asBinder作为关键字;

    BroadcastRecord

    记录broadcast的信息

    2.1 AMS::broadcastIntentLocked 发送广播

    /**
     * State of all active sticky broadcasts per user.  Keys are the action of the
     * sticky Intent, values are an ArrayList of all broadcasted intents with
     * that action (which should usually be one).  The SparseArray is keyed
     * by the user ID the sticky is for, and can include UserHandle.USER_ALL
     * for stickies that are sent to all users.
     */
    final SparseArray<ArrayMap<String, ArrayList<Intent>>> mStickyBroadcasts =
            new SparseArray<ArrayMap<String, ArrayList<Intent>>>();
    
    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) {
        //1.  Flag处理
        // By default broadcasts do not go to stopped apps.
        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); // 默认不发送给force-stop的activity
        // 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);
        }
    
        // 2. 权限管理 检查受保护的广播等
        // Verify that protected broadcasts are only being sent by system code,
        // and that system code is only sending protected broadcasts.
        final String action = intent.getAction();
        final boolean isProtectedBroadcastisProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
        ...
         // 3. 处理系统广播
        switch (action) {
            case Intent.ACTION_UID_REMOVED:
            case Intent.ACTION_PACKAGE_REMOVED:
            ..
        }
        ...
        // 4. 处理粘性广播
        // Add to the sticky list if requested.
        if (sticky) { ... } // mStickyBroadcasts 保存粘性广播
        ...
        // 5. 收集静态 动态注册的广播
        List receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
        List<BroadcastFilter> registeredReceiversForUser = mReceiverResolver.queryIntent(intent, resolvedType, false, users[i]);
    
        ...
        // 6. 无序广播且存在动态注册的广播
        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); // 2.2
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,
                    appOp, brOptions, registeredReceivers/*动态注册的广播*/, resultTo, resultCode, resultData,
                    resultExtras, ordered, sticky, false, userId);
            final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
            if (!replaced) {
                queue.enqueueParallelBroadcastLocked(r); // 加入并行广播队列
                queue.scheduleBroadcastsLocked(); //2.3 通过发送消息触发系统处理广播BROADCAST_INTENT_MSG
            }
            registeredReceivers = null;
            NR = 0;
        }
        // 7. 合并广播
        // Merge into one list. 
        // 当前发送的是order广播,非order广播在6已经处理
        int ir = 0;
        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++;
        }
        ...
        // 8. 发送广播
        if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            BroadcastQueue queue = broadcastQueueForIntent(intent); // 2.2
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers/* 静态 + 动态 */, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId);
            ...
            boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r); 
            if (!replaced) {
                queue.enqueueOrderedBroadcastLocked(r); // 串行广播队列
                queue.scheduleBroadcastsLocked(); //2.3 通过发送消息触发系统处理广播BROADCAST_INTENT_MSG
            }
        ...
    }
    

    2.2 AMS::broadcastQueueForIntent

    BroadcastQueue broadcastQueueForIntent(Intent intent) {
        final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0; // 是否是前台广播
        return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
    }
    

    根据Intent.FLAG_RECEIVER_FOREGROUND获取前台或者后台广播;

    2.3 BroadcastQueue::handleMessage

    private final class BroadcastHandler extends Handler {
        public BroadcastHandler(Looper looper) {
            super(looper, null, true);
        }
    
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BROADCAST_INTENT_MSG: {
                    processNextBroadcast(true);  // 3.1 处理广播
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true); // 3.6
                    }
                } break;
                case SCHEDULE_TEMP_WHITELIST_MSG: {
                    DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;
                    if (dic != null) {
                        dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
                                msg.arg2, true, (String)msg.obj);
                    }
                } break;
            }
        }
    }
    

    fromMsg:指processNextBroadcast()是否由BroadcastHandler所调用的。

    3.1 BroadcastQueue::processNextBroadcast

    final void processNextBroadcast(boolean fromMsg) {
        synchronized(mService) {
            // First, deliver any non-serialized broadcasts right away. // 无序广播
            while (mParallelBroadcasts.size() > 0) { // 遍历无序广播
                r = mParallelBroadcasts.remove(0);
                // when dispatch started on this set of receivers
                r.dispatchTime = SystemClock.uptimeMillis(); 
                r.dispatchClockTime = System.currentTimeMillis();
                final int N = r.receivers.size();
                for (int i=0; i<N; i++) { // 遍历当前无序广播的接收者
                    Object target = r.receivers.get(i); // 参考动态广播的存储结构
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i); // 3.2 处理动态广播
                }
                addBroadcastToHistoryLocked(r);
            }
    
            // Now take care of the next serialized(串行) one... // 开始处理有序广播
    
            // If we are waiting for a process to come up to handle the next // 如果正在等待进程处理下一个广播,则什么也不做
            // broadcast, then do nothing at this point.  Just in case, we // 以防万一,如果检查正在等待的进程是否存在
            // check that the process we're waiting for still exists.
            if (mPendingBroadcast != null) { // 该进程可能先需要启动,然后在处理广播(processCurBroadcastLocked)
                boolean isDead;
                synchronized (mService.mPidsSelfLocked) {
                    ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid); // 如果进程处理完curApp应该为null
                    isDead = proc == null || proc.crashing;
                }
                if (!isDead) {
                    // It's still alive, so keep waiting
                    return;
                } else { // 如果该进程已经死掉,则重置mPendingBroadcast
                    Slog.w(TAG, "pending app  ["
                            + mQueueName + "]" + mPendingBroadcast.curApp
                            + " died before responding to broadcast");
                    mPendingBroadcast.state = BroadcastRecord.IDLE;
                    mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
                    mPendingBroadcast = null;
                }
            }
    
            // 获取第一条有序广播
            do {
                if (mOrderedBroadcasts.size() == 0) { // 无有序广播时,通知AMS进行GC
                    // No more broadcasts pending, so all done!
                    mService.scheduleAppGcsLocked();
                    ...
                    return;
                }
                r = mOrderedBroadcasts.get(0); // 获取第一个有序广播
                boolean forceReceive = false;
    
                // This is only done if the system is ready so that PRE_BOOT_COMPLETED
                // receivers don't get executed with timeouts. They're intended for
                // one time heavy lifting after system upgrades and can take
                // significant amounts of time.
                int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
                if (mService.mProcessesReady && r.dispatchTime > 0) { // systemReady
                    long now = SystemClock.uptimeMillis();
                    if ((numReceivers > 0) &&
                            (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers)) &&
                            /// M: ANR debug mechanism for defer ANR
                            !mService.mANRManager.isAnrDeferrable()) { 
                        broadcastTimeoutLocked(false); // 3.6
                        // 1. finishReceiverLocked:: forcibly finish this broadcast 强制finish广播
                        // 2. mOrderedBroadcasts中下标为0的应用进程ANR
                        forceReceive = true;
                        r.state = BroadcastRecord.IDLE;
                        // 如果超时,当前广播的下一个及之后接收者接收不到广播
                    }
                }
                // 1. 广播接收者已经全部分发
                // 2. 无下一个广播
                // 3. 有序广播被中断
                // 4. 强制finish广播
                if (r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) { // 
                    // No more receivers for this broadcast!  Send the final
                    // result if requested...
                    if (r.resultTo != null) {
                        try {
                            performReceiveLocked(r.callerApp, r.resultTo,
                                new Intent(r.intent), r.resultCode,
                                r.resultData, r.resultExtras, false, false, r.userId); // 3.3 结束当前广播
                            // Set this to null so that the reference
                            r.resultTo = null;
                    }
    
                    cancelBroadcastTimeoutLocked(); // 3.6 broadcast 取消ANR
    
                    // ... and on to the next...
                    addBroadcastToHistoryLocked(r);
                    if (r.intent.getComponent() == null && r.intent.getPackage() == null
                            && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                        // This was an implicit broadcast... let's record it for posterity.
                        mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
                                r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
                    }
                    mOrderedBroadcasts.remove(0);
                    r = null;
                    looped = true;
                    continue;
                }
            } while (r == null); //
    
    
    
            // 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 (! mPendingBroadcastTimeoutMessage) {
                long timeoutTime = r.receiverTime + mTimeoutPeriod;
                setBroadcastTimeoutLocked(timeoutTime); // 延迟发送ANR超时通知消息
            }
    
            final BroadcastOptions brOptions = r.options;
            final Object nextReceiver = r.receivers.get(recIdx);
    
            if (nextReceiver instanceof BroadcastFilter) {
                // Simple case: this is a registered receiver who gets
                // a direct call.
                BroadcastFilter filter = (BroadcastFilter)nextReceiver;
                deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx); // 3.2 有序队列中的动态广播
                ...
                return;
            }
            ...
            ResolveInfo info = (ResolveInfo)nextReceiver; // 静态广播
            ComponentName component = new ComponentName(info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
            ...
            if (skip) { // 权限等检查不通过
                r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
                r.receiver = null;
                r.curFilter = null;
                r.state = BroadcastRecord.IDLE;
                scheduleBroadcastsLocked();
                return;
            }
            ...
            // Broadcast is being executed, its package can't be stopped.
            AppGlobals.getPackageManager().setPackageStoppedState(r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid)); // 不能处于stop状态
    
            // Is this receiver's application already running?
            if (app != null && app.thread != null) {
                app.addPackage(info.activityInfo.packageName,
                        info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
                processCurBroadcastLocked(r, app); // 3.7 处理静态广播
                return;
            } catch { // 异常
                finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false);
                scheduleBroadcastsLocked();
            }
    
           if ((r.curApp=mService.startProcessLocked(targetProcess,
                    info.activityInfo.applicationInfo, true,
                    r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
                    "broadcast", r.curComponent,
                    (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                            == null) {
                // 启动进程失败的处理
                return;
            }
    
            mPendingBroadcast = r;
            mPendingBroadcastRecvIndex = recIdx;
    }
    

    3.2 BroadcastQueue::deliverToRegisteredReceiverLocked

    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
            ... // 权限检查
            // If this is not being sent as an ordered broadcast, then we 如果不是有序广播,则不记录
            // don't want to touch the fields that keep track of the current
            // state of ordered broadcasts.
            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.curReceiver = r;
                    mService.updateOomAdjLocked(r.curApp);
                }
            }
            ...
            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                // Skip delivery if full backup in progress 备份状态且是有序广播,则skip
                // If it's an ordered broadcast, we need to continue to the next receiver.
                if (ordered) {
                    skipReceiverLocked(r);
                }
            } else { // skip == false
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId); // 3.3
            }
            if (ordered) {
                r.state = BroadcastRecord.CALL_DONE_RECEIVE;
            }
    }
    

    3.3 BroadcastQueue::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) { // 动态注册的无序广播 app进程是存在的,走else
            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.
                app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser, app.repProcState);
            }
        } else {
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser); // 3.4
        }
    }
    

    3.4 LoadedApk::ReceiverDispatcher::InnerReceiver::performReceive

    @Override
    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);
        } 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
            ...
        }
    }
    

    3.5 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);
        ...
        if (intent == null || !mActivityThread.post(args)) { 
            if (mRegistered && ordered) { // 有序广播,则 sendFinished
                ... 
                args.sendFinished(mgr);
            }
        }
    }
    
    • 通过post方式调用Args::run方法,最终调用ReceiveronReceive方法;
    • finish委托调用AMS::finishReceiver

    3.6 BroadcastQueue::broadcastTimeoutLocked

        final void broadcastTimeoutLocked(boolean fromMsg) {
            if (fromMsg) { // fromMsg = false
                ...
            }
    
            BroadcastRecord br = mOrderedBroadcasts.get(0); // 获取第一个有序广播
            if (br.state == BroadcastRecord. ) {
                // 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: " + (br.curComponent != null
                        ? br.curComponent.flattenToShortString() : "(null)"));
                br.curComponent = null;
                br.state = BroadcastRecord.IDLE;
                processNextBroadcast(false); // 处理下一条广播
                return;
            }
            ...
            // Move on to the next receiver.
            finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false);
            scheduleBroadcastsLocked();
    
            if (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));
            }
        }
    

    3.7 BroadcastQueue::processCurBroadcastLocked

    private final void processCurBroadcastLocked(BroadcastRecord r,
            ProcessRecord app) throws RemoteException {
        ...
        r.receiver = app.thread.asBinder();
        r.curApp = app;
        app.curReceiver = r;
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
        mService.updateLruProcessLocked(app, false, null);
        mService.updateOomAdjLocked();
    
        // Tell the application to launch this receiver.
        r.intent.setComponent(r.curComponent);
    
        boolean started = false;
        try {
            ...
            app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
                    mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
                    r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
                    app.repProcState);
            ...
            started = true;
        } finally {
            if (!started) {
                if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                        "Process cur broadcast " + r + ": NOT STARTED!");
                r.receiver = null;
                r.curApp = null; // 处理完成之后置null
                app.curReceiver = null;
            }
        }
    }
    

    3.8 动态注册的广播ActivityThread中的处理:

    最终调用rd.innnerevicerperformreceiver,然后调用其外部类的performreceiver,此时候会通过Handler消息Args分发在子线程加载(classloader) BroadcastReceiver,并回调onReceiver

    4.1 processNextBroadcast分发广播流程图

    广播发送整体流程图

    相关文章

      网友评论

        本文标题:Android broadcast处理流程分析

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