美文网首页android之基础学习攻克
广播相关学习-processNextBroadcast相关逻辑

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

作者: weiinter105 | 来源:发表于2018-12-19 23:55 被阅读0次

    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

    相关文章

      网友评论

        本文标题:广播相关学习-processNextBroadcast相关逻辑

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