1 /* 2 * Copyright (C) 2017 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.usage; 18 19 import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START; 20 import static android.app.usage.UsageEvents.Event.NOTIFICATION_SEEN; 21 import static android.app.usage.UsageEvents.Event.SLICE_PINNED; 22 import static android.app.usage.UsageEvents.Event.SLICE_PINNED_PRIV; 23 import static android.app.usage.UsageEvents.Event.SYSTEM_INTERACTION; 24 import static android.app.usage.UsageEvents.Event.USER_INTERACTION; 25 import static android.app.usage.UsageStatsManager.REASON_MAIN_DEFAULT; 26 import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_SYSTEM; 27 import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER; 28 import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED; 29 import static android.app.usage.UsageStatsManager.REASON_MAIN_TIMEOUT; 30 import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE; 31 import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE; 32 import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE; 33 import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY; 34 import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED; 35 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE; 36 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_FOREGROUND; 37 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYNC_ADAPTER; 38 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYSTEM_INTERACTION; 39 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACTION; 40 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE; 41 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED; 42 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT; 43 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER; 44 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE; 45 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RESTRICTED; 46 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET; 47 import static android.content.pm.PackageManager.PERMISSION_DENIED; 48 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 49 50 import static com.android.server.usage.AppStandbyController.DEFAULT_ELAPSED_TIME_THRESHOLDS; 51 import static com.android.server.usage.AppStandbyController.DEFAULT_SCREEN_TIME_THRESHOLDS; 52 import static com.android.server.usage.AppStandbyController.MINIMUM_ELAPSED_TIME_THRESHOLDS; 53 import static com.android.server.usage.AppStandbyController.MINIMUM_SCREEN_TIME_THRESHOLDS; 54 55 import static org.junit.Assert.assertEquals; 56 import static org.junit.Assert.assertFalse; 57 import static org.junit.Assert.assertNotEquals; 58 import static org.junit.Assert.assertTrue; 59 import static org.junit.Assert.fail; 60 import static org.junit.Assume.assumeTrue; 61 import static org.mockito.AdditionalMatchers.not; 62 import static org.mockito.ArgumentMatchers.anyLong; 63 import static org.mockito.ArgumentMatchers.anyString; 64 import static org.mockito.ArgumentMatchers.eq; 65 import static org.mockito.Matchers.any; 66 import static org.mockito.Matchers.anyInt; 67 import static org.mockito.Matchers.eq; 68 import static org.mockito.Matchers.intThat; 69 import static org.mockito.Mockito.doReturn; 70 import static org.mockito.Mockito.mock; 71 import static org.mockito.Mockito.spy; 72 import static org.mockito.Mockito.when; 73 74 import android.annotation.NonNull; 75 import android.app.ActivityManager; 76 import android.app.usage.AppStandbyInfo; 77 import android.app.usage.UsageEvents; 78 import android.app.usage.UsageStatsManagerInternal; 79 import android.appwidget.AppWidgetManager; 80 import android.content.Context; 81 import android.content.ContextWrapper; 82 import android.content.Intent; 83 import android.content.pm.ActivityInfo; 84 import android.content.pm.ApplicationInfo; 85 import android.content.pm.PackageInfo; 86 import android.content.pm.PackageManager; 87 import android.content.pm.PackageManagerInternal; 88 import android.content.pm.ResolveInfo; 89 import android.hardware.display.DisplayManager; 90 import android.os.BatteryStats; 91 import android.os.Handler; 92 import android.os.Looper; 93 import android.os.RemoteException; 94 import android.os.UserHandle; 95 import android.platform.test.annotations.Presubmit; 96 import android.provider.DeviceConfig; 97 import android.util.ArraySet; 98 import android.util.Pair; 99 import android.view.Display; 100 101 import androidx.test.InstrumentationRegistry; 102 import androidx.test.filters.FlakyTest; 103 import androidx.test.filters.SmallTest; 104 import androidx.test.runner.AndroidJUnit4; 105 106 import com.android.internal.util.ArrayUtils; 107 import com.android.server.LocalServices; 108 import com.android.server.SystemService; 109 import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener; 110 111 import org.junit.After; 112 import org.junit.Before; 113 import org.junit.Test; 114 import org.junit.runner.RunWith; 115 import org.mockito.Mock; 116 import org.mockito.MockitoAnnotations; 117 118 import java.io.File; 119 import java.util.ArrayList; 120 import java.util.Arrays; 121 import java.util.Collections; 122 import java.util.List; 123 import java.util.Objects; 124 import java.util.Random; 125 import java.util.Set; 126 import java.util.concurrent.CountDownLatch; 127 import java.util.concurrent.TimeUnit; 128 import java.util.stream.Collectors; 129 130 /** 131 * Unit test for AppStandbyController. 132 */ 133 @RunWith(AndroidJUnit4.class) 134 @Presubmit 135 @SmallTest 136 public class AppStandbyControllerTests { 137 138 private static final String PACKAGE_1 = "com.example.foo.1"; 139 private static final int UID_1 = 10000; 140 private static final String PACKAGE_2 = "com.example.foo.2"; 141 private static final int UID_2 = 20000; 142 private static final String PACKAGE_EXEMPTED_1 = "com.android.exempted"; 143 private static final int UID_EXEMPTED_1 = 10001; 144 private static final String PACKAGE_SYSTEM_HEADFULL = "com.example.system.headfull"; 145 private static final int UID_SYSTEM_HEADFULL = 10002; 146 private static final String PACKAGE_SYSTEM_HEADLESS = "com.example.system.headless"; 147 private static final int UID_SYSTEM_HEADLESS = 10003; 148 private static final String PACKAGE_WELLBEING = "com.example.wellbeing"; 149 private static final int UID_WELLBEING = 10004; 150 private static final String PACKAGE_BACKGROUND_LOCATION = "com.example.backgroundLocation"; 151 private static final int UID_BACKGROUND_LOCATION = 10005; 152 private static final int USER_ID = 0; 153 private static final int USER_ID2 = 10; 154 private static final UserHandle USER_HANDLE_USER2 = new UserHandle(USER_ID2); 155 private static final int USER_ID3 = 11; 156 157 private static final String PACKAGE_UNKNOWN = "com.example.unknown"; 158 159 private static final String ADMIN_PKG = "com.android.admin"; 160 private static final String ADMIN_PKG2 = "com.android.admin2"; 161 private static final String ADMIN_PKG3 = "com.android.admin3"; 162 163 private static final String ADMIN_PROTECTED_PKG = "com.android.admin.protected"; 164 private static final String ADMIN_PROTECTED_PKG2 = "com.android.admin.protected2"; 165 166 private static final long MINUTE_MS = 60 * 1000; 167 private static final long HOUR_MS = 60 * MINUTE_MS; 168 private static final long DAY_MS = 24 * HOUR_MS; 169 170 private static final long WORKING_SET_THRESHOLD = 12 * HOUR_MS; 171 private static final long FREQUENT_THRESHOLD = 24 * HOUR_MS; 172 private static final long RARE_THRESHOLD = 48 * HOUR_MS; 173 private static final long RESTRICTED_THRESHOLD = 96 * HOUR_MS; 174 175 private static final int ASSERT_RETRY_ATTEMPTS = 20; 176 private static final int ASSERT_RETRY_DELAY_MILLISECONDS = 500; 177 178 /** Mock variable used in {@link MyInjector#isPackageInstalled(String, int, int)} */ 179 private static boolean isPackageInstalled = true; 180 181 private static final Random sRandom = new Random(); 182 183 private MyInjector mInjector; 184 private AppStandbyController mController; 185 186 private CountDownLatch mStateChangedLatch = new CountDownLatch(1); 187 private CountDownLatch mQuotaBumpLatch = new CountDownLatch(1); 188 private String mLatchPkgName = null; 189 private int mLatchUserId = -1; 190 private AppIdleStateChangeListener mListener = new AppIdleStateChangeListener() { 191 @Override 192 public void onAppIdleStateChanged(String packageName, int userId, 193 boolean idle, int bucket, int reason) { 194 // Ignore events not related to mLatchPkgName, if set. 195 if (mLatchPkgName != null && !mLatchPkgName.equals(packageName)) return; 196 mStateChangedLatch.countDown(); 197 } 198 199 @Override 200 public void triggerTemporaryQuotaBump(String packageName, int userId) { 201 // Ignore events not related to mLatchPkgName, if set. 202 if ((mLatchPkgName != null && !mLatchPkgName.equals(packageName)) 203 || (mLatchUserId != -1 && mLatchUserId != userId)) { 204 return; 205 } 206 mQuotaBumpLatch.countDown(); 207 } 208 }; 209 210 static class MyContextWrapper extends ContextWrapper { 211 PackageManager mockPm = mock(PackageManager.class); 212 MyContextWrapper(Context base)213 public MyContextWrapper(Context base) { 214 super(base); 215 } 216 getPackageManager()217 public PackageManager getPackageManager() { 218 return mockPm; 219 } 220 getSystemService(@onNull String name)221 public Object getSystemService(@NonNull String name) { 222 if (Context.ACTIVITY_SERVICE.equals(name)) { 223 return mock(ActivityManager.class); 224 } 225 return super.getSystemService(name); 226 } 227 } 228 229 static class MyInjector extends AppStandbyController.Injector { 230 @Mock 231 private PackageManagerInternal mPackageManagerInternal; 232 long mElapsedRealtime; 233 boolean mIsAppIdleEnabled = true; 234 boolean mIsCharging; 235 List<String> mNonIdleWhitelistApps = new ArrayList<>(); 236 boolean mDisplayOn; 237 DisplayManager.DisplayListener mDisplayListener; 238 String mBoundWidgetPackage = PACKAGE_EXEMPTED_1; 239 int[] mRunningUsers = new int[] {USER_ID}; 240 List<UserHandle> mCrossProfileTargets = Collections.emptyList(); 241 boolean mDeviceIdleMode = false; 242 Set<Pair<String, Integer>> mClockApps = new ArraySet<>(); 243 DeviceConfig.Properties.Builder mSettingsBuilder = 244 new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_APP_STANDBY) 245 .setLong("screen_threshold_active", 0) 246 .setLong("screen_threshold_working_set", 0) 247 .setLong("screen_threshold_frequent", 0) 248 .setLong("screen_threshold_rare", HOUR_MS) 249 // screen_threshold_restricted intentionally skipped 250 .setLong("elapsed_threshold_active", 0) 251 .setLong("elapsed_threshold_working_set", WORKING_SET_THRESHOLD) 252 .setLong("elapsed_threshold_frequent", FREQUENT_THRESHOLD) 253 .setLong("elapsed_threshold_rare", RARE_THRESHOLD) 254 .setLong("elapsed_threshold_restricted", RESTRICTED_THRESHOLD); 255 DeviceConfig.OnPropertiesChangedListener mPropertiesChangedListener; 256 String mExpectedNoteEventPackage = null; 257 int mLastNoteEvent = BatteryStats.HistoryItem.EVENT_NONE; 258 MyInjector(Context context, Looper looper)259 MyInjector(Context context, Looper looper) { 260 super(context, looper); 261 MockitoAnnotations.initMocks(this); 262 } 263 264 @Override onBootPhase(int phase)265 void onBootPhase(int phase) { 266 } 267 268 @Override getBootPhase()269 int getBootPhase() { 270 return SystemService.PHASE_BOOT_COMPLETED; 271 } 272 273 @Override elapsedRealtime()274 long elapsedRealtime() { 275 return mElapsedRealtime; 276 } 277 278 @Override currentTimeMillis()279 long currentTimeMillis() { 280 return mElapsedRealtime; 281 } 282 283 @Override isAppIdleEnabled()284 boolean isAppIdleEnabled() { 285 return mIsAppIdleEnabled; 286 } 287 288 @Override isCharging()289 boolean isCharging() { 290 return mIsCharging; 291 } 292 293 @Override isNonIdleWhitelisted(String packageName)294 boolean isNonIdleWhitelisted(String packageName) { 295 return mNonIdleWhitelistApps.contains(packageName); 296 } 297 298 @Override isWellbeingPackage(String packageName)299 boolean isWellbeingPackage(String packageName) { 300 return PACKAGE_WELLBEING.equals(packageName); 301 } 302 303 @Override shouldGetExactAlarmBucketElevation(String packageName, int uid)304 boolean shouldGetExactAlarmBucketElevation(String packageName, int uid) { 305 return mClockApps.contains(Pair.create(packageName, uid)); 306 } 307 308 @Override getPackageManagerInternal()309 PackageManagerInternal getPackageManagerInternal() { 310 return mPackageManagerInternal; 311 } 312 313 @Override updatePowerWhitelistCache()314 void updatePowerWhitelistCache() { 315 } 316 317 @Override getDataSystemDirectory()318 File getDataSystemDirectory() { 319 return new File(getContext().getFilesDir(), Long.toString(sRandom.nextLong())); 320 } 321 322 @Override noteEvent(int event, String packageName, int uid)323 void noteEvent(int event, String packageName, int uid) throws RemoteException { 324 if (Objects.equals(mExpectedNoteEventPackage, packageName)) { 325 mLastNoteEvent = event; 326 } 327 } 328 329 @Override isPackageEphemeral(int userId, String packageName)330 boolean isPackageEphemeral(int userId, String packageName) { 331 // TODO: update when testing ephemeral apps scenario 332 return false; 333 } 334 335 @Override isPackageInstalled(String packageName, int flags, int userId)336 boolean isPackageInstalled(String packageName, int flags, int userId) { 337 // Should always return true (default value) unless testing for an uninstalled app 338 return isPackageInstalled; 339 } 340 341 @Override getRunningUserIds()342 int[] getRunningUserIds() { 343 return mRunningUsers; 344 } 345 346 @Override isDefaultDisplayOn()347 boolean isDefaultDisplayOn() { 348 return mDisplayOn; 349 } 350 351 @Override registerDisplayListener(DisplayManager.DisplayListener listener, Handler handler)352 void registerDisplayListener(DisplayManager.DisplayListener listener, Handler handler) { 353 mDisplayListener = listener; 354 } 355 356 @Override getActiveNetworkScorer()357 String getActiveNetworkScorer() { 358 return null; 359 } 360 361 @Override isBoundWidgetPackage(AppWidgetManager appWidgetManager, String packageName, int userId)362 public boolean isBoundWidgetPackage(AppWidgetManager appWidgetManager, String packageName, 363 int userId) { 364 return packageName != null && packageName.equals(mBoundWidgetPackage); 365 } 366 367 @Override 368 @NonNull getDeviceConfigProperties(String... keys)369 DeviceConfig.Properties getDeviceConfigProperties(String... keys) { 370 return mSettingsBuilder.build(); 371 } 372 373 @Override isDeviceIdleMode()374 public boolean isDeviceIdleMode() { 375 return mDeviceIdleMode; 376 } 377 378 @Override getValidCrossProfileTargets(String pkg, int userId)379 public List<UserHandle> getValidCrossProfileTargets(String pkg, int userId) { 380 return mCrossProfileTargets; 381 } 382 383 @Override registerDeviceConfigPropertiesChangedListener( @onNull DeviceConfig.OnPropertiesChangedListener listener)384 public void registerDeviceConfigPropertiesChangedListener( 385 @NonNull DeviceConfig.OnPropertiesChangedListener listener) { 386 mPropertiesChangedListener = listener; 387 } 388 389 // Internal methods 390 setDisplayOn(boolean on)391 void setDisplayOn(boolean on) { 392 mDisplayOn = on; 393 if (mDisplayListener != null) { 394 mDisplayListener.onDisplayChanged(Display.DEFAULT_DISPLAY); 395 } 396 } 397 } 398 setupPm(PackageManager mockPm)399 private void setupPm(PackageManager mockPm) throws PackageManager.NameNotFoundException { 400 List<PackageInfo> packages = new ArrayList<>(); 401 PackageInfo pi = new PackageInfo(); 402 pi.applicationInfo = new ApplicationInfo(); 403 pi.applicationInfo.uid = UID_1; 404 pi.packageName = PACKAGE_1; 405 packages.add(pi); 406 407 PackageInfo pInfo = new PackageInfo(); 408 pInfo.applicationInfo = new ApplicationInfo(); 409 pInfo.applicationInfo.uid = UID_2; 410 pInfo.packageName = PACKAGE_2; 411 packages.add(pInfo); 412 413 PackageInfo pie = new PackageInfo(); 414 pie.applicationInfo = new ApplicationInfo(); 415 pie.applicationInfo.uid = UID_EXEMPTED_1; 416 pie.packageName = PACKAGE_EXEMPTED_1; 417 packages.add(pie); 418 419 PackageInfo pis = new PackageInfo(); 420 pis.activities = new ActivityInfo[]{mock(ActivityInfo.class)}; 421 pis.applicationInfo = new ApplicationInfo(); 422 pis.applicationInfo.uid = UID_SYSTEM_HEADFULL; 423 pis.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; 424 pis.packageName = PACKAGE_SYSTEM_HEADFULL; 425 packages.add(pis); 426 427 PackageInfo pish = new PackageInfo(); 428 pish.applicationInfo = new ApplicationInfo(); 429 pish.applicationInfo.uid = UID_SYSTEM_HEADLESS; 430 pish.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; 431 pish.packageName = PACKAGE_SYSTEM_HEADLESS; 432 packages.add(pish); 433 434 PackageInfo piw = new PackageInfo(); 435 piw.applicationInfo = new ApplicationInfo(); 436 piw.applicationInfo.uid = UID_WELLBEING; 437 piw.packageName = PACKAGE_WELLBEING; 438 packages.add(piw); 439 440 PackageInfo pib = new PackageInfo(); 441 pib.applicationInfo = new ApplicationInfo(); 442 pib.applicationInfo.uid = UID_BACKGROUND_LOCATION; 443 pib.packageName = PACKAGE_BACKGROUND_LOCATION; 444 packages.add(pib); 445 446 447 // Set up getInstalledPackagesAsUser(). 448 doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(), 449 anyInt()); 450 451 // Set up getInstalledPackagesAsUser() for "MATCH_ONLY_SYSTEM" 452 doReturn( 453 packages.stream().filter(pinfo -> pinfo.applicationInfo.isSystemApp()) 454 .collect(Collectors.toList()) 455 ).when(mockPm).getInstalledPackagesAsUser( 456 intThat(i -> (i & PackageManager.MATCH_SYSTEM_ONLY) != 0), 457 anyInt()); 458 459 // Set up queryIntentActivitiesAsUser() 460 final ArrayList<ResolveInfo> systemFrontDoorActivities = new ArrayList<>(); 461 final ResolveInfo frontDoorActivity = new ResolveInfo(); 462 frontDoorActivity.activityInfo = new ActivityInfo(); 463 frontDoorActivity.activityInfo.packageName = pis.packageName; 464 systemFrontDoorActivities.add(frontDoorActivity); 465 doReturn(systemFrontDoorActivities).when(mockPm) 466 .queryIntentActivitiesAsUser(any(Intent.class), 467 intThat(i -> (i & PackageManager.MATCH_SYSTEM_ONLY) != 0), 468 anyInt()); 469 470 // Set up other APIs. 471 try { 472 for (int i = 0; i < packages.size(); ++i) { 473 PackageInfo pkg = packages.get(i); 474 475 doReturn(pkg.applicationInfo.uid).when(mockPm) 476 .getPackageUidAsUser(eq(pkg.packageName), anyInt()); 477 doReturn(pkg.applicationInfo.uid).when(mockPm) 478 .getPackageUidAsUser(eq(pkg.packageName), anyInt(), anyInt()); 479 doReturn(pkg.applicationInfo).when(mockPm) 480 .getApplicationInfo(eq(pkg.packageName), anyInt()); 481 482 if (pkg.packageName.equals(PACKAGE_BACKGROUND_LOCATION)) { 483 doReturn(PERMISSION_GRANTED).when(mockPm).checkPermission( 484 eq(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION), 485 eq(pkg.packageName)); 486 doReturn(PERMISSION_DENIED).when(mockPm).checkPermission( 487 not(eq(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION)), 488 eq(pkg.packageName)); 489 } else { 490 doReturn(PERMISSION_DENIED).when(mockPm).checkPermission(anyString(), 491 eq(pkg.packageName)); 492 } 493 } 494 } catch (PackageManager.NameNotFoundException nnfe) {} 495 } 496 setChargingState(AppStandbyController controller, boolean charging)497 private void setChargingState(AppStandbyController controller, boolean charging) { 498 mInjector.mIsCharging = charging; 499 if (controller != null) { 500 controller.setChargingState(charging); 501 } 502 } 503 setAppIdleEnabled(AppStandbyController controller, boolean enabled)504 private void setAppIdleEnabled(AppStandbyController controller, boolean enabled) { 505 mInjector.mIsAppIdleEnabled = enabled; 506 if (controller != null) { 507 controller.setAppIdleEnabled(enabled); 508 } 509 } 510 setupController()511 private AppStandbyController setupController() throws Exception { 512 mInjector.mElapsedRealtime = 0; 513 setupPm(mInjector.getContext().getPackageManager()); 514 AppStandbyController controller = new AppStandbyController(mInjector); 515 controller.initializeDefaultsForSystemApps(USER_ID); 516 controller.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); 517 controller.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); 518 mInjector.setDisplayOn(false); 519 mInjector.setDisplayOn(true); 520 setChargingState(controller, false); 521 controller.checkIdleStates(USER_ID); 522 assertNotEquals(STANDBY_BUCKET_EXEMPTED, 523 controller.getAppStandbyBucket(PACKAGE_1, USER_ID, 524 mInjector.mElapsedRealtime, false)); 525 526 controller.addListener(mListener); 527 mLatchPkgName = null; 528 return controller; 529 } 530 setupInitialUsageHistory()531 private void setupInitialUsageHistory() throws Exception { 532 final int[] userIds = new int[] { USER_ID, USER_ID2, USER_ID3 }; 533 final String[] packages = new String[] { 534 PACKAGE_1, 535 PACKAGE_2, 536 PACKAGE_EXEMPTED_1, 537 PACKAGE_SYSTEM_HEADFULL, 538 PACKAGE_SYSTEM_HEADLESS, 539 PACKAGE_WELLBEING, 540 PACKAGE_BACKGROUND_LOCATION, 541 ADMIN_PKG, 542 ADMIN_PKG2, 543 ADMIN_PKG3 544 }; 545 for (int userId : userIds) { 546 for (String pkg : packages) { 547 final AppIdleHistory.AppUsageHistory usageHistory = mController 548 .getAppIdleHistoryForTest().getAppUsageHistory( 549 pkg, userId, mInjector.mElapsedRealtime); 550 usageHistory.lastUsedElapsedTime = 0; 551 usageHistory.lastUsedByUserElapsedTime = 0; 552 usageHistory.lastUsedScreenTime = 0; 553 } 554 } 555 } 556 557 @Before setUp()558 public void setUp() throws Exception { 559 LocalServices.removeServiceForTest(UsageStatsManagerInternal.class); 560 LocalServices.addService( 561 UsageStatsManagerInternal.class, mock(UsageStatsManagerInternal.class)); 562 MyContextWrapper myContext = new MyContextWrapper(InstrumentationRegistry.getContext()); 563 mInjector = new MyInjector(myContext, Looper.getMainLooper()); 564 mController = setupController(); 565 setupInitialUsageHistory(); 566 } 567 568 @After tearDown()569 public void tearDown() { 570 LocalServices.removeServiceForTest(UsageStatsManagerInternal.class); 571 } 572 573 @Test 574 @FlakyTest(bugId = 185169504) testBoundWidgetPackageExempt()575 public void testBoundWidgetPackageExempt() throws Exception { 576 assumeTrue(mInjector.getContext().getSystemService(AppWidgetManager.class) != null); 577 assertEquals(STANDBY_BUCKET_ACTIVE, 578 mController.getAppStandbyBucket(PACKAGE_EXEMPTED_1, USER_ID, 579 mInjector.mElapsedRealtime, false)); 580 } 581 582 @Test testGetIdleUidsForUser()583 public void testGetIdleUidsForUser() { 584 final AppStandbyController controllerUnderTest = spy(mController); 585 586 final int userIdForTest = 325; 587 final int[] uids = new int[]{129, 23, 129, 129, 44, 23, 41, 751}; 588 final boolean[] idle = new boolean[]{true, true, false, true, false, true, false, true}; 589 // Based on uids[] and idle[], the only two uids that have all true's in idle[]. 590 final int[] expectedIdleUids = new int[]{23, 751}; 591 592 final List<ApplicationInfo> installedApps = new ArrayList<>(); 593 for (int i = 0; i < uids.length; i++) { 594 final ApplicationInfo ai = mock(ApplicationInfo.class); 595 ai.uid = uids[i]; 596 ai.packageName = "example.package.name." + i; 597 installedApps.add(ai); 598 when(controllerUnderTest.isAppIdleFiltered(eq(ai.packageName), 599 eq(UserHandle.getAppId(ai.uid)), eq(userIdForTest), anyLong())) 600 .thenReturn(idle[i]); 601 } 602 when(mInjector.mPackageManagerInternal.getInstalledApplications(anyLong(), 603 eq(userIdForTest), anyInt())).thenReturn(installedApps); 604 final int[] returnedIdleUids = controllerUnderTest.getIdleUidsForUser(userIdForTest); 605 606 assertEquals(expectedIdleUids.length, returnedIdleUids.length); 607 for (final int uid : expectedIdleUids) { 608 assertTrue("Idle uid: " + uid + " not found in result: " + Arrays.toString( 609 returnedIdleUids), ArrayUtils.contains(returnedIdleUids, uid)); 610 } 611 } 612 613 private static class TestParoleListener extends AppIdleStateChangeListener { 614 private boolean mIsParoleOn = false; 615 private CountDownLatch mLatch; 616 private boolean mIsExpecting = false; 617 private boolean mExpectedParoleState; 618 getParoleState()619 boolean getParoleState() { 620 synchronized (this) { 621 return mIsParoleOn; 622 } 623 } 624 rearmLatch(boolean expectedParoleState)625 void rearmLatch(boolean expectedParoleState) { 626 synchronized (this) { 627 mLatch = new CountDownLatch(1); 628 mIsExpecting = true; 629 mExpectedParoleState = expectedParoleState; 630 } 631 } 632 awaitOnLatch(long time)633 void awaitOnLatch(long time) throws Exception { 634 mLatch.await(time, TimeUnit.MILLISECONDS); 635 } 636 637 @Override onAppIdleStateChanged(String packageName, int userId, boolean idle, int bucket, int reason)638 public void onAppIdleStateChanged(String packageName, int userId, boolean idle, 639 int bucket, int reason) { 640 } 641 642 @Override onParoleStateChanged(boolean isParoleOn)643 public void onParoleStateChanged(boolean isParoleOn) { 644 synchronized (this) { 645 // Only record information if it is being looked for 646 if (mLatch != null && mLatch.getCount() > 0) { 647 mIsParoleOn = isParoleOn; 648 if (mIsExpecting && isParoleOn == mExpectedParoleState) { 649 mLatch.countDown(); 650 } 651 } 652 } 653 } 654 } 655 656 @Test 657 @FlakyTest(bugId = 185169504) testIsAppIdle_Charging()658 public void testIsAppIdle_Charging() throws Exception { 659 TestParoleListener paroleListener = new TestParoleListener(); 660 mController.addListener(paroleListener); 661 662 setChargingState(mController, false); 663 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 664 REASON_MAIN_FORCED_BY_SYSTEM); 665 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 666 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); 667 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false)); 668 assertFalse(mController.isInParole()); 669 670 paroleListener.rearmLatch(true); 671 setChargingState(mController, true); 672 paroleListener.awaitOnLatch(2000); 673 assertTrue(paroleListener.getParoleState()); 674 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 675 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); 676 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false)); 677 assertTrue(mController.isInParole()); 678 679 paroleListener.rearmLatch(false); 680 setChargingState(mController, false); 681 paroleListener.awaitOnLatch(2000); 682 assertFalse(paroleListener.getParoleState()); 683 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 684 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); 685 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false)); 686 assertFalse(mController.isInParole()); 687 } 688 689 @Test 690 @FlakyTest(bugId = 185169504) testIsAppIdle_Enabled()691 public void testIsAppIdle_Enabled() throws Exception { 692 setChargingState(mController, false); 693 TestParoleListener paroleListener = new TestParoleListener(); 694 mController.addListener(paroleListener); 695 696 setAppIdleEnabled(mController, true); 697 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 698 REASON_MAIN_FORCED_BY_SYSTEM); 699 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 700 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); 701 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false)); 702 703 paroleListener.rearmLatch(false); 704 setAppIdleEnabled(mController, false); 705 paroleListener.awaitOnLatch(2000); 706 assertTrue(paroleListener.mIsParoleOn); 707 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); 708 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false)); 709 710 paroleListener.rearmLatch(true); 711 setAppIdleEnabled(mController, true); 712 paroleListener.awaitOnLatch(2000); 713 assertFalse(paroleListener.getParoleState()); 714 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 715 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); 716 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false)); 717 } 718 assertTimeout(AppStandbyController controller, long elapsedTime, int bucket)719 private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket) { 720 assertTimeout(controller, elapsedTime, bucket, USER_ID); 721 } 722 assertTimeout(AppStandbyController controller, long elapsedTime, int bucket, int userId)723 private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket, 724 int userId) { 725 mInjector.mElapsedRealtime = elapsedTime; 726 controller.checkIdleStates(userId); 727 assertEquals(bucket, 728 controller.getAppStandbyBucket(PACKAGE_1, userId, mInjector.mElapsedRealtime, 729 false)); 730 } 731 reportEvent(AppStandbyController controller, int eventType, long elapsedTime, String packageName)732 private void reportEvent(AppStandbyController controller, int eventType, long elapsedTime, 733 String packageName) { 734 // Back to ACTIVE on event 735 mInjector.mElapsedRealtime = elapsedTime; 736 UsageEvents.Event ev = new UsageEvents.Event(); 737 ev.mPackage = packageName; 738 ev.mEventType = eventType; 739 controller.onUsageEvent(USER_ID, ev); 740 } 741 getStandbyBucket(AppStandbyController controller, String packageName)742 private int getStandbyBucket(AppStandbyController controller, String packageName) { 743 return getStandbyBucket(USER_ID, controller, packageName); 744 } 745 getStandbyBucket(int userId, AppStandbyController controller, String packageName)746 private int getStandbyBucket(int userId, AppStandbyController controller, String packageName) { 747 return controller.getAppStandbyBucket(packageName, userId, mInjector.mElapsedRealtime, 748 true); 749 } 750 getStandbyBucketReason(String packageName)751 private int getStandbyBucketReason(String packageName) { 752 return mController.getAppStandbyBucketReason(packageName, USER_ID, 753 mInjector.mElapsedRealtime); 754 } 755 assertBucket(int bucket)756 private void assertBucket(int bucket) throws InterruptedException { 757 assertBucket(bucket, PACKAGE_1); 758 } 759 assertBucket(int bucket, String pkg)760 private void assertBucket(int bucket, String pkg) throws InterruptedException { 761 int retries = 0; 762 do { 763 if (bucket == getStandbyBucket(mController, pkg)) { 764 // Success 765 return; 766 } 767 Thread.sleep(ASSERT_RETRY_DELAY_MILLISECONDS); 768 retries++; 769 } while(retries < ASSERT_RETRY_ATTEMPTS); 770 // try one last time 771 assertEquals(bucket, getStandbyBucket(mController, pkg)); 772 } 773 assertNotBucket(int bucket)774 private void assertNotBucket(int bucket) throws InterruptedException { 775 final String pkg = PACKAGE_1; 776 int retries = 0; 777 do { 778 if (bucket != getStandbyBucket(mController, pkg)) { 779 // Success 780 return; 781 } 782 Thread.sleep(ASSERT_RETRY_DELAY_MILLISECONDS); 783 retries++; 784 } while(retries < ASSERT_RETRY_ATTEMPTS); 785 // try one last time 786 assertNotEquals(bucket, getStandbyBucket(mController, pkg)); 787 } 788 789 @Test 790 @FlakyTest(bugId = 185169504) testBuckets()791 public void testBuckets() throws Exception { 792 assertTimeout(mController, 0, STANDBY_BUCKET_NEVER); 793 794 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 795 796 // ACTIVE bucket 797 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE); 798 799 // WORKING_SET bucket 800 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET); 801 802 // WORKING_SET bucket 803 assertTimeout(mController, FREQUENT_THRESHOLD - 1, STANDBY_BUCKET_WORKING_SET); 804 805 // FREQUENT bucket 806 assertTimeout(mController, FREQUENT_THRESHOLD + 1, STANDBY_BUCKET_FREQUENT); 807 808 // RARE bucket 809 assertTimeout(mController, RARE_THRESHOLD + 1, STANDBY_BUCKET_RARE); 810 811 // RESTRICTED bucket 812 assertTimeout(mController, RESTRICTED_THRESHOLD + 1, STANDBY_BUCKET_RESTRICTED); 813 814 reportEvent(mController, USER_INTERACTION, RARE_THRESHOLD + 1, PACKAGE_1); 815 816 assertTimeout(mController, RARE_THRESHOLD + 1, STANDBY_BUCKET_ACTIVE); 817 818 // RESTRICTED bucket 819 assertTimeout(mController, RESTRICTED_THRESHOLD * 2 + 2, STANDBY_BUCKET_RESTRICTED); 820 } 821 822 @Test 823 @FlakyTest(bugId = 185169504) testSetAppStandbyBucket()824 public void testSetAppStandbyBucket() throws Exception { 825 // For a known package, standby bucket should be set properly 826 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 827 mInjector.mElapsedRealtime = HOUR_MS; 828 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 829 REASON_MAIN_TIMEOUT); 830 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 831 832 // For an unknown package, standby bucket should not be set, hence NEVER is returned 833 // Ensure the unknown package is not already in history by removing it 834 mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID); 835 isPackageInstalled = false; // Mock package is not installed 836 mController.setAppStandbyBucket(PACKAGE_UNKNOWN, USER_ID, STANDBY_BUCKET_ACTIVE, 837 REASON_MAIN_TIMEOUT); 838 isPackageInstalled = true; // Reset mocked variable for other tests 839 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN)); 840 } 841 842 @Test 843 @FlakyTest(bugId = 185169504) testAppStandbyBucketOnInstallAndUninstall()844 public void testAppStandbyBucketOnInstallAndUninstall() throws Exception { 845 // On package install, standby bucket should be ACTIVE 846 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_UNKNOWN); 847 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_UNKNOWN)); 848 849 // On uninstall, package should not exist in history and should return a NEVER bucket 850 mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID); 851 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN)); 852 // Ensure uninstalled app is not in history 853 List<AppStandbyInfo> buckets = mController.getAppStandbyBuckets(USER_ID); 854 for(AppStandbyInfo bucket : buckets) { 855 if (bucket.mPackageName.equals(PACKAGE_UNKNOWN)) { 856 fail("packageName found in app idle history after uninstall."); 857 } 858 } 859 } 860 861 @Test 862 @FlakyTest(bugId = 185169504) testScreenTimeAndBuckets()863 public void testScreenTimeAndBuckets() throws Exception { 864 mInjector.setDisplayOn(false); 865 866 assertTimeout(mController, 0, STANDBY_BUCKET_NEVER); 867 868 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 869 870 // ACTIVE bucket 871 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE); 872 873 // WORKING_SET bucket 874 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET); 875 876 // RARE bucket, should fail because the screen wasn't ON. 877 mInjector.mElapsedRealtime = RARE_THRESHOLD + 1; 878 mController.checkIdleStates(USER_ID); 879 assertNotEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 880 881 mInjector.setDisplayOn(true); 882 assertTimeout(mController, RARE_THRESHOLD + 2 * HOUR_MS + 1, STANDBY_BUCKET_RARE); 883 } 884 885 @Test 886 @FlakyTest(bugId = 185169504) testForcedIdle()887 public void testForcedIdle() throws Exception { 888 mController.forceIdleState(PACKAGE_1, USER_ID, true); 889 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 890 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); 891 892 mController.forceIdleState(PACKAGE_1, USER_ID, false); 893 assertEquals(STANDBY_BUCKET_ACTIVE, mController.getAppStandbyBucket(PACKAGE_1, USER_ID, 0, 894 true)); 895 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); 896 } 897 898 @Test testNotificationEvent_bucketPromotion()899 public void testNotificationEvent_bucketPromotion() throws Exception { 900 mInjector.mPropertiesChangedListener 901 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 902 903 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 904 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 905 mInjector.mElapsedRealtime = 1; 906 rearmQuotaBumpLatch(PACKAGE_1, USER_ID); 907 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1); 908 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 909 910 mController.forceIdleState(PACKAGE_1, USER_ID, true); 911 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1); 912 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1)); 913 assertFalse(mQuotaBumpLatch.await(1, TimeUnit.SECONDS)); 914 } 915 916 @Test testNotificationEvent_bucketPromotion_changePromotedBucket()917 public void testNotificationEvent_bucketPromotion_changePromotedBucket() throws Exception { 918 mInjector.mPropertiesChangedListener 919 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 920 mController.forceIdleState(PACKAGE_1, USER_ID, true); 921 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1); 922 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1)); 923 924 // TODO: Avoid hardcoding these string constants. 925 mInjector.mSettingsBuilder.setInt("notification_seen_promoted_bucket", 926 STANDBY_BUCKET_FREQUENT); 927 mInjector.mPropertiesChangedListener.onPropertiesChanged( 928 mInjector.getDeviceConfigProperties()); 929 mController.forceIdleState(PACKAGE_1, USER_ID, true); 930 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1); 931 assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1)); 932 } 933 934 @Test 935 @FlakyTest(bugId = 185169504) testNotificationEvent_quotaBump()936 public void testNotificationEvent_quotaBump() throws Exception { 937 mInjector.mSettingsBuilder 938 .setBoolean("trigger_quota_bump_on_notification_seen", true); 939 mInjector.mSettingsBuilder 940 .setInt("notification_seen_promoted_bucket", STANDBY_BUCKET_NEVER); 941 mInjector.mPropertiesChangedListener 942 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 943 944 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 945 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 946 mInjector.mElapsedRealtime = RARE_THRESHOLD * 2; 947 setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM); 948 949 rearmQuotaBumpLatch(PACKAGE_1, USER_ID); 950 mInjector.mElapsedRealtime += 1; 951 952 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1); 953 assertTrue(mQuotaBumpLatch.await(1, TimeUnit.SECONDS)); 954 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 955 } 956 957 @Test 958 @FlakyTest(bugId = 185169504) testSlicePinnedEvent()959 public void testSlicePinnedEvent() throws Exception { 960 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 961 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 962 mInjector.mElapsedRealtime = 1; 963 reportEvent(mController, SLICE_PINNED, mInjector.mElapsedRealtime, PACKAGE_1); 964 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 965 966 mController.forceIdleState(PACKAGE_1, USER_ID, true); 967 reportEvent(mController, SLICE_PINNED, mInjector.mElapsedRealtime, PACKAGE_1); 968 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1)); 969 } 970 971 @Test 972 @FlakyTest(bugId = 185169504) testSlicePinnedPrivEvent()973 public void testSlicePinnedPrivEvent() throws Exception { 974 mController.forceIdleState(PACKAGE_1, USER_ID, true); 975 reportEvent(mController, SLICE_PINNED_PRIV, mInjector.mElapsedRealtime, PACKAGE_1); 976 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 977 } 978 979 @Test 980 @FlakyTest(bugId = 185169504) testPredictionTimedOut()981 public void testPredictionTimedOut() throws Exception { 982 // Set it to timeout or usage, so that prediction can override it 983 mInjector.mElapsedRealtime = HOUR_MS; 984 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 985 REASON_MAIN_TIMEOUT); 986 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 987 988 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 989 REASON_MAIN_PREDICTED); 990 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 991 992 // Fast forward 12 hours 993 mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD; 994 mController.checkIdleStates(USER_ID); 995 // Should still be in predicted bucket, since prediction timeout is 1 day since prediction 996 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 997 // Fast forward two more hours 998 mInjector.mElapsedRealtime += 2 * HOUR_MS; 999 mController.checkIdleStates(USER_ID); 1000 // Should have now applied prediction timeout 1001 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1)); 1002 1003 // Fast forward RARE bucket 1004 mInjector.mElapsedRealtime += RARE_THRESHOLD; 1005 mController.checkIdleStates(USER_ID); 1006 // Should continue to apply prediction timeout 1007 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 1008 } 1009 1010 @Test 1011 @FlakyTest(bugId = 185169504) testOverrides()1012 public void testOverrides() throws Exception { 1013 // Can force to NEVER 1014 mInjector.mElapsedRealtime = HOUR_MS; 1015 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, 1016 REASON_MAIN_FORCED_BY_USER); 1017 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1)); 1018 1019 // Prediction can't override FORCED reasons 1020 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 1021 REASON_MAIN_FORCED_BY_SYSTEM); 1022 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1023 REASON_MAIN_PREDICTED); 1024 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 1025 1026 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, 1027 REASON_MAIN_FORCED_BY_USER); 1028 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1029 REASON_MAIN_PREDICTED); 1030 assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1)); 1031 1032 // Prediction can't override NEVER 1033 mInjector.mElapsedRealtime = 2 * HOUR_MS; 1034 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, 1035 REASON_MAIN_DEFAULT); 1036 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 1037 REASON_MAIN_PREDICTED); 1038 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1)); 1039 1040 // Prediction can't set to NEVER 1041 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 1042 REASON_MAIN_USAGE); 1043 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, 1044 REASON_MAIN_PREDICTED); 1045 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 1046 1047 // Prediction can't remove from RESTRICTED 1048 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1049 REASON_MAIN_FORCED_BY_USER); 1050 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1051 REASON_MAIN_PREDICTED); 1052 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1053 1054 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1055 REASON_MAIN_FORCED_BY_SYSTEM); 1056 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1057 REASON_MAIN_PREDICTED); 1058 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1059 1060 // Force from user can remove from RESTRICTED 1061 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1062 REASON_MAIN_FORCED_BY_USER); 1063 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1064 REASON_MAIN_FORCED_BY_USER); 1065 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1)); 1066 1067 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1068 REASON_MAIN_FORCED_BY_SYSTEM); 1069 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1070 REASON_MAIN_FORCED_BY_USER); 1071 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1)); 1072 1073 // Force from system can remove from RESTRICTED if it was put it in due to system 1074 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1075 REASON_MAIN_FORCED_BY_SYSTEM); 1076 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1077 REASON_MAIN_FORCED_BY_SYSTEM); 1078 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1)); 1079 1080 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1081 REASON_MAIN_FORCED_BY_USER); 1082 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1083 REASON_MAIN_FORCED_BY_SYSTEM); 1084 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1085 1086 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1087 REASON_MAIN_PREDICTED); 1088 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1089 REASON_MAIN_FORCED_BY_SYSTEM); 1090 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1091 1092 // Non-user usage can't remove from RESTRICTED 1093 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1094 REASON_MAIN_FORCED_BY_SYSTEM); 1095 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1096 REASON_MAIN_USAGE); 1097 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1098 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1099 REASON_MAIN_USAGE | REASON_SUB_USAGE_SYSTEM_INTERACTION); 1100 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1101 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1102 REASON_MAIN_USAGE | REASON_SUB_USAGE_SYNC_ADAPTER); 1103 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1104 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1105 REASON_MAIN_USAGE | REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE); 1106 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1107 1108 // Explicit user usage can remove from RESTRICTED 1109 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1110 REASON_MAIN_FORCED_BY_USER); 1111 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1112 REASON_MAIN_USAGE | REASON_SUB_USAGE_USER_INTERACTION); 1113 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1)); 1114 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1115 REASON_MAIN_FORCED_BY_SYSTEM); 1116 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 1117 REASON_MAIN_USAGE | REASON_SUB_USAGE_MOVE_TO_FOREGROUND); 1118 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 1119 } 1120 1121 @Test 1122 @FlakyTest(bugId = 185169504) testTimeout()1123 public void testTimeout() throws Exception { 1124 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 1125 assertBucket(STANDBY_BUCKET_ACTIVE); 1126 1127 mInjector.mElapsedRealtime = 2000; 1128 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, 1129 REASON_MAIN_PREDICTED); 1130 assertBucket(STANDBY_BUCKET_ACTIVE); 1131 1132 // bucketing works after timeout 1133 mInjector.mElapsedRealtime = mController.mPredictionTimeoutMillis - 100; 1134 mController.checkIdleStates(USER_ID); 1135 // Use recent prediction 1136 assertBucket(STANDBY_BUCKET_FREQUENT); 1137 1138 // Way past prediction timeout, use system thresholds 1139 mInjector.mElapsedRealtime = RARE_THRESHOLD; 1140 mController.checkIdleStates(USER_ID); 1141 assertBucket(STANDBY_BUCKET_RARE); 1142 } 1143 1144 /** Test that timeouts still work properly even if invalid configuration values are set. */ 1145 @Test 1146 @FlakyTest(bugId = 185169504) testTimeout_InvalidThresholds()1147 public void testTimeout_InvalidThresholds() throws Exception { 1148 mInjector.mSettingsBuilder 1149 .setLong("screen_threshold_active", -1) 1150 .setLong("screen_threshold_working_set", -1) 1151 .setLong("screen_threshold_frequent", -1) 1152 .setLong("screen_threshold_rare", -1) 1153 .setLong("screen_threshold_restricted", -1) 1154 .setLong("elapsed_threshold_active", -1) 1155 .setLong("elapsed_threshold_working_set", -1) 1156 .setLong("elapsed_threshold_frequent", -1) 1157 .setLong("elapsed_threshold_rare", -1) 1158 .setLong("elapsed_threshold_restricted", -1); 1159 mInjector.mPropertiesChangedListener 1160 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 1161 1162 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 1163 mController.checkIdleStates(USER_ID); 1164 assertBucket(STANDBY_BUCKET_ACTIVE); 1165 1166 mInjector.mElapsedRealtime = HOUR_MS; 1167 mController.checkIdleStates(USER_ID); 1168 assertBucket(STANDBY_BUCKET_FREQUENT); 1169 1170 mInjector.mElapsedRealtime = 2 * HOUR_MS; 1171 mController.checkIdleStates(USER_ID); 1172 assertBucket(STANDBY_BUCKET_RARE); 1173 1174 mInjector.mElapsedRealtime = 4 * HOUR_MS; 1175 mController.checkIdleStates(USER_ID); 1176 assertBucket(STANDBY_BUCKET_RESTRICTED); 1177 } 1178 1179 /** 1180 * Test that setAppStandbyBucket to RESTRICTED doesn't change the bucket until the usage 1181 * timeout has passed. 1182 */ 1183 @Test 1184 @FlakyTest(bugId = 185169504) testTimeoutBeforeRestricted()1185 public void testTimeoutBeforeRestricted() throws Exception { 1186 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 1187 assertBucket(STANDBY_BUCKET_ACTIVE); 1188 1189 mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD; 1190 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1191 REASON_MAIN_FORCED_BY_SYSTEM); 1192 // Bucket shouldn't change 1193 assertBucket(STANDBY_BUCKET_ACTIVE); 1194 1195 // bucketing works after timeout 1196 mInjector.mElapsedRealtime += DAY_MS; 1197 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1198 REASON_MAIN_FORCED_BY_SYSTEM); 1199 assertBucket(STANDBY_BUCKET_RESTRICTED); 1200 1201 // Way past all timeouts. Make sure timeout processing doesn't raise bucket. 1202 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4; 1203 mController.checkIdleStates(USER_ID); 1204 assertBucket(STANDBY_BUCKET_RESTRICTED); 1205 } 1206 1207 /** 1208 * Test that an app is put into the RESTRICTED bucket after enough time has passed. 1209 */ 1210 @Test 1211 @FlakyTest(bugId = 185169504) testRestrictedDelay()1212 public void testRestrictedDelay() throws Exception { 1213 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 1214 assertBucket(STANDBY_BUCKET_ACTIVE); 1215 1216 mInjector.mElapsedRealtime += mInjector.getAutoRestrictedBucketDelayMs() - 5000; 1217 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1218 REASON_MAIN_FORCED_BY_SYSTEM); 1219 // Bucket shouldn't change 1220 assertBucket(STANDBY_BUCKET_ACTIVE); 1221 1222 // bucketing works after timeout 1223 mInjector.mElapsedRealtime += 6000; 1224 1225 Thread.sleep(6000); 1226 // Enough time has passed. The app should automatically be put into the RESTRICTED bucket. 1227 assertBucket(STANDBY_BUCKET_RESTRICTED); 1228 } 1229 1230 /** 1231 * Test that an app is put into the RESTRICTED bucket after enough time has passed. 1232 */ 1233 @Test 1234 @FlakyTest(bugId = 185169504) testRestrictedDelay_DelayChange()1235 public void testRestrictedDelay_DelayChange() throws Exception { 1236 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 1237 assertBucket(STANDBY_BUCKET_ACTIVE); 1238 1239 mInjector.mAutoRestrictedBucketDelayMs = 2 * HOUR_MS; 1240 mInjector.mElapsedRealtime += 2 * HOUR_MS - 5000; 1241 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1242 REASON_MAIN_FORCED_BY_SYSTEM); 1243 // Bucket shouldn't change 1244 assertBucket(STANDBY_BUCKET_ACTIVE); 1245 1246 // bucketing works after timeout 1247 mInjector.mElapsedRealtime += 6000; 1248 1249 Thread.sleep(6000); 1250 // Enough time has passed. The app should automatically be put into the RESTRICTED bucket. 1251 assertBucket(STANDBY_BUCKET_RESTRICTED); 1252 } 1253 1254 /** 1255 * Test that an app is "timed out" into the RESTRICTED bucket if prediction tries to put it into 1256 * a low bucket after the RESTRICTED timeout. 1257 */ 1258 @Test 1259 @FlakyTest(bugId = 185169504) testRestrictedTimeoutOverridesRestoredLowBucketPrediction()1260 public void testRestrictedTimeoutOverridesRestoredLowBucketPrediction() throws Exception { 1261 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1262 assertBucket(STANDBY_BUCKET_ACTIVE); 1263 1264 // Predict to RARE Not long enough to time out into RESTRICTED. 1265 mInjector.mElapsedRealtime += RARE_THRESHOLD; 1266 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 1267 REASON_MAIN_PREDICTED); 1268 assertBucket(STANDBY_BUCKET_RARE); 1269 1270 // Add a short timeout event 1271 mInjector.mElapsedRealtime += 1000; 1272 reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1273 assertBucket(STANDBY_BUCKET_ACTIVE); 1274 mInjector.mElapsedRealtime += 1000; 1275 mController.checkIdleStates(USER_ID); 1276 assertBucket(STANDBY_BUCKET_ACTIVE); 1277 1278 // Long enough that it could have timed out into RESTRICTED. Instead of reverting to 1279 // predicted RARE, should go into RESTRICTED 1280 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4; 1281 mController.checkIdleStates(USER_ID); 1282 assertBucket(STANDBY_BUCKET_RESTRICTED); 1283 1284 // Ensure that prediction can still raise it out despite this override. 1285 mInjector.mElapsedRealtime += 1; 1286 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 1287 REASON_MAIN_PREDICTED); 1288 assertBucket(STANDBY_BUCKET_ACTIVE); 1289 } 1290 1291 /** 1292 * Test that an app is "timed out" into the RESTRICTED bucket if prediction tries to put it into 1293 * a low bucket after the RESTRICTED timeout. 1294 */ 1295 @Test 1296 @FlakyTest(bugId = 185169504) testRestrictedTimeoutOverridesPredictionLowBucket()1297 public void testRestrictedTimeoutOverridesPredictionLowBucket() throws Exception { 1298 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1299 1300 // Not long enough to time out into RESTRICTED. 1301 mInjector.mElapsedRealtime += RARE_THRESHOLD; 1302 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 1303 REASON_MAIN_PREDICTED); 1304 assertBucket(STANDBY_BUCKET_RARE); 1305 1306 mInjector.mElapsedRealtime += 1; 1307 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1308 1309 // Long enough that it could have timed out into RESTRICTED. 1310 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4; 1311 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 1312 REASON_MAIN_PREDICTED); 1313 assertBucket(STANDBY_BUCKET_ACTIVE); 1314 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 1315 REASON_MAIN_PREDICTED); 1316 assertBucket(STANDBY_BUCKET_RESTRICTED); 1317 } 1318 1319 /** 1320 * Test that an app that "timed out" into the RESTRICTED bucket can be raised out by system 1321 * interaction. 1322 */ 1323 @Test 1324 @FlakyTest(bugId = 185169504) testSystemInteractionOverridesRestrictedTimeout()1325 public void testSystemInteractionOverridesRestrictedTimeout() throws Exception { 1326 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1327 assertBucket(STANDBY_BUCKET_ACTIVE); 1328 1329 // Long enough that it could have timed out into RESTRICTED. 1330 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4; 1331 mController.checkIdleStates(USER_ID); 1332 assertBucket(STANDBY_BUCKET_RESTRICTED); 1333 1334 // Report system interaction. 1335 mInjector.mElapsedRealtime += 1000; 1336 reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1337 1338 // Ensure that it's raised out of RESTRICTED for the system interaction elevation duration. 1339 assertBucket(STANDBY_BUCKET_ACTIVE); 1340 mInjector.mElapsedRealtime += 1000; 1341 mController.checkIdleStates(USER_ID); 1342 assertBucket(STANDBY_BUCKET_ACTIVE); 1343 1344 // Elevation duration over. Should fall back down. 1345 mInjector.mElapsedRealtime += 10 * MINUTE_MS; 1346 mController.checkIdleStates(USER_ID); 1347 assertBucket(STANDBY_BUCKET_RESTRICTED); 1348 } 1349 1350 @Test 1351 @FlakyTest(bugId = 185169504) testPredictionRaiseFromRestrictedTimeout_highBucket()1352 public void testPredictionRaiseFromRestrictedTimeout_highBucket() throws Exception { 1353 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1354 1355 // Way past all timeouts. App times out into RESTRICTED bucket. 1356 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4; 1357 mController.checkIdleStates(USER_ID); 1358 assertBucket(STANDBY_BUCKET_RESTRICTED); 1359 1360 // Since the app timed out into RESTRICTED, prediction should be able to remove from the 1361 // bucket. 1362 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD; 1363 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 1364 REASON_MAIN_PREDICTED); 1365 assertBucket(STANDBY_BUCKET_ACTIVE); 1366 } 1367 1368 @Test 1369 @FlakyTest(bugId = 185169504) testPredictionRaiseFromRestrictedTimeout_lowBucket()1370 public void testPredictionRaiseFromRestrictedTimeout_lowBucket() throws Exception { 1371 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1372 1373 // Way past all timeouts. App times out into RESTRICTED bucket. 1374 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4; 1375 mController.checkIdleStates(USER_ID); 1376 assertBucket(STANDBY_BUCKET_RESTRICTED); 1377 1378 // Prediction into a low bucket means no expectation of the app being used, so we shouldn't 1379 // elevate the app from RESTRICTED. 1380 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD; 1381 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 1382 REASON_MAIN_PREDICTED); 1383 assertBucket(STANDBY_BUCKET_RESTRICTED); 1384 } 1385 1386 @Test 1387 @FlakyTest(bugId = 185169504) testCascadingTimeouts()1388 public void testCascadingTimeouts() throws Exception { 1389 mInjector.mPropertiesChangedListener 1390 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 1391 1392 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 1393 assertBucket(STANDBY_BUCKET_ACTIVE); 1394 1395 reportEvent(mController, NOTIFICATION_SEEN, 1000, PACKAGE_1); 1396 assertBucket(STANDBY_BUCKET_ACTIVE); 1397 1398 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 1399 REASON_MAIN_PREDICTED); 1400 assertBucket(STANDBY_BUCKET_ACTIVE); 1401 1402 mInjector.mElapsedRealtime = 2000 + mController.mStrongUsageTimeoutMillis; 1403 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, 1404 REASON_MAIN_PREDICTED); 1405 assertBucket(STANDBY_BUCKET_WORKING_SET); 1406 1407 mInjector.mElapsedRealtime = 2000 + mController.mNotificationSeenTimeoutMillis; 1408 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, 1409 REASON_MAIN_PREDICTED); 1410 assertBucket(STANDBY_BUCKET_FREQUENT); 1411 } 1412 1413 @Test 1414 @FlakyTest(bugId = 185169504) testOverlappingTimeouts()1415 public void testOverlappingTimeouts() throws Exception { 1416 mInjector.mPropertiesChangedListener 1417 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 1418 1419 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 1420 assertBucket(STANDBY_BUCKET_ACTIVE); 1421 1422 reportEvent(mController, NOTIFICATION_SEEN, 1000, PACKAGE_1); 1423 assertBucket(STANDBY_BUCKET_ACTIVE); 1424 1425 // Overlapping USER_INTERACTION before previous one times out 1426 reportEvent(mController, USER_INTERACTION, mController.mStrongUsageTimeoutMillis - 1000, 1427 PACKAGE_1); 1428 assertBucket(STANDBY_BUCKET_ACTIVE); 1429 1430 // Still in ACTIVE after first USER_INTERACTION times out 1431 mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis + 1000; 1432 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, 1433 REASON_MAIN_PREDICTED); 1434 assertBucket(STANDBY_BUCKET_ACTIVE); 1435 1436 // Both timed out, so NOTIFICATION_SEEN timeout should be effective 1437 mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis * 2 + 2000; 1438 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, 1439 REASON_MAIN_PREDICTED); 1440 assertBucket(STANDBY_BUCKET_WORKING_SET); 1441 1442 mInjector.mElapsedRealtime = mController.mNotificationSeenTimeoutMillis + 2000; 1443 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 1444 REASON_MAIN_PREDICTED); 1445 assertBucket(STANDBY_BUCKET_RARE); 1446 } 1447 1448 @Test 1449 @FlakyTest(bugId = 185169504) testSystemInteractionTimeout()1450 public void testSystemInteractionTimeout() throws Exception { 1451 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 1452 // Fast forward to RARE 1453 mInjector.mElapsedRealtime = RARE_THRESHOLD + 100; 1454 mController.checkIdleStates(USER_ID); 1455 assertBucket(STANDBY_BUCKET_RARE); 1456 1457 // Trigger a SYSTEM_INTERACTION and verify bucket 1458 reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1459 assertBucket(STANDBY_BUCKET_ACTIVE); 1460 1461 // Verify it's still in ACTIVE close to end of timeout 1462 mInjector.mElapsedRealtime += mController.mSystemInteractionTimeoutMillis - 100; 1463 mController.checkIdleStates(USER_ID); 1464 assertBucket(STANDBY_BUCKET_ACTIVE); 1465 1466 // Verify bucket moves to RARE after timeout 1467 mInjector.mElapsedRealtime += 200; 1468 mController.checkIdleStates(USER_ID); 1469 assertBucket(STANDBY_BUCKET_RARE); 1470 } 1471 1472 @Test 1473 @FlakyTest(bugId = 185169504) testInitialForegroundServiceTimeout()1474 public void testInitialForegroundServiceTimeout() throws Exception { 1475 mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100; 1476 // Make sure app is in NEVER bucket 1477 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, 1478 REASON_MAIN_FORCED_BY_USER); 1479 mController.checkIdleStates(USER_ID); 1480 assertBucket(STANDBY_BUCKET_NEVER); 1481 1482 mInjector.mElapsedRealtime += 100; 1483 1484 // Trigger a FOREGROUND_SERVICE_START and verify bucket 1485 reportEvent(mController, FOREGROUND_SERVICE_START, mInjector.mElapsedRealtime, PACKAGE_1); 1486 mController.checkIdleStates(USER_ID); 1487 assertBucket(STANDBY_BUCKET_ACTIVE); 1488 1489 // Verify it's still in ACTIVE close to end of timeout 1490 mInjector.mElapsedRealtime += mController.mInitialForegroundServiceStartTimeoutMillis - 100; 1491 mController.checkIdleStates(USER_ID); 1492 assertBucket(STANDBY_BUCKET_ACTIVE); 1493 1494 // Verify bucket moves to RARE after timeout 1495 mInjector.mElapsedRealtime += 200; 1496 mController.checkIdleStates(USER_ID); 1497 assertBucket(STANDBY_BUCKET_RARE); 1498 1499 // Trigger a FOREGROUND_SERVICE_START again 1500 reportEvent(mController, FOREGROUND_SERVICE_START, mInjector.mElapsedRealtime, PACKAGE_1); 1501 mController.checkIdleStates(USER_ID); 1502 // Bucket should not be immediately elevated on subsequent service starts 1503 assertBucket(STANDBY_BUCKET_RARE); 1504 } 1505 1506 @Test 1507 @FlakyTest(bugId = 185169504) testPredictionNotOverridden()1508 public void testPredictionNotOverridden() throws Exception { 1509 mInjector.mPropertiesChangedListener 1510 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 1511 1512 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 1513 assertBucket(STANDBY_BUCKET_ACTIVE); 1514 1515 mInjector.mElapsedRealtime = WORKING_SET_THRESHOLD - 1000; 1516 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1); 1517 assertBucket(STANDBY_BUCKET_ACTIVE); 1518 1519 // Falls back to WORKING_SET 1520 mInjector.mElapsedRealtime += 5000; 1521 mController.checkIdleStates(USER_ID); 1522 assertBucket(STANDBY_BUCKET_WORKING_SET); 1523 1524 // Predict to ACTIVE 1525 mInjector.mElapsedRealtime += 1000; 1526 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 1527 REASON_MAIN_PREDICTED); 1528 assertBucket(STANDBY_BUCKET_ACTIVE); 1529 1530 // CheckIdleStates should not change the prediction 1531 mInjector.mElapsedRealtime += 1000; 1532 mController.checkIdleStates(USER_ID); 1533 assertBucket(STANDBY_BUCKET_ACTIVE); 1534 } 1535 1536 @Test 1537 @FlakyTest(bugId = 185169504) testPredictionStrikesBack()1538 public void testPredictionStrikesBack() throws Exception { 1539 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 1540 assertBucket(STANDBY_BUCKET_ACTIVE); 1541 1542 // Predict to FREQUENT 1543 mInjector.mElapsedRealtime = RARE_THRESHOLD; 1544 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, 1545 REASON_MAIN_PREDICTED); 1546 assertBucket(STANDBY_BUCKET_FREQUENT); 1547 1548 // Add a short timeout event 1549 mInjector.mElapsedRealtime += 1000; 1550 reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1551 assertBucket(STANDBY_BUCKET_ACTIVE); 1552 mInjector.mElapsedRealtime += 1000; 1553 mController.checkIdleStates(USER_ID); 1554 assertBucket(STANDBY_BUCKET_ACTIVE); 1555 1556 // Verify it reverted to predicted 1557 mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD / 2; 1558 mController.checkIdleStates(USER_ID); 1559 assertBucket(STANDBY_BUCKET_FREQUENT); 1560 } 1561 1562 @Test 1563 @FlakyTest(bugId = 185169504) testSystemForcedFlags_NotAddedForUserForce()1564 public void testSystemForcedFlags_NotAddedForUserForce() throws Exception { 1565 final int expectedReason = REASON_MAIN_FORCED_BY_USER; 1566 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1567 REASON_MAIN_FORCED_BY_USER); 1568 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1569 assertEquals(expectedReason, getStandbyBucketReason(PACKAGE_1)); 1570 1571 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1572 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE); 1573 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1574 assertEquals(expectedReason, getStandbyBucketReason(PACKAGE_1)); 1575 } 1576 1577 @Test 1578 @FlakyTest(bugId = 185169504) testSystemForcedFlags_AddedForSystemForce()1579 public void testSystemForcedFlags_AddedForSystemForce() throws Exception { 1580 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 1581 REASON_MAIN_DEFAULT); 1582 mInjector.mElapsedRealtime += 4 * RESTRICTED_THRESHOLD; 1583 1584 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1585 REASON_MAIN_FORCED_BY_SYSTEM 1586 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE); 1587 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1588 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM 1589 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE, 1590 getStandbyBucketReason(PACKAGE_1)); 1591 1592 mController.restrictApp(PACKAGE_1, USER_ID, REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE); 1593 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1594 // Flags should be combined 1595 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM 1596 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE 1597 | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE, getStandbyBucketReason(PACKAGE_1)); 1598 } 1599 1600 @Test 1601 @FlakyTest(bugId = 185169504) testSystemForcedFlags_SystemForceChangesBuckets()1602 public void testSystemForcedFlags_SystemForceChangesBuckets() throws Exception { 1603 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 1604 REASON_MAIN_DEFAULT); 1605 mInjector.mElapsedRealtime += 4 * RESTRICTED_THRESHOLD; 1606 1607 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, 1608 REASON_MAIN_FORCED_BY_SYSTEM 1609 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE); 1610 assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1)); 1611 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM 1612 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE, 1613 getStandbyBucketReason(PACKAGE_1)); 1614 1615 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, 1616 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE); 1617 assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1)); 1618 // Flags should be combined 1619 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM 1620 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE 1621 | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE, 1622 getStandbyBucketReason(PACKAGE_1)); 1623 1624 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 1625 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY); 1626 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 1627 // Flags should be combined 1628 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY, 1629 getStandbyBucketReason(PACKAGE_1)); 1630 1631 mController.restrictApp(PACKAGE_1, USER_ID, REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED); 1632 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1633 // Flags should not be combined since the bucket changed. 1634 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED, 1635 getStandbyBucketReason(PACKAGE_1)); 1636 } 1637 1638 @Test 1639 @FlakyTest(bugId = 185169504) testRestrictApp_MainReason()1640 public void testRestrictApp_MainReason() throws Exception { 1641 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 1642 REASON_MAIN_DEFAULT); 1643 mInjector.mElapsedRealtime += 4 * RESTRICTED_THRESHOLD; 1644 1645 mController.restrictApp(PACKAGE_1, USER_ID, REASON_MAIN_PREDICTED, 0); 1646 // Call should be ignored. 1647 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 1648 1649 mController.restrictApp(PACKAGE_1, USER_ID, REASON_MAIN_FORCED_BY_USER, 0); 1650 // Call should go through 1651 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1652 } 1653 1654 @Test testAddActiveDeviceAdmin()1655 public void testAddActiveDeviceAdmin() throws Exception { 1656 assertActiveAdmins(USER_ID, (String[]) null); 1657 assertActiveAdmins(USER_ID2, (String[]) null); 1658 1659 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID); 1660 assertActiveAdmins(USER_ID, ADMIN_PKG); 1661 assertActiveAdmins(USER_ID2, (String[]) null); 1662 1663 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID); 1664 assertActiveAdmins(USER_ID, ADMIN_PKG); 1665 assertActiveAdmins(USER_ID2, (String[]) null); 1666 1667 mController.addActiveDeviceAdmin(ADMIN_PKG2, USER_ID2); 1668 assertActiveAdmins(USER_ID, ADMIN_PKG); 1669 assertActiveAdmins(USER_ID2, ADMIN_PKG2); 1670 } 1671 1672 @Test testSetActiveAdminApps()1673 public void testSetActiveAdminApps() { 1674 assertActiveAdmins(USER_ID, (String[]) null); 1675 assertActiveAdmins(USER_ID2, (String[]) null); 1676 1677 setActiveAdmins(USER_ID, ADMIN_PKG, ADMIN_PKG2); 1678 assertActiveAdmins(USER_ID, ADMIN_PKG, ADMIN_PKG2); 1679 assertActiveAdmins(USER_ID2, (String[]) null); 1680 1681 mController.addActiveDeviceAdmin(ADMIN_PKG2, USER_ID2); 1682 setActiveAdmins(USER_ID2, ADMIN_PKG); 1683 assertActiveAdmins(USER_ID, ADMIN_PKG, ADMIN_PKG2); 1684 assertActiveAdmins(USER_ID2, ADMIN_PKG); 1685 1686 mController.setActiveAdminApps(null, USER_ID); 1687 assertActiveAdmins(USER_ID, (String[]) null); 1688 } 1689 1690 @Test isActiveDeviceAdmin()1691 public void isActiveDeviceAdmin() throws Exception { 1692 assertActiveAdmins(USER_ID, (String[]) null); 1693 assertActiveAdmins(USER_ID2, (String[]) null); 1694 1695 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID); 1696 assertIsActiveAdmin(ADMIN_PKG, USER_ID); 1697 assertIsNotActiveAdmin(ADMIN_PKG, USER_ID2); 1698 1699 mController.addActiveDeviceAdmin(ADMIN_PKG2, USER_ID2); 1700 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID2); 1701 assertIsActiveAdmin(ADMIN_PKG, USER_ID); 1702 assertIsNotActiveAdmin(ADMIN_PKG2, USER_ID); 1703 assertIsActiveAdmin(ADMIN_PKG, USER_ID2); 1704 assertIsActiveAdmin(ADMIN_PKG2, USER_ID2); 1705 1706 setActiveAdmins(USER_ID2, ADMIN_PKG2); 1707 assertIsActiveAdmin(ADMIN_PKG2, USER_ID2); 1708 assertIsNotActiveAdmin(ADMIN_PKG, USER_ID2); 1709 assertIsActiveAdmin(ADMIN_PKG, USER_ID); 1710 assertIsNotActiveAdmin(ADMIN_PKG2, USER_ID); 1711 } 1712 1713 @Test testSetAdminProtectedPackages()1714 public void testSetAdminProtectedPackages() { 1715 assertAdminProtectedPackagesForTest(USER_ID, (String[]) null); 1716 assertAdminProtectedPackagesForTest(USER_ID2, (String[]) null); 1717 1718 setAdminProtectedPackages(USER_ID, ADMIN_PROTECTED_PKG, ADMIN_PROTECTED_PKG2); 1719 assertAdminProtectedPackagesForTest(USER_ID, ADMIN_PROTECTED_PKG, ADMIN_PROTECTED_PKG2); 1720 assertAdminProtectedPackagesForTest(USER_ID2, (String[]) null); 1721 1722 setAdminProtectedPackages(USER_ID, (String[]) null); 1723 assertAdminProtectedPackagesForTest(USER_ID, (String[]) null); 1724 } 1725 1726 @Test 1727 @FlakyTest(bugId = 185169504) testUserInteraction_CrossProfile()1728 public void testUserInteraction_CrossProfile() throws Exception { 1729 mInjector.mRunningUsers = new int[] {USER_ID, USER_ID2, USER_ID3}; 1730 mInjector.mCrossProfileTargets = Arrays.asList(USER_HANDLE_USER2); 1731 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 1732 assertEquals("Cross profile connected package bucket should be elevated on usage", 1733 STANDBY_BUCKET_ACTIVE, getStandbyBucket(USER_ID2, mController, PACKAGE_1)); 1734 assertEquals("Not Cross profile connected package bucket should not be elevated on usage", 1735 STANDBY_BUCKET_NEVER, getStandbyBucket(USER_ID3, mController, PACKAGE_1)); 1736 1737 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE, USER_ID); 1738 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE, USER_ID2); 1739 1740 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET, USER_ID); 1741 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET, USER_ID2); 1742 1743 mInjector.mCrossProfileTargets = Collections.emptyList(); 1744 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 1745 assertEquals("No longer cross profile connected package bucket should not be " 1746 + "elevated on usage", 1747 STANDBY_BUCKET_WORKING_SET, getStandbyBucket(USER_ID2, mController, PACKAGE_1)); 1748 } 1749 1750 @Test 1751 @FlakyTest(bugId = 185169504) testUnexemptedSyncScheduled()1752 public void testUnexemptedSyncScheduled() throws Exception { 1753 rearmLatch(PACKAGE_1); 1754 mController.addListener(mListener); 1755 assertEquals("Test package did not start in the Never bucket", STANDBY_BUCKET_NEVER, 1756 getStandbyBucket(mController, PACKAGE_1)); 1757 1758 mController.postReportSyncScheduled(PACKAGE_1, USER_ID, false); 1759 mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS); 1760 assertEquals("Unexempted sync scheduled should bring the package out of the Never bucket", 1761 STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1)); 1762 1763 setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM); 1764 1765 rearmLatch(PACKAGE_1); 1766 mController.postReportSyncScheduled(PACKAGE_1, USER_ID, false); 1767 mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS); 1768 assertEquals("Unexempted sync scheduled should not elevate a non Never bucket", 1769 STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); 1770 } 1771 1772 @Test 1773 @FlakyTest(bugId = 185169504) testExemptedSyncScheduled()1774 public void testExemptedSyncScheduled() throws Exception { 1775 setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM); 1776 mInjector.mDeviceIdleMode = true; 1777 rearmLatch(PACKAGE_1); 1778 mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true); 1779 mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS); 1780 assertEquals("Exempted sync scheduled in doze should set bucket to working set", 1781 STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1)); 1782 1783 setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM); 1784 mInjector.mDeviceIdleMode = false; 1785 rearmLatch(PACKAGE_1); 1786 mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true); 1787 mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS); 1788 assertEquals("Exempted sync scheduled while not in doze should set bucket to active", 1789 STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); 1790 } 1791 1792 @Test testAppUpdateOnRestrictedBucketStatus()1793 public void testAppUpdateOnRestrictedBucketStatus() throws Exception { 1794 // Updates shouldn't change bucket if the app timed out. 1795 // Way past all timeouts. App times out into RESTRICTED bucket. 1796 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1797 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4; 1798 mController.checkIdleStates(USER_ID); 1799 assertBucket(STANDBY_BUCKET_RESTRICTED); 1800 1801 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID); 1802 assertBucket(STANDBY_BUCKET_RESTRICTED); 1803 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2); 1804 assertBucket(STANDBY_BUCKET_RESTRICTED); 1805 mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID); 1806 assertBucket(STANDBY_BUCKET_RESTRICTED); 1807 1808 // Updates shouldn't change bucket if the app was forced by the system for a non-buggy 1809 // reason. 1810 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1811 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4; 1812 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1813 REASON_MAIN_FORCED_BY_SYSTEM 1814 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE); 1815 1816 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID); 1817 assertBucket(STANDBY_BUCKET_RESTRICTED); 1818 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2); 1819 assertBucket(STANDBY_BUCKET_RESTRICTED); 1820 mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID); 1821 assertBucket(STANDBY_BUCKET_RESTRICTED); 1822 1823 // Updates should change bucket if the app was forced by the system for a buggy reason. 1824 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1825 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4; 1826 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1827 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY); 1828 1829 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2); 1830 assertBucket(STANDBY_BUCKET_RESTRICTED); 1831 mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID); 1832 assertBucket(STANDBY_BUCKET_RESTRICTED); 1833 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID); 1834 assertNotEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1)); 1835 1836 // Updates shouldn't change bucket if the app was forced by the system for more than just 1837 // a buggy reason. 1838 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1839 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4; 1840 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1841 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE 1842 | REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY); 1843 1844 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID); 1845 assertBucket(STANDBY_BUCKET_RESTRICTED); 1846 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE, 1847 getStandbyBucketReason(PACKAGE_1)); 1848 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2); 1849 assertBucket(STANDBY_BUCKET_RESTRICTED); 1850 mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID); 1851 assertBucket(STANDBY_BUCKET_RESTRICTED); 1852 1853 // Updates shouldn't change bucket if the app was forced by the user. 1854 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1855 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4; 1856 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 1857 REASON_MAIN_FORCED_BY_USER); 1858 1859 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID); 1860 assertBucket(STANDBY_BUCKET_RESTRICTED); 1861 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2); 1862 assertBucket(STANDBY_BUCKET_RESTRICTED); 1863 mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID); 1864 assertBucket(STANDBY_BUCKET_RESTRICTED); 1865 } 1866 1867 @Test testSystemHeadlessAppElevated()1868 public void testSystemHeadlessAppElevated() throws Exception { 1869 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1870 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, 1871 PACKAGE_SYSTEM_HEADFULL); 1872 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, 1873 PACKAGE_SYSTEM_HEADLESS); 1874 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD; 1875 1876 1877 mController.setAppStandbyBucket(PACKAGE_SYSTEM_HEADFULL, USER_ID, STANDBY_BUCKET_RARE, 1878 REASON_MAIN_TIMEOUT); 1879 assertBucket(STANDBY_BUCKET_RARE, PACKAGE_SYSTEM_HEADFULL); 1880 1881 // Make sure headless system apps don't get lowered. 1882 mController.setAppStandbyBucket(PACKAGE_SYSTEM_HEADLESS, USER_ID, STANDBY_BUCKET_RARE, 1883 REASON_MAIN_TIMEOUT); 1884 assertBucket(STANDBY_BUCKET_ACTIVE, PACKAGE_SYSTEM_HEADLESS); 1885 1886 // Package 1 doesn't have activities and is headless, but is not a system app, so it can 1887 // be lowered. 1888 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 1889 REASON_MAIN_TIMEOUT); 1890 assertBucket(STANDBY_BUCKET_RARE, PACKAGE_1); 1891 } 1892 1893 @Test testWellbeingAppElevated()1894 public void testWellbeingAppElevated() throws Exception { 1895 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_WELLBEING); 1896 assertBucket(STANDBY_BUCKET_ACTIVE, PACKAGE_WELLBEING); 1897 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1898 assertBucket(STANDBY_BUCKET_ACTIVE, PACKAGE_1); 1899 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD; 1900 1901 // Make sure the default wellbeing app does not get lowered below WORKING_SET. 1902 mController.setAppStandbyBucket(PACKAGE_WELLBEING, USER_ID, STANDBY_BUCKET_RARE, 1903 REASON_MAIN_TIMEOUT); 1904 assertBucket(STANDBY_BUCKET_WORKING_SET, PACKAGE_WELLBEING); 1905 1906 // A non default wellbeing app should be able to fall lower than WORKING_SET. 1907 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 1908 REASON_MAIN_TIMEOUT); 1909 assertBucket(STANDBY_BUCKET_RARE, PACKAGE_1); 1910 } 1911 1912 @Test testClockAppElevated()1913 public void testClockAppElevated() throws Exception { 1914 mInjector.mClockApps.add(Pair.create(PACKAGE_1, UID_1)); 1915 1916 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); 1917 assertBucket(STANDBY_BUCKET_ACTIVE, PACKAGE_1); 1918 1919 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_2); 1920 assertBucket(STANDBY_BUCKET_ACTIVE, PACKAGE_2); 1921 1922 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD; 1923 1924 // Make sure a clock app does not get lowered below WORKING_SET. 1925 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 1926 REASON_MAIN_TIMEOUT); 1927 assertBucket(STANDBY_BUCKET_WORKING_SET, PACKAGE_1); 1928 1929 // A non clock app should be able to fall lower than WORKING_SET. 1930 mController.setAppStandbyBucket(PACKAGE_2, USER_ID, STANDBY_BUCKET_RARE, 1931 REASON_MAIN_TIMEOUT); 1932 assertBucket(STANDBY_BUCKET_RARE, PACKAGE_2); 1933 } 1934 1935 @Test testChangingSettings_ElapsedThreshold_Invalid()1936 public void testChangingSettings_ElapsedThreshold_Invalid() { 1937 mInjector.mSettingsBuilder 1938 .setLong("elapsed_threshold_active", -1) 1939 .setLong("elapsed_threshold_working_set", -1) 1940 .setLong("elapsed_threshold_frequent", -1) 1941 .setLong("elapsed_threshold_rare", -1) 1942 .setLong("elapsed_threshold_restricted", -1); 1943 mInjector.mPropertiesChangedListener 1944 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 1945 for (int i = 0; i < MINIMUM_ELAPSED_TIME_THRESHOLDS.length; ++i) { 1946 assertEquals(MINIMUM_ELAPSED_TIME_THRESHOLDS[i], 1947 mController.mAppStandbyElapsedThresholds[i]); 1948 } 1949 } 1950 1951 @Test testChangingSettings_ElapsedThreshold_Valid()1952 public void testChangingSettings_ElapsedThreshold_Valid() { 1953 // Effectively clear values 1954 mInjector.mSettingsBuilder 1955 .setString("elapsed_threshold_active", null) 1956 .setString("elapsed_threshold_working_set", null) 1957 .setString("elapsed_threshold_frequent", null) 1958 .setString("elapsed_threshold_rare", null) 1959 .setString("elapsed_threshold_restricted", null); 1960 mInjector.mPropertiesChangedListener 1961 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 1962 for (int i = 0; i < DEFAULT_ELAPSED_TIME_THRESHOLDS.length; ++i) { 1963 assertEquals(DEFAULT_ELAPSED_TIME_THRESHOLDS[i], 1964 mController.mAppStandbyElapsedThresholds[i]); 1965 } 1966 1967 // Set really high thresholds 1968 mInjector.mSettingsBuilder 1969 .setLong("elapsed_threshold_active", 90 * DAY_MS) 1970 .setLong("elapsed_threshold_working_set", 91 * DAY_MS) 1971 .setLong("elapsed_threshold_frequent", 92 * DAY_MS) 1972 .setLong("elapsed_threshold_rare", 93 * DAY_MS) 1973 .setLong("elapsed_threshold_restricted", 94 * DAY_MS); 1974 mInjector.mPropertiesChangedListener 1975 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 1976 for (int i = 0; i < mController.mAppStandbyElapsedThresholds.length; ++i) { 1977 assertEquals((90 + i) * DAY_MS, mController.mAppStandbyElapsedThresholds[i]); 1978 } 1979 1980 // Only set a few values 1981 mInjector.mSettingsBuilder 1982 .setString("elapsed_threshold_active", null) 1983 .setLong("elapsed_threshold_working_set", 31 * DAY_MS) 1984 .setLong("elapsed_threshold_frequent", 62 * DAY_MS) 1985 .setString("elapsed_threshold_rare", null) 1986 .setLong("elapsed_threshold_restricted", 93 * DAY_MS); 1987 mInjector.mPropertiesChangedListener 1988 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 1989 1990 assertEquals(DEFAULT_ELAPSED_TIME_THRESHOLDS[0], 1991 mController.mAppStandbyElapsedThresholds[0]); 1992 assertEquals(31 * DAY_MS, mController.mAppStandbyElapsedThresholds[1]); 1993 assertEquals(62 * DAY_MS, mController.mAppStandbyElapsedThresholds[2]); 1994 assertEquals(DEFAULT_ELAPSED_TIME_THRESHOLDS[3], 1995 mController.mAppStandbyElapsedThresholds[3]); 1996 assertEquals(93 * DAY_MS, mController.mAppStandbyElapsedThresholds[4]); 1997 } 1998 1999 @Test testChangingSettings_ScreenThreshold_Invalid()2000 public void testChangingSettings_ScreenThreshold_Invalid() { 2001 mInjector.mSettingsBuilder 2002 .setLong("screen_threshold_active", -1) 2003 .setLong("screen_threshold_working_set", -1) 2004 .setLong("screen_threshold_frequent", -1) 2005 .setLong("screen_threshold_rare", -1) 2006 .setLong("screen_threshold_restricted", -1); 2007 mInjector.mPropertiesChangedListener 2008 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 2009 for (int i = 0; i < MINIMUM_SCREEN_TIME_THRESHOLDS.length; ++i) { 2010 assertEquals(MINIMUM_SCREEN_TIME_THRESHOLDS[i], 2011 mController.mAppStandbyScreenThresholds[i]); 2012 } 2013 } 2014 2015 @Test testChangingSettings_ScreenThreshold_Valid()2016 public void testChangingSettings_ScreenThreshold_Valid() { 2017 // Effectively clear values 2018 mInjector.mSettingsBuilder 2019 .setString("screen_threshold_active", null) 2020 .setString("screen_threshold_working_set", null) 2021 .setString("screen_threshold_frequent", null) 2022 .setString("screen_threshold_rare", null) 2023 .setString("screen_threshold_restricted", null); 2024 mInjector.mPropertiesChangedListener 2025 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 2026 for (int i = 0; i < DEFAULT_SCREEN_TIME_THRESHOLDS.length; ++i) { 2027 assertEquals(DEFAULT_SCREEN_TIME_THRESHOLDS[i], 2028 mController.mAppStandbyScreenThresholds[i]); 2029 } 2030 2031 // Set really high thresholds 2032 mInjector.mSettingsBuilder 2033 .setLong("screen_threshold_active", 90 * DAY_MS) 2034 .setLong("screen_threshold_working_set", 91 * DAY_MS) 2035 .setLong("screen_threshold_frequent", 92 * DAY_MS) 2036 .setLong("screen_threshold_rare", 93 * DAY_MS) 2037 .setLong("screen_threshold_restricted", 94 * DAY_MS); 2038 mInjector.mPropertiesChangedListener 2039 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 2040 for (int i = 0; i < mController.mAppStandbyScreenThresholds.length; ++i) { 2041 assertEquals((90 + i) * DAY_MS, mController.mAppStandbyScreenThresholds[i]); 2042 } 2043 2044 // Only set a few values 2045 mInjector.mSettingsBuilder 2046 .setString("screen_threshold_active", null) 2047 .setLong("screen_threshold_working_set", 31 * DAY_MS) 2048 .setLong("screen_threshold_frequent", 62 * DAY_MS) 2049 .setString("screen_threshold_rare", null) 2050 .setLong("screen_threshold_restricted", 93 * DAY_MS); 2051 mInjector.mPropertiesChangedListener 2052 .onPropertiesChanged(mInjector.getDeviceConfigProperties()); 2053 2054 assertEquals(DEFAULT_SCREEN_TIME_THRESHOLDS[0], mController.mAppStandbyScreenThresholds[0]); 2055 assertEquals(31 * DAY_MS, mController.mAppStandbyScreenThresholds[1]); 2056 assertEquals(62 * DAY_MS, mController.mAppStandbyScreenThresholds[2]); 2057 assertEquals(DEFAULT_SCREEN_TIME_THRESHOLDS[3], mController.mAppStandbyScreenThresholds[3]); 2058 assertEquals(93 * DAY_MS, mController.mAppStandbyScreenThresholds[4]); 2059 } 2060 2061 /** 2062 * Package with ACCESS_BACKGROUND_LOCATION permission has minimum bucket 2063 * STANDBY_BUCKET_FREQUENT. 2064 * @throws Exception 2065 */ 2066 @Test testBackgroundLocationBucket()2067 public void testBackgroundLocationBucket() throws Exception { 2068 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, 2069 PACKAGE_BACKGROUND_LOCATION); 2070 assertBucket(STANDBY_BUCKET_ACTIVE, PACKAGE_BACKGROUND_LOCATION); 2071 2072 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD; 2073 // Make sure PACKAGE_BACKGROUND_LOCATION does not get lowered than STANDBY_BUCKET_FREQUENT. 2074 mController.setAppStandbyBucket(PACKAGE_BACKGROUND_LOCATION, USER_ID, STANDBY_BUCKET_RARE, 2075 REASON_MAIN_TIMEOUT); 2076 assertBucket(STANDBY_BUCKET_FREQUENT, PACKAGE_BACKGROUND_LOCATION); 2077 } 2078 2079 @Test testBatteryStatsNoteEvent()2080 public void testBatteryStatsNoteEvent() throws Exception { 2081 mInjector.mExpectedNoteEventPackage = PACKAGE_1; 2082 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); 2083 2084 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 2085 REASON_MAIN_FORCED_BY_USER); 2086 assertEquals(BatteryStats.HistoryItem.EVENT_PACKAGE_INACTIVE, mInjector.mLastNoteEvent); 2087 2088 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 2089 REASON_MAIN_FORCED_BY_USER); 2090 assertEquals(BatteryStats.HistoryItem.EVENT_PACKAGE_ACTIVE, mInjector.mLastNoteEvent); 2091 2092 // Since we're staying on the PACKAGE_ACTIVE side, noteEvent shouldn't be called. 2093 // Reset the last event to confirm the method isn't called. 2094 mInjector.mLastNoteEvent = BatteryStats.HistoryItem.EVENT_NONE; 2095 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, 2096 REASON_MAIN_FORCED_BY_USER); 2097 assertEquals(BatteryStats.HistoryItem.EVENT_NONE, mInjector.mLastNoteEvent); 2098 2099 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, 2100 REASON_MAIN_FORCED_BY_USER); 2101 assertEquals(BatteryStats.HistoryItem.EVENT_PACKAGE_INACTIVE, mInjector.mLastNoteEvent); 2102 2103 // Since we're staying on the PACKAGE_ACTIVE side, noteEvent shouldn't be called. 2104 // Reset the last event to confirm the method isn't called. 2105 mInjector.mLastNoteEvent = BatteryStats.HistoryItem.EVENT_NONE; 2106 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 2107 REASON_MAIN_FORCED_BY_USER); 2108 assertEquals(BatteryStats.HistoryItem.EVENT_NONE, mInjector.mLastNoteEvent); 2109 2110 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, 2111 REASON_MAIN_FORCED_BY_USER); 2112 assertEquals(BatteryStats.HistoryItem.EVENT_PACKAGE_ACTIVE, mInjector.mLastNoteEvent); 2113 2114 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, 2115 REASON_MAIN_FORCED_BY_USER); 2116 assertEquals(BatteryStats.HistoryItem.EVENT_PACKAGE_INACTIVE, mInjector.mLastNoteEvent); 2117 2118 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_EXEMPTED, 2119 REASON_MAIN_FORCED_BY_USER); 2120 assertEquals(BatteryStats.HistoryItem.EVENT_PACKAGE_ACTIVE, mInjector.mLastNoteEvent); 2121 } 2122 getAdminAppsStr(int userId)2123 private String getAdminAppsStr(int userId) { 2124 return getAdminAppsStr(userId, mController.getActiveAdminAppsForTest(userId)); 2125 } 2126 getAdminAppsStr(int userId, Set<String> adminApps)2127 private String getAdminAppsStr(int userId, Set<String> adminApps) { 2128 return "admin apps for u" + userId + ": " 2129 + (adminApps == null ? "null" : Arrays.toString(adminApps.toArray())); 2130 } 2131 assertIsActiveAdmin(String adminApp, int userId)2132 private void assertIsActiveAdmin(String adminApp, int userId) { 2133 assertTrue(adminApp + " should be an active admin; " + getAdminAppsStr(userId), 2134 mController.isActiveDeviceAdmin(adminApp, userId)); 2135 } 2136 assertIsNotActiveAdmin(String adminApp, int userId)2137 private void assertIsNotActiveAdmin(String adminApp, int userId) { 2138 assertFalse(adminApp + " shouldn't be an active admin; " + getAdminAppsStr(userId), 2139 mController.isActiveDeviceAdmin(adminApp, userId)); 2140 } 2141 assertActiveAdmins(int userId, String... admins)2142 private void assertActiveAdmins(int userId, String... admins) { 2143 final Set<String> actualAdminApps = mController.getActiveAdminAppsForTest(userId); 2144 if (admins == null) { 2145 if (actualAdminApps != null && !actualAdminApps.isEmpty()) { 2146 fail("Admin apps should be null; " + getAdminAppsStr(userId, actualAdminApps)); 2147 } 2148 return; 2149 } 2150 assertEquals("No. of admin apps not equal; " + getAdminAppsStr(userId, actualAdminApps) 2151 + "; expected=" + Arrays.toString(admins), admins.length, actualAdminApps.size()); 2152 final Set<String> adminAppsCopy = new ArraySet<>(actualAdminApps); 2153 for (String admin : admins) { 2154 adminAppsCopy.remove(admin); 2155 } 2156 assertTrue("Unexpected admin apps; " + getAdminAppsStr(userId, actualAdminApps) 2157 + "; expected=" + Arrays.toString(admins), adminAppsCopy.isEmpty()); 2158 } 2159 setActiveAdmins(int userId, String... admins)2160 private void setActiveAdmins(int userId, String... admins) { 2161 mController.setActiveAdminApps(new ArraySet<>(Arrays.asList(admins)), userId); 2162 } 2163 setAdminProtectedPackages(int userId, String... packageNames)2164 private void setAdminProtectedPackages(int userId, String... packageNames) { 2165 Set<String> adminProtectedPackages = packageNames != null ? new ArraySet<>( 2166 Arrays.asList(packageNames)) : null; 2167 mController.setAdminProtectedPackages(adminProtectedPackages, userId); 2168 } 2169 assertAdminProtectedPackagesForTest(int userId, String... packageNames)2170 private void assertAdminProtectedPackagesForTest(int userId, String... packageNames) { 2171 final Set<String> actualAdminProtectedPackages = 2172 mController.getAdminProtectedPackagesForTest(userId); 2173 if (packageNames == null) { 2174 if (actualAdminProtectedPackages != null && !actualAdminProtectedPackages.isEmpty()) { 2175 fail("Admin protected packages should be null; " + getAdminAppsStr(userId, 2176 actualAdminProtectedPackages)); 2177 } 2178 return; 2179 } 2180 assertEquals(packageNames.length, actualAdminProtectedPackages.size()); 2181 for (String adminProtectedPackage : packageNames) { 2182 assertTrue(actualAdminProtectedPackages.contains(adminProtectedPackage)); 2183 } 2184 } 2185 setAndAssertBucket(String pkg, int user, int bucket, int reason)2186 private void setAndAssertBucket(String pkg, int user, int bucket, int reason) throws Exception { 2187 rearmLatch(pkg); 2188 mController.setAppStandbyBucket(pkg, user, bucket, reason); 2189 mStateChangedLatch.await(1, TimeUnit.SECONDS); 2190 assertEquals("Failed to set package bucket", bucket, 2191 getStandbyBucket(mController, PACKAGE_1)); 2192 } 2193 rearmLatch(String pkgName)2194 private void rearmLatch(String pkgName) { 2195 mLatchPkgName = pkgName; 2196 mStateChangedLatch = new CountDownLatch(1); 2197 } 2198 rearmLatch()2199 private void rearmLatch() { 2200 rearmLatch(null); 2201 } 2202 rearmQuotaBumpLatch(String pkgName, int userId)2203 private void rearmQuotaBumpLatch(String pkgName, int userId) { 2204 mLatchPkgName = pkgName; 2205 mLatchUserId = userId; 2206 mQuotaBumpLatch = new CountDownLatch(1); 2207 } 2208 } 2209