Loading services/core/java/com/android/server/am/BroadcastProcessQueue.java +18 −4 Original line number Diff line number Diff line Loading @@ -170,6 +170,8 @@ class BroadcastProcessQueue { private int mCountInstrumented; private int mCountManifest; private boolean mPrioritizeEarliest; private @UptimeMillisLong long mRunnableAt = Long.MAX_VALUE; private @Reason int mRunnableAtReason = REASON_EMPTY; private boolean mRunnableAtInvalidated; Loading Loading @@ -605,8 +607,9 @@ class BroadcastProcessQueue { final BroadcastRecord nextLPRecord = (BroadcastRecord) nextLPArgs.arg1; final int nextLPRecordIndex = nextLPArgs.argi1; final BroadcastRecord nextHPRecord = (BroadcastRecord) highPriorityQueue.peekFirst().arg1; final boolean isLPQueueEligible = consecutiveHighPriorityCount >= maxHighPriorityDispatchLimit final boolean shouldConsiderLPQueue = (mPrioritizeEarliest || consecutiveHighPriorityCount >= maxHighPriorityDispatchLimit); final boolean isLPQueueEligible = shouldConsiderLPQueue && nextLPRecord.enqueueTime <= nextHPRecord.enqueueTime && !blockedOnOrderedDispatch(nextLPRecord, nextLPRecordIndex); return isLPQueueEligible ? lowPriorityQueue : highPriorityQueue; Loading @@ -616,6 +619,17 @@ class BroadcastProcessQueue { return (queue == null || queue.isEmpty()); } /** * When {@code prioritizeEarliest} is set to {@code true}, then earliest enqueued * broadcasts would be prioritized for dispatching, even if there are urgent broadcasts * waiting. This is typically used in case there are callers waiting for "barrier" to be * reached. */ @VisibleForTesting void setPrioritizeEarliest(boolean prioritizeEarliest) { mPrioritizeEarliest = prioritizeEarliest; } /** * Returns null if there are no pending broadcasts */ Loading services/core/java/com/android/server/am/BroadcastQueueModernImpl.java +19 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Predicate; /** Loading Loading @@ -1224,6 +1225,17 @@ class BroadcastQueueModernImpl extends BroadcastQueue { return didSomething; } private void forEachQueue(@NonNull Consumer<BroadcastProcessQueue> consumer) { for (int i = 0; i < mProcessQueues.size(); ++i) { BroadcastProcessQueue leaf = mProcessQueues.valueAt(i); while (leaf != null) { consumer.accept(leaf); updateRunnableList(leaf); leaf = leaf.processNameNext; } } } @Override public void start(@NonNull ContentResolver resolver) { mFgConstants.startObserving(mHandler, resolver); Loading Loading @@ -1282,12 +1294,19 @@ class BroadcastQueueModernImpl extends BroadcastQueue { final CountDownLatch latch = new CountDownLatch(1); synchronized (mService) { mWaitingFor.add(Pair.create(condition, latch)); forEachQueue(q -> q.setPrioritizeEarliest(true)); } enqueueUpdateRunningList(); try { latch.await(); } catch (InterruptedException e) { throw new RuntimeException(e); } finally { synchronized (mService) { if (mWaitingFor.isEmpty()) { forEachQueue(q -> q.setPrioritizeEarliest(false)); } } } } Loading services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java +105 −36 Original line number Diff line number Diff line Loading @@ -195,6 +195,12 @@ public class BroadcastQueueModernImplTest { false, null, false, null); } private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue, BroadcastRecord record, int recordIndex, long enqueueTime) { queue.enqueueOrReplaceBroadcast(record, recordIndex); record.enqueueTime = enqueueTime; } @Test public void testRunnableList_Simple() { assertRunnableList(List.of(), mHead); Loading Loading @@ -549,29 +555,32 @@ public class BroadcastQueueModernImplTest { mConstants.MAX_CONSECUTIVE_URGENT_DISPATCHES = 2; BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); long timeCounter = 100; // mix of broadcasts, with more than 2 fg/urgent queue.enqueueOrReplaceBroadcast( makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 0); queue.enqueueOrReplaceBroadcast( makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 0); queue.enqueueOrReplaceBroadcast( makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0); queue.enqueueOrReplaceBroadcast( enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_LOCALE_CHANGED) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0); queue.enqueueOrReplaceBroadcast( .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_APPLICATION_PREFERENCES), optInteractive), 0); queue.enqueueOrReplaceBroadcast( optInteractive), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE), optInteractive), 0); queue.enqueueOrReplaceBroadcast( optInteractive), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_INPUT_METHOD_CHANGED) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0); queue.enqueueOrReplaceBroadcast( .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_NEW_OUTGOING_CALL), optInteractive), 0); optInteractive), 0, timeCounter++); queue.makeActiveNextPending(); assertEquals(Intent.ACTION_LOCALE_CHANGED, queue.getActive().intent.getAction()); Loading Loading @@ -604,35 +613,38 @@ public class BroadcastQueueModernImplTest { mConstants.MAX_CONSECUTIVE_NORMAL_DISPATCHES = 2; final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); long timeCounter = 100; // mix of broadcasts, with more than 2 normal queue.enqueueOrReplaceBroadcast( enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_BOOT_COMPLETED) .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0); queue.enqueueOrReplaceBroadcast( makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 0); queue.enqueueOrReplaceBroadcast( .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_PACKAGE_CHANGED) .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0); queue.enqueueOrReplaceBroadcast( makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 0); queue.enqueueOrReplaceBroadcast( makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0); queue.enqueueOrReplaceBroadcast( .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_LOCALE_CHANGED) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0); queue.enqueueOrReplaceBroadcast( .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_APPLICATION_PREFERENCES), optInteractive), 0); queue.enqueueOrReplaceBroadcast( optInteractive), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE), optInteractive), 0); queue.enqueueOrReplaceBroadcast( optInteractive), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_INPUT_METHOD_CHANGED) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0); queue.enqueueOrReplaceBroadcast( .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_NEW_OUTGOING_CALL), optInteractive), 0); optInteractive), 0, timeCounter++); queue.makeActiveNextPending(); assertEquals(Intent.ACTION_LOCALE_CHANGED, queue.getActive().intent.getAction()); Loading @@ -658,6 +670,63 @@ public class BroadcastQueueModernImplTest { assertEquals(Intent.ACTION_INPUT_METHOD_CHANGED, queue.getActive().intent.getAction()); } /** * Verify that BroadcastProcessQueue#setPrioritizeEarliest() works as expected. */ @Test public void testPrioritizeEarliest() { final BroadcastOptions optInteractive = BroadcastOptions.makeBasic(); optInteractive.setInteractive(true); BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); queue.setPrioritizeEarliest(true); long timeCounter = 100; enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_BOOT_COMPLETED) .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_PACKAGE_CHANGED) .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_LOCALE_CHANGED) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE), optInteractive), 0, timeCounter++); // When we mark BroadcastProcessQueue to prioritize earliest, we should // expect to dispatch broadcasts in the order they were enqueued queue.makeActiveNextPending(); assertEquals(Intent.ACTION_BOOT_COMPLETED, queue.getActive().intent.getAction()); queue.makeActiveNextPending(); assertEquals(Intent.ACTION_TIMEZONE_CHANGED, queue.getActive().intent.getAction()); // after MAX_CONSECUTIVE_URGENT_DISPATCHES expect an ordinary one next queue.makeActiveNextPending(); assertEquals(Intent.ACTION_PACKAGE_CHANGED, queue.getActive().intent.getAction()); // and then back to prioritizing urgent ones queue.makeActiveNextPending(); assertEquals(Intent.ACTION_ALARM_CHANGED, queue.getActive().intent.getAction()); queue.makeActiveNextPending(); assertEquals(Intent.ACTION_TIME_TICK, queue.getActive().intent.getAction()); queue.makeActiveNextPending(); assertEquals(Intent.ACTION_LOCALE_CHANGED, queue.getActive().intent.getAction()); // verify the reset-count-then-resume worked too queue.makeActiveNextPending(); assertEquals(AppWidgetManager.ACTION_APPWIDGET_UPDATE, queue.getActive().intent.getAction()); } /** * Verify that sending a broadcast that removes any matching pending * broadcasts is applied as expected. Loading Loading
services/core/java/com/android/server/am/BroadcastProcessQueue.java +18 −4 Original line number Diff line number Diff line Loading @@ -170,6 +170,8 @@ class BroadcastProcessQueue { private int mCountInstrumented; private int mCountManifest; private boolean mPrioritizeEarliest; private @UptimeMillisLong long mRunnableAt = Long.MAX_VALUE; private @Reason int mRunnableAtReason = REASON_EMPTY; private boolean mRunnableAtInvalidated; Loading Loading @@ -605,8 +607,9 @@ class BroadcastProcessQueue { final BroadcastRecord nextLPRecord = (BroadcastRecord) nextLPArgs.arg1; final int nextLPRecordIndex = nextLPArgs.argi1; final BroadcastRecord nextHPRecord = (BroadcastRecord) highPriorityQueue.peekFirst().arg1; final boolean isLPQueueEligible = consecutiveHighPriorityCount >= maxHighPriorityDispatchLimit final boolean shouldConsiderLPQueue = (mPrioritizeEarliest || consecutiveHighPriorityCount >= maxHighPriorityDispatchLimit); final boolean isLPQueueEligible = shouldConsiderLPQueue && nextLPRecord.enqueueTime <= nextHPRecord.enqueueTime && !blockedOnOrderedDispatch(nextLPRecord, nextLPRecordIndex); return isLPQueueEligible ? lowPriorityQueue : highPriorityQueue; Loading @@ -616,6 +619,17 @@ class BroadcastProcessQueue { return (queue == null || queue.isEmpty()); } /** * When {@code prioritizeEarliest} is set to {@code true}, then earliest enqueued * broadcasts would be prioritized for dispatching, even if there are urgent broadcasts * waiting. This is typically used in case there are callers waiting for "barrier" to be * reached. */ @VisibleForTesting void setPrioritizeEarliest(boolean prioritizeEarliest) { mPrioritizeEarliest = prioritizeEarliest; } /** * Returns null if there are no pending broadcasts */ Loading
services/core/java/com/android/server/am/BroadcastQueueModernImpl.java +19 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Predicate; /** Loading Loading @@ -1224,6 +1225,17 @@ class BroadcastQueueModernImpl extends BroadcastQueue { return didSomething; } private void forEachQueue(@NonNull Consumer<BroadcastProcessQueue> consumer) { for (int i = 0; i < mProcessQueues.size(); ++i) { BroadcastProcessQueue leaf = mProcessQueues.valueAt(i); while (leaf != null) { consumer.accept(leaf); updateRunnableList(leaf); leaf = leaf.processNameNext; } } } @Override public void start(@NonNull ContentResolver resolver) { mFgConstants.startObserving(mHandler, resolver); Loading Loading @@ -1282,12 +1294,19 @@ class BroadcastQueueModernImpl extends BroadcastQueue { final CountDownLatch latch = new CountDownLatch(1); synchronized (mService) { mWaitingFor.add(Pair.create(condition, latch)); forEachQueue(q -> q.setPrioritizeEarliest(true)); } enqueueUpdateRunningList(); try { latch.await(); } catch (InterruptedException e) { throw new RuntimeException(e); } finally { synchronized (mService) { if (mWaitingFor.isEmpty()) { forEachQueue(q -> q.setPrioritizeEarliest(false)); } } } } Loading
services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java +105 −36 Original line number Diff line number Diff line Loading @@ -195,6 +195,12 @@ public class BroadcastQueueModernImplTest { false, null, false, null); } private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue, BroadcastRecord record, int recordIndex, long enqueueTime) { queue.enqueueOrReplaceBroadcast(record, recordIndex); record.enqueueTime = enqueueTime; } @Test public void testRunnableList_Simple() { assertRunnableList(List.of(), mHead); Loading Loading @@ -549,29 +555,32 @@ public class BroadcastQueueModernImplTest { mConstants.MAX_CONSECUTIVE_URGENT_DISPATCHES = 2; BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); long timeCounter = 100; // mix of broadcasts, with more than 2 fg/urgent queue.enqueueOrReplaceBroadcast( makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 0); queue.enqueueOrReplaceBroadcast( makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 0); queue.enqueueOrReplaceBroadcast( makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0); queue.enqueueOrReplaceBroadcast( enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_LOCALE_CHANGED) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0); queue.enqueueOrReplaceBroadcast( .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_APPLICATION_PREFERENCES), optInteractive), 0); queue.enqueueOrReplaceBroadcast( optInteractive), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE), optInteractive), 0); queue.enqueueOrReplaceBroadcast( optInteractive), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_INPUT_METHOD_CHANGED) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0); queue.enqueueOrReplaceBroadcast( .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_NEW_OUTGOING_CALL), optInteractive), 0); optInteractive), 0, timeCounter++); queue.makeActiveNextPending(); assertEquals(Intent.ACTION_LOCALE_CHANGED, queue.getActive().intent.getAction()); Loading Loading @@ -604,35 +613,38 @@ public class BroadcastQueueModernImplTest { mConstants.MAX_CONSECUTIVE_NORMAL_DISPATCHES = 2; final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); long timeCounter = 100; // mix of broadcasts, with more than 2 normal queue.enqueueOrReplaceBroadcast( enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_BOOT_COMPLETED) .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0); queue.enqueueOrReplaceBroadcast( makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 0); queue.enqueueOrReplaceBroadcast( .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_PACKAGE_CHANGED) .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0); queue.enqueueOrReplaceBroadcast( makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 0); queue.enqueueOrReplaceBroadcast( makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0); queue.enqueueOrReplaceBroadcast( .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_LOCALE_CHANGED) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0); queue.enqueueOrReplaceBroadcast( .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_APPLICATION_PREFERENCES), optInteractive), 0); queue.enqueueOrReplaceBroadcast( optInteractive), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE), optInteractive), 0); queue.enqueueOrReplaceBroadcast( optInteractive), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_INPUT_METHOD_CHANGED) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0); queue.enqueueOrReplaceBroadcast( .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_NEW_OUTGOING_CALL), optInteractive), 0); optInteractive), 0, timeCounter++); queue.makeActiveNextPending(); assertEquals(Intent.ACTION_LOCALE_CHANGED, queue.getActive().intent.getAction()); Loading @@ -658,6 +670,63 @@ public class BroadcastQueueModernImplTest { assertEquals(Intent.ACTION_INPUT_METHOD_CHANGED, queue.getActive().intent.getAction()); } /** * Verify that BroadcastProcessQueue#setPrioritizeEarliest() works as expected. */ @Test public void testPrioritizeEarliest() { final BroadcastOptions optInteractive = BroadcastOptions.makeBasic(); optInteractive.setInteractive(true); BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); queue.setPrioritizeEarliest(true); long timeCounter = 100; enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_BOOT_COMPLETED) .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_PACKAGE_CHANGED) .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(Intent.ACTION_LOCALE_CHANGED) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE), optInteractive), 0, timeCounter++); // When we mark BroadcastProcessQueue to prioritize earliest, we should // expect to dispatch broadcasts in the order they were enqueued queue.makeActiveNextPending(); assertEquals(Intent.ACTION_BOOT_COMPLETED, queue.getActive().intent.getAction()); queue.makeActiveNextPending(); assertEquals(Intent.ACTION_TIMEZONE_CHANGED, queue.getActive().intent.getAction()); // after MAX_CONSECUTIVE_URGENT_DISPATCHES expect an ordinary one next queue.makeActiveNextPending(); assertEquals(Intent.ACTION_PACKAGE_CHANGED, queue.getActive().intent.getAction()); // and then back to prioritizing urgent ones queue.makeActiveNextPending(); assertEquals(Intent.ACTION_ALARM_CHANGED, queue.getActive().intent.getAction()); queue.makeActiveNextPending(); assertEquals(Intent.ACTION_TIME_TICK, queue.getActive().intent.getAction()); queue.makeActiveNextPending(); assertEquals(Intent.ACTION_LOCALE_CHANGED, queue.getActive().intent.getAction()); // verify the reset-count-then-resume worked too queue.makeActiveNextPending(); assertEquals(AppWidgetManager.ACTION_APPWIDGET_UPDATE, queue.getActive().intent.getAction()); } /** * Verify that sending a broadcast that removes any matching pending * broadcasts is applied as expected. Loading