1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.am; 18 19 import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN; 20 21 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; 22 import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED; 23 import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD; 24 import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST; 25 import static com.android.server.am.ActivityManagerDebugConfig.LOG_WRITER_INFO; 26 import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_ALARM; 27 import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_FOREGROUND; 28 import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_INTERACTIVE; 29 import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_MANIFEST; 30 import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_ORDERED; 31 import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_PRIORITIZED; 32 import static com.android.server.am.BroadcastProcessQueue.insertIntoRunnableList; 33 import static com.android.server.am.BroadcastProcessQueue.removeFromRunnableList; 34 import static com.android.server.am.BroadcastQueueTest.CLASS_BLUE; 35 import static com.android.server.am.BroadcastQueueTest.CLASS_GREEN; 36 import static com.android.server.am.BroadcastQueueTest.CLASS_RED; 37 import static com.android.server.am.BroadcastQueueTest.CLASS_YELLOW; 38 import static com.android.server.am.BroadcastQueueTest.PACKAGE_BLUE; 39 import static com.android.server.am.BroadcastQueueTest.PACKAGE_GREEN; 40 import static com.android.server.am.BroadcastQueueTest.PACKAGE_RED; 41 import static com.android.server.am.BroadcastQueueTest.PACKAGE_YELLOW; 42 import static com.android.server.am.BroadcastQueueTest.getUidForPackage; 43 import static com.android.server.am.BroadcastQueueTest.makeManifestReceiver; 44 import static com.android.server.am.BroadcastQueueTest.withPriority; 45 import static com.android.server.am.BroadcastRecord.isReceiverEquals; 46 47 import static com.google.common.truth.Truth.assertThat; 48 49 import static org.junit.Assert.assertEquals; 50 import static org.junit.Assert.assertFalse; 51 import static org.junit.Assert.assertNotEquals; 52 import static org.junit.Assert.assertNull; 53 import static org.junit.Assert.assertTrue; 54 import static org.junit.Assert.fail; 55 import static org.mockito.ArgumentMatchers.any; 56 import static org.mockito.ArgumentMatchers.anyInt; 57 import static org.mockito.ArgumentMatchers.anyLong; 58 import static org.mockito.ArgumentMatchers.anyString; 59 import static org.mockito.ArgumentMatchers.eq; 60 import static org.mockito.ArgumentMatchers.nullable; 61 import static org.mockito.Mockito.doAnswer; 62 import static org.mockito.Mockito.doReturn; 63 import static org.mockito.Mockito.mock; 64 import static org.mockito.Mockito.spy; 65 import static org.mockito.Mockito.times; 66 67 import android.annotation.NonNull; 68 import android.app.Activity; 69 import android.app.ActivityManager; 70 import android.app.AppOpsManager; 71 import android.app.BackgroundStartPrivileges; 72 import android.app.BroadcastOptions; 73 import android.appwidget.AppWidgetManager; 74 import android.content.IIntentReceiver; 75 import android.content.Intent; 76 import android.content.IntentFilter; 77 import android.content.pm.ResolveInfo; 78 import android.media.AudioManager; 79 import android.os.Bundle; 80 import android.os.BundleMerger; 81 import android.os.DropBoxManager; 82 import android.os.HandlerThread; 83 import android.os.Process; 84 import android.os.SystemClock; 85 import android.os.TestLooperManager; 86 import android.os.UserHandle; 87 import android.provider.Settings; 88 import android.util.IndentingPrintWriter; 89 import android.util.Pair; 90 91 import androidx.test.filters.SmallTest; 92 import androidx.test.platform.app.InstrumentationRegistry; 93 94 import com.android.internal.util.FrameworkStatsLog; 95 import com.android.server.ExtendedMockitoRule; 96 97 import org.junit.After; 98 import org.junit.Before; 99 import org.junit.Rule; 100 import org.junit.Test; 101 import org.mockito.Mock; 102 103 import java.io.PrintWriter; 104 import java.io.Writer; 105 import java.lang.reflect.Array; 106 import java.util.ArrayList; 107 import java.util.List; 108 import java.util.Objects; 109 110 @SmallTest 111 public final class BroadcastQueueModernImplTest { 112 private static final int TEST_UID = android.os.Process.FIRST_APPLICATION_UID; 113 private static final int TEST_UID2 = android.os.Process.FIRST_APPLICATION_UID + 1; 114 115 @Mock ActivityManagerService mAms; 116 @Mock ProcessRecord mProcess; 117 118 @Mock BroadcastProcessQueue mQueue1; 119 @Mock BroadcastProcessQueue mQueue2; 120 @Mock BroadcastProcessQueue mQueue3; 121 @Mock BroadcastProcessQueue mQueue4; 122 123 HandlerThread mHandlerThread; 124 TestLooperManager mLooper; 125 126 BroadcastConstants mConstants; 127 private BroadcastSkipPolicy mSkipPolicy; 128 BroadcastQueueModernImpl mImpl; 129 130 BroadcastProcessQueue mHead; 131 132 @Rule 133 public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) 134 .spyStatic(FrameworkStatsLog.class) 135 .build(); 136 137 @Before setUp()138 public void setUp() throws Exception { 139 mHandlerThread = new HandlerThread(getClass().getSimpleName()); 140 mHandlerThread.start(); 141 142 // Pause all event processing until a test chooses to resume 143 mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation() 144 .acquireLooperManager(mHandlerThread.getLooper())); 145 146 mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS); 147 mConstants.DELAY_URGENT_MILLIS = -120_000; 148 mConstants.DELAY_NORMAL_MILLIS = 10_000; 149 mConstants.DELAY_CACHED_MILLIS = 120_000; 150 151 mSkipPolicy = spy(new BroadcastSkipPolicy(mAms)); 152 doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any()); 153 doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any()); 154 155 final BroadcastHistory emptyHistory = new BroadcastHistory(mConstants) { 156 public void addBroadcastToHistoryLocked(BroadcastRecord original) { 157 // Ignored 158 } 159 }; 160 161 mImpl = new BroadcastQueueModernImpl(mAms, mHandlerThread.getThreadHandler(), 162 mConstants, mConstants, mSkipPolicy, emptyHistory); 163 164 doReturn(1L).when(mQueue1).getRunnableAt(); 165 doReturn(2L).when(mQueue2).getRunnableAt(); 166 doReturn(3L).when(mQueue3).getRunnableAt(); 167 doReturn(4L).when(mQueue4).getRunnableAt(); 168 } 169 170 @After tearDown()171 public void tearDown() throws Exception { 172 mHandlerThread.quit(); 173 } 174 175 /** 176 * Un-pause our handler to process pending events, wait for our queue to go 177 * idle, and then re-pause the handler. 178 */ waitForIdle()179 private void waitForIdle() throws Exception { 180 mLooper.release(); 181 mImpl.waitForIdle(LOG_WRITER_INFO); 182 mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation() 183 .acquireLooperManager(mHandlerThread.getLooper())); 184 } 185 assertOrphan(BroadcastProcessQueue queue)186 private static void assertOrphan(BroadcastProcessQueue queue) { 187 assertNull(queue.runnableAtNext); 188 assertNull(queue.runnableAtPrev); 189 } 190 assertRunnableList(@onNull List<BroadcastProcessQueue> expected, @NonNull BroadcastProcessQueue actualHead)191 private static void assertRunnableList(@NonNull List<BroadcastProcessQueue> expected, 192 @NonNull BroadcastProcessQueue actualHead) { 193 BroadcastProcessQueue test = actualHead; 194 final int N = expected.size(); 195 for (int i = 0; i < N; i++) { 196 final BroadcastProcessQueue expectedPrev = (i > 0) ? expected.get(i - 1) : null; 197 final BroadcastProcessQueue expectedTest = expected.get(i); 198 final BroadcastProcessQueue expectedNext = (i < N - 1) ? expected.get(i + 1) : null; 199 200 assertEquals("prev", expectedPrev, test.runnableAtPrev); 201 assertEquals("test", expectedTest, test); 202 assertEquals("next", expectedNext, test.runnableAtNext); 203 204 test = test.runnableAtNext; 205 } 206 if (N == 0) { 207 assertNull(actualHead); 208 } 209 } 210 makeMockIntent()211 private static Intent makeMockIntent() { 212 return mock(Intent.class); 213 } 214 makeMockManifestReceiver()215 private static ResolveInfo makeMockManifestReceiver() { 216 return mock(ResolveInfo.class); 217 } 218 makeMockRegisteredReceiver()219 private static BroadcastFilter makeMockRegisteredReceiver() { 220 return mock(BroadcastFilter.class); 221 } 222 makeBroadcastRecord(Intent intent)223 private BroadcastRecord makeBroadcastRecord(Intent intent) { 224 return makeBroadcastRecord(intent, BroadcastOptions.makeBasic(), 225 List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN)), false); 226 } 227 makeOrderedBroadcastRecord(Intent intent)228 private BroadcastRecord makeOrderedBroadcastRecord(Intent intent) { 229 return makeBroadcastRecord(intent, BroadcastOptions.makeBasic(), 230 List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN)), true); 231 } 232 makeBroadcastRecord(Intent intent, List receivers)233 private BroadcastRecord makeBroadcastRecord(Intent intent, List receivers) { 234 return makeBroadcastRecord(intent, BroadcastOptions.makeBasic(), receivers, false); 235 } 236 makeBroadcastRecord(Intent intent, BroadcastOptions options)237 private BroadcastRecord makeBroadcastRecord(Intent intent, BroadcastOptions options) { 238 return makeBroadcastRecord(intent, options, 239 List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN)), false); 240 } 241 makeBroadcastRecord(Intent intent, BroadcastOptions options, List receivers, boolean ordered)242 private BroadcastRecord makeBroadcastRecord(Intent intent, BroadcastOptions options, 243 List receivers, boolean ordered) { 244 return makeBroadcastRecord(intent, options, receivers, null, ordered); 245 } 246 makeBroadcastRecord(Intent intent, BroadcastOptions options, List receivers, IIntentReceiver resultTo, boolean ordered)247 private BroadcastRecord makeBroadcastRecord(Intent intent, BroadcastOptions options, 248 List receivers, IIntentReceiver resultTo, boolean ordered) { 249 return new BroadcastRecord(mImpl, intent, mProcess, PACKAGE_RED, null, 21, 42, false, null, 250 null, null, null, AppOpsManager.OP_NONE, options, receivers, null, resultTo, 251 Activity.RESULT_OK, null, null, ordered, false, false, UserHandle.USER_SYSTEM, 252 BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN); 253 } 254 enqueueOrReplaceBroadcast(BroadcastProcessQueue queue, BroadcastRecord record, int recordIndex)255 private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue, 256 BroadcastRecord record, int recordIndex) { 257 enqueueOrReplaceBroadcast(queue, record, recordIndex, 42_000_000L); 258 } 259 enqueueOrReplaceBroadcast(BroadcastProcessQueue queue, BroadcastRecord record, int recordIndex, long enqueueTime)260 private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue, 261 BroadcastRecord record, int recordIndex, long enqueueTime) { 262 queue.enqueueOrReplaceBroadcast(record, recordIndex, (r, i) -> { 263 throw new UnsupportedOperationException(); 264 }); 265 record.enqueueTime = enqueueTime; 266 record.enqueueRealTime = enqueueTime; 267 record.enqueueClockTime = enqueueTime; 268 } 269 270 @Test testRunnableList_Simple()271 public void testRunnableList_Simple() { 272 assertRunnableList(List.of(), mHead); 273 274 mHead = insertIntoRunnableList(mHead, mQueue1); 275 assertRunnableList(List.of(mQueue1), mHead); 276 277 mHead = removeFromRunnableList(mHead, mQueue1); 278 assertRunnableList(List.of(), mHead); 279 } 280 281 @Test testRunnableList_InsertLast()282 public void testRunnableList_InsertLast() { 283 mHead = insertIntoRunnableList(mHead, mQueue1); 284 mHead = insertIntoRunnableList(mHead, mQueue2); 285 mHead = insertIntoRunnableList(mHead, mQueue3); 286 mHead = insertIntoRunnableList(mHead, mQueue4); 287 assertRunnableList(List.of(mQueue1, mQueue2, mQueue3, mQueue4), mHead); 288 } 289 290 @Test testRunnableList_InsertFirst()291 public void testRunnableList_InsertFirst() { 292 mHead = insertIntoRunnableList(mHead, mQueue4); 293 mHead = insertIntoRunnableList(mHead, mQueue3); 294 mHead = insertIntoRunnableList(mHead, mQueue2); 295 mHead = insertIntoRunnableList(mHead, mQueue1); 296 assertRunnableList(List.of(mQueue1, mQueue2, mQueue3, mQueue4), mHead); 297 } 298 299 @Test testRunnableList_InsertMiddle()300 public void testRunnableList_InsertMiddle() { 301 mHead = insertIntoRunnableList(mHead, mQueue1); 302 mHead = insertIntoRunnableList(mHead, mQueue3); 303 mHead = insertIntoRunnableList(mHead, mQueue2); 304 assertRunnableList(List.of(mQueue1, mQueue2, mQueue3), mHead); 305 } 306 307 @Test testRunnableList_Remove()308 public void testRunnableList_Remove() { 309 mHead = insertIntoRunnableList(mHead, mQueue1); 310 mHead = insertIntoRunnableList(mHead, mQueue2); 311 mHead = insertIntoRunnableList(mHead, mQueue3); 312 mHead = insertIntoRunnableList(mHead, mQueue4); 313 314 mHead = removeFromRunnableList(mHead, mQueue3); 315 assertRunnableList(List.of(mQueue1, mQueue2, mQueue4), mHead); 316 317 mHead = removeFromRunnableList(mHead, mQueue1); 318 assertRunnableList(List.of(mQueue2, mQueue4), mHead); 319 320 mHead = removeFromRunnableList(mHead, mQueue4); 321 assertRunnableList(List.of(mQueue2), mHead); 322 323 mHead = removeFromRunnableList(mHead, mQueue2); 324 assertRunnableList(List.of(), mHead); 325 326 // Verify all links cleaned up during removal 327 assertOrphan(mQueue1); 328 assertOrphan(mQueue2); 329 assertOrphan(mQueue3); 330 assertOrphan(mQueue4); 331 } 332 333 @Test testRunnableList_sameRunnableAt()334 public void testRunnableList_sameRunnableAt() { 335 doReturn(2L).when(mQueue1).getRunnableAt(); 336 doReturn(2L).when(mQueue2).getRunnableAt(); 337 doReturn(2L).when(mQueue3).getRunnableAt(); 338 doReturn(2L).when(mQueue4).getRunnableAt(); 339 340 mHead = insertIntoRunnableList(mHead, mQueue1); 341 mHead = insertIntoRunnableList(mHead, mQueue2); 342 mHead = insertIntoRunnableList(mHead, mQueue3); 343 mHead = insertIntoRunnableList(mHead, mQueue4); 344 assertRunnableList(List.of(mQueue1, mQueue2, mQueue3, mQueue4), mHead); 345 } 346 347 @Test testProcessQueue_Complex()348 public void testProcessQueue_Complex() { 349 BroadcastProcessQueue red = mImpl.getOrCreateProcessQueue(PACKAGE_RED, TEST_UID); 350 BroadcastProcessQueue green = mImpl.getOrCreateProcessQueue(PACKAGE_GREEN, TEST_UID); 351 BroadcastProcessQueue blue = mImpl.getOrCreateProcessQueue(PACKAGE_BLUE, TEST_UID); 352 353 assertEquals(PACKAGE_RED, red.processName); 354 assertEquals(PACKAGE_GREEN, green.processName); 355 assertEquals(PACKAGE_BLUE, blue.processName); 356 357 // Verify that removing middle queue works 358 mImpl.removeProcessQueue(PACKAGE_GREEN, TEST_UID); 359 assertEquals(red, mImpl.getProcessQueue(PACKAGE_RED, TEST_UID)); 360 assertNull(mImpl.getProcessQueue(PACKAGE_GREEN, TEST_UID)); 361 assertEquals(blue, mImpl.getProcessQueue(PACKAGE_BLUE, TEST_UID)); 362 assertNull(mImpl.getProcessQueue(PACKAGE_YELLOW, TEST_UID)); 363 364 // Verify that removing head queue works 365 mImpl.removeProcessQueue(PACKAGE_RED, TEST_UID); 366 assertNull(mImpl.getProcessQueue(PACKAGE_RED, TEST_UID)); 367 assertNull(mImpl.getProcessQueue(PACKAGE_GREEN, TEST_UID)); 368 assertEquals(blue, mImpl.getProcessQueue(PACKAGE_BLUE, TEST_UID)); 369 assertNull(mImpl.getProcessQueue(PACKAGE_YELLOW, TEST_UID)); 370 371 // Verify that removing last queue works 372 mImpl.removeProcessQueue(PACKAGE_BLUE, TEST_UID); 373 assertNull(mImpl.getProcessQueue(PACKAGE_RED, TEST_UID)); 374 assertNull(mImpl.getProcessQueue(PACKAGE_GREEN, TEST_UID)); 375 assertNull(mImpl.getProcessQueue(PACKAGE_BLUE, TEST_UID)); 376 assertNull(mImpl.getProcessQueue(PACKAGE_YELLOW, TEST_UID)); 377 378 // Verify that removing missing doesn't crash 379 mImpl.removeProcessQueue(PACKAGE_YELLOW, TEST_UID); 380 381 // Verify that we can start all over again safely 382 BroadcastProcessQueue yellow = mImpl.getOrCreateProcessQueue(PACKAGE_YELLOW, TEST_UID); 383 assertEquals(yellow, mImpl.getProcessQueue(PACKAGE_YELLOW, TEST_UID)); 384 } 385 386 /** 387 * Empty queue isn't runnable. 388 */ 389 @Test testRunnableAt_Empty()390 public void testRunnableAt_Empty() { 391 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 392 PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); 393 assertFalse(queue.isRunnable()); 394 assertEquals(Long.MAX_VALUE, queue.getRunnableAt()); 395 assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); 396 } 397 398 /** 399 * Queue with a "normal" and "deferrable" broadcast is runnable at different times depending 400 * on process cached state; when cached it's delayed indefinitely. 401 */ 402 @Test testRunnableAt_Normal_Deferrable()403 public void testRunnableAt_Normal_Deferrable() { 404 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 405 PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); 406 407 final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 408 final BroadcastOptions options = BroadcastOptions.makeBasic() 409 .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE); 410 final BroadcastRecord airplaneRecord = makeBroadcastRecord(airplane, options, 411 List.of(makeMockRegisteredReceiver()), false); 412 enqueueOrReplaceBroadcast(queue, airplaneRecord, 0); 413 414 queue.setProcessAndUidState(mProcess, false, false); 415 final long notCachedRunnableAt = queue.getRunnableAt(); 416 queue.setProcessAndUidState(mProcess, false, true); 417 final long cachedRunnableAt = queue.getRunnableAt(); 418 assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt); 419 assertFalse(queue.isRunnable()); 420 assertEquals(BroadcastProcessQueue.REASON_CACHED_INFINITE_DEFER, 421 queue.getRunnableAtReason()); 422 assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); 423 } 424 425 /** 426 * Queue with a "normal" broadcast is runnable at different times depending 427 * on process cached state; when cached it's delayed by some amount. 428 */ 429 @Test testRunnableAt_Normal()430 public void testRunnableAt_Normal() { 431 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 432 PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); 433 434 final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 435 final BroadcastOptions options = BroadcastOptions.makeBasic() 436 .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_NONE); 437 final BroadcastRecord airplaneRecord = makeBroadcastRecord(airplane, options, 438 List.of(makeMockRegisteredReceiver()), false); 439 enqueueOrReplaceBroadcast(queue, airplaneRecord, 0); 440 441 queue.setProcessAndUidState(mProcess, false, false); 442 final long notCachedRunnableAt = queue.getRunnableAt(); 443 queue.setProcessAndUidState(mProcess, false, true); 444 final long cachedRunnableAt = queue.getRunnableAt(); 445 assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt); 446 assertTrue(queue.isRunnable()); 447 assertEquals(BroadcastProcessQueue.REASON_CACHED, queue.getRunnableAtReason()); 448 assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); 449 } 450 451 /** 452 * Queue with foreground broadcast is always runnable immediately, 453 * regardless of process cached state. 454 */ 455 @Test testRunnableAt_Foreground()456 public void testRunnableAt_Foreground() { 457 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 458 PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); 459 460 // enqueue a bg-priority broadcast then a fg-priority one 461 final Intent timezone = new Intent(Intent.ACTION_TIMEZONE_CHANGED); 462 final BroadcastRecord timezoneRecord = makeBroadcastRecord(timezone); 463 enqueueOrReplaceBroadcast(queue, timezoneRecord, 0); 464 465 final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 466 airplane.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 467 final BroadcastRecord airplaneRecord = makeBroadcastRecord(airplane); 468 enqueueOrReplaceBroadcast(queue, airplaneRecord, 0); 469 470 // verify that: 471 // (a) the queue is immediately runnable by existence of a fg-priority broadcast 472 // (b) the next one up is the fg-priority broadcast despite its later enqueue time 473 queue.setProcessAndUidState(null, false, false); 474 assertTrue(queue.isRunnable()); 475 assertThat(queue.getRunnableAt()).isAtMost(airplaneRecord.enqueueClockTime); 476 assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); 477 assertEquals(queue.peekNextBroadcastRecord(), airplaneRecord); 478 479 queue.setProcessAndUidState(null, false, true); 480 assertTrue(queue.isRunnable()); 481 assertThat(queue.getRunnableAt()).isAtMost(airplaneRecord.enqueueClockTime); 482 assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); 483 assertEquals(queue.peekNextBroadcastRecord(), airplaneRecord); 484 } 485 486 /** 487 * Queue with ordered broadcast is runnable only once we've made enough 488 * progress on earlier blocking items. 489 */ 490 @Test testRunnableAt_Ordered()491 public void testRunnableAt_Ordered() { 492 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 493 PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); 494 495 final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 496 final BroadcastRecord airplaneRecord = makeBroadcastRecord(airplane, null, 497 List.of(withPriority(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN), 10), 498 withPriority(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN), 0)), true); 499 enqueueOrReplaceBroadcast(queue, airplaneRecord, 1); 500 501 assertFalse(queue.isRunnable()); 502 assertEquals(BroadcastProcessQueue.REASON_BLOCKED, queue.getRunnableAtReason()); 503 504 // Bumping past barrier makes us now runnable 505 airplaneRecord.setDeliveryState(0, BroadcastRecord.DELIVERY_DELIVERED, 506 "testRunnableAt_Ordered"); 507 queue.invalidateRunnableAt(); 508 assertTrue(queue.isRunnable()); 509 assertNotEquals(BroadcastProcessQueue.REASON_BLOCKED, queue.getRunnableAtReason()); 510 } 511 512 /** 513 * Queue with too many pending broadcasts is runnable. 514 */ 515 @Test testRunnableAt_Huge()516 public void testRunnableAt_Huge() { 517 BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 518 PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); 519 520 final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 521 final BroadcastRecord airplaneRecord = makeBroadcastRecord(airplane, 522 List.of(makeMockRegisteredReceiver())); 523 enqueueOrReplaceBroadcast(queue, airplaneRecord, 0); 524 525 mConstants.MAX_PENDING_BROADCASTS = 128; 526 queue.invalidateRunnableAt(); 527 assertThat(queue.getRunnableAt()).isGreaterThan(airplaneRecord.enqueueTime); 528 assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); 529 530 mConstants.MAX_PENDING_BROADCASTS = 1; 531 queue.invalidateRunnableAt(); 532 assertThat(queue.getRunnableAt()).isAtMost(airplaneRecord.enqueueTime); 533 assertEquals(BroadcastProcessQueue.REASON_MAX_PENDING, queue.getRunnableAtReason()); 534 } 535 536 @Test testRunnableAt_uidForeground()537 public void testRunnableAt_uidForeground() { 538 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, PACKAGE_GREEN, 539 getUidForPackage(PACKAGE_GREEN)); 540 541 final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); 542 final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, 543 List.of(makeMockRegisteredReceiver())); 544 enqueueOrReplaceBroadcast(queue, timeTickRecord, 0); 545 546 assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); 547 assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); 548 549 queue.setProcessAndUidState(mProcess, true, false); 550 assertThat(queue.getRunnableAt()).isLessThan(timeTickRecord.enqueueTime); 551 assertEquals(BroadcastProcessQueue.REASON_FOREGROUND, queue.getRunnableAtReason()); 552 553 queue.setProcessAndUidState(mProcess, false, false); 554 assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); 555 assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); 556 } 557 558 @Test testRunnableAt_processTop()559 public void testRunnableAt_processTop() { 560 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, PACKAGE_GREEN, 561 getUidForPackage(PACKAGE_GREEN)); 562 563 doReturn(ActivityManager.PROCESS_STATE_TOP).when(mProcess).getSetProcState(); 564 queue.setProcessAndUidState(mProcess, false, false); 565 566 final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); 567 final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, 568 List.of(makeMockRegisteredReceiver())); 569 enqueueOrReplaceBroadcast(queue, timeTickRecord, 0); 570 571 assertThat(queue.getRunnableAt()).isLessThan(timeTickRecord.enqueueTime); 572 assertEquals(BroadcastProcessQueue.REASON_TOP_PROCESS, queue.getRunnableAtReason()); 573 574 doReturn(ActivityManager.PROCESS_STATE_SERVICE).when(mProcess).getSetProcState(); 575 queue.setProcessAndUidState(mProcess, false, false); 576 577 // The new process state will only be taken into account the next time a broadcast 578 // is sent to the process. 579 enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(timeTick, 580 List.of(makeMockRegisteredReceiver())), 0); 581 assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); 582 assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); 583 } 584 585 @Test testRunnableAt_persistentProc()586 public void testRunnableAt_persistentProc() { 587 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, PACKAGE_GREEN, 588 getUidForPackage(PACKAGE_GREEN)); 589 590 final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); 591 final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, 592 List.of(makeMockRegisteredReceiver())); 593 enqueueOrReplaceBroadcast(queue, timeTickRecord, 0); 594 595 assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); 596 assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); 597 598 doReturn(true).when(mProcess).isPersistent(); 599 queue.setProcessAndUidState(mProcess, false, false); 600 assertThat(queue.getRunnableAt()).isLessThan(timeTickRecord.enqueueTime); 601 assertEquals(BroadcastProcessQueue.REASON_PERSISTENT, queue.getRunnableAtReason()); 602 603 doReturn(false).when(mProcess).isPersistent(); 604 queue.setProcessAndUidState(mProcess, false, false); 605 assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); 606 assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); 607 } 608 609 @Test testRunnableAt_coreUid()610 public void testRunnableAt_coreUid() { 611 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 612 "com.android.bluetooth", Process.BLUETOOTH_UID); 613 614 final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); 615 final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, 616 List.of(makeMockRegisteredReceiver())); 617 enqueueOrReplaceBroadcast(queue, timeTickRecord, 0); 618 619 assertThat(queue.getRunnableAt()).isEqualTo(timeTickRecord.enqueueTime); 620 assertEquals(BroadcastProcessQueue.REASON_CORE_UID, queue.getRunnableAtReason()); 621 } 622 623 @Test testRunnableAt_freezableCoreUid()624 public void testRunnableAt_freezableCoreUid() { 625 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 626 "com.android.bluetooth", Process.BLUETOOTH_UID); 627 628 // Mark the process as freezable 629 queue.setProcessAndUidState(mProcess, false, true); 630 final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); 631 final BroadcastOptions options = BroadcastOptions.makeWithDeferUntilActive(true); 632 final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, options, 633 List.of(makeMockRegisteredReceiver()), false); 634 enqueueOrReplaceBroadcast(queue, timeTickRecord, 0); 635 636 assertEquals(Long.MAX_VALUE, queue.getRunnableAt()); 637 assertEquals(BroadcastProcessQueue.REASON_CACHED_INFINITE_DEFER, 638 queue.getRunnableAtReason()); 639 640 queue.setProcessAndUidState(mProcess, false, false); 641 assertThat(queue.getRunnableAt()).isEqualTo(timeTickRecord.enqueueTime); 642 assertEquals(BroadcastProcessQueue.REASON_CORE_UID, queue.getRunnableAtReason()); 643 } 644 645 /** 646 * Verify that a cached process that would normally be delayed becomes 647 * immediately runnable when the given broadcast is enqueued. 648 */ doRunnableAt_Cached(BroadcastRecord testRecord, int testRunnableAtReason)649 private void doRunnableAt_Cached(BroadcastRecord testRecord, int testRunnableAtReason) { 650 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 651 PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); 652 queue.setProcessAndUidState(null, false, true); 653 654 final BroadcastRecord lazyRecord = makeBroadcastRecord( 655 new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED), 656 List.of(makeMockRegisteredReceiver())); 657 658 enqueueOrReplaceBroadcast(queue, lazyRecord, 0); 659 assertThat(queue.getRunnableAt()).isGreaterThan(lazyRecord.enqueueTime); 660 assertThat(queue.getRunnableAtReason()).isNotEqualTo(testRunnableAtReason); 661 662 enqueueOrReplaceBroadcast(queue, testRecord, 0); 663 assertThat(queue.getRunnableAt()).isAtMost(testRecord.enqueueTime); 664 assertThat(queue.getRunnableAtReason()).isEqualTo(testRunnableAtReason); 665 } 666 667 @Test testRunnableAt_Cached_Manifest()668 public void testRunnableAt_Cached_Manifest() { 669 doRunnableAt_Cached(makeBroadcastRecord(makeMockIntent(), null, 670 List.of(makeMockManifestReceiver()), null, false), REASON_CONTAINS_MANIFEST); 671 } 672 673 @Test testRunnableAt_Cached_Ordered()674 public void testRunnableAt_Cached_Ordered() { 675 doRunnableAt_Cached(makeBroadcastRecord(makeMockIntent(), null, 676 List.of(makeMockRegisteredReceiver()), null, true), REASON_CONTAINS_ORDERED); 677 } 678 679 @Test testRunnableAt_Cached_Foreground()680 public void testRunnableAt_Cached_Foreground() { 681 final Intent foregroundIntent = new Intent(); 682 foregroundIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 683 doRunnableAt_Cached(makeBroadcastRecord(foregroundIntent, null, 684 List.of(makeMockRegisteredReceiver()), null, false), REASON_CONTAINS_FOREGROUND); 685 } 686 687 @Test testRunnableAt_Cached_Interactive()688 public void testRunnableAt_Cached_Interactive() { 689 final BroadcastOptions options = BroadcastOptions.makeBasic(); 690 options.setInteractive(true); 691 doRunnableAt_Cached(makeBroadcastRecord(makeMockIntent(), options, 692 List.of(makeMockRegisteredReceiver()), null, false), REASON_CONTAINS_INTERACTIVE); 693 } 694 695 @Test testRunnableAt_Cached_Alarm()696 public void testRunnableAt_Cached_Alarm() { 697 final BroadcastOptions options = BroadcastOptions.makeBasic(); 698 options.setAlarmBroadcast(true); 699 doRunnableAt_Cached(makeBroadcastRecord(makeMockIntent(), options, 700 List.of(makeMockRegisteredReceiver()), null, false), REASON_CONTAINS_ALARM); 701 } 702 703 @Test testRunnableAt_Cached_Prioritized_NonDeferrable()704 public void testRunnableAt_Cached_Prioritized_NonDeferrable() { 705 final List receivers = List.of( 706 withPriority(makeManifestReceiver(PACKAGE_RED, PACKAGE_RED), 10), 707 withPriority(makeManifestReceiver(PACKAGE_GREEN, PACKAGE_GREEN), -10)); 708 final BroadcastOptions options = BroadcastOptions.makeBasic() 709 .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_NONE); 710 doRunnableAt_Cached(makeBroadcastRecord(makeMockIntent(), options, 711 receivers, null, false), REASON_CONTAINS_PRIORITIZED); 712 } 713 714 /** 715 * Confirm that we always prefer running pending items marked as "urgent", 716 * then "normal", then "offload", dispatching by the relative ordering 717 * within each of those clustering groups. 718 */ 719 @Test testMakeActiveNextPending()720 public void testMakeActiveNextPending() { 721 BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 722 PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); 723 724 enqueueOrReplaceBroadcast(queue, 725 makeBroadcastRecord(new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED) 726 .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0); 727 enqueueOrReplaceBroadcast(queue, 728 makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 0); 729 enqueueOrReplaceBroadcast(queue, 730 makeBroadcastRecord(new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED) 731 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0); 732 enqueueOrReplaceBroadcast(queue, 733 makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED) 734 .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0); 735 enqueueOrReplaceBroadcast(queue, 736 makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0); 737 enqueueOrReplaceBroadcast(queue, 738 makeBroadcastRecord(new Intent(Intent.ACTION_LOCALE_CHANGED) 739 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0); 740 741 queue.makeActiveNextPending(); 742 assertEquals(Intent.ACTION_LOCKED_BOOT_COMPLETED, queue.getActive().intent.getAction()); 743 744 // To maximize test coverage, dump current state; we're not worried 745 // about the actual output, just that we don't crash 746 queue.getActive().setDeliveryState(0, BroadcastRecord.DELIVERY_SCHEDULED, "Test-driven"); 747 queue.dumpLocked(SystemClock.uptimeMillis(), 748 new IndentingPrintWriter(new PrintWriter(Writer.nullWriter()))); 749 750 queue.makeActiveNextPending(); 751 assertEquals(Intent.ACTION_LOCALE_CHANGED, queue.getActive().intent.getAction()); 752 queue.makeActiveNextPending(); 753 assertEquals(Intent.ACTION_TIMEZONE_CHANGED, queue.getActive().intent.getAction()); 754 queue.makeActiveNextPending(); 755 assertEquals(Intent.ACTION_TIME_TICK, queue.getActive().intent.getAction()); 756 queue.makeActiveNextPending(); 757 assertEquals(Intent.ACTION_AIRPLANE_MODE_CHANGED, queue.getActive().intent.getAction()); 758 queue.makeActiveNextPending(); 759 assertEquals(Intent.ACTION_ALARM_CHANGED, queue.getActive().intent.getAction()); 760 assertTrue(queue.isEmpty()); 761 } 762 763 /** 764 * Verify that we don't let urgent broadcasts starve delivery of non-urgent 765 */ 766 @Test testUrgentStarvation()767 public void testUrgentStarvation() { 768 final BroadcastOptions optInteractive = BroadcastOptions.makeBasic(); 769 optInteractive.setInteractive(true); 770 771 mConstants.MAX_CONSECUTIVE_URGENT_DISPATCHES = 2; 772 BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 773 PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); 774 long timeCounter = 100; 775 776 // mix of broadcasts, with more than 2 fg/urgent 777 enqueueOrReplaceBroadcast(queue, 778 makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 779 0, timeCounter++); 780 enqueueOrReplaceBroadcast(queue, 781 makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 782 0, timeCounter++); 783 enqueueOrReplaceBroadcast(queue, 784 makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0, timeCounter++); 785 enqueueOrReplaceBroadcast(queue, 786 makeBroadcastRecord(new Intent(Intent.ACTION_LOCALE_CHANGED) 787 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); 788 enqueueOrReplaceBroadcast(queue, 789 makeBroadcastRecord(new Intent(Intent.ACTION_APPLICATION_PREFERENCES), 790 optInteractive), 0, timeCounter++); 791 enqueueOrReplaceBroadcast(queue, 792 makeBroadcastRecord(new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE), 793 optInteractive), 0, timeCounter++); 794 enqueueOrReplaceBroadcast(queue, 795 makeBroadcastRecord(new Intent(Intent.ACTION_INPUT_METHOD_CHANGED) 796 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); 797 enqueueOrReplaceBroadcast(queue, 798 makeBroadcastRecord(new Intent(Intent.ACTION_NEW_OUTGOING_CALL), 799 optInteractive), 0, timeCounter++); 800 801 queue.makeActiveNextPending(); 802 assertEquals(Intent.ACTION_LOCALE_CHANGED, queue.getActive().intent.getAction()); 803 queue.makeActiveNextPending(); 804 assertEquals(Intent.ACTION_APPLICATION_PREFERENCES, queue.getActive().intent.getAction()); 805 // after MAX_CONSECUTIVE_URGENT_DISPATCHES expect an ordinary one next 806 queue.makeActiveNextPending(); 807 assertEquals(Intent.ACTION_TIMEZONE_CHANGED, queue.getActive().intent.getAction()); 808 // and then back to prioritizing urgent ones 809 queue.makeActiveNextPending(); 810 assertEquals(AppWidgetManager.ACTION_APPWIDGET_UPDATE, 811 queue.getActive().intent.getAction()); 812 queue.makeActiveNextPending(); 813 assertEquals(Intent.ACTION_INPUT_METHOD_CHANGED, queue.getActive().intent.getAction()); 814 // verify the reset-count-then-resume worked too 815 queue.makeActiveNextPending(); 816 assertEquals(Intent.ACTION_ALARM_CHANGED, queue.getActive().intent.getAction()); 817 } 818 819 /** 820 * Verify that offload broadcasts are not starved because of broadcasts in higher priority 821 * queues. 822 */ 823 @Test testOffloadStarvation()824 public void testOffloadStarvation() { 825 final BroadcastOptions optInteractive = BroadcastOptions.makeBasic(); 826 optInteractive.setInteractive(true); 827 828 mConstants.MAX_CONSECUTIVE_URGENT_DISPATCHES = 1; 829 mConstants.MAX_CONSECUTIVE_NORMAL_DISPATCHES = 2; 830 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 831 PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); 832 long timeCounter = 100; 833 834 // mix of broadcasts, with more than 2 normal 835 enqueueOrReplaceBroadcast(queue, 836 makeBroadcastRecord(new Intent(Intent.ACTION_BOOT_COMPLETED) 837 .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); 838 enqueueOrReplaceBroadcast(queue, 839 makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 840 0, timeCounter++); 841 enqueueOrReplaceBroadcast(queue, 842 makeBroadcastRecord(new Intent(Intent.ACTION_PACKAGE_CHANGED) 843 .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); 844 enqueueOrReplaceBroadcast(queue, 845 makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 846 0, timeCounter++); 847 enqueueOrReplaceBroadcast(queue, 848 makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 0, timeCounter++); 849 enqueueOrReplaceBroadcast(queue, 850 makeBroadcastRecord(new Intent(Intent.ACTION_LOCALE_CHANGED) 851 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); 852 enqueueOrReplaceBroadcast(queue, 853 makeBroadcastRecord(new Intent(Intent.ACTION_APPLICATION_PREFERENCES), 854 optInteractive), 0, timeCounter++); 855 enqueueOrReplaceBroadcast(queue, 856 makeBroadcastRecord(new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE), 857 optInteractive), 0, timeCounter++); 858 enqueueOrReplaceBroadcast(queue, 859 makeBroadcastRecord(new Intent(Intent.ACTION_INPUT_METHOD_CHANGED) 860 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); 861 enqueueOrReplaceBroadcast(queue, 862 makeBroadcastRecord(new Intent(Intent.ACTION_NEW_OUTGOING_CALL), 863 optInteractive), 0, timeCounter++); 864 865 queue.makeActiveNextPending(); 866 assertEquals(Intent.ACTION_LOCALE_CHANGED, queue.getActive().intent.getAction()); 867 // after MAX_CONSECUTIVE_URGENT_DISPATCHES expect an ordinary one next 868 queue.makeActiveNextPending(); 869 assertEquals(Intent.ACTION_TIMEZONE_CHANGED, queue.getActive().intent.getAction()); 870 // and then back to prioritizing urgent ones 871 queue.makeActiveNextPending(); 872 assertEquals(Intent.ACTION_APPLICATION_PREFERENCES, queue.getActive().intent.getAction()); 873 // after MAX_CONSECUTIVE_URGENT_DISPATCHES, again an ordinary one next 874 queue.makeActiveNextPending(); 875 assertEquals(Intent.ACTION_ALARM_CHANGED, queue.getActive().intent.getAction()); 876 // and then back to prioritizing urgent ones 877 queue.makeActiveNextPending(); 878 assertEquals(AppWidgetManager.ACTION_APPWIDGET_UPDATE, 879 queue.getActive().intent.getAction()); 880 // after MAX_CONSECUTIVE_URGENT_DISPATCHES and MAX_CONSECUTIVE_NORMAL_DISPATCHES, 881 // expect an offload one 882 queue.makeActiveNextPending(); 883 assertEquals(Intent.ACTION_BOOT_COMPLETED, queue.getActive().intent.getAction()); 884 // and then back to prioritizing urgent ones 885 queue.makeActiveNextPending(); 886 assertEquals(Intent.ACTION_INPUT_METHOD_CHANGED, queue.getActive().intent.getAction()); 887 } 888 889 /** 890 * Verify that BroadcastProcessQueue#setPrioritizeEarliest() works as expected. 891 */ 892 @Test testPrioritizeEarliest()893 public void testPrioritizeEarliest() { 894 final BroadcastOptions optInteractive = BroadcastOptions.makeBasic(); 895 optInteractive.setInteractive(true); 896 897 BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 898 PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); 899 queue.addPrioritizeEarliestRequest(); 900 long timeCounter = 100; 901 902 enqueueOrReplaceBroadcast(queue, 903 makeBroadcastRecord(new Intent(Intent.ACTION_BOOT_COMPLETED) 904 .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); 905 enqueueOrReplaceBroadcast(queue, 906 makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 907 0, timeCounter++); 908 enqueueOrReplaceBroadcast(queue, 909 makeBroadcastRecord(new Intent(Intent.ACTION_PACKAGE_CHANGED) 910 .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); 911 enqueueOrReplaceBroadcast(queue, 912 makeBroadcastRecord(new Intent(Intent.ACTION_ALARM_CHANGED)), 913 0, timeCounter++); 914 enqueueOrReplaceBroadcast(queue, 915 makeBroadcastRecord(new Intent(Intent.ACTION_TIME_TICK)), 916 0, timeCounter++); 917 enqueueOrReplaceBroadcast(queue, 918 makeBroadcastRecord(new Intent(Intent.ACTION_LOCALE_CHANGED) 919 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); 920 enqueueOrReplaceBroadcast(queue, 921 makeBroadcastRecord(new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE), 922 optInteractive), 0, timeCounter++); 923 924 // When we mark BroadcastProcessQueue to prioritize earliest, we should 925 // expect to dispatch broadcasts in the order they were enqueued 926 queue.makeActiveNextPending(); 927 assertEquals(Intent.ACTION_BOOT_COMPLETED, queue.getActive().intent.getAction()); 928 queue.makeActiveNextPending(); 929 assertEquals(Intent.ACTION_TIMEZONE_CHANGED, queue.getActive().intent.getAction()); 930 // after MAX_CONSECUTIVE_URGENT_DISPATCHES expect an ordinary one next 931 queue.makeActiveNextPending(); 932 assertEquals(Intent.ACTION_PACKAGE_CHANGED, queue.getActive().intent.getAction()); 933 // and then back to prioritizing urgent ones 934 queue.makeActiveNextPending(); 935 assertEquals(Intent.ACTION_ALARM_CHANGED, queue.getActive().intent.getAction()); 936 queue.makeActiveNextPending(); 937 assertEquals(Intent.ACTION_TIME_TICK, queue.getActive().intent.getAction()); 938 queue.makeActiveNextPending(); 939 assertEquals(Intent.ACTION_LOCALE_CHANGED, queue.getActive().intent.getAction()); 940 // verify the reset-count-then-resume worked too 941 queue.makeActiveNextPending(); 942 assertEquals(AppWidgetManager.ACTION_APPWIDGET_UPDATE, 943 queue.getActive().intent.getAction()); 944 945 946 queue.removePrioritizeEarliestRequest(); 947 948 enqueueOrReplaceBroadcast(queue, 949 makeBroadcastRecord(new Intent(Intent.ACTION_BOOT_COMPLETED) 950 .addFlags(Intent.FLAG_RECEIVER_OFFLOAD)), 0, timeCounter++); 951 enqueueOrReplaceBroadcast(queue, 952 makeBroadcastRecord(new Intent(Intent.ACTION_TIMEZONE_CHANGED)), 953 0, timeCounter++); 954 enqueueOrReplaceBroadcast(queue, 955 makeBroadcastRecord(new Intent(Intent.ACTION_LOCALE_CHANGED) 956 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)), 0, timeCounter++); 957 958 // Once the request to prioritize earliest is removed, we should expect broadcasts 959 // to be dispatched in the order of foreground, normal and then offload. 960 queue.makeActiveNextPending(); 961 assertEquals(Intent.ACTION_LOCALE_CHANGED, queue.getActive().intent.getAction()); 962 queue.makeActiveNextPending(); 963 assertEquals(Intent.ACTION_TIMEZONE_CHANGED, queue.getActive().intent.getAction()); 964 queue.makeActiveNextPending(); 965 assertEquals(Intent.ACTION_BOOT_COMPLETED, queue.getActive().intent.getAction()); 966 } 967 968 /** 969 * Verify that sending a broadcast with DELIVERY_GROUP_POLICY_MOST_RECENT works as expected. 970 */ 971 @Test testDeliveryGroupPolicy_mostRecent()972 public void testDeliveryGroupPolicy_mostRecent() { 973 final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); 974 final BroadcastOptions optionsTimeTick = BroadcastOptions.makeBasic(); 975 optionsTimeTick.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT); 976 977 final Intent musicVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION); 978 musicVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, 979 AudioManager.STREAM_MUSIC); 980 final BroadcastOptions optionsMusicVolumeChanged = BroadcastOptions.makeBasic(); 981 optionsMusicVolumeChanged.setDeliveryGroupPolicy( 982 BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT); 983 optionsMusicVolumeChanged.setDeliveryGroupMatchingKey("audio", 984 String.valueOf(AudioManager.STREAM_MUSIC)); 985 986 final Intent alarmVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION); 987 alarmVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, 988 AudioManager.STREAM_ALARM); 989 final BroadcastOptions optionsAlarmVolumeChanged = BroadcastOptions.makeBasic(); 990 optionsAlarmVolumeChanged.setDeliveryGroupPolicy( 991 BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT); 992 optionsAlarmVolumeChanged.setDeliveryGroupMatchingKey("audio", 993 String.valueOf(AudioManager.STREAM_ALARM)); 994 995 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(timeTick, optionsTimeTick)); 996 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(musicVolumeChanged, 997 optionsMusicVolumeChanged)); 998 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(alarmVolumeChanged, 999 optionsAlarmVolumeChanged)); 1000 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(musicVolumeChanged, 1001 optionsMusicVolumeChanged)); 1002 1003 final BroadcastProcessQueue queue = mImpl.getProcessQueue(PACKAGE_GREEN, 1004 getUidForPackage(PACKAGE_GREEN)); 1005 // Verify that the older musicVolumeChanged has been removed. 1006 verifyPendingRecords(queue, 1007 List.of(timeTick, alarmVolumeChanged, musicVolumeChanged)); 1008 1009 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(timeTick, optionsTimeTick)); 1010 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(alarmVolumeChanged, 1011 optionsAlarmVolumeChanged)); 1012 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(musicVolumeChanged, 1013 optionsMusicVolumeChanged)); 1014 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(alarmVolumeChanged, 1015 optionsAlarmVolumeChanged)); 1016 // Verify that the older alarmVolumeChanged has been removed. 1017 verifyPendingRecords(queue, 1018 List.of(timeTick, musicVolumeChanged, alarmVolumeChanged)); 1019 1020 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(timeTick, optionsTimeTick)); 1021 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(musicVolumeChanged, 1022 optionsMusicVolumeChanged)); 1023 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(alarmVolumeChanged, 1024 optionsAlarmVolumeChanged)); 1025 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(timeTick, optionsTimeTick)); 1026 // Verify that the older timeTick has been removed. 1027 verifyPendingRecords(queue, 1028 List.of(musicVolumeChanged, alarmVolumeChanged, timeTick)); 1029 } 1030 1031 @Test testDeliveryGroupPolicy_diffReceivers()1032 public void testDeliveryGroupPolicy_diffReceivers() { 1033 final Intent screenOn = new Intent(Intent.ACTION_SCREEN_ON); 1034 final Intent screenOff = new Intent(Intent.ACTION_SCREEN_OFF); 1035 final BroadcastOptions screenOnOffOptions = BroadcastOptions.makeBasic() 1036 .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) 1037 .setDeliveryGroupMatchingKey("screenOnOff", Intent.ACTION_SCREEN_ON); 1038 1039 final Object greenReceiver = makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN); 1040 final Object redReceiver = makeManifestReceiver(PACKAGE_RED, CLASS_RED); 1041 final Object blueReceiver = makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE); 1042 1043 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, screenOnOffOptions, 1044 List.of(greenReceiver, blueReceiver), false)); 1045 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, screenOnOffOptions, 1046 List.of(greenReceiver, redReceiver, blueReceiver), false)); 1047 final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN, 1048 getUidForPackage(PACKAGE_GREEN)); 1049 final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED, 1050 getUidForPackage(PACKAGE_RED)); 1051 final BroadcastProcessQueue blueQueue = mImpl.getProcessQueue(PACKAGE_BLUE, 1052 getUidForPackage(PACKAGE_BLUE)); 1053 verifyPendingRecords(greenQueue, List.of(screenOff)); 1054 verifyPendingRecords(redQueue, List.of(screenOff)); 1055 verifyPendingRecords(blueQueue, List.of(screenOff)); 1056 1057 assertTrue(greenQueue.isEmpty()); 1058 assertTrue(redQueue.isEmpty()); 1059 assertTrue(blueQueue.isEmpty()); 1060 1061 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, screenOnOffOptions, 1062 List.of(greenReceiver, redReceiver, blueReceiver), false)); 1063 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, screenOnOffOptions, 1064 List.of(greenReceiver, blueReceiver), false)); 1065 verifyPendingRecords(greenQueue, List.of(screenOn)); 1066 verifyPendingRecords(redQueue, List.of(screenOff)); 1067 verifyPendingRecords(blueQueue, List.of(screenOn)); 1068 } 1069 1070 @Test testDeliveryGroupPolicy_ordered_diffReceivers()1071 public void testDeliveryGroupPolicy_ordered_diffReceivers() { 1072 final Intent screenOn = new Intent(Intent.ACTION_SCREEN_ON); 1073 final Intent screenOff = new Intent(Intent.ACTION_SCREEN_OFF); 1074 final BroadcastOptions screenOnOffOptions = BroadcastOptions.makeBasic() 1075 .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) 1076 .setDeliveryGroupMatchingKey("screenOnOff", Intent.ACTION_SCREEN_ON); 1077 1078 final Object greenReceiver = makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN); 1079 final Object redReceiver = makeManifestReceiver(PACKAGE_RED, CLASS_RED); 1080 final Object blueReceiver = makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE); 1081 1082 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, screenOnOffOptions, 1083 List.of(greenReceiver, blueReceiver), true)); 1084 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, screenOnOffOptions, 1085 List.of(greenReceiver, redReceiver, blueReceiver), true)); 1086 final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN, 1087 getUidForPackage(PACKAGE_GREEN)); 1088 final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED, 1089 getUidForPackage(PACKAGE_RED)); 1090 final BroadcastProcessQueue blueQueue = mImpl.getProcessQueue(PACKAGE_BLUE, 1091 getUidForPackage(PACKAGE_BLUE)); 1092 verifyPendingRecords(greenQueue, List.of(screenOff)); 1093 verifyPendingRecords(redQueue, List.of(screenOff)); 1094 verifyPendingRecords(blueQueue, List.of(screenOff)); 1095 1096 assertTrue(greenQueue.isEmpty()); 1097 assertTrue(redQueue.isEmpty()); 1098 assertTrue(blueQueue.isEmpty()); 1099 1100 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, screenOnOffOptions, 1101 List.of(greenReceiver, redReceiver, blueReceiver), true)); 1102 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, screenOnOffOptions, 1103 List.of(greenReceiver, blueReceiver), true)); 1104 verifyPendingRecords(greenQueue, List.of(screenOff, screenOn)); 1105 verifyPendingRecords(redQueue, List.of(screenOff)); 1106 verifyPendingRecords(blueQueue, List.of(screenOff, screenOn)); 1107 } 1108 1109 @Test testDeliveryGroupPolicy_resultTo_diffReceivers()1110 public void testDeliveryGroupPolicy_resultTo_diffReceivers() { 1111 final Intent screenOn = new Intent(Intent.ACTION_SCREEN_ON); 1112 final Intent screenOff = new Intent(Intent.ACTION_SCREEN_OFF); 1113 final BroadcastOptions screenOnOffOptions = BroadcastOptions.makeBasic() 1114 .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) 1115 .setDeliveryGroupMatchingKey("screenOnOff", Intent.ACTION_SCREEN_ON); 1116 1117 final Object greenReceiver = makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN); 1118 final Object redReceiver = makeManifestReceiver(PACKAGE_RED, CLASS_RED); 1119 final Object blueReceiver = makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE); 1120 final IIntentReceiver resultTo = mock(IIntentReceiver.class); 1121 1122 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, screenOnOffOptions, 1123 List.of(greenReceiver, blueReceiver), resultTo, false)); 1124 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, screenOnOffOptions, 1125 List.of(greenReceiver, redReceiver, blueReceiver), resultTo, false)); 1126 final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN, 1127 getUidForPackage(PACKAGE_GREEN)); 1128 final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED, 1129 getUidForPackage(PACKAGE_RED)); 1130 final BroadcastProcessQueue blueQueue = mImpl.getProcessQueue(PACKAGE_BLUE, 1131 getUidForPackage(PACKAGE_BLUE)); 1132 verifyPendingRecords(greenQueue, List.of(screenOff)); 1133 verifyPendingRecords(redQueue, List.of(screenOff)); 1134 verifyPendingRecords(blueQueue, List.of(screenOff)); 1135 1136 assertTrue(greenQueue.isEmpty()); 1137 assertTrue(redQueue.isEmpty()); 1138 assertTrue(blueQueue.isEmpty()); 1139 1140 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, screenOnOffOptions, 1141 List.of(greenReceiver, redReceiver, blueReceiver), resultTo, false)); 1142 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, screenOnOffOptions, 1143 List.of(greenReceiver, blueReceiver), resultTo, false)); 1144 verifyPendingRecords(greenQueue, List.of(screenOff, screenOn)); 1145 verifyPendingRecords(redQueue, List.of(screenOff)); 1146 verifyPendingRecords(blueQueue, List.of(screenOff, screenOn)); 1147 1148 final BroadcastRecord screenOffRecord = makeBroadcastRecord(screenOff, screenOnOffOptions, 1149 List.of(greenReceiver, redReceiver, blueReceiver), resultTo, false); 1150 screenOffRecord.setDeliveryState(2, BroadcastRecord.DELIVERY_DEFERRED, 1151 "testDeliveryGroupPolicy_resultTo_diffReceivers"); 1152 mImpl.enqueueBroadcastLocked(screenOffRecord); 1153 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, screenOnOffOptions, 1154 List.of(greenReceiver, blueReceiver), resultTo, false)); 1155 verifyPendingRecords(greenQueue, List.of(screenOff, screenOn)); 1156 verifyPendingRecords(redQueue, List.of(screenOff)); 1157 verifyPendingRecords(blueQueue, List.of(screenOn)); 1158 } 1159 1160 @Test testDeliveryGroupPolicy_prioritized_diffReceivers()1161 public void testDeliveryGroupPolicy_prioritized_diffReceivers() { 1162 final Intent screenOn = new Intent(Intent.ACTION_SCREEN_ON); 1163 final Intent screenOff = new Intent(Intent.ACTION_SCREEN_OFF); 1164 final BroadcastOptions screenOnOffOptions = BroadcastOptions.makeBasic() 1165 .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) 1166 .setDeliveryGroupMatchingKey("screenOnOff", Intent.ACTION_SCREEN_ON); 1167 1168 final Object greenReceiver = withPriority( 1169 makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN), 10); 1170 final Object redReceiver = withPriority( 1171 makeManifestReceiver(PACKAGE_RED, CLASS_RED), 5); 1172 final Object blueReceiver = withPriority( 1173 makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE), 0); 1174 1175 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, screenOnOffOptions, 1176 List.of(greenReceiver, blueReceiver), false)); 1177 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, screenOnOffOptions, 1178 List.of(greenReceiver, redReceiver, blueReceiver), false)); 1179 final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN, 1180 getUidForPackage(PACKAGE_GREEN)); 1181 final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED, 1182 getUidForPackage(PACKAGE_RED)); 1183 final BroadcastProcessQueue blueQueue = mImpl.getProcessQueue(PACKAGE_BLUE, 1184 getUidForPackage(PACKAGE_BLUE)); 1185 verifyPendingRecords(greenQueue, List.of(screenOff)); 1186 verifyPendingRecords(redQueue, List.of(screenOff)); 1187 verifyPendingRecords(blueQueue, List.of(screenOff)); 1188 1189 assertTrue(greenQueue.isEmpty()); 1190 assertTrue(redQueue.isEmpty()); 1191 assertTrue(blueQueue.isEmpty()); 1192 1193 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, screenOnOffOptions, 1194 List.of(greenReceiver, redReceiver, blueReceiver), false)); 1195 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, screenOnOffOptions, 1196 List.of(greenReceiver, blueReceiver), false)); 1197 verifyPendingRecords(greenQueue, List.of(screenOff, screenOn)); 1198 verifyPendingRecords(redQueue, List.of(screenOff)); 1199 verifyPendingRecords(blueQueue, List.of(screenOff, screenOn)); 1200 } 1201 1202 /** 1203 * Verify that sending a broadcast with DELIVERY_GROUP_POLICY_MERGED works as expected. 1204 */ 1205 @Test testDeliveryGroupPolicy_merged()1206 public void testDeliveryGroupPolicy_merged() { 1207 final BundleMerger extrasMerger = new BundleMerger(); 1208 extrasMerger.setMergeStrategy(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, 1209 BundleMerger.STRATEGY_ARRAY_APPEND); 1210 1211 final Intent packageChangedForUid = createPackageChangedIntent(TEST_UID, 1212 List.of("com.testuid.component1")); 1213 final BroadcastOptions optionsPackageChangedForUid = BroadcastOptions.makeBasic(); 1214 optionsPackageChangedForUid.setDeliveryGroupPolicy( 1215 BroadcastOptions.DELIVERY_GROUP_POLICY_MERGED); 1216 optionsPackageChangedForUid.setDeliveryGroupMatchingKey("package", 1217 String.valueOf(TEST_UID)); 1218 optionsPackageChangedForUid.setDeliveryGroupExtrasMerger(extrasMerger); 1219 1220 final Intent secondPackageChangedForUid = createPackageChangedIntent(TEST_UID, 1221 List.of("com.testuid.component2", "com.testuid.component3")); 1222 1223 final Intent packageChangedForUid2 = createPackageChangedIntent(TEST_UID2, 1224 List.of("com.testuid2.component1")); 1225 final BroadcastOptions optionsPackageChangedForUid2 = BroadcastOptions.makeBasic(); 1226 optionsPackageChangedForUid.setDeliveryGroupPolicy( 1227 BroadcastOptions.DELIVERY_GROUP_POLICY_MERGED); 1228 optionsPackageChangedForUid.setDeliveryGroupMatchingKey("package", 1229 String.valueOf(TEST_UID2)); 1230 optionsPackageChangedForUid.setDeliveryGroupExtrasMerger(extrasMerger); 1231 1232 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(packageChangedForUid, 1233 optionsPackageChangedForUid)); 1234 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(packageChangedForUid2, 1235 optionsPackageChangedForUid2)); 1236 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(secondPackageChangedForUid, 1237 optionsPackageChangedForUid)); 1238 1239 final BroadcastProcessQueue queue = mImpl.getProcessQueue(PACKAGE_GREEN, 1240 getUidForPackage(PACKAGE_GREEN)); 1241 final Intent expectedPackageChangedForUid = createPackageChangedIntent(TEST_UID, 1242 List.of("com.testuid.component2", "com.testuid.component3", 1243 "com.testuid.component1")); 1244 // Verify that packageChangedForUid and secondPackageChangedForUid broadcasts 1245 // have been merged. 1246 verifyPendingRecords(queue, List.of(packageChangedForUid2, expectedPackageChangedForUid)); 1247 } 1248 1249 @Test testDeliveryGroupPolicy_matchingFilter()1250 public void testDeliveryGroupPolicy_matchingFilter() { 1251 final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); 1252 final BroadcastOptions optionsTimeTick = BroadcastOptions.makeBasic(); 1253 optionsTimeTick.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT); 1254 1255 final Intent musicVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION); 1256 musicVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, 1257 AudioManager.STREAM_MUSIC); 1258 final IntentFilter filterMusicVolumeChanged = new IntentFilter( 1259 AudioManager.VOLUME_CHANGED_ACTION); 1260 filterMusicVolumeChanged.addExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, 1261 AudioManager.STREAM_MUSIC); 1262 final BroadcastOptions optionsMusicVolumeChanged = BroadcastOptions.makeBasic(); 1263 optionsMusicVolumeChanged.setDeliveryGroupPolicy( 1264 BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT); 1265 optionsMusicVolumeChanged.setDeliveryGroupMatchingFilter(filterMusicVolumeChanged); 1266 1267 final Intent alarmVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION); 1268 alarmVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, 1269 AudioManager.STREAM_ALARM); 1270 final IntentFilter filterAlarmVolumeChanged = new IntentFilter( 1271 AudioManager.VOLUME_CHANGED_ACTION); 1272 filterAlarmVolumeChanged.addExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, 1273 AudioManager.STREAM_ALARM); 1274 final BroadcastOptions optionsAlarmVolumeChanged = BroadcastOptions.makeBasic(); 1275 optionsAlarmVolumeChanged.setDeliveryGroupPolicy( 1276 BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT); 1277 optionsAlarmVolumeChanged.setDeliveryGroupMatchingFilter(filterAlarmVolumeChanged); 1278 1279 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(timeTick, optionsTimeTick)); 1280 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(musicVolumeChanged, 1281 optionsMusicVolumeChanged)); 1282 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(alarmVolumeChanged, 1283 optionsAlarmVolumeChanged)); 1284 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(musicVolumeChanged, 1285 optionsMusicVolumeChanged)); 1286 1287 final BroadcastProcessQueue queue = mImpl.getProcessQueue(PACKAGE_GREEN, 1288 getUidForPackage(PACKAGE_GREEN)); 1289 // Verify that the older musicVolumeChanged has been removed. 1290 verifyPendingRecords(queue, 1291 List.of(timeTick, alarmVolumeChanged, musicVolumeChanged)); 1292 1293 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(timeTick, optionsTimeTick)); 1294 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(alarmVolumeChanged, 1295 optionsAlarmVolumeChanged)); 1296 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(musicVolumeChanged, 1297 optionsMusicVolumeChanged)); 1298 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(alarmVolumeChanged, 1299 optionsAlarmVolumeChanged)); 1300 // Verify that the older alarmVolumeChanged has been removed. 1301 verifyPendingRecords(queue, 1302 List.of(timeTick, musicVolumeChanged, alarmVolumeChanged)); 1303 1304 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(timeTick, optionsTimeTick)); 1305 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(musicVolumeChanged, 1306 optionsMusicVolumeChanged)); 1307 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(alarmVolumeChanged, 1308 optionsAlarmVolumeChanged)); 1309 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(timeTick, optionsTimeTick)); 1310 // Verify that the older timeTick has been removed. 1311 verifyPendingRecords(queue, 1312 List.of(musicVolumeChanged, alarmVolumeChanged, timeTick)); 1313 } 1314 1315 @Test testDeliveryGroupPolicy_merged_matchingFilter()1316 public void testDeliveryGroupPolicy_merged_matchingFilter() { 1317 final long now = SystemClock.elapsedRealtime(); 1318 final Pair<Intent, BroadcastOptions> dropboxEntryBroadcast1 = createDropboxBroadcast( 1319 "TAG_A", now, 2); 1320 final Pair<Intent, BroadcastOptions> dropboxEntryBroadcast2 = createDropboxBroadcast( 1321 "TAG_B", now + 1000, 4); 1322 final Pair<Intent, BroadcastOptions> dropboxEntryBroadcast3 = createDropboxBroadcast( 1323 "TAG_A", now + 2000, 7); 1324 1325 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(dropboxEntryBroadcast1.first, 1326 dropboxEntryBroadcast1.second)); 1327 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(dropboxEntryBroadcast2.first, 1328 dropboxEntryBroadcast2.second)); 1329 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(dropboxEntryBroadcast3.first, 1330 dropboxEntryBroadcast3.second)); 1331 1332 final BroadcastProcessQueue queue = mImpl.getProcessQueue(PACKAGE_GREEN, 1333 getUidForPackage(PACKAGE_GREEN)); 1334 // dropboxEntryBroadcast1 and dropboxEntryBroadcast3 should be merged as they use the same 1335 // tag and there shouldn't be a change to dropboxEntryBroadcast2. 1336 final Pair<Intent, BroadcastOptions> expectedMergedBroadcast = createDropboxBroadcast( 1337 "TAG_A", now + 2000, 10); 1338 verifyPendingRecords(queue, List.of( 1339 dropboxEntryBroadcast2.first, expectedMergedBroadcast.first)); 1340 } 1341 1342 @Test testDeliveryGroupPolicy_merged_multipleReceivers()1343 public void testDeliveryGroupPolicy_merged_multipleReceivers() { 1344 final long now = SystemClock.elapsedRealtime(); 1345 final Pair<Intent, BroadcastOptions> dropboxEntryBroadcast1 = createDropboxBroadcast( 1346 "TAG_A", now, 2); 1347 final Pair<Intent, BroadcastOptions> dropboxEntryBroadcast2 = createDropboxBroadcast( 1348 "TAG_A", now + 1000, 4); 1349 1350 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(dropboxEntryBroadcast1.first, 1351 dropboxEntryBroadcast1.second, 1352 List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN), 1353 makeManifestReceiver(PACKAGE_RED, CLASS_RED)), 1354 false)); 1355 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(dropboxEntryBroadcast2.first, 1356 dropboxEntryBroadcast2.second, 1357 List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN), 1358 makeManifestReceiver(PACKAGE_RED, CLASS_RED)), 1359 false)); 1360 1361 final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN, 1362 getUidForPackage(PACKAGE_GREEN)); 1363 final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED, 1364 getUidForPackage(PACKAGE_RED)); 1365 1366 verifyPendingRecords(greenQueue, 1367 List.of(dropboxEntryBroadcast1.first, dropboxEntryBroadcast2.first)); 1368 verifyPendingRecords(redQueue, 1369 List.of(dropboxEntryBroadcast1.first, dropboxEntryBroadcast2.first)); 1370 } 1371 1372 @Test testDeliveryGroupPolicy_sameAction_differentMatchingCriteria()1373 public void testDeliveryGroupPolicy_sameAction_differentMatchingCriteria() { 1374 final Intent closeSystemDialogs1 = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 1375 final BroadcastOptions optionsCloseSystemDialog1 = BroadcastOptions.makeBasic() 1376 .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT); 1377 1378 final Intent closeSystemDialogs2 = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) 1379 .putExtra("reason", "testing"); 1380 final BroadcastOptions optionsCloseSystemDialog2 = BroadcastOptions.makeBasic() 1381 .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) 1382 .setDeliveryGroupMatchingKey(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, "testing"); 1383 1384 mImpl.enqueueBroadcastLocked(makeBroadcastRecord( 1385 closeSystemDialogs1, optionsCloseSystemDialog1)); 1386 mImpl.enqueueBroadcastLocked(makeBroadcastRecord( 1387 closeSystemDialogs2, optionsCloseSystemDialog2)); 1388 mImpl.enqueueBroadcastLocked(makeBroadcastRecord( 1389 closeSystemDialogs1, optionsCloseSystemDialog1)); 1390 // Verify that only the older broadcast with no extras was removed. 1391 final BroadcastProcessQueue queue = mImpl.getProcessQueue(PACKAGE_GREEN, 1392 getUidForPackage(PACKAGE_GREEN)); 1393 verifyPendingRecords(queue, List.of(closeSystemDialogs2, closeSystemDialogs1)); 1394 1395 mImpl.enqueueBroadcastLocked(makeBroadcastRecord( 1396 closeSystemDialogs2, optionsCloseSystemDialog2)); 1397 mImpl.enqueueBroadcastLocked(makeBroadcastRecord( 1398 closeSystemDialogs1, optionsCloseSystemDialog1)); 1399 mImpl.enqueueBroadcastLocked(makeBroadcastRecord( 1400 closeSystemDialogs2, optionsCloseSystemDialog2)); 1401 // Verify that only the older broadcast with no extras was removed. 1402 verifyPendingRecords(queue, List.of(closeSystemDialogs1, closeSystemDialogs2)); 1403 } 1404 createDropboxBroadcast(String tag, long timestampMs, int droppedCount)1405 private Pair<Intent, BroadcastOptions> createDropboxBroadcast(String tag, long timestampMs, 1406 int droppedCount) { 1407 final Intent dropboxEntryAdded = new Intent(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED); 1408 dropboxEntryAdded.putExtra(DropBoxManager.EXTRA_TAG, tag); 1409 dropboxEntryAdded.putExtra(DropBoxManager.EXTRA_TIME, timestampMs); 1410 dropboxEntryAdded.putExtra(DropBoxManager.EXTRA_DROPPED_COUNT, droppedCount); 1411 1412 final BundleMerger extrasMerger = new BundleMerger(); 1413 extrasMerger.setDefaultMergeStrategy(BundleMerger.STRATEGY_FIRST); 1414 extrasMerger.setMergeStrategy(DropBoxManager.EXTRA_TIME, 1415 BundleMerger.STRATEGY_COMPARABLE_MAX); 1416 extrasMerger.setMergeStrategy(DropBoxManager.EXTRA_DROPPED_COUNT, 1417 BundleMerger.STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD); 1418 final IntentFilter matchingFilter = new IntentFilter( 1419 DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED); 1420 matchingFilter.addExtra(DropBoxManager.EXTRA_TAG, tag); 1421 final BroadcastOptions optionsDropboxEntryAdded = BroadcastOptions.makeBasic() 1422 .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MERGED) 1423 .setDeliveryGroupMatchingFilter(matchingFilter) 1424 .setDeliveryGroupExtrasMerger(extrasMerger); 1425 return Pair.create(dropboxEntryAdded, optionsDropboxEntryAdded); 1426 } 1427 1428 @Test testVerifyEnqueuedTime_withReplacePending()1429 public void testVerifyEnqueuedTime_withReplacePending() { 1430 final Intent userPresent = new Intent(Intent.ACTION_USER_PRESENT); 1431 userPresent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 1432 1433 final BroadcastRecord userPresentRecord1 = makeBroadcastRecord(userPresent); 1434 final BroadcastRecord userPresentRecord2 = makeBroadcastRecord(userPresent); 1435 1436 mImpl.enqueueBroadcastLocked(userPresentRecord1); 1437 mImpl.enqueueBroadcastLocked(userPresentRecord2); 1438 1439 final BroadcastProcessQueue queue = mImpl.getProcessQueue(PACKAGE_GREEN, 1440 getUidForPackage(PACKAGE_GREEN)); 1441 queue.makeActiveNextPending(); 1442 1443 // Verify that there is only one record pending and its enqueueTime is 1444 // same as that of userPresentRecord1. 1445 final BroadcastRecord activeRecord = queue.getActive(); 1446 assertEquals(userPresentRecord1.enqueueTime, activeRecord.enqueueTime); 1447 assertEquals(userPresentRecord1.enqueueRealTime, activeRecord.enqueueRealTime); 1448 assertEquals(userPresentRecord1.enqueueClockTime, activeRecord.enqueueClockTime); 1449 assertThat(activeRecord.originalEnqueueClockTime) 1450 .isGreaterThan(activeRecord.enqueueClockTime); 1451 assertTrue(queue.isEmpty()); 1452 } 1453 1454 @Test testCleanupDisabledPackageReceiversLocked()1455 public void testCleanupDisabledPackageReceiversLocked() { 1456 final Intent userPresent = new Intent(Intent.ACTION_USER_PRESENT); 1457 final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); 1458 1459 final BroadcastRecord record1 = makeBroadcastRecord(userPresent, List.of( 1460 makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN), 1461 makeManifestReceiver(PACKAGE_RED, CLASS_BLUE), 1462 makeManifestReceiver(PACKAGE_YELLOW, CLASS_RED), 1463 makeManifestReceiver(PACKAGE_BLUE, CLASS_GREEN) 1464 )); 1465 final BroadcastRecord record2 = makeBroadcastRecord(timeTick, List.of( 1466 makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN), 1467 makeManifestReceiver(PACKAGE_RED, CLASS_RED), 1468 makeManifestReceiver(PACKAGE_YELLOW, CLASS_YELLOW) 1469 )); 1470 1471 mImpl.enqueueBroadcastLocked(record1); 1472 mImpl.enqueueBroadcastLocked(record2); 1473 1474 mImpl.cleanupDisabledPackageReceiversLocked(null, null, UserHandle.USER_SYSTEM); 1475 1476 // Verify that all receivers have been marked as "skipped". 1477 for (BroadcastRecord record : new BroadcastRecord[] {record1, record2}) { 1478 for (int i = 0; i < record.receivers.size(); ++i) { 1479 final String errMsg = "Unexpected delivery state for record:" + record 1480 + "; receiver=" + record.receivers.get(i); 1481 assertEquals(errMsg, BroadcastRecord.DELIVERY_SKIPPED, record.getDeliveryState(i)); 1482 } 1483 } 1484 } 1485 1486 @Test testBroadcastDeliveryEventReported()1487 public void testBroadcastDeliveryEventReported() throws Exception { 1488 final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); 1489 final BroadcastOptions optionsTimeTick = BroadcastOptions.makeBasic(); 1490 optionsTimeTick.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT); 1491 1492 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(timeTick, optionsTimeTick)); 1493 mImpl.enqueueBroadcastLocked(makeBroadcastRecord(timeTick, optionsTimeTick)); 1494 waitForIdle(); 1495 1496 // Verify that there is only one delivery event reported since one of the broadcasts 1497 // should have been skipped. 1498 verify(() -> FrameworkStatsLog.write(eq(BROADCAST_DELIVERY_EVENT_REPORTED), 1499 eq(getUidForPackage(PACKAGE_GREEN)), anyInt(), eq(Intent.ACTION_TIME_TICK), 1500 eq(BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST), 1501 eq(BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD), 1502 anyLong(), anyLong(), anyLong(), anyInt(), nullable(String.class), 1503 anyString(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt()), 1504 times(1)); 1505 } 1506 1507 @Test testGetPreferredSchedulingGroup()1508 public void testGetPreferredSchedulingGroup() throws Exception { 1509 final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, 1510 PACKAGE_GREEN, getUidForPackage(PACKAGE_GREEN)); 1511 1512 assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); 1513 1514 final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK) 1515 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 1516 enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(timeTick, 1517 List.of(makeMockRegisteredReceiver())), 0); 1518 assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); 1519 1520 // Make the foreground broadcast as active. 1521 queue.makeActiveNextPending(); 1522 assertEquals(ProcessList.SCHED_GROUP_DEFAULT, queue.getPreferredSchedulingGroupLocked()); 1523 1524 queue.makeActiveIdle(); 1525 assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); 1526 1527 final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 1528 enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(airplane, 1529 List.of(makeMockRegisteredReceiver())), 0); 1530 1531 // Make the background broadcast as active. 1532 queue.makeActiveNextPending(); 1533 assertEquals(ProcessList.SCHED_GROUP_BACKGROUND, queue.getPreferredSchedulingGroupLocked()); 1534 1535 enqueueOrReplaceBroadcast(queue, makeBroadcastRecord(timeTick, 1536 List.of(makeMockRegisteredReceiver())), 0); 1537 // Even though the active broadcast is not a foreground one, scheduling group will be 1538 // DEFAULT since there is a foreground broadcast waiting to be delivered. 1539 assertEquals(ProcessList.SCHED_GROUP_DEFAULT, queue.getPreferredSchedulingGroupLocked()); 1540 } 1541 1542 @Test testSkipPolicy_atEnqueueTime()1543 public void testSkipPolicy_atEnqueueTime() throws Exception { 1544 final Intent userPresent = new Intent(Intent.ACTION_USER_PRESENT); 1545 final Object greenReceiver = makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN); 1546 final Object redReceiver = makeManifestReceiver(PACKAGE_RED, CLASS_RED); 1547 1548 final BroadcastRecord userPresentRecord = makeBroadcastRecord(userPresent, 1549 List.of(greenReceiver, redReceiver)); 1550 1551 final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); 1552 final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, 1553 List.of(greenReceiver, redReceiver)); 1554 1555 doAnswer(invocation -> { 1556 final BroadcastRecord r = invocation.getArgument(0); 1557 final Object o = invocation.getArgument(1); 1558 if (userPresent.getAction().equals(r.intent.getAction()) 1559 && isReceiverEquals(o, greenReceiver)) { 1560 return "receiver skipped by test"; 1561 } 1562 return null; 1563 }).when(mSkipPolicy).shouldSkipMessage(any(BroadcastRecord.class), any()); 1564 1565 mImpl.enqueueBroadcastLocked(userPresentRecord); 1566 mImpl.enqueueBroadcastLocked(timeTickRecord); 1567 1568 final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN, 1569 getUidForPackage(PACKAGE_GREEN)); 1570 // There should be only one broadcast for green process as the other would have 1571 // been skipped. 1572 verifyPendingRecords(greenQueue, List.of(timeTick)); 1573 final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED, 1574 getUidForPackage(PACKAGE_RED)); 1575 verifyPendingRecords(redQueue, List.of(userPresent, timeTick)); 1576 } 1577 createPackageChangedIntent(int uid, List<String> componentNameList)1578 private Intent createPackageChangedIntent(int uid, List<String> componentNameList) { 1579 final Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED); 1580 packageChangedIntent.putExtra(Intent.EXTRA_UID, uid); 1581 packageChangedIntent.putExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, 1582 componentNameList.toArray()); 1583 return packageChangedIntent; 1584 } 1585 verifyPendingRecords(BroadcastProcessQueue queue, List<Intent> intents)1586 private void verifyPendingRecords(BroadcastProcessQueue queue, 1587 List<Intent> intents) { 1588 for (int i = 0; i < intents.size(); i++) { 1589 queue.makeActiveNextPending(); 1590 1591 // While we're here, give our health check some test coverage 1592 queue.assertHealthLocked(); 1593 queue.dumpLocked(0L, new IndentingPrintWriter(Writer.nullWriter())); 1594 1595 final Intent actualIntent = queue.getActive().intent; 1596 final Intent expectedIntent = intents.get(i); 1597 final String errMsg = "actual=" + actualIntent + ", expected=" + expectedIntent 1598 + ", actual_extras=" + actualIntent.getExtras() 1599 + ", expected_extras=" + expectedIntent.getExtras(); 1600 assertTrue(errMsg, actualIntent.filterEquals(expectedIntent)); 1601 assertBundleEquals(expectedIntent.getExtras(), actualIntent.getExtras()); 1602 } 1603 assertTrue(queue.isEmpty()); 1604 } 1605 assertBundleEquals(Bundle expected, Bundle actual)1606 private void assertBundleEquals(Bundle expected, Bundle actual) { 1607 final String errMsg = "expected=" + expected + ", actual=" + actual; 1608 if (expected == actual) { 1609 return; 1610 } else if (expected == null || actual == null) { 1611 fail(errMsg); 1612 } 1613 if (!expected.keySet().equals(actual.keySet())) { 1614 fail(errMsg); 1615 } 1616 for (String key : expected.keySet()) { 1617 final Object expectedValue = expected.get(key); 1618 final Object actualValue = actual.get(key); 1619 if (expectedValue == actualValue) { 1620 continue; 1621 } else if (expectedValue == null || actualValue == null) { 1622 fail(errMsg); 1623 } 1624 assertEquals(errMsg, expectedValue.getClass(), actualValue.getClass()); 1625 if (expectedValue.getClass().isArray()) { 1626 assertEquals(errMsg, Array.getLength(expectedValue), Array.getLength(actualValue)); 1627 for (int i = 0; i < Array.getLength(expectedValue); ++i) { 1628 assertEquals(errMsg, Array.get(expectedValue, i), Array.get(actualValue, i)); 1629 } 1630 } else if (expectedValue instanceof ArrayList) { 1631 final ArrayList<?> expectedList = (ArrayList<?>) expectedValue; 1632 final ArrayList<?> actualList = (ArrayList<?>) actualValue; 1633 assertEquals(errMsg, expectedList.size(), actualList.size()); 1634 for (int i = 0; i < expectedList.size(); ++i) { 1635 assertEquals(errMsg, expectedList.get(i), actualList.get(i)); 1636 } 1637 } else { 1638 assertEquals(errMsg, expectedValue, actualValue); 1639 } 1640 } 1641 } 1642 } 1643