Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d5e919c3 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge changes from topic "nov2"

* changes:
  BroadcastQueue: omit overly noisy trace event.
  BroadcastQueue: DISPATCH_SENDING_BROADCAST_EVENT.
  BroadcastQueue: tests for dispatch ordering.
  BroadcastQueue: pre-calculate blocked counts.
parents 726f141e 6d57fc31
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -14723,6 +14723,15 @@ public class ActivityManagerService extends IActivityManager.Stub
        mCurBroadcastStats.addBackgroundCheckViolation(action, targetPackage);
    }
    final void notifyBroadcastFinishedLocked(@NonNull BroadcastRecord original) {
        final ApplicationInfo info = original.callerApp != null ? original.callerApp.info : null;
        final String callerPackage = info != null ? info.packageName : original.callerPackage;
        if (callerPackage != null) {
            mHandler.obtainMessage(ActivityManagerService.DISPATCH_SENDING_BROADCAST_EVENT,
                    original.callingUid, 0, callerPackage).sendToTarget();
        }
    }
    final Intent verifyBroadcastLocked(Intent intent) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors() == true) {
+12 −28
Original line number Diff line number Diff line
@@ -134,14 +134,6 @@ class BroadcastProcessQueue {
     */
    private int mActiveIndex;

    /**
     * When defined, the receiver actively being dispatched into this process
     * was considered "blocked" until at least the given count of other
     * receivers have reached a terminal state; typically used for ordered
     * broadcasts and priority traunches.
     */
    private int mActiveBlockedUntilTerminalCount;

    /**
     * Count of {@link #mActive} broadcasts that have been dispatched since this
     * queue was last idle.
@@ -206,15 +198,11 @@ class BroadcastProcessQueue {
     * given count of other receivers have reached a terminal state; typically
     * used for ordered broadcasts and priority traunches.
     */
    public void enqueueOrReplaceBroadcast(@NonNull BroadcastRecord record, int recordIndex,
            int blockedUntilTerminalCount) {
    public void enqueueOrReplaceBroadcast(@NonNull BroadcastRecord record, int recordIndex) {
        if (record.isReplacePending()) {
            boolean didReplace = replaceBroadcastInQueue(mPending, record, recordIndex,
                    blockedUntilTerminalCount)
                    || replaceBroadcastInQueue(mPendingUrgent, record, recordIndex,
                            blockedUntilTerminalCount)
                    || replaceBroadcastInQueue(mPendingOffload, record, recordIndex,
                            blockedUntilTerminalCount);
            boolean didReplace = replaceBroadcastInQueue(mPending, record, recordIndex)
                    || replaceBroadcastInQueue(mPendingUrgent, record, recordIndex)
                    || replaceBroadcastInQueue(mPendingOffload, record, recordIndex);
            if (didReplace) {
                return;
            }
@@ -225,7 +213,6 @@ class BroadcastProcessQueue {
        SomeArgs newBroadcastArgs = SomeArgs.obtain();
        newBroadcastArgs.arg1 = record;
        newBroadcastArgs.argi1 = recordIndex;
        newBroadcastArgs.argi2 = blockedUntilTerminalCount;

        // Cross-broadcast prioritization policy:  some broadcasts might warrant being
        // issued ahead of others that are already pending, for example if this new
@@ -244,7 +231,7 @@ class BroadcastProcessQueue {
     * {@code false} otherwise.
     */
    private boolean replaceBroadcastInQueue(@NonNull ArrayDeque<SomeArgs> queue,
            @NonNull BroadcastRecord record, int recordIndex, int blockedUntilTerminalCount) {
            @NonNull BroadcastRecord record, int recordIndex) {
        final Iterator<SomeArgs> it = queue.descendingIterator();
        final Object receiver = record.receivers.get(recordIndex);
        while (it.hasNext()) {
@@ -259,7 +246,6 @@ class BroadcastProcessQueue {
                // Exact match found; perform in-place swap
                args.arg1 = record;
                args.argi1 = recordIndex;
                args.argi2 = blockedUntilTerminalCount;
                onBroadcastDequeued(testRecord, testRecordIndex);
                onBroadcastEnqueued(record, recordIndex);
                return true;
@@ -411,7 +397,6 @@ class BroadcastProcessQueue {
        final SomeArgs next = removeNextBroadcast();
        mActive = (BroadcastRecord) next.arg1;
        mActiveIndex = next.argi1;
        mActiveBlockedUntilTerminalCount = next.argi2;
        mActiveCountSinceIdle++;
        mActiveViaColdStart = false;
        next.recycle();
@@ -424,7 +409,6 @@ class BroadcastProcessQueue {
    public void makeActiveIdle() {
        mActive = null;
        mActiveIndex = 0;
        mActiveBlockedUntilTerminalCount = -1;
        mActiveCountSinceIdle = 0;
        mActiveViaColdStart = false;
        invalidateRunnableAt();
@@ -705,7 +689,7 @@ class BroadcastProcessQueue {
        if (next != null) {
            final BroadcastRecord r = (BroadcastRecord) next.arg1;
            final int index = next.argi1;
            final int blockedUntilTerminalCount = next.argi2;
            final int blockedUntilTerminalCount = r.blockedUntilTerminalCount[index];
            final long runnableAt = r.enqueueTime;

            // We might be blocked waiting for other receivers to finish,
@@ -871,19 +855,19 @@ class BroadcastProcessQueue {
        pw.println();
        pw.increaseIndent();
        if (mActive != null) {
            dumpRecord("ACTIVE", now, pw, mActive, mActiveIndex, mActiveBlockedUntilTerminalCount);
            dumpRecord("ACTIVE", now, pw, mActive, mActiveIndex);
        }
        for (SomeArgs args : mPendingUrgent) {
            final BroadcastRecord r = (BroadcastRecord) args.arg1;
            dumpRecord("URGENT", now, pw, r, args.argi1, args.argi2);
            dumpRecord("URGENT", now, pw, r, args.argi1);
        }
        for (SomeArgs args : mPending) {
            final BroadcastRecord r = (BroadcastRecord) args.arg1;
            dumpRecord(null, now, pw, r, args.argi1, args.argi2);
            dumpRecord(null, now, pw, r, args.argi1);
        }
        for (SomeArgs args : mPendingOffload) {
            final BroadcastRecord r = (BroadcastRecord) args.arg1;
            dumpRecord("OFFLOAD", now, pw, r, args.argi1, args.argi2);
            dumpRecord("OFFLOAD", now, pw, r, args.argi1);
        }
        pw.decreaseIndent();
        pw.println();
@@ -891,8 +875,7 @@ class BroadcastProcessQueue {

    @NeverCompile
    private void dumpRecord(@Nullable String flavor, @UptimeMillisLong long now,
            @NonNull IndentingPrintWriter pw, @NonNull BroadcastRecord record, int recordIndex,
            int blockedUntilTerminalCount) {
            @NonNull IndentingPrintWriter pw, @NonNull BroadcastRecord record, int recordIndex) {
        TimeUtils.formatDuration(record.enqueueTime, now, pw);
        pw.print(' ');
        pw.println(record.toShortString());
@@ -918,6 +901,7 @@ class BroadcastProcessQueue {
            pw.print(info.activityInfo.name);
        }
        pw.println();
        final int blockedUntilTerminalCount = record.blockedUntilTerminalCount[recordIndex];
        if (blockedUntilTerminalCount != -1) {
            pw.print("    blocked until ");
            pw.print(blockedUntilTerminalCount);
+1 −7
Original line number Diff line number Diff line
@@ -1690,13 +1690,7 @@ public class BroadcastQueueImpl extends BroadcastQueue {
                System.identityHashCode(original));
        }

        final ApplicationInfo info = original.callerApp != null ? original.callerApp.info : null;
        final String callerPackage = info != null ? info.packageName : original.callerPackage;
        if (callerPackage != null) {
            mService.mHandler.obtainMessage(ActivityManagerService.DISPATCH_SENDING_BROADCAST_EVENT,
                    original.callingUid, 0, callerPackage).sendToTarget();
        }

        mService.notifyBroadcastFinishedLocked(original);
        mHistory.addBroadcastToHistoryLocked(original);
    }

+2 −30
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import static com.android.server.am.BroadcastProcessQueue.reasonToString;
import static com.android.server.am.BroadcastProcessQueue.removeFromRunnableList;
import static com.android.server.am.BroadcastRecord.deliveryStateToString;
import static com.android.server.am.BroadcastRecord.getReceiverPackageName;
import static com.android.server.am.BroadcastRecord.getReceiverPriority;
import static com.android.server.am.BroadcastRecord.getReceiverProcessName;
import static com.android.server.am.BroadcastRecord.getReceiverUid;
import static com.android.server.am.BroadcastRecord.isDeliveryStateTerminal;
@@ -320,7 +319,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
            return;
        }

        final int cookie = traceBegin("updateRunnableList");
        final boolean wantQueue = queue.isRunnable();
        final boolean inQueue = (queue == mRunnableHead) || (queue.runnableAtPrev != null)
                || (queue.runnableAtNext != null);
@@ -347,8 +345,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        if (queue.isEmpty() && !queue.isActive() && !queue.isProcessWarm()) {
            removeProcessQueue(queue.processName, queue.uid);
        }

        traceEnd(cookie);
    }

    /**
@@ -591,36 +587,11 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        r.enqueueRealTime = SystemClock.elapsedRealtime();
        r.enqueueClockTime = System.currentTimeMillis();

        int lastPriority = 0;
        int lastPriorityIndex = 0;

        for (int i = 0; i < r.receivers.size(); i++) {
            final Object receiver = r.receivers.get(i);
            final BroadcastProcessQueue queue = getOrCreateProcessQueue(
                    getReceiverProcessName(receiver), getReceiverUid(receiver));

            final int blockedUntilTerminalCount;
            if (r.ordered) {
                // When sending an ordered broadcast, we need to block this
                // receiver until all previous receivers have terminated
                blockedUntilTerminalCount = i;
            } else if (r.prioritized) {
                // When sending a prioritized broadcast, we only need to wait
                // for the previous traunch of receivers to be terminated
                final int thisPriority = getReceiverPriority(receiver);
                if ((i == 0) || (thisPriority != lastPriority)) {
                    lastPriority = thisPriority;
                    lastPriorityIndex = i;
                    blockedUntilTerminalCount = i;
                } else {
                    blockedUntilTerminalCount = lastPriorityIndex;
                }
            } else {
                // Otherwise we don't need to block at all
                blockedUntilTerminalCount = -1;
            }

            queue.enqueueOrReplaceBroadcast(r, i, blockedUntilTerminalCount);
            queue.enqueueOrReplaceBroadcast(r, i);
            updateRunnableList(queue);
            enqueueUpdateRunningList();
        }
@@ -1431,6 +1402,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {

        final boolean recordFinished = (r.terminalCount == r.receivers.size());
        if (recordFinished) {
            mService.notifyBroadcastFinishedLocked(r);
            mHistory.addBroadcastToHistoryLocked(r);

            r.finishTime = SystemClock.uptimeMillis();
+53 −12
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ final class BroadcastRecord extends Binder {
    final @Nullable BroadcastOptions options; // BroadcastOptions supplied by caller
    final @NonNull List<Object> receivers;   // contains BroadcastFilter and ResolveInfo
    final @DeliveryState int[] delivery;   // delivery state of each receiver
    final int[] blockedUntilTerminalCount; // blocked until count of each receiver
    @Nullable ProcessRecord resultToApp; // who receives final result if non-null
    @Nullable IIntentReceiver resultTo; // who receives final result if non-null
    boolean deferred;
@@ -375,6 +376,7 @@ final class BroadcastRecord extends Binder {
        options = _options;
        receivers = (_receivers != null) ? _receivers : EMPTY_RECEIVERS;
        delivery = new int[_receivers != null ? _receivers.size() : 0];
        blockedUntilTerminalCount = calculateBlockedUntilTerminalCount(receivers, _serialized);
        scheduledTime = new long[delivery.length];
        terminalTime = new long[delivery.length];
        resultToApp = _resultToApp;
@@ -385,7 +387,7 @@ final class BroadcastRecord extends Binder {
        ordered = _serialized;
        sticky = _sticky;
        initialSticky = _initialSticky;
        prioritized = isPrioritized(receivers);
        prioritized = isPrioritized(blockedUntilTerminalCount, _serialized);
        userId = _userId;
        nextReceiver = 0;
        state = IDLE;
@@ -427,6 +429,7 @@ final class BroadcastRecord extends Binder {
        options = from.options;
        receivers = from.receivers;
        delivery = from.delivery;
        blockedUntilTerminalCount = from.blockedUntilTerminalCount;
        scheduledTime = from.scheduledTime;
        terminalTime = from.terminalTime;
        resultToApp = from.resultToApp;
@@ -690,22 +693,60 @@ final class BroadcastRecord extends Binder {
    }

    /**
     * Return if given receivers list has more than one traunch of priorities.
     * Determine if the result of {@link #calculateBlockedUntilTerminalCount}
     * has prioritized tranches of receivers.
     */
    @VisibleForTesting
    static boolean isPrioritized(@NonNull List<Object> receivers) {
        int firstPriority = 0;
        for (int i = 0; i < receivers.size(); i++) {
    static boolean isPrioritized(@NonNull int[] blockedUntilTerminalCount,
            boolean ordered) {
        return !ordered && (blockedUntilTerminalCount.length > 0)
                && (blockedUntilTerminalCount[0] != -1);
    }

    /**
     * Calculate the {@link #terminalCount} that each receiver should be
     * considered blocked until.
     * <p>
     * For example, in an ordered broadcast, receiver {@code N} is blocked until
     * receiver {@code N-1} reaches a terminal state. Similarly, in a
     * prioritized broadcast, receiver {@code N} is blocked until all receivers
     * of a higher priority reach a terminal state.
     * <p>
     * When there are no terminal count constraints, the blocked value for each
     * receiver is {@code -1}.
     */
    @VisibleForTesting
    static @NonNull int[] calculateBlockedUntilTerminalCount(
            @NonNull List<Object> receivers, boolean ordered) {
        final int N = receivers.size();
        final int[] blockedUntilTerminalCount = new int[N];
        int lastPriority = 0;
        int lastPriorityIndex = 0;
        for (int i = 0; i < N; i++) {
            if (ordered) {
                // When sending an ordered broadcast, we need to block this
                // receiver until all previous receivers have terminated
                blockedUntilTerminalCount[i] = i;
            } else {
                // When sending a prioritized broadcast, we only need to wait
                // for the previous tranche of receivers to be terminated
                final int thisPriority = getReceiverPriority(receivers.get(i));
            if (i == 0) {
                firstPriority = thisPriority;
            } else if (thisPriority != firstPriority) {
                return true;
                if ((i == 0) || (thisPriority != lastPriority)) {
                    lastPriority = thisPriority;
                    lastPriorityIndex = i;
                    blockedUntilTerminalCount[i] = i;
                } else {
                    blockedUntilTerminalCount[i] = lastPriorityIndex;
                }
            }
        return false;
        }

        // If the entire list is in the same priority tranche, mark as -1 to
        // indicate that none of them need to wait
        if (N > 0 && blockedUntilTerminalCount[N - 1] == 0) {
            Arrays.fill(blockedUntilTerminalCount, -1);
        }
        return blockedUntilTerminalCount;
    }

    static int getReceiverUid(@NonNull Object receiver) {
        if (receiver instanceof BroadcastFilter) {
Loading