Loading services/core/java/com/android/server/am/BroadcastProcessQueue.java +57 −22 Original line number Diff line number Diff line Loading @@ -114,7 +114,14 @@ class BroadcastProcessQueue { * dispatched to this process, in the same representation as * {@link #mPending}. */ private final ArrayDeque<SomeArgs> mPendingUrgent = new ArrayDeque<>(); private final ArrayDeque<SomeArgs> mPendingUrgent = new ArrayDeque<>(4); /** * Ordered collection of "offload" broadcasts that are waiting to be * dispatched to this process, in the same representation as * {@link #mPending}. */ private final ArrayDeque<SomeArgs> mPendingOffload = new ArrayDeque<>(4); /** * Broadcast actively being dispatched to this process. Loading Loading @@ -148,8 +155,7 @@ class BroadcastProcessQueue { private boolean mActiveViaColdStart; /** * Count of {@link #mPending} and {@link #mPendingUrgent} broadcasts of * these various flavors. * Count of pending broadcasts of these various flavors. */ private int mCountForeground; private int mCountOrdered; Loading Loading @@ -177,6 +183,16 @@ class BroadcastProcessQueue { this.uid = uid; } private @NonNull ArrayDeque<SomeArgs> getQueueForBroadcast(@NonNull BroadcastRecord record) { if (record.isUrgent()) { return mPendingUrgent; } else if (record.isOffload()) { return mPendingOffload; } else { return mPending; } } /** * Enqueue the given broadcast to be dispatched to this process at some * future point in time. The target receiver is indicated by the given index Loading @@ -193,10 +209,12 @@ class BroadcastProcessQueue { public void enqueueOrReplaceBroadcast(@NonNull BroadcastRecord record, int recordIndex, int blockedUntilTerminalCount) { if (record.isReplacePending()) { boolean didReplace = replaceBroadcastInQueue(mPending, record, recordIndex, blockedUntilTerminalCount) || replaceBroadcastInQueue(mPendingUrgent, record, recordIndex, blockedUntilTerminalCount); boolean didReplace = replaceBroadcastInQueue(mPending, record, recordIndex, blockedUntilTerminalCount) || replaceBroadcastInQueue(mPendingUrgent, record, recordIndex, blockedUntilTerminalCount) || replaceBroadcastInQueue(mPendingOffload, record, recordIndex, blockedUntilTerminalCount); if (didReplace) { return; } Loading @@ -213,8 +231,7 @@ class BroadcastProcessQueue { // issued ahead of others that are already pending, for example if this new // broadcast is in a different delivery class or is tied to a direct user interaction // with implicit responsiveness expectations. final ArrayDeque<SomeArgs> queue = record.isUrgent() ? mPendingUrgent : mPending; queue.addLast(newBroadcastArgs); getQueueForBroadcast(record).addLast(newBroadcastArgs); onBroadcastEnqueued(record, recordIndex); } Loading Loading @@ -279,10 +296,13 @@ class BroadcastProcessQueue { */ public boolean forEachMatchingBroadcast(@NonNull BroadcastPredicate predicate, @NonNull BroadcastConsumer consumer, boolean andRemove) { boolean didSomething = forEachMatchingBroadcastInQueue(mPending, boolean didSomething = false; didSomething |= forEachMatchingBroadcastInQueue(mPending, predicate, consumer, andRemove); didSomething |= forEachMatchingBroadcastInQueue(mPendingUrgent, predicate, consumer, andRemove); didSomething |= forEachMatchingBroadcastInQueue(mPendingOffload, predicate, consumer, andRemove); return didSomething; } Loading Loading @@ -516,7 +536,7 @@ class BroadcastProcessQueue { } public boolean isEmpty() { return mPending.isEmpty() && mPendingUrgent.isEmpty(); return mPending.isEmpty() && mPendingUrgent.isEmpty() && mPendingOffload.isEmpty(); } public boolean isActive() { Loading @@ -537,6 +557,8 @@ class BroadcastProcessQueue { return mPendingUrgent; } else if (!mPending.isEmpty()) { return mPending; } else if (!mPendingOffload.isEmpty()) { return mPendingOffload; } return null; } Loading Loading @@ -581,12 +603,15 @@ class BroadcastProcessQueue { } final SomeArgs next = mPending.peekFirst(); final SomeArgs nextUrgent = mPendingUrgent.peekFirst(); final SomeArgs nextOffload = mPendingOffload.peekFirst(); // Empty queue is past any barrier final boolean nextLater = next == null final boolean nextLater = (next == null) || ((BroadcastRecord) next.arg1).enqueueTime > barrierTime; final boolean nextUrgentLater = nextUrgent == null final boolean nextUrgentLater = (nextUrgent == null) || ((BroadcastRecord) nextUrgent.arg1).enqueueTime > barrierTime; return nextLater && nextUrgentLater; final boolean nextOffloadLater = (nextOffload == null) || ((BroadcastRecord) nextOffload.arg1).enqueueTime > barrierTime; return nextLater && nextUrgentLater && nextOffloadLater; } public boolean isRunnable() { Loading Loading @@ -726,8 +751,9 @@ class BroadcastProcessQueue { // If we have too many broadcasts pending, bypass any delays that // might have been applied above to aid draining if (mPending.size() + mPendingUrgent.size() >= constants.MAX_PENDING_BROADCASTS) { mRunnableAt = runnableAt; if (mPending.size() + mPendingUrgent.size() + mPendingOffload.size() >= constants.MAX_PENDING_BROADCASTS) { mRunnableAt = Math.min(mRunnableAt, runnableAt); mRunnableAtReason = REASON_MAX_PENDING; } } else { Loading Loading @@ -845,23 +871,28 @@ class BroadcastProcessQueue { pw.println(); pw.increaseIndent(); if (mActive != null) { dumpRecord(now, pw, mActive, mActiveIndex, mActiveBlockedUntilTerminalCount); dumpRecord("ACTIVE", now, pw, mActive, mActiveIndex, mActiveBlockedUntilTerminalCount); } for (SomeArgs args : mPendingUrgent) { final BroadcastRecord r = (BroadcastRecord) args.arg1; dumpRecord(now, pw, r, args.argi1, args.argi2); dumpRecord("URGENT", now, pw, r, args.argi1, args.argi2); } for (SomeArgs args : mPending) { final BroadcastRecord r = (BroadcastRecord) args.arg1; dumpRecord(now, pw, r, args.argi1, args.argi2); dumpRecord(null, now, pw, r, args.argi1, args.argi2); } for (SomeArgs args : mPendingOffload) { final BroadcastRecord r = (BroadcastRecord) args.arg1; dumpRecord("OFFLOAD", now, pw, r, args.argi1, args.argi2); } pw.decreaseIndent(); pw.println(); } @NeverCompile private void dumpRecord(@UptimeMillisLong long now, @NonNull IndentingPrintWriter pw, @NonNull BroadcastRecord record, int recordIndex, int blockedUntilTerminalCount) { private void dumpRecord(@Nullable String flavor, @UptimeMillisLong long now, @NonNull IndentingPrintWriter pw, @NonNull BroadcastRecord record, int recordIndex, int blockedUntilTerminalCount) { TimeUtils.formatDuration(record.enqueueTime, now, pw); pw.print(' '); pw.println(record.toShortString()); Loading @@ -872,6 +903,10 @@ class BroadcastProcessQueue { pw.print(" at "); TimeUtils.formatDuration(record.scheduledTime[recordIndex], now, pw); } if (flavor != null) { pw.print(' '); pw.print(flavor); } final Object receiver = record.receivers.get(recordIndex); if (receiver instanceof BroadcastFilter) { final BroadcastFilter filter = (BroadcastFilter) receiver; Loading services/core/java/com/android/server/am/BroadcastRecord.java +4 −0 Original line number Diff line number Diff line Loading @@ -617,6 +617,10 @@ final class BroadcastRecord extends Binder { return (intent.getFlags() & Intent.FLAG_RECEIVER_NO_ABORT) != 0; } boolean isOffload() { return (intent.getFlags() & Intent.FLAG_RECEIVER_OFFLOAD) != 0; } /** * Core policy determination about this broadcast's delivery prioritization */ Loading Loading
services/core/java/com/android/server/am/BroadcastProcessQueue.java +57 −22 Original line number Diff line number Diff line Loading @@ -114,7 +114,14 @@ class BroadcastProcessQueue { * dispatched to this process, in the same representation as * {@link #mPending}. */ private final ArrayDeque<SomeArgs> mPendingUrgent = new ArrayDeque<>(); private final ArrayDeque<SomeArgs> mPendingUrgent = new ArrayDeque<>(4); /** * Ordered collection of "offload" broadcasts that are waiting to be * dispatched to this process, in the same representation as * {@link #mPending}. */ private final ArrayDeque<SomeArgs> mPendingOffload = new ArrayDeque<>(4); /** * Broadcast actively being dispatched to this process. Loading Loading @@ -148,8 +155,7 @@ class BroadcastProcessQueue { private boolean mActiveViaColdStart; /** * Count of {@link #mPending} and {@link #mPendingUrgent} broadcasts of * these various flavors. * Count of pending broadcasts of these various flavors. */ private int mCountForeground; private int mCountOrdered; Loading Loading @@ -177,6 +183,16 @@ class BroadcastProcessQueue { this.uid = uid; } private @NonNull ArrayDeque<SomeArgs> getQueueForBroadcast(@NonNull BroadcastRecord record) { if (record.isUrgent()) { return mPendingUrgent; } else if (record.isOffload()) { return mPendingOffload; } else { return mPending; } } /** * Enqueue the given broadcast to be dispatched to this process at some * future point in time. The target receiver is indicated by the given index Loading @@ -193,10 +209,12 @@ class BroadcastProcessQueue { public void enqueueOrReplaceBroadcast(@NonNull BroadcastRecord record, int recordIndex, int blockedUntilTerminalCount) { if (record.isReplacePending()) { boolean didReplace = replaceBroadcastInQueue(mPending, record, recordIndex, blockedUntilTerminalCount) || replaceBroadcastInQueue(mPendingUrgent, record, recordIndex, blockedUntilTerminalCount); boolean didReplace = replaceBroadcastInQueue(mPending, record, recordIndex, blockedUntilTerminalCount) || replaceBroadcastInQueue(mPendingUrgent, record, recordIndex, blockedUntilTerminalCount) || replaceBroadcastInQueue(mPendingOffload, record, recordIndex, blockedUntilTerminalCount); if (didReplace) { return; } Loading @@ -213,8 +231,7 @@ class BroadcastProcessQueue { // issued ahead of others that are already pending, for example if this new // broadcast is in a different delivery class or is tied to a direct user interaction // with implicit responsiveness expectations. final ArrayDeque<SomeArgs> queue = record.isUrgent() ? mPendingUrgent : mPending; queue.addLast(newBroadcastArgs); getQueueForBroadcast(record).addLast(newBroadcastArgs); onBroadcastEnqueued(record, recordIndex); } Loading Loading @@ -279,10 +296,13 @@ class BroadcastProcessQueue { */ public boolean forEachMatchingBroadcast(@NonNull BroadcastPredicate predicate, @NonNull BroadcastConsumer consumer, boolean andRemove) { boolean didSomething = forEachMatchingBroadcastInQueue(mPending, boolean didSomething = false; didSomething |= forEachMatchingBroadcastInQueue(mPending, predicate, consumer, andRemove); didSomething |= forEachMatchingBroadcastInQueue(mPendingUrgent, predicate, consumer, andRemove); didSomething |= forEachMatchingBroadcastInQueue(mPendingOffload, predicate, consumer, andRemove); return didSomething; } Loading Loading @@ -516,7 +536,7 @@ class BroadcastProcessQueue { } public boolean isEmpty() { return mPending.isEmpty() && mPendingUrgent.isEmpty(); return mPending.isEmpty() && mPendingUrgent.isEmpty() && mPendingOffload.isEmpty(); } public boolean isActive() { Loading @@ -537,6 +557,8 @@ class BroadcastProcessQueue { return mPendingUrgent; } else if (!mPending.isEmpty()) { return mPending; } else if (!mPendingOffload.isEmpty()) { return mPendingOffload; } return null; } Loading Loading @@ -581,12 +603,15 @@ class BroadcastProcessQueue { } final SomeArgs next = mPending.peekFirst(); final SomeArgs nextUrgent = mPendingUrgent.peekFirst(); final SomeArgs nextOffload = mPendingOffload.peekFirst(); // Empty queue is past any barrier final boolean nextLater = next == null final boolean nextLater = (next == null) || ((BroadcastRecord) next.arg1).enqueueTime > barrierTime; final boolean nextUrgentLater = nextUrgent == null final boolean nextUrgentLater = (nextUrgent == null) || ((BroadcastRecord) nextUrgent.arg1).enqueueTime > barrierTime; return nextLater && nextUrgentLater; final boolean nextOffloadLater = (nextOffload == null) || ((BroadcastRecord) nextOffload.arg1).enqueueTime > barrierTime; return nextLater && nextUrgentLater && nextOffloadLater; } public boolean isRunnable() { Loading Loading @@ -726,8 +751,9 @@ class BroadcastProcessQueue { // If we have too many broadcasts pending, bypass any delays that // might have been applied above to aid draining if (mPending.size() + mPendingUrgent.size() >= constants.MAX_PENDING_BROADCASTS) { mRunnableAt = runnableAt; if (mPending.size() + mPendingUrgent.size() + mPendingOffload.size() >= constants.MAX_PENDING_BROADCASTS) { mRunnableAt = Math.min(mRunnableAt, runnableAt); mRunnableAtReason = REASON_MAX_PENDING; } } else { Loading Loading @@ -845,23 +871,28 @@ class BroadcastProcessQueue { pw.println(); pw.increaseIndent(); if (mActive != null) { dumpRecord(now, pw, mActive, mActiveIndex, mActiveBlockedUntilTerminalCount); dumpRecord("ACTIVE", now, pw, mActive, mActiveIndex, mActiveBlockedUntilTerminalCount); } for (SomeArgs args : mPendingUrgent) { final BroadcastRecord r = (BroadcastRecord) args.arg1; dumpRecord(now, pw, r, args.argi1, args.argi2); dumpRecord("URGENT", now, pw, r, args.argi1, args.argi2); } for (SomeArgs args : mPending) { final BroadcastRecord r = (BroadcastRecord) args.arg1; dumpRecord(now, pw, r, args.argi1, args.argi2); dumpRecord(null, now, pw, r, args.argi1, args.argi2); } for (SomeArgs args : mPendingOffload) { final BroadcastRecord r = (BroadcastRecord) args.arg1; dumpRecord("OFFLOAD", now, pw, r, args.argi1, args.argi2); } pw.decreaseIndent(); pw.println(); } @NeverCompile private void dumpRecord(@UptimeMillisLong long now, @NonNull IndentingPrintWriter pw, @NonNull BroadcastRecord record, int recordIndex, int blockedUntilTerminalCount) { private void dumpRecord(@Nullable String flavor, @UptimeMillisLong long now, @NonNull IndentingPrintWriter pw, @NonNull BroadcastRecord record, int recordIndex, int blockedUntilTerminalCount) { TimeUtils.formatDuration(record.enqueueTime, now, pw); pw.print(' '); pw.println(record.toShortString()); Loading @@ -872,6 +903,10 @@ class BroadcastProcessQueue { pw.print(" at "); TimeUtils.formatDuration(record.scheduledTime[recordIndex], now, pw); } if (flavor != null) { pw.print(' '); pw.print(flavor); } final Object receiver = record.receivers.get(recordIndex); if (receiver instanceof BroadcastFilter) { final BroadcastFilter filter = (BroadcastFilter) receiver; Loading
services/core/java/com/android/server/am/BroadcastRecord.java +4 −0 Original line number Diff line number Diff line Loading @@ -617,6 +617,10 @@ final class BroadcastRecord extends Binder { return (intent.getFlags() & Intent.FLAG_RECEIVER_NO_ABORT) != 0; } boolean isOffload() { return (intent.getFlags() & Intent.FLAG_RECEIVER_OFFLOAD) != 0; } /** * Core policy determination about this broadcast's delivery prioritization */ Loading