广播相关学习-processNextBroadcast相关逻辑

BroadcastQueue#addBroadcastToHistoryLocked

1528    private final void addBroadcastToHistoryLocked(BroadcastRecord original) {
1529        if (original.callingUid < 0) {
1530            // This was from a registerReceiver() call; ignore it.
1531            return;
1532        }
            //注意这里为BroadcastRecord的finishTime赋值了
1533        original.finishTime = SystemClock.uptimeMillis();
1534
1535        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
1536            Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
1537                createBroadcastTraceTitle(original, BroadcastRecord.DELIVERY_DELIVERED),
1538                System.identityHashCode(original));
1539        }
1540
1541        // Note sometimes (only for sticky broadcasts?) we reuse BroadcastRecords,
1542        // So don't change the incoming record directly.
1543        final BroadcastRecord historyRecord = original.maybeStripForHistory();
1544
1545        mBroadcastHistory[mHistoryNext] = historyRecord;
1546        mHistoryNext = ringAdvance(mHistoryNext, 1, MAX_BROADCAST_HISTORY);
1547
1548        mBroadcastSummaryHistory[mSummaryHistoryNext] = historyRecord.intent;
1549        mSummaryHistoryEnqueueTime[mSummaryHistoryNext] = historyRecord.enqueueClockTime;
1550        mSummaryHistoryDispatchTime[mSummaryHistoryNext] = historyRecord.dispatchClockTime;
1551        mSummaryHistoryFinishTime[mSummaryHistoryNext] = System.currentTimeMillis();
1552        mSummaryHistoryNext = ringAdvance(mSummaryHistoryNext, 1, MAX_BROADCAST_SUMMARY_HISTORY);
1553    }

这个方用的调用处有两处
对于并行广播:

843        // First, deliver any non-serialized broadcasts right away.
844        while (mParallelBroadcasts.size() > 0) {
845            r = mParallelBroadcasts.remove(0);
846            r.dispatchTime = SystemClock.uptimeMillis();
847            r.dispatchClockTime = System.currentTimeMillis();
848
849            if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
850                Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
851                    createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
852                    System.identityHashCode(r));
853                Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
854                    createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
855                    System.identityHashCode(r));
856            }
857
858            final int N = r.receivers.size();
859            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
860                    + mQueueName + "] " + r);
861            for (int i=0; i<N; i++) {
862                Object target = r.receivers.get(i);
863                if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
864                        "Delivering non-ordered on [" + mQueueName + "] to registered "
865                        + target + ": " + r);
866                deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
867            }
868            addBroadcastToHistoryLocked(r);
869            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
870                    + mQueueName + "] " + r);
871        }

对于串行广播:

910        do {
911            if (mOrderedBroadcasts.size() == 0) {
912                // No more broadcasts pending, so all done!
913                mService.scheduleAppGcsLocked();
914                if (looped) {
915                    // If we had finished the last ordered broadcast, then
916                    // make sure all processes have correct oom and sched
917                    // adjustments.
918                    mService.updateOomAdjLocked();
919                }
920                return;
921            }
922            r = mOrderedBroadcasts.get(0);
923            boolean forceReceive = false;
924
925            // Ensure that even if something goes awry with the timeout
926            // detection, we catch "hung" broadcasts here, discard them,
927            // and continue to make progress.
928            //
929            // This is only done if the system is ready so that PRE_BOOT_COMPLETED
930            // receivers don't get executed with timeouts. They're intended for
931            // one time heavy lifting after system upgrades and can take
932            // significant amounts of time.
933            int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
934            if (mService.mProcessesReady && r.dispatchTime > 0) {
935                long now = SystemClock.uptimeMillis();
936                if ((numReceivers > 0) &&
937                        (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
938                    Slog.w(TAG, "Hung broadcast ["
939                            + mQueueName + "] discarded after timeout failure:"
940                            + " now=" + now
941                            + " dispatchTime=" + r.dispatchTime
942                            + " startTime=" + r.receiverTime
943                            + " intent=" + r.intent
944                            + " numReceivers=" + numReceivers
945                            + " nextReceiver=" + r.nextReceiver
946                            + " state=" + r.state);
947                    broadcastTimeoutLocked(false); // forcibly finish this broadcast
948                    forceReceive = true;
949                    r.state = BroadcastRecord.IDLE;
950                }
951            }
952
953            if (r.state != BroadcastRecord.IDLE) {
954                if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
955                        "processNextBroadcast("
956                        + mQueueName + ") called when not idle (state="
957                        + r.state + ")");
958                return;
959            }
960
961            if (r.receivers == null || r.nextReceiver >= numReceivers
962                    || r.resultAbort || forceReceive) {
963                // No more receivers for this broadcast!  Send the final
964                // result if requested...
965                if (r.resultTo != null) {
966                    try {
967                        if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
968                                "Finishing broadcast [" + mQueueName + "] "
969                                + r.intent.getAction() + " app=" + r.callerApp);
970                        performReceiveLocked(r.callerApp, r.resultTo,
971                            new Intent(r.intent), r.resultCode,
972                            r.resultData, r.resultExtras, false, false, r.userId);
973                        // Set this to null so that the reference
974                        // (local and remote) isn't kept in the mBroadcastHistory.
975                        r.resultTo = null;
976                    } catch (RemoteException e) {
977                        r.resultTo = null;
978                        Slog.w(TAG, "Failure ["
979                                + mQueueName + "] sending broadcast result of "
980                                + r.intent, e);
981
982                    }
983                }
984
985                if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");
986                cancelBroadcastTimeoutLocked();
987
988                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
989                        "Finished with ordered broadcast " + r);
990
991                // ... and on to the next...
992                addBroadcastToHistoryLocked(r);
993                if (r.intent.getComponent() == null && r.intent.getPackage() == null
994                        && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
995                    // This was an implicit broadcast... let's record it for posterity.
996                    mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
997                            r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
998                }
999                mOrderedBroadcasts.remove(0);
1000                r = null;
1001                looped = true;
1002                continue;
1003            }
1004        } while (r == null);

因此,Broadcast的finishTime属于当一个BroadcastRecord中所有receiver执行完成,或者超时强制终止时,作为BroadcastRecord的finishTime

BroadcastQueue#skipReceiverLocked

主动跳过一个receiver,触发下一次处理流程

389    private void skipReceiverLocked(BroadcastRecord r) {
390        logBroadcastReceiverDiscardLocked(r);
391        finishReceiverLocked(r, r.resultCode, r.resultData,
392                r.resultExtras, r.resultAbort, false);
393        scheduleBroadcastsLocked(); //用于触发进行nextReceiver的处理
394    }

BroadcastQueue#logBroadcastReceiverDiscardLocked

将BroadcastRecord当前receiver放弃了,打印event log

1651    final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
1652        final int logIndex = r.nextReceiver - 1;
1653        if (logIndex >= 0 && logIndex < r.receivers.size()) {
1654            Object curReceiver = r.receivers.get(logIndex);
1655            if (curReceiver instanceof BroadcastFilter) {
1656                BroadcastFilter bf = (BroadcastFilter) curReceiver;
1657                EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
1658                        bf.owningUserId, System.identityHashCode(r),
1659                        r.intent.getAction(), logIndex, System.identityHashCode(bf));
1660            } else {
1661                ResolveInfo ri = (ResolveInfo) curReceiver;
1662                EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
1663                        UserHandle.getUserId(ri.activityInfo.applicationInfo.uid),
1664                        System.identityHashCode(r), r.intent.getAction(), logIndex, ri.toString());
1665            }
1666        } else {
1667            if (logIndex < 0) Slog.w(TAG,
1668                    "Discarding broadcast before first receiver is invoked: " + r);
1669            EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
1670                    -1, System.identityHashCode(r),
1671                    r.intent.getAction(),
1672                    r.nextReceiver,
1673                    "NONE");
1674        }
1675    }

BroadcastQueue#finishReceiverLocked

418    public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
419            String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
420        final int state = r.state;
421        final ActivityInfo receiver = r.curReceiver;
422        r.state = BroadcastRecord.IDLE;
423        if (state == BroadcastRecord.IDLE) {
424            Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
425        }
426        r.receiver = null;
427        r.intent.setComponent(null);
428        if (r.curApp != null && r.curApp.curReceivers.contains(r)) {
429            r.curApp.curReceivers.remove(r);
430        }
431        if (r.curFilter != null) {
432            r.curFilter.receiverList.curBroadcast = null;
433        }
434        r.curFilter = null;
435        r.curReceiver = null;
436        r.curApp = null;
437        mPendingBroadcast = null;
//置空操作
//将当前BroadcastRecord中的一些值置空
438
439        r.resultCode = resultCode;
440        r.resultData = resultData;
441        r.resultExtras = resultExtras;
442        if (resultAbort && (r.intent.getFlags()&Intent.FLAG_RECEIVER_NO_ABORT) == 0) {
443            r.resultAbort = resultAbort;
444        } else {
445            r.resultAbort = false;
446        }
447       //waitForServices的特殊情况
448        if (waitForServices && r.curComponent != null && r.queue.mDelayBehindServices
449                && r.queue.mOrderedBroadcasts.size() > 0
450                && r.queue.mOrderedBroadcasts.get(0) == r) {
451            ActivityInfo nextReceiver;
452            if (r.nextReceiver < r.receivers.size()) {
453                Object obj = r.receivers.get(r.nextReceiver);
454                nextReceiver = (obj instanceof ActivityInfo) ? (ActivityInfo)obj : null;
455            } else {
456                nextReceiver = null;
457            }
458            // Don't do this if the next receive is in the same process as the current one.
459            if (receiver == null || nextReceiver == null
460                    || receiver.applicationInfo.uid != nextReceiver.applicationInfo.uid
461                    || !receiver.processName.equals(nextReceiver.processName)) {
462                // In this case, we are ready to process the next receiver for the current broadcast,
463                // but are on a queue that would like to wait for services to finish before moving
464                // on.  If there are background services currently starting, then we will go into a
465                // special state where we hold off on continuing this broadcast until they are done.
466                if (mService.mServices.hasBackgroundServicesLocked(r.userId)) {
467                    Slog.i(TAG, "Delay finish: " + r.curComponent.flattenToShortString());
468                    r.state = BroadcastRecord.WAITING_SERVICES; //Broadcast已经执行完了,要等当前user的后台服务执行完才继续下一个broadcast;或者是当我们切换用户时或者进程时,我们需要把当前用户的后台服务执行完,才执行下一个BroadcastRecord或者BroadcastReceiver
469                    return false; //返回false,代表暂时不执行下一个broadcast
470                }
471            }
472        }
473
474        r.curComponent = null;
475
476        // We will process the next receiver right now if this is finishing
477        // an app receiver (which is always asynchronous) or after we have
478        // come back from calling a receiver.
479        return state == BroadcastRecord.APP_RECEIVE
480                || state == BroadcastRecord.CALL_DONE_RECEIVE;
         //CALL_DONE_RECEIVE 串行广播+动态注册receiver:执行完performReceiveLocked后,将BroadcastRecord的state置为CALL_DONE_RECEIVE
         //APP_RECEIVE 串行广播+静态注册receiver:执行processCurBroadcastLocked之前就将状态置为APP_RECEIVE
         //总之是针对串行广播的,这个返回值会在finishReceiver中被用到,返回true则自动调用processNextBroadcastLocked,进行BroadcastRecord的下一个receiver的处理
481    }

BroadcastQueue#scheduleBroadcastsLocked

通过BROADCAST_INTENT_MSG消息触发下一个receiver的处理

396    public void scheduleBroadcastsLocked() {
397        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
398                + mQueueName + "]: current="
399                + mBroadcastsScheduled);
400
401        if (mBroadcastsScheduled) {
402            return;
403        }
404        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
405        mBroadcastsScheduled = true;
406    }

ActivityManagerService#finishReceiver

如调用BroadcastReceiver实例的onReceive函数过程中,如果receiver所在进程死了;最终会调用到

22570    public void finishReceiver(IBinder who, int resultCode, String resultData,
22571            Bundle resultExtras, boolean resultAbort, int flags) {
22572        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Finish receiver: " + who);
22573
22574        // Refuse possible leaked file descriptors
22575        if (resultExtras != null && resultExtras.hasFileDescriptors()) {
22576            throw new IllegalArgumentException("File descriptors passed in Bundle");
22577        }
22578
22579        final long origId = Binder.clearCallingIdentity();
22580        try {
22581            boolean doNext = false;
22582            BroadcastRecord r;
22583
22584            synchronized(this) {
22585                BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
22586                        ? mFgBroadcastQueue : mBgBroadcastQueue;
22587                r = queue.getMatchingOrderedReceiver(who);
22588                if (r != null) {
22589                    doNext = r.queue.finishReceiverLocked(r, resultCode,
22590                        resultData, resultExtras, resultAbort, true); //处理当前BroadcastRecord状态,并返回一个结果,用于判断是否要触发下一个processNextBroadcastLocked
22591                }
22592                if (doNext) {
22593                    r.queue.processNextBroadcastLocked(/*fromMsg=*/ false, /*skipOomAdj=*/ true);
                              //所以processNextBroadcastLocked中的next不是BroadcastRecord这个粒度的,而是BroadcatReceiver这个粒度的(针对串行广播)
                              //对于并行广播而言,每执行一次都会将并行队列中的Broadcast全部处理完毕
22594                }
22595                // updateOomAdjLocked() will be done here
22596                trimApplicationsLocked();
22597            }
22598
22599        } finally {
22600            Binder.restoreCallingIdentity(origId);
22601        }
22602    }

超时发生ANR的相关逻辑

每个receiver都会尝试发送,但是只有mPendingBroadcastTimeoutMessage为false是才会真正发送;每次取出BroadcastRecord中的一个receiver准备执行时,就会先尝试发送一个broadcast的timeout消息

1074        if (! mPendingBroadcastTimeoutMessage) { //mPendingBroadcastTimeoutMessage = true代表当前已经有BROADCAST_TIMEOUT_MSG消息了,无需再重复发送了
1075            long timeoutTime = r.receiverTime + mTimeoutPeriod;
1076            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
1077                    "Submitting BROADCAST_TIMEOUT_MSG ["
1078                    + mQueueName + "] for " + r + " at " + timeoutTime);
1079            setBroadcastTimeoutLocked(timeoutTime); //针对BroadcastReceiver发送超时消息
1080        }

BroadcastQueue#setBroadcastTimeoutLocked

1475    final void setBroadcastTimeoutLocked(long timeoutTime) {
1476        if (! mPendingBroadcastTimeoutMessage) {
1477            Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
1478            mHandler.sendMessageAtTime(msg, timeoutTime);
1479            mPendingBroadcastTimeoutMessage = true; 
1480        }
1481    }

那么比如我有4个receiver,每个3s,那么会在第四个的时候进行broadcastTimeoutLocked的处理(如果相关线程不繁忙的话)

166    final class BroadcastHandler extends Handler {
167        public BroadcastHandler(Looper looper) {
168            super(looper, null, true);
169        }
170
171        @Override
172        public void handleMessage(Message msg) {
173            switch (msg.what) {
174                case BROADCAST_INTENT_MSG: {
175                    if (DEBUG_BROADCAST) Slog.v(
176                            TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
177                    processNextBroadcast(true);
178                } break;
179                case BROADCAST_TIMEOUT_MSG: {
180                    synchronized (mService) {
181                        broadcastTimeoutLocked(true);
182                    }
183                } break;
184            }
185        }
186    }

BroadcastQueue#broadcastTimeoutLocked

发生超时时,当前BroadcastReceiver所在进程ANR

1490    final void broadcastTimeoutLocked(boolean fromMsg) {
1491        if (fromMsg) {
1492            mPendingBroadcastTimeoutMessage = false; //调到这以后mPendingBroadcastTimeoutMessage 置为false,就可以重新发送超时消息了
1493        }
1494
1495        if (mOrderedBroadcasts.size() == 0) {
1496            return;
1497        }
1498
1499        long now = SystemClock.uptimeMillis();
1500        BroadcastRecord r = mOrderedBroadcasts.get(0); 
1501        if (fromMsg) {
1502            if (!mService.mProcessesReady) {
1503                // Only process broadcast timeouts if the system is ready. That way
1504                // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1505                // to do heavy lifting for system up.
1506                return;
1507            }
1508
1509            long timeoutTime = r.receiverTime + mTimeoutPeriod;  
1510            if (timeoutTime > now) {
1511                // We can observe premature timeouts because we do not cancel and reset the
1512                // broadcast timeout message after each receiver finishes.  Instead, we set up
1513                // an initial timeout then kick it down the road a little further as needed
1514                // when it expires.
1515                if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
1516                        "Premature timeout ["
1517                        + mQueueName + "] @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
1518                        + timeoutTime);
1519                setBroadcastTimeoutLocked(timeoutTime); //重新发送BROADCAST_TIMEOUT_MSG消息并直接返回
1520                return;
1521            }
1522        }
1523
1524        BroadcastRecord br = mOrderedBroadcasts.get(0);
1525        if (br.state == BroadcastRecord.WAITING_SERVICES) {
1526            // In this case the broadcast had already finished, but we had decided to wait
1527            // for started services to finish as well before going on.  So if we have actually
1528            // waited long enough time timeout the broadcast, let's give up on the whole thing
1529            // and just move on to the next.
1530            Slog.i(TAG, "Waited long enough for: " + (br.curComponent != null
1531                    ? br.curComponent.flattenToShortString() : "(null)"));
1532            br.curComponent = null;
1533            br.state = BroadcastRecord.IDLE;
1534            processNextBroadcast(false);
1535            return;
1536        }
1537
                //确定超时了,将r.receiverTime改为当前时间(这样就不会因为这个broadcast超时影响下一个receiver所在进程也ANR了),然后finish当前Receiver,重新触发下一轮流程
1538        // If the receiver app is being debugged we quietly ignore unresponsiveness, just
1539        // tidying up and moving on to the next broadcast without crashing or ANRing this
1540        // app just because it's stopped at a breakpoint.
1541        final boolean debugging = (r.curApp != null && r.curApp.debugging);
1542
1543        Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
1544                + ", started " + (now - r.receiverTime) + "ms ago");
1545        r.receiverTime = now;
1546        if (!debugging) {
1547            r.anrCount++;
1548        }
1549
1550        ProcessRecord app = null;
1551        String anrMessage = null;
1552
1553        Object curReceiver;
1554        if (r.nextReceiver > 0) {
1555            curReceiver = r.receivers.get(r.nextReceiver-1);
1556            r.delivery[r.nextReceiver-1] = BroadcastRecord.DELIVERY_TIMEOUT;
1557        } else {
1558            curReceiver = r.curReceiver;
1559        }
1560        Slog.w(TAG, "Receiver during timeout of " + r + " : " + curReceiver);
1561        logBroadcastReceiverDiscardLocked(r);
1562        if (curReceiver != null && curReceiver instanceof BroadcastFilter) {
1563            BroadcastFilter bf = (BroadcastFilter)curReceiver;
1564            if (bf.receiverList.pid != 0
1565                    && bf.receiverList.pid != ActivityManagerService.MY_PID) {
1566                synchronized (mService.mPidsSelfLocked) {
1567                    app = mService.mPidsSelfLocked.get(
1568                            bf.receiverList.pid);
1569                }
1570            }
1571        } else {
1572            app = r.curApp;
1573        }
1574
1575        if (app != null) {
1576            anrMessage = "Broadcast of " + r.intent.toString();
1577        }
1578
1579        if (mPendingBroadcast == r) {
1580            mPendingBroadcast = null;
1581        }
1582
1583        // Move on to the next receiver.
1584        finishReceiverLocked(r, r.resultCode, r.resultData,
1585                r.resultExtras, r.resultAbort, false);
1586        scheduleBroadcastsLocked();
1587
1588        if (!debugging && anrMessage != null) {
1589            // Post the ANR to the handler since we do not want to process ANRs while
1590            // potentially holding our lock.
1591            mHandler.post(new AppNotResponding(app, anrMessage));
1592        }
1593    }

BroadcastQueue#cancelBroadcastTimeoutLocked

只有当串行广播所有的BroadcastReceiver时,或者当广播强制被结束时,才会调用cancelBroadcastTimeoutLocked,取消队列中BROADCAST_TIMEOUT_MSG消息

1409    final void cancelBroadcastTimeoutLocked() {
1410        if (mPendingBroadcastTimeoutMessage) {
1411            mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this); //BROADCAST_TIMEOUT_MSG消息从队列中移除
1412            mPendingBroadcastTimeoutMessage = false;
1413        }
1414    }

下面举例说明下,已前台广播为例:
1.一个broadcast有4个receiver,分别是3,3,3,3

时间轴
0 3 6 9 10(耗时操作消息被取出执行执行了,此时dispatch time = 9,9+10 = 19)12 此时整个Broadcast执行完了,会cancel超时小心;因此整个并没有耗时

2.一个broadcast有2个receiver,分别是1,13
0 1 10(耗时操作消息被取出执行执行了,此时dispatch time = 1,1+10 = 11) 11(此时超时了,receiver所在进程发生ANR),然后进入下一轮流程,进入下一个broadcast

3.一个broadcast有3个receiver,分别是1,13,2
0 1 10(耗时操作消息被取出执行执行了,此时dispatch time = 1,1+10 = 11) 11(此时超时了,receiver所在进程发生ANR),然后进入下一轮流程,进入下一个receiver,发送超时消息(时间为11+10 = 21),13(该Broadcast执行完成,取消超时消息);进入下一个Broadcast

4.一个broadcast有3个receiver,分别是5,等待7s才进入下一轮,5,2

0 5 10 (下一轮timeout = 15) 12(取出开始执行) 15(ANR,当前receiver执行超时),(下一轮timeout = 25),17(此时结束,取消超时消息,触发一个BroadcastRecord)

总结

用这种方式能查出两个receiver处理之间的耗时超过timeout就会ANR(本次receiver处理的相关Message,BROADCAST_INTENT_MSG等待取出时间+执行时间 >= timeout),且不会连带影响下一个receiver(看起来system_server中的ActivityMananger线程耗时以及receiver所在进程的主线程耗时,来回binder call耗时,都可能会造成相关receiver广播超时)

deliverToRegisteredReceiverLocked

处理动态注册的receiver
首先检查相关权限,然后调用performReceiveLocked进行相关处理

530    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
531            BroadcastFilter filter, boolean ordered, int index) {
532        boolean skip = false;
//检查广播发送方是否有BroadcastReceiver指定的权限
533        if (filter.requiredPermission != null) {
534            int perm = mService.checkComponentPermission(filter.requiredPermission,
535                    r.callingPid, r.callingUid, -1, true);
536            if (perm != PackageManager.PERMISSION_GRANTED) {
537                Slog.w(TAG, "Permission Denial: broadcasting "
538                        + r.intent.toString()
539                        + " from " + r.callerPackage + " (pid="
540                        + r.callingPid + ", uid=" + r.callingUid + ")"
541                        + " requires " + filter.requiredPermission
542                        + " due to registered receiver " + filter);
543                skip = true;
544            } else {
545                final int opCode = AppOpsManager.permissionToOpCode(filter.requiredPermission);
546                if (opCode != AppOpsManager.OP_NONE
547                        && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
548                                r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
549                    Slog.w(TAG, "Appop Denial: broadcasting "
550                            + r.intent.toString()
551                            + " from " + r.callerPackage + " (pid="
552                            + r.callingPid + ", uid=" + r.callingUid + ")"
553                            + " requires appop " + AppOpsManager.permissionToOp(
554                                    filter.requiredPermission)
555                            + " due to registered receiver " + filter);
556                    skip = true;
557                }
558            }
559        }
560        if (!skip && r.requiredPermissions != null && r.requiredPermissions.length > 0) {
561            for (int i = 0; i < r.requiredPermissions.length; i++) {
562                String requiredPermission = r.requiredPermissions[i];
563                int perm = mService.checkComponentPermission(requiredPermission,
564                        filter.receiverList.pid, filter.receiverList.uid, -1, true);
565                if (perm != PackageManager.PERMISSION_GRANTED) {
566                    Slog.w(TAG, "Permission Denial: receiving "
567                            + r.intent.toString()
568                            + " to " + filter.receiverList.app
569                            + " (pid=" + filter.receiverList.pid
570                            + ", uid=" + filter.receiverList.uid + ")"
571                            + " requires " + requiredPermission
572                            + " due to sender " + r.callerPackage
573                            + " (uid " + r.callingUid + ")");
574                    skip = true;
575                    break;
576                }
577                int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
578                if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
//检查BroadcastReceiver是否有Broadcast要求的权限
581                        && mService.mAppOpsService.checkOperation(appOp,
582                        filter.receiverList.uid, filter.packageName)
583                        != AppOpsManager.MODE_ALLOWED) {
584                    Slog.w(TAG, "Appop Denial: receiving "
585                            + r.intent.toString()
586                            + " to " + filter.receiverList.app
587                            + " (pid=" + filter.receiverList.pid
588                            + ", uid=" + filter.receiverList.uid + ")"
589                            + " requires appop " + AppOpsManager.permissionToOp(
590                            requiredPermission)
591                            + " due to sender " + r.callerPackage
592                            + " (uid " + r.callingUid + ")");
593                    skip = true;
594                    break;
595                }
596            }
597        }
598        if (!skip && (r.requiredPermissions == null || r.requiredPermissions.length == 0)) {
599            int perm = mService.checkComponentPermission(null,
600                    filter.receiverList.pid, filter.receiverList.uid, -1, true);
601            if (perm != PackageManager.PERMISSION_GRANTED) {
602                Slog.w(TAG, "Permission Denial: security check failed when receiving "
603                        + r.intent.toString()
604                        + " to " + filter.receiverList.app
605                        + " (pid=" + filter.receiverList.pid
606                        + ", uid=" + filter.receiverList.uid + ")"
607                        + " due to sender " + r.callerPackage
608                        + " (uid " + r.callingUid + ")");
609                skip = true;
610            }
611        }
612        if (!skip && r.appOp != AppOpsManager.OP_NONE
613               
614                 && mService.mAppOpsService.noteOperation(r.appOp,
615                filter.receiverList.uid, filter.packageName)
619                != AppOpsManager.MODE_ALLOWED) {
620            Slog.w(TAG, "Appop Denial: receiving "
621                    + r.intent.toString()
622                    + " to " + filter.receiverList.app
623                    + " (pid=" + filter.receiverList.pid
624                    + ", uid=" + filter.receiverList.uid + ")"
625                    + " requires appop " + AppOpsManager.opToName(r.appOp)
626                    + " due to sender " + r.callerPackage
627                    + " (uid " + r.callingUid + ")");
628            skip = true;
629        }
630
636
637        if (!mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
638                r.callingPid, r.resolvedType, filter.receiverList.uid)) {
639            skip = true;
640        }
641
642        if (!skip && (filter.receiverList.app == null || filter.receiverList.app.killed
643                || filter.receiverList.app.crashing)) {
644            Slog.w(TAG, "Skipping deliver [" + mQueueName + "] " + r
645                    + " to " + filter.receiverList + ": process gone or crashing");
646            skip = true;
647        }
648
649        // Ensure that broadcasts are only sent to other Instant Apps if they are marked as
650        // visible to Instant Apps.
651        final boolean visibleToInstantApps =
652                (r.intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
653
654        if (!skip && !visibleToInstantApps && filter.instantApp
655                && filter.receiverList.uid != r.callingUid) {
656            Slog.w(TAG, "Instant App Denial: receiving "
657                    + r.intent.toString()
658                    + " to " + filter.receiverList.app
659                    + " (pid=" + filter.receiverList.pid
660                    + ", uid=" + filter.receiverList.uid + ")"
661                    + " due to sender " + r.callerPackage
662                    + " (uid " + r.callingUid + ")"
663                    + " not specifying FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS");
664            skip = true;
665        }
666
667        if (!skip && !filter.visibleToInstantApp && r.callerInstantApp
668                && filter.receiverList.uid != r.callingUid) {
669            Slog.w(TAG, "Instant App Denial: receiving "
670                    + r.intent.toString()
671                    + " to " + filter.receiverList.app
672                    + " (pid=" + filter.receiverList.pid
673                    + ", uid=" + filter.receiverList.uid + ")"
674                    + " requires receiver be visible to instant apps"
675                    + " due to sender " + r.callerPackage
676                    + " (uid " + r.callingUid + ")");
677            skip = true;
678        }
679
680        if (skip) {
//不满足发送条件的话,标记一下,结束发送
681            r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
682            return;
683        }
684
685        // If permissions need a review before any of the app components can run, we drop
686        // the broadcast and if the calling app is in the foreground and the broadcast is
687        // explicit we launch the review UI passing it a pending intent to send the skipped
688        // broadcast.
//特殊情况,还需要再次检查权限,中断广播发送
    //再次满足发送条件后,会重新进入到后续的发送流程
689        if (mService.mPermissionReviewRequired) {
690            if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName,
691                    filter.owningUserId)) {
692                r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
693                return;
694            }
695        }
696
697        r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;//可以发送了,标记一下
698
699        // If this is not being sent as an ordered broadcast, then we
700        // don't want to touch the fields that keep track of the current
701        // state of ordered broadcasts.
702        if (ordered) { //针对串行广播,保存BroadRecord,BroadcastFilter中的结构,代表串行广播走到哪了
703            r.receiver = filter.receiverList.receiver.asBinder();
704            r.curFilter = filter;
705            filter.receiverList.curBroadcast = r;
706            r.state = BroadcastRecord.CALL_IN_RECEIVE; //当前Broadcast的状态
707            if (filter.receiverList.app != null) {
708                // Bump hosting application to no longer be in background
709                // scheduling class.  Note that we can't do that if there
710                // isn't an app...  but we can only be in that case for
711                // things that directly call the IActivityManager API, which
712                // are already core system stuff so don't matter for this.
713                r.curApp = filter.receiverList.app;
714                filter.receiverList.app.curReceivers.add(r);
715                mService.updateOomAdjLocked(r.curApp, true);
716            }
717        }
723        try {
724            if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
725                    "Delivering to " + filter + " : " + r);
726            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                      //若BroadcastReceiver对应的进程处于fullBackup状态(备份和恢复),则不发送广播
727                // Skip delivery if full backup in progress
728                // If it's an ordered broadcast, we need to continue to the next receiver.
729                if (ordered) {
                          //有序广播必须处理完一个,才能处理下一个,因此这里主动触发一下
730                    skipReceiverLocked(r);
731                }
732            } else {
                                //执行发送工作
733                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
734                        new Intent(r.intent), r.resultCode, r.resultData,
735                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
736            }
737            if (ordered) {
738                r.state = BroadcastRecord.CALL_DONE_RECEIVE; //将BroadcastRecord的state设为CALL_DONE_RECEIVE
                                     //从字面上理解,似乎取已经通过performReceiveLocked来调用BroadcastRecord实例中的onReceive了
739            }
740        } catch (RemoteException e) {
741            Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
742            if (ordered) {
743                r.receiver = null;
744                r.curFilter = null;
745                filter.receiverList.curBroadcast = null;
746                if (filter.receiverList.app != null) {
747                    filter.receiverList.app.curReceivers.remove(r);
748                }
749            }
750        }
751    }

BroadcastQueue#performReceiveLocked

495    void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
496            Intent intent, int resultCode, String data, Bundle extras,
497            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
498        // Send the intent to the receiver asynchronously using one-way binder calls.
499        if (app != null) { //app:receiver所在进程
500            if (app.thread != null) {
501                // If we have an app thread, do the call through that so it is
502                // correctly ordered with other one-way calls.
503                try {
504                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
505                            data, extras, ordered, sticky, sendingUser, app.repProcState);
                     //app进程中的一个binder线程响应(binder call都是binder线程响应的),在其中会调用mActivityThread.post来发送消息,最终调用onReceive函数;mActivityThread默认为null
506                // TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
507                // DeadObjectException when the process isn't actually dead.
508                //} catch (DeadObjectException ex) {
509                // Failed to call into the process.  It's dying so just let it die and move on.
510                //    throw ex;
511                } catch (RemoteException ex) {
512                    // Failed to call into the process. It's either dying or wedged. Kill it gently.
513                    synchronized (mService) {
514                        Slog.w(TAG, "Can't deliver broadcast to " + app.processName
515                                + " (pid " + app.pid + "). Crashing it.");
516                        app.scheduleCrash("can't deliver broadcast");
517                    }
518                    throw ex;
519                }
520            } else {
521                // Application has died. Receiver doesn't exist.
522                throw new RemoteException("app.thread must not be null");
523            }
524        } else {
                  //如果动态接收者的所在进程已死亡,则IIntentReceiver中弱引用的LoadedApk.ReceiverDispatcher为null
                 //则调用AMS的finishReceiver
525            receiver.performReceive(intent, resultCode, data, extras, ordered,
526                    sticky, sendingUser);
527        }
528    }

BroadcastQueue#processCurBroadcastLocked

处理静态广播(此时所在进程已唤起)

273    private final void processCurBroadcastLocked(BroadcastRecord r,
274            ProcessRecord app, boolean skipOomAdj) throws RemoteException {
275        if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
276                "Process cur broadcast " + r + " for app " + app);
277        if (app.thread == null) {
278            throw new RemoteException();
279        }
280        if (app.inFullBackup) {
281            skipReceiverLocked(r);
282            return;
283        }
284
285        r.receiver = app.thread.asBinder();
286        r.curApp = app;
287        app.curReceivers.add(r);
288        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
289        mService.updateLruProcessLocked(app, false, null);
                // 要派发之前,调整这个进程的优先级
                // 所以app在receiver执行的过程中优先级是很高的
290        if (!skipOomAdj) {
291            mService.updateOomAdjLocked();
292        }
293
294        // Tell the application to launch this receiver.
295        r.intent.setComponent(r.curComponent);
296
297        boolean started = false;
298        try {
299            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
300                    "Delivering to component " + r.curComponent
301                    + ": " + r);
302            mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
303                                      PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
                  // binder call到app进程 调用onReceive
304            app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
305                    mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
306                    r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
307                    app.repProcState);
308            if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
309                    "Process cur broadcast " + r + " DELIVERED for app " + app);
310            started = true;
311        } finally {
312            if (!started) {
313                if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
314                        "Process cur broadcast " + r + ": NOT STARTED!");
315                r.receiver = null;
316                r.curApp = null;
317                app.curReceivers.remove(r);
318            }
319        }
320    }

ActivityThread#scheduleReceiver

776        public final void scheduleReceiver(Intent intent, ActivityInfo info,
777                CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
778                boolean sync, int sendingUser, int processState) {
779            updateProcessState(processState, false);
780            ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
781                    sync, false, mAppThread.asBinder(), sendingUser);
782            r.info = info;
783            r.compatInfo = compatInfo;
784            sendMessage(H.RECEIVER, r);
785        }
1660                case RECEIVER:
1661                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
1662                    handleReceiver((ReceiverData)msg.obj);
1663                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1664                    break;

ActivityThread#handleReceiver

    private void handleReceiver(ReceiverData data) {
3334        // If we are getting ready to gc after going to the background, well
3335        // we are back active so skip it.
3336        unscheduleGcIdler();
3337
3338        String component = data.intent.getComponent().getClassName();
3339
3340        LoadedApk packageInfo = getPackageInfoNoCheck(
3341                data.info.applicationInfo, data.compatInfo);
3342
3343        IActivityManager mgr = ActivityManager.getService();
3344
3345        Application app;
3346        BroadcastReceiver receiver;
3347        ContextImpl context;
3348        try {
3349            app = packageInfo.makeApplication(false, mInstrumentation);
3350            context = (ContextImpl) app.getBaseContext();
3351            if (data.info.splitName != null) {
3352                context = (ContextImpl) context.createContextForSplit(data.info.splitName);
3353            }
3354            java.lang.ClassLoader cl = context.getClassLoader();
3355            data.intent.setExtrasClassLoader(cl);
3356            data.intent.prepareToEnterProcess();
3357            data.setExtrasClassLoader(cl);
3358            receiver = packageInfo.getAppFactory()
3359                    .instantiateReceiver(cl, data.info.name, data.intent);
        //对于静态广播而言,启动进程后就调用scheduleReceiver函数处理广播
        //BroadcastReceiver的实例还没有创建,因此需要在此进行反射初始化
3360        } catch (Exception e) {
3361            if (DEBUG_BROADCAST) Slog.i(TAG,
3362                    "Finishing failed broadcast to " + data.intent.getComponent());
               //静态广播创建出问题,需要通知AMS,调用AMS的finishReceiver
3363            data.sendFinished(mgr);
3364            throw new RuntimeException(
3365                "Unable to instantiate receiver " + component
3366                + ": " + e.toString(), e);
3367        }
3368
3369        try {
3370            if (localLOGV) Slog.v(
3371                TAG, "Performing receive of " + data.intent
3372                + ": app=" + app
3373                + ", appName=" + app.getPackageName()
3374                + ", pkg=" + packageInfo.getPackageName()
3375                + ", comp=" + data.intent.getComponent().toShortString()
3376                + ", dir=" + packageInfo.getAppDir());
3377
3378            sCurrentBroadcastIntent.set(data.intent);
3379            receiver.setPendingResult(data);
3380            receiver.onReceive(context.getReceiverRestrictedContext(),
3381                    data.intent);
3382        } catch (Exception e) {
3383            if (DEBUG_BROADCAST) Slog.i(TAG,
3384                    "Finishing failed broadcast to " + data.intent.getComponent());
             //静态广播调用onReceive时出问题,如所在进程已被销毁,需要通知AMS,调用AMS的finishReceiver
3385            data.sendFinished(mgr);
3386            if (!mInstrumentation.onException(receiver, e)) {
3387                throw new RuntimeException(
3388                    "Unable to start receiver " + component
3389                    + ": " + e.toString(), e);
3390            }
3391        } finally {
3392            sCurrentBroadcastIntent.set(null);
3393        }
3394
3395        if (receiver.getPendingResult() != null) {
3396            data.finish();
3397        }
3398    }
send Broadcast.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • 面试必背 会舍弃、总结概括——根据我这些年面试和看面试题搜集过来的知识点汇总而来 建议根据我的写的面试应对思路中的...
    luoyangzk阅读 6,711评论 6 173
  • Android系统的广播机制是一种基于消息发布和订阅的事件驱动模型,即广播发送者负责发布消息,而接收者需要先订阅消...
    泡面先生_Jack阅读 1,137评论 0 2
  • 现实中的广播:电台为了传达一些消息而发送广播,通过广播携带要传达的消息,群众只要买一个收音机,就可以收到广播了。 ...
    stevewang阅读 4,220评论 0 8
  • 1、动态注册过程源码分析: 在Activity中动态注册广播室,在注册方法之前其实省略了Context,也就是实际...
    骑着猪的蜗牛阅读 703评论 0 1
  • 昨夜心头 连帘幽梦 已然往事 今朝梦碎 滴滴泪痕 沉淀 前行 还看往昔 字字珠玑 落得黄花飘瘦 何不归
    鹿饭饭阅读 201评论 0 1