1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.am; 18 19 import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION; 20 import static android.Manifest.permission.ACCESS_COARSE_LOCATION; 21 import static android.Manifest.permission.ACCESS_FINE_LOCATION; 22 import static android.Manifest.permission.CAMERA; 23 import static android.Manifest.permission.RECORD_AUDIO; 24 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; 25 import static android.app.ActivityManager.PROCESS_STATE_TOP; 26 import static android.app.ActivityManager.RESTRICTION_LEVEL_ADAPTIVE_BUCKET; 27 import static android.app.ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED; 28 import static android.app.ActivityManager.RESTRICTION_LEVEL_EXEMPTED; 29 import static android.app.ActivityManager.RESTRICTION_LEVEL_RESTRICTED_BUCKET; 30 import static android.app.ActivityManager.isLowRamDeviceStatic; 31 import static android.app.AppOpsManager.MODE_ALLOWED; 32 import static android.app.AppOpsManager.MODE_IGNORED; 33 import static android.app.AppOpsManager.OP_ACTIVATE_PLATFORM_VPN; 34 import static android.app.AppOpsManager.OP_ACTIVATE_VPN; 35 import static android.app.AppOpsManager.OP_CAMERA; 36 import static android.app.AppOpsManager.OP_FINE_LOCATION; 37 import static android.app.AppOpsManager.OP_NONE; 38 import static android.app.AppOpsManager.OP_RECORD_AUDIO; 39 import static android.app.AppOpsManager.OP_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS; 40 import static android.app.usage.UsageStatsManager.REASON_MAIN_DEFAULT; 41 import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_SYSTEM; 42 import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER; 43 import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK; 44 import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE; 45 import static android.app.usage.UsageStatsManager.REASON_SUB_DEFAULT_UNDEFINED; 46 import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE; 47 import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_USER_FLAG_INTERACTION; 48 import static android.app.usage.UsageStatsManager.REASON_SUB_MASK; 49 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACTION; 50 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE; 51 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED; 52 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT; 53 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER; 54 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE; 55 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RESTRICTED; 56 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET; 57 import static android.content.pm.PackageManager.PERMISSION_DENIED; 58 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 59 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; 60 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION; 61 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK; 62 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE; 63 import static android.os.PowerExemptionManager.REASON_CARRIER_PRIVILEGED_APP; 64 import static android.os.PowerExemptionManager.REASON_DENIED; 65 66 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 67 68 import static com.android.internal.notification.SystemNotificationChannels.ABUSIVE_BACKGROUND_APPS; 69 import static com.android.server.am.AppBatteryTracker.AppBatteryPolicy.getFloatArray; 70 import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_BACKGROUND; 71 import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_CACHED; 72 import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND; 73 import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND_SERVICE; 74 import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATT_DIMENS; 75 import static com.android.server.am.AppPermissionTracker.AppPermissionPolicy; 76 import static com.android.server.am.AppRestrictionController.STOCK_PM_FLAGS; 77 import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_FGS_LOCATION; 78 import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_FGS_MEDIA_PLAYBACK; 79 import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_FGS_WITH_NOTIFICATION; 80 import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_MEDIA_SESSION; 81 import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_PERMISSION; 82 83 import static org.junit.Assert.assertEquals; 84 import static org.junit.Assert.assertTrue; 85 import static org.junit.Assert.fail; 86 import static org.mockito.ArgumentMatchers.any; 87 import static org.mockito.ArgumentMatchers.eq; 88 import static org.mockito.Mockito.anyBoolean; 89 import static org.mockito.Mockito.anyInt; 90 import static org.mockito.Mockito.anyLong; 91 import static org.mockito.Mockito.anyObject; 92 import static org.mockito.Mockito.anyString; 93 import static org.mockito.Mockito.atLeast; 94 import static org.mockito.Mockito.clearInvocations; 95 import static org.mockito.Mockito.doAnswer; 96 import static org.mockito.Mockito.doReturn; 97 import static org.mockito.Mockito.mock; 98 import static org.mockito.Mockito.never; 99 import static org.mockito.Mockito.spy; 100 import static org.mockito.Mockito.timeout; 101 import static org.mockito.Mockito.times; 102 import static org.mockito.Mockito.verify; 103 104 import android.annotation.UserIdInt; 105 import android.app.ActivityManagerInternal; 106 import android.app.ActivityManagerInternal.AppBackgroundRestrictionListener; 107 import android.app.ActivityManagerInternal.BindServiceEventListener; 108 import android.app.ActivityManagerInternal.BroadcastEventListener; 109 import android.app.AppOpsManager; 110 import android.app.IActivityManager; 111 import android.app.IUidObserver; 112 import android.app.Notification; 113 import android.app.NotificationManager; 114 import android.app.role.RoleManager; 115 import android.app.usage.AppStandbyInfo; 116 import android.content.Context; 117 import android.content.Intent; 118 import android.content.pm.PackageManager; 119 import android.content.pm.PackageManagerInternal; 120 import android.media.session.MediaController; 121 import android.media.session.MediaSession; 122 import android.media.session.MediaSessionManager; 123 import android.media.session.MediaSessionManager.OnActiveSessionsChangedListener; 124 import android.os.BatteryManagerInternal; 125 import android.os.BatteryStatsInternal; 126 import android.os.BatteryUsageStats; 127 import android.os.Handler; 128 import android.os.MessageQueue; 129 import android.os.Process; 130 import android.os.RemoteException; 131 import android.os.SystemClock; 132 import android.os.UidBatteryConsumer; 133 import android.os.UserHandle; 134 import android.permission.PermissionManager; 135 import android.provider.DeviceConfig; 136 import android.service.notification.StatusBarNotification; 137 import android.telephony.TelephonyManager; 138 import android.telephony.TelephonyManager.CarrierPrivilegesCallback; 139 import android.util.Log; 140 import android.util.Pair; 141 import android.util.SparseArray; 142 143 import androidx.test.runner.AndroidJUnit4; 144 145 import com.android.internal.R; 146 import com.android.internal.app.IAppOpsService; 147 import com.android.server.AppStateTracker; 148 import com.android.server.DeviceIdleInternal; 149 import com.android.server.am.AppBatteryExemptionTracker.AppBatteryExemptionPolicy; 150 import com.android.server.am.AppBatteryExemptionTracker.UidBatteryStates; 151 import com.android.server.am.AppBatteryExemptionTracker.UidStateEventWithBattery; 152 import com.android.server.am.AppBatteryTracker.AppBatteryPolicy; 153 import com.android.server.am.AppBatteryTracker.ImmutableBatteryUsage; 154 import com.android.server.am.AppBindServiceEventsTracker.AppBindServiceEventsPolicy; 155 import com.android.server.am.AppBroadcastEventsTracker.AppBroadcastEventsPolicy; 156 import com.android.server.am.AppFGSTracker.AppFGSPolicy; 157 import com.android.server.am.AppMediaSessionTracker.AppMediaSessionPolicy; 158 import com.android.server.am.AppRestrictionController.ConstantsObserver; 159 import com.android.server.am.AppRestrictionController.NotificationHelper; 160 import com.android.server.am.AppRestrictionController.RestrictionSettings; 161 import com.android.server.am.AppRestrictionController.UidBatteryUsageProvider; 162 import com.android.server.am.BaseAppStateTimeEvents.BaseTimeEvent; 163 import com.android.server.apphibernation.AppHibernationManagerInternal; 164 import com.android.server.notification.NotificationManagerInternal; 165 import com.android.server.pm.UserManagerInternal; 166 import com.android.server.pm.permission.PermissionManagerServiceInternal; 167 import com.android.server.usage.AppStandbyInternal; 168 import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener; 169 170 import org.junit.After; 171 import org.junit.Before; 172 import org.junit.Test; 173 import org.junit.runner.RunWith; 174 import org.mockito.ArgumentCaptor; 175 import org.mockito.Captor; 176 import org.mockito.Mock; 177 import org.mockito.MockitoAnnotations; 178 import org.mockito.verification.VerificationMode; 179 180 import java.io.File; 181 import java.time.Duration; 182 import java.util.ArrayList; 183 import java.util.Arrays; 184 import java.util.Collections; 185 import java.util.LinkedList; 186 import java.util.List; 187 import java.util.Set; 188 import java.util.concurrent.CountDownLatch; 189 import java.util.concurrent.Executor; 190 import java.util.concurrent.TimeUnit; 191 import java.util.concurrent.TimeoutException; 192 import java.util.function.BiConsumer; 193 import java.util.stream.Collectors; 194 195 /** 196 * Tests for {@link AppRestrictionController}. 197 * 198 * Build/Install/Run: 199 * atest FrameworksMockingServicesTests:BackgroundRestrictionTest 200 */ 201 @RunWith(AndroidJUnit4.class) 202 public final class BackgroundRestrictionTest { 203 private static final String TAG = BackgroundRestrictionTest.class.getSimpleName(); 204 205 private static final int TEST_USER0 = UserHandle.USER_SYSTEM; 206 private static final int TEST_USER1 = UserHandle.MIN_SECONDARY_USER_ID; 207 private static final int[] TEST_USERS = new int[] {TEST_USER0, TEST_USER1}; 208 private static final String TEST_PACKAGE_BASE = "test_"; 209 private static final int TEST_PACKAGE_APPID_BASE = Process.FIRST_APPLICATION_UID; 210 private static final int[] TEST_PACKAGE_USER0_UIDS = new int[] { 211 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 0), 212 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 1), 213 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 2), 214 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 3), 215 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 4), 216 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 5), 217 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 6), 218 }; 219 private static final int[] TEST_PACKAGE_USER1_UIDS = new int[] { 220 UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 0), 221 UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 1), 222 UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 2), 223 UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 3), 224 UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 4), 225 UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 5), 226 UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 6), 227 }; 228 private static final int[][] TEST_UIDS = new int[][] { 229 TEST_PACKAGE_USER0_UIDS, 230 TEST_PACKAGE_USER1_UIDS, 231 }; 232 private static final int[] TEST_STANDBY_BUCKETS = new int[] { 233 STANDBY_BUCKET_EXEMPTED, 234 STANDBY_BUCKET_ACTIVE, 235 STANDBY_BUCKET_WORKING_SET, 236 STANDBY_BUCKET_FREQUENT, 237 STANDBY_BUCKET_RARE, 238 STANDBY_BUCKET_RESTRICTED, 239 STANDBY_BUCKET_NEVER, 240 }; 241 242 private static final int BATTERY_FULL_CHARGE_MAH = 5_000; 243 244 private static final String[] MOCK_PRIVILEGED_PACKAGES_0 = new String[] { 245 TEST_PACKAGE_BASE + 0, 246 TEST_PACKAGE_BASE + 1, 247 }; 248 private static final String[] MOCK_PRIVILEGED_PACKAGES_1 = new String[] { 249 TEST_PACKAGE_BASE + 2, 250 TEST_PACKAGE_BASE + 3, 251 }; 252 private static final String[] MOCK_PRIVILEGED_PACKAGES_2 = new String[] { 253 TEST_PACKAGE_BASE + 4, 254 TEST_PACKAGE_BASE + 5, 255 }; 256 private static final int[] MOCK_PRIVILEGED_UIDS_0 = new int[] { 257 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 0), 258 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 1), 259 }; 260 private static final int[] MOCK_PRIVILEGED_UIDS_1 = new int[] { 261 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 2), 262 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 3), 263 }; 264 private static final int[] MOCK_PRIVILEGED_UIDS_2 = new int[] { 265 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 4), 266 UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 5), 267 }; 268 private static final String[][] MOCK_PRIVILEGED_PACKAGES = new String[][] { 269 MOCK_PRIVILEGED_PACKAGES_0, 270 MOCK_PRIVILEGED_PACKAGES_1, 271 }; 272 private static final int[][] MOCK_PRIVILEGED_UIDS = new int[][] { 273 MOCK_PRIVILEGED_UIDS_0, 274 MOCK_PRIVILEGED_UIDS_1, 275 }; 276 277 @Mock private ActivityManagerInternal mActivityManagerInternal; 278 @Mock private ActivityManagerService mActivityManagerService; 279 @Mock private ActivityManagerConstants mActivityManagerConstants; 280 @Mock private AppOpsManager mAppOpsManager; 281 @Mock private AppStandbyInternal mAppStandbyInternal; 282 @Mock private AppHibernationManagerInternal mAppHibernationInternal; 283 @Mock private AppStateTracker mAppStateTracker; 284 @Mock private BatteryManagerInternal mBatteryManagerInternal; 285 @Mock private BatteryStatsInternal mBatteryStatsInternal; 286 @Mock private DeviceIdleInternal mDeviceIdleInternal; 287 @Mock private IActivityManager mIActivityManager; 288 @Mock private UserManagerInternal mUserManagerInternal; 289 @Mock private PackageManager mPackageManager; 290 @Mock private PackageManagerInternal mPackageManagerInternal; 291 @Mock private NotificationManager mNotificationManager; 292 @Mock private NotificationManagerInternal mNotificationManagerInternal; 293 @Mock private PermissionManager mPermissionManager; 294 @Mock private PermissionManagerServiceInternal mPermissionManagerServiceInternal; 295 @Mock private MediaSessionManager mMediaSessionManager; 296 @Mock private RoleManager mRoleManager; 297 @Mock private TelephonyManager mTelephonyManager; 298 @Mock private IAppOpsService mIAppOpsService; 299 300 private PhoneCarrierPrivileges mPhoneCarrierPrivileges; 301 302 private long mCurrentTimeMillis; 303 304 @Captor private ArgumentCaptor<AppStateTracker.BackgroundRestrictedAppListener> mFasListenerCap; 305 private AppStateTracker.BackgroundRestrictedAppListener mFasListener; 306 307 @Captor private ArgumentCaptor<AppIdleStateChangeListener> mIdleStateListenerCap; 308 private AppIdleStateChangeListener mIdleStateListener; 309 310 @Captor private ArgumentCaptor<IUidObserver> mUidObserversCap; 311 private IUidObserver mUidObservers; 312 313 @Captor private ArgumentCaptor<OnActiveSessionsChangedListener> mActiveSessionListenerCap; 314 private OnActiveSessionsChangedListener mActiveSessionListener; 315 316 @Captor private ArgumentCaptor<BroadcastEventListener> mBroadcastEventListenerCap; 317 private BroadcastEventListener mBroadcastEventListener; 318 319 @Captor private ArgumentCaptor<BindServiceEventListener> mBindServiceEventListenerCap; 320 private BindServiceEventListener mBindServiceEventListener; 321 322 private Context mContext = getInstrumentation().getTargetContext(); 323 private TestBgRestrictionInjector mInjector; 324 private AppRestrictionController mBgRestrictionController; 325 private AppBatteryTracker mAppBatteryTracker; 326 private AppBatteryPolicy mAppBatteryPolicy; 327 private AppBatteryExemptionTracker mAppBatteryExemptionTracker; 328 private AppBroadcastEventsTracker mAppBroadcastEventsTracker; 329 private AppBindServiceEventsTracker mAppBindServiceEventsTracker; 330 private AppFGSTracker mAppFGSTracker; 331 private AppMediaSessionTracker mAppMediaSessionTracker; 332 private AppPermissionTracker mAppPermissionTracker; 333 334 @Before setUp()335 public void setUp() throws Exception { 336 MockitoAnnotations.initMocks(this); 337 initController(); 338 } 339 initController()340 private void initController() throws Exception { 341 mInjector = spy(new TestBgRestrictionInjector(mContext)); 342 mBgRestrictionController = spy(new AppRestrictionController(mInjector, 343 mActivityManagerService)); 344 345 mActivityManagerService.mConstants = mActivityManagerConstants; 346 mPhoneCarrierPrivileges = new PhoneCarrierPrivileges( 347 mInjector.getTelephonyManager(), MOCK_PRIVILEGED_PACKAGES.length); 348 for (int i = 0; i < MOCK_PRIVILEGED_PACKAGES.length; i++) { 349 mPhoneCarrierPrivileges.addNewPrivilegePackages(i, 350 MOCK_PRIVILEGED_PACKAGES[i], MOCK_PRIVILEGED_UIDS[i]); 351 } 352 353 doReturn(PROCESS_STATE_FOREGROUND_SERVICE).when(mActivityManagerInternal) 354 .getUidProcessState(anyInt()); 355 doReturn(TEST_USERS).when(mUserManagerInternal).getUserIds(); 356 for (int userId: TEST_USERS) { 357 final ArrayList<AppStandbyInfo> appStandbyInfoList = new ArrayList<>(); 358 for (int i = 0; i < TEST_STANDBY_BUCKETS.length; i++) { 359 final String packageName = TEST_PACKAGE_BASE + i; 360 final int uid = UserHandle.getUid(userId, TEST_PACKAGE_APPID_BASE + i); 361 appStandbyInfoList.add(new AppStandbyInfo(packageName, TEST_STANDBY_BUCKETS[i])); 362 doReturn(uid) 363 .when(mPackageManagerInternal) 364 .getPackageUid(packageName, STOCK_PM_FLAGS, userId); 365 doReturn(false) 366 .when(mAppStateTracker) 367 .isAppBackgroundRestricted(uid, packageName); 368 doReturn(TEST_STANDBY_BUCKETS[i]) 369 .when(mAppStandbyInternal) 370 .getAppStandbyBucket(eq(packageName), eq(userId), anyLong(), anyBoolean()); 371 doReturn(new String[]{packageName}) 372 .when(mPackageManager) 373 .getPackagesForUid(eq(uid)); 374 final int[] ops = new int[] { 375 OP_ACTIVATE_VPN, 376 OP_ACTIVATE_PLATFORM_VPN, 377 OP_FINE_LOCATION, 378 OP_CAMERA, 379 OP_RECORD_AUDIO, 380 OP_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS, 381 }; 382 for (int op : ops) { 383 setAppOpState(packageName, uid, op, false); 384 } 385 final String[] permissions = new String[] {ACCESS_BACKGROUND_LOCATION, 386 ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION, CAMERA, RECORD_AUDIO, 387 }; 388 for (String permission : permissions) { 389 setPermissionState(packageName, uid, permission, false); 390 } 391 } 392 doReturn(appStandbyInfoList).when(mAppStandbyInternal).getAppStandbyBuckets(userId); 393 } 394 395 doReturn(BATTERY_FULL_CHARGE_MAH * 1000).when(mBatteryManagerInternal) 396 .getBatteryFullCharge(); 397 398 mBgRestrictionController.onSystemReady(); 399 400 verify(mInjector.getAppStateTracker()) 401 .addBackgroundRestrictedAppListener(mFasListenerCap.capture()); 402 mFasListener = mFasListenerCap.getValue(); 403 verify(mInjector.getAppStandbyInternal()) 404 .addListener(mIdleStateListenerCap.capture()); 405 mIdleStateListener = mIdleStateListenerCap.getValue(); 406 verify(mInjector.getIActivityManager()) 407 .registerUidObserver(mUidObserversCap.capture(), 408 anyInt(), anyInt(), anyString()); 409 mUidObservers = mUidObserversCap.getValue(); 410 verify(mAppMediaSessionTracker.mInjector.getMediaSessionManager()) 411 .addOnActiveSessionsChangedListener(any(), any(), any(), 412 mActiveSessionListenerCap.capture()); 413 mActiveSessionListener = mActiveSessionListenerCap.getValue(); 414 verify(mAppBroadcastEventsTracker.mInjector.getActivityManagerInternal()) 415 .addBroadcastEventListener(mBroadcastEventListenerCap.capture()); 416 mBroadcastEventListener = mBroadcastEventListenerCap.getValue(); 417 verify(mAppBindServiceEventsTracker.mInjector.getActivityManagerInternal()) 418 .addBindServiceEventListener(mBindServiceEventListenerCap.capture()); 419 mBindServiceEventListener = mBindServiceEventListenerCap.getValue(); 420 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 421 } 422 423 @After tearDown()424 public void tearDown() { 425 mBgRestrictionController.tearDown(); 426 mBgRestrictionController.getBackgroundHandlerThread().quitSafely(); 427 } 428 429 @Test testInitialLevels()430 public void testInitialLevels() throws Exception { 431 final int[] expectedLevels = { 432 RESTRICTION_LEVEL_EXEMPTED, 433 RESTRICTION_LEVEL_ADAPTIVE_BUCKET, 434 RESTRICTION_LEVEL_ADAPTIVE_BUCKET, 435 RESTRICTION_LEVEL_ADAPTIVE_BUCKET, 436 RESTRICTION_LEVEL_ADAPTIVE_BUCKET, 437 RESTRICTION_LEVEL_RESTRICTED_BUCKET, 438 RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, 439 }; 440 for (int i = 0; i < TEST_UIDS.length; i++) { 441 final int[] uids = TEST_UIDS[i]; 442 for (int j = 0; j < uids.length; j++) { 443 assertEquals(expectedLevels[j], 444 mBgRestrictionController.getRestrictionLevel(uids[j])); 445 assertEquals(expectedLevels[j], 446 mBgRestrictionController.getRestrictionLevel(uids[j], 447 TEST_PACKAGE_BASE + j)); 448 } 449 } 450 } 451 452 @Test testTogglingBackgroundRestrict()453 public void testTogglingBackgroundRestrict() throws Exception { 454 DeviceConfigSession<Boolean> bgAutoRestrictedBucketOnBgRestriction = null; 455 try { 456 bgAutoRestrictedBucketOnBgRestriction = new DeviceConfigSession<>( 457 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 458 ConstantsObserver.KEY_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION, 459 DeviceConfig::getBoolean, 460 ConstantsObserver.DEFAULT_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION); 461 bgAutoRestrictedBucketOnBgRestriction.set(true); 462 463 testTogglingBackgroundRestrictInternal(); 464 } finally { 465 closeIfNotNull(bgAutoRestrictedBucketOnBgRestriction); 466 } 467 } 468 testTogglingBackgroundRestrictInternal()469 private void testTogglingBackgroundRestrictInternal() throws Exception { 470 final int testPkgIndex = 2; 471 final String testPkgName = TEST_PACKAGE_BASE + testPkgIndex; 472 final int testUser = TEST_USER0; 473 final int testUid = UserHandle.getUid(testUser, TEST_PACKAGE_APPID_BASE + testPkgIndex); 474 final TestAppRestrictionLevelListener listener = new TestAppRestrictionLevelListener(); 475 final long timeout = 1_000; // ms 476 477 mBgRestrictionController.addAppBackgroundRestrictionListener(listener); 478 479 setBackgroundRestrict(testPkgName, testUid, false, listener); 480 481 // Verify the current settings. 482 verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid); 483 assertEquals(STANDBY_BUCKET_WORKING_SET, mInjector.getAppStandbyInternal() 484 .getAppStandbyBucket(testPkgName, testUser, SystemClock.elapsedRealtime(), false)); 485 486 // Now toggling ON the background restrict. 487 setBackgroundRestrict(testPkgName, testUid, true, listener); 488 489 // We should have been in the background restricted level. 490 verifyRestrictionLevel(RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, testPkgName, testUid); 491 492 listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_BACKGROUND_RESTRICTED); 493 494 // The app should have been put into the restricted standby bucket. 495 verify(mInjector.getAppStandbyInternal(), atLeast(1)).restrictApp( 496 eq(testPkgName), 497 eq(testUser), 498 eq(REASON_MAIN_FORCED_BY_USER), 499 eq(REASON_SUB_FORCED_USER_FLAG_INTERACTION)); 500 501 // Changing to the restricted standby bucket won't make a difference. 502 listener.mLatchHolder[0] = new CountDownLatch(1); 503 mIdleStateListener.onAppIdleStateChanged(testPkgName, testUser, false, 504 STANDBY_BUCKET_RESTRICTED, REASON_MAIN_USAGE); 505 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 506 verifyRestrictionLevel(RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, testPkgName, testUid); 507 try { 508 listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_BACKGROUND_RESTRICTED); 509 fail("There shouldn't be any level change events"); 510 } catch (Exception e) { 511 // Expected. 512 } 513 514 clearInvocations(mInjector.getAppStandbyInternal()); 515 516 // Toggling back. 517 setBackgroundRestrict(testPkgName, testUid, false, listener); 518 519 // It should have gone back to adaptive level. 520 verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid); 521 522 // The app standby bucket should be the rare. 523 verify(mInjector.getAppStandbyInternal(), atLeast(1)).maybeUnrestrictApp( 524 eq(testPkgName), 525 eq(testUser), 526 eq(REASON_MAIN_FORCED_BY_USER), 527 eq(REASON_SUB_FORCED_USER_FLAG_INTERACTION), 528 eq(REASON_MAIN_USAGE), 529 eq(REASON_SUB_USAGE_USER_INTERACTION)); 530 531 listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_ADAPTIVE_BUCKET); 532 533 clearInvocations(mInjector.getAppStandbyInternal()); 534 535 // Now set its UID state active. 536 mUidObservers.onUidActive(testUid); 537 538 // Now toggling ON the background restrict. 539 setBackgroundRestrict(testPkgName, testUid, true, listener); 540 541 // We should have been in the background restricted level. 542 verifyRestrictionLevel(RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, testPkgName, testUid); 543 544 listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_BACKGROUND_RESTRICTED); 545 546 // The app should have NOT been put into the restricted standby bucket. 547 verify(mInjector.getAppStandbyInternal(), never()).restrictApp( 548 eq(testPkgName), 549 eq(testUser), 550 eq(REASON_MAIN_FORCED_BY_USER), 551 eq(REASON_SUB_FORCED_USER_FLAG_INTERACTION)); 552 553 // Now set its UID to idle. 554 mUidObservers.onUidIdle(testUid, false); 555 556 // The app should have been put into the restricted standby bucket because we're idle now. 557 verify(mInjector.getAppStandbyInternal(), timeout(timeout).times(1)).restrictApp( 558 eq(testPkgName), 559 eq(testUser), 560 eq(REASON_MAIN_FORCED_BY_USER), 561 eq(REASON_SUB_FORCED_USER_FLAG_INTERACTION)); 562 } 563 564 @Test testTogglingStandbyBucket()565 public void testTogglingStandbyBucket() throws Exception { 566 final int testPkgIndex = 2; 567 final String testPkgName = TEST_PACKAGE_BASE + testPkgIndex; 568 final int testUser = TEST_USER0; 569 final int testUid = UserHandle.getUid(testUser, TEST_PACKAGE_APPID_BASE + testPkgIndex); 570 final TestAppRestrictionLevelListener listener = new TestAppRestrictionLevelListener(); 571 final long timeout = 1_000; // ms 572 573 mBgRestrictionController.addAppBackgroundRestrictionListener(listener); 574 575 setBackgroundRestrict(testPkgName, testUid, false, listener); 576 577 // Verify the current settings. 578 verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid); 579 580 for (int bucket: Arrays.asList(STANDBY_BUCKET_ACTIVE, STANDBY_BUCKET_WORKING_SET, 581 STANDBY_BUCKET_FREQUENT, STANDBY_BUCKET_RARE)) { 582 listener.mLatchHolder[0] = new CountDownLatch(1); 583 mIdleStateListener.onAppIdleStateChanged(testPkgName, testUser, false, 584 bucket, REASON_MAIN_USAGE); 585 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 586 verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid); 587 588 try { 589 listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_ADAPTIVE_BUCKET); 590 fail("There shouldn't be any level change events"); 591 } catch (Exception e) { 592 // Expected. 593 } 594 } 595 596 // Toggling restricted bucket. 597 listener.mLatchHolder[0] = new CountDownLatch(1); 598 mIdleStateListener.onAppIdleStateChanged(testPkgName, testUser, false, 599 STANDBY_BUCKET_RESTRICTED, REASON_MAIN_USAGE); 600 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 601 verifyRestrictionLevel(RESTRICTION_LEVEL_RESTRICTED_BUCKET, testPkgName, testUid); 602 listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_RESTRICTED_BUCKET); 603 604 // Toggling exempted bucket. 605 listener.mLatchHolder[0] = new CountDownLatch(1); 606 mIdleStateListener.onAppIdleStateChanged(testPkgName, testUser, false, 607 STANDBY_BUCKET_EXEMPTED, REASON_MAIN_FORCED_BY_SYSTEM); 608 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 609 verifyRestrictionLevel(RESTRICTION_LEVEL_EXEMPTED, testPkgName, testUid); 610 listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_EXEMPTED); 611 } 612 613 @Test testBgCurrentDrainMonitor()614 public void testBgCurrentDrainMonitor() throws Exception { 615 final BatteryUsageStats stats = mock(BatteryUsageStats.class); 616 final List<BatteryUsageStats> statsList = Arrays.asList(stats); 617 final int testPkgIndex = 2; 618 final String testPkgName = TEST_PACKAGE_BASE + testPkgIndex; 619 final int testUser = TEST_USER0; 620 final int testUid = UserHandle.getUid(testUser, 621 TEST_PACKAGE_APPID_BASE + testPkgIndex); 622 final int testUid2 = UserHandle.getUid(testUser, 623 TEST_PACKAGE_APPID_BASE + testPkgIndex + 1); 624 final TestAppRestrictionLevelListener listener = new TestAppRestrictionLevelListener(); 625 final long timeout = 626 AppBatteryTracker.BATTERY_USAGE_STATS_POLLING_INTERVAL_MS_DEBUG * 2; 627 final long windowMs = 2_000; 628 final float restrictBucketThreshold = 2.0f; 629 final float restrictBucketThresholdMah = 630 BATTERY_FULL_CHARGE_MAH * restrictBucketThreshold / 100.0f; 631 final float bgRestrictedThreshold = 4.0f; 632 final float bgRestrictedThresholdMah = 633 BATTERY_FULL_CHARGE_MAH * bgRestrictedThreshold / 100.0f; 634 final int testPid = 1234; 635 final int notificationId = 1000; 636 637 DeviceConfigSession<Boolean> bgCurrentDrainMonitor = null; 638 DeviceConfigSession<Long> bgCurrentDrainWindow = null; 639 DeviceConfigSession<Long> bgCurrentDrainInteractionGracePeriod = null; 640 DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketThreshold = null; 641 DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null; 642 DeviceConfigSession<Boolean> bgCurrentDrainAutoRestrictAbusiveApps = null; 643 DeviceConfigSession<Boolean> bgPromptFgsWithNotiToBgRestricted = null; 644 DeviceConfigSession<Boolean> bgPromptAbusiveAppToBgRestricted = null; 645 DeviceConfigSession<Long> bgNotificationMinInterval = null; 646 DeviceConfigSession<Integer> bgBatteryExemptionTypes = null; 647 DeviceConfigSession<Boolean> bgCurrentDrainDecoupleThresholds = null; 648 649 mBgRestrictionController.addAppBackgroundRestrictionListener(listener); 650 651 setBackgroundRestrict(testPkgName, testUid, false, listener); 652 653 // Verify the current settings. 654 verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid); 655 656 final double[] zeros = new double[]{0.0f, 0.0f}; 657 final int[] uids = new int[]{testUid, testUid2}; 658 659 try { 660 bgCurrentDrainMonitor = new DeviceConfigSession<>( 661 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 662 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_MONITOR_ENABLED, 663 DeviceConfig::getBoolean, 664 mContext.getResources().getBoolean( 665 R.bool.config_bg_current_drain_monitor_enabled)); 666 bgCurrentDrainMonitor.set(true); 667 668 bgCurrentDrainWindow = new DeviceConfigSession<>( 669 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 670 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_WINDOW, 671 DeviceConfig::getLong, 672 (long) mContext.getResources().getInteger( 673 R.integer.config_bg_current_drain_window)); 674 bgCurrentDrainWindow.set(windowMs); 675 676 bgCurrentDrainInteractionGracePeriod = new DeviceConfigSession<>( 677 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 678 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD, 679 DeviceConfig::getLong, 680 (long) mContext.getResources().getInteger( 681 R.integer.config_bg_current_drain_window)); 682 bgCurrentDrainInteractionGracePeriod.set(windowMs); 683 684 bgCurrentDrainRestrictedBucketThreshold = new DeviceConfigSession<>( 685 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 686 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET, 687 DeviceConfig::getFloat, 688 getFloatArray(mContext.getResources().obtainTypedArray( 689 R.array.config_bg_current_drain_threshold_to_restricted_bucket))[ 690 isLowRamDeviceStatic() ? 1 : 0]); 691 bgCurrentDrainRestrictedBucketThreshold.set(restrictBucketThreshold); 692 693 bgCurrentDrainBgRestrictedThreshold = new DeviceConfigSession<>( 694 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 695 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_BG_RESTRICTED, 696 DeviceConfig::getFloat, 697 getFloatArray(mContext.getResources().obtainTypedArray( 698 R.array.config_bg_current_drain_threshold_to_bg_restricted))[ 699 isLowRamDeviceStatic() ? 1 : 0]); 700 bgCurrentDrainBgRestrictedThreshold.set(bgRestrictedThreshold); 701 702 bgCurrentDrainAutoRestrictAbusiveApps = new DeviceConfigSession<>( 703 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 704 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_AUTO_RESTRICT_ABUSIVE_APPS_ENABLED, 705 DeviceConfig::getBoolean, 706 mContext.getResources().getBoolean( 707 R.bool.config_bg_current_drain_auto_restrict_abusive_apps)); 708 bgCurrentDrainAutoRestrictAbusiveApps.set(true); 709 710 bgPromptFgsWithNotiToBgRestricted = new DeviceConfigSession<>( 711 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 712 ConstantsObserver.KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_TO_BG_RESTRICTED, 713 DeviceConfig::getBoolean, 714 mContext.getResources().getBoolean( 715 R.bool.config_bg_prompt_fgs_with_noti_to_bg_restricted)); 716 bgPromptFgsWithNotiToBgRestricted.set(true); 717 718 bgPromptAbusiveAppToBgRestricted = new DeviceConfigSession<>( 719 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 720 ConstantsObserver.KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED, 721 DeviceConfig::getBoolean, 722 mContext.getResources().getBoolean( 723 R.bool.config_bg_prompt_abusive_apps_to_bg_restricted)); 724 bgPromptAbusiveAppToBgRestricted.set(true); 725 726 bgNotificationMinInterval = new DeviceConfigSession<>( 727 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 728 ConstantsObserver.KEY_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL, 729 DeviceConfig::getLong, 730 ConstantsObserver.DEFAULT_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL_MS); 731 bgNotificationMinInterval.set(windowMs); 732 733 bgBatteryExemptionTypes = new DeviceConfigSession<>( 734 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 735 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_EXEMPTED_TYPES, 736 DeviceConfig::getInt, 737 mContext.getResources().getInteger( 738 R.integer.config_bg_current_drain_exempted_types)); 739 bgBatteryExemptionTypes.set(0); 740 741 bgCurrentDrainDecoupleThresholds = new DeviceConfigSession<>( 742 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 743 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLDS, 744 DeviceConfig::getBoolean, 745 AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLD); 746 bgCurrentDrainDecoupleThresholds.set(true); 747 748 mCurrentTimeMillis = 10_000L; 749 doReturn(mCurrentTimeMillis - windowMs).when(stats).getStatsStartTimestamp(); 750 doReturn(mCurrentTimeMillis).when(stats).getStatsEndTimestamp(); 751 doReturn(statsList).when(mBatteryStatsInternal).getBatteryUsageStats(anyObject()); 752 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName, testUid, 753 testPid, true); 754 mAppFGSTracker.onForegroundServiceNotificationUpdated( 755 testPkgName, testUid, notificationId, false); 756 mAppFGSTracker.mNotificationListener.onNotificationPosted(new StatusBarNotification( 757 testPkgName, null, notificationId, null, testUid, testPid, 758 new Notification(), UserHandle.of(testUser), null, mCurrentTimeMillis), null); 759 760 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 761 new double[]{restrictBucketThresholdMah - 1, 0}, 762 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 763 () -> { 764 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 765 doReturn(mCurrentTimeMillis + windowMs) 766 .when(stats).getStatsEndTimestamp(); 767 mCurrentTimeMillis += windowMs + 1; 768 try { 769 listener.verify(timeout, testUid, testPkgName, 770 RESTRICTION_LEVEL_ADAPTIVE_BUCKET); 771 fail("There shouldn't be any level change events"); 772 } catch (Exception e) { 773 // Expected. 774 } 775 }); 776 777 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 778 new double[]{restrictBucketThresholdMah + 1, 0}, 779 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 780 () -> { 781 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 782 doReturn(mCurrentTimeMillis + windowMs) 783 .when(stats).getStatsEndTimestamp(); 784 mCurrentTimeMillis += windowMs + 1; 785 // It should have gone to the restricted bucket. 786 listener.verify(timeout, testUid, testPkgName, 787 RESTRICTION_LEVEL_RESTRICTED_BUCKET); 788 verify(mInjector.getAppStandbyInternal()).restrictApp( 789 eq(testPkgName), 790 eq(testUser), 791 anyInt(), anyInt()); 792 }); 793 794 795 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 796 new double[]{restrictBucketThresholdMah - 1, 0}, 797 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 798 () -> { 799 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 800 doReturn(mCurrentTimeMillis + windowMs) 801 .when(stats).getStatsEndTimestamp(); 802 mCurrentTimeMillis += windowMs + 1; 803 // We won't change restriction level until user interactions. 804 try { 805 listener.verify(timeout, testUid, testPkgName, 806 RESTRICTION_LEVEL_ADAPTIVE_BUCKET); 807 fail("There shouldn't be any level change events"); 808 } catch (Exception e) { 809 // Expected. 810 } 811 verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket( 812 eq(testPkgName), 813 eq(STANDBY_BUCKET_RARE), 814 eq(testUser), 815 anyInt(), anyInt()); 816 }); 817 818 // Trigger user interaction. 819 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 820 new double[]{restrictBucketThresholdMah - 1, 0}, 821 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 822 () -> { 823 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 824 doReturn(mCurrentTimeMillis + windowMs) 825 .when(stats).getStatsEndTimestamp(); 826 mCurrentTimeMillis += windowMs + 1; 827 mIdleStateListener.onUserInteractionStarted(testPkgName, testUser); 828 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 829 // It should have been back to normal. 830 listener.verify(timeout, testUid, testPkgName, 831 RESTRICTION_LEVEL_ADAPTIVE_BUCKET); 832 verify(mInjector.getAppStandbyInternal(), atLeast(1)).maybeUnrestrictApp( 833 eq(testPkgName), 834 eq(testUser), 835 eq(REASON_MAIN_FORCED_BY_SYSTEM), 836 eq(REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE), 837 eq(REASON_MAIN_USAGE), 838 eq(REASON_SUB_USAGE_USER_INTERACTION)); 839 }); 840 841 clearInvocations(mInjector.getAppStandbyInternal()); 842 843 // It won't be restricted since user just interacted with it. 844 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 845 zeros, new double[]{0, restrictBucketThresholdMah - 1}, 846 zeros, new double[]{restrictBucketThresholdMah + 1, 0}, 847 () -> { 848 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 849 doReturn(mCurrentTimeMillis + windowMs) 850 .when(stats).getStatsEndTimestamp(); 851 mCurrentTimeMillis += windowMs + 1; 852 try { 853 listener.verify(timeout, testUid, testPkgName, 854 RESTRICTION_LEVEL_RESTRICTED_BUCKET); 855 fail("There shouldn't be any level change events"); 856 } catch (Exception e) { 857 // Expected. 858 } 859 verify(mInjector.getAppStandbyInternal(), never()).restrictApp( 860 eq(testPkgName), 861 eq(testUser), 862 anyInt(), anyInt()); 863 }); 864 865 // Sleep a while. 866 Thread.sleep(windowMs); 867 clearInvocations(mInjector.getAppStandbyInternal()); 868 // Now it should have been restricted. 869 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 870 zeros, new double[]{0, restrictBucketThresholdMah - 1}, 871 zeros, new double[]{restrictBucketThresholdMah + 1, 0}, 872 () -> { 873 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 874 doReturn(mCurrentTimeMillis + windowMs) 875 .when(stats).getStatsEndTimestamp(); 876 mCurrentTimeMillis += windowMs + 1; 877 // It should have gone to the restricted bucket. 878 listener.verify(timeout, testUid, testPkgName, 879 RESTRICTION_LEVEL_RESTRICTED_BUCKET); 880 verify(mInjector.getAppStandbyInternal(), times(1)).restrictApp( 881 eq(testPkgName), 882 eq(testUser), 883 anyInt(), anyInt()); 884 }); 885 886 clearInvocations(mInjector.getAppStandbyInternal()); 887 // Drain a bit more, there shouldn't be any level changes. 888 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 889 zeros, new double[]{0, restrictBucketThresholdMah - 1}, 890 zeros, new double[]{restrictBucketThresholdMah + 2, 0}, 891 () -> { 892 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 893 doReturn(mCurrentTimeMillis + windowMs) 894 .when(stats).getStatsEndTimestamp(); 895 mCurrentTimeMillis += windowMs + 1; 896 // We won't change restriction level until user interactions. 897 try { 898 listener.verify(timeout, testUid, testPkgName, 899 RESTRICTION_LEVEL_ADAPTIVE_BUCKET); 900 fail("There shouldn't be any level change events"); 901 } catch (Exception e) { 902 // Expected. 903 } 904 verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket( 905 eq(testPkgName), 906 eq(STANDBY_BUCKET_RARE), 907 eq(testUser), 908 anyInt(), anyInt()); 909 }); 910 911 // Pretend we have the standby buckets set above. 912 doReturn(STANDBY_BUCKET_RESTRICTED) 913 .when(mAppStandbyInternal) 914 .getAppStandbyBucket(eq(testPkgName), eq(testUser), anyLong(), anyBoolean()); 915 916 // Sleep a while and set a higher drain 917 Thread.sleep(windowMs); 918 clearInvocations(mInjector.getAppStandbyInternal()); 919 clearInvocations(mInjector.getNotificationManager()); 920 clearInvocations(mBgRestrictionController); 921 922 // We're not going to prompt the user if the abusive app has a FGS with notification. 923 bgPromptFgsWithNotiToBgRestricted.set(false); 924 925 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 926 new double[]{bgRestrictedThresholdMah + 1, 0}, 927 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 928 () -> { 929 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 930 doReturn(mCurrentTimeMillis + windowMs) 931 .when(stats).getStatsEndTimestamp(); 932 mCurrentTimeMillis += windowMs + 1; 933 // We won't change restriction level automatically because it needs 934 // user consent. 935 try { 936 listener.verify(timeout, testUid, testPkgName, 937 RESTRICTION_LEVEL_BACKGROUND_RESTRICTED); 938 fail("There shouldn't be level change event like this"); 939 } catch (Exception e) { 940 // Expected. 941 } 942 verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket( 943 eq(testPkgName), 944 eq(STANDBY_BUCKET_RARE), 945 eq(testUser), 946 anyInt(), anyInt()); 947 // We should have requested to goto background restricted level. 948 verify(mBgRestrictionController, times(1)).handleRequestBgRestricted( 949 eq(testPkgName), 950 eq(testUid)); 951 // However, we won't have the prompt to user posted because the policy 952 // is not to show that for FGS with notification. 953 checkNotificationShown(new String[] {testPkgName}, never(), false); 954 }); 955 956 // Pretend we have the notification dismissed. 957 mAppFGSTracker.onForegroundServiceNotificationUpdated( 958 testPkgName, testUid, notificationId, true); 959 clearInvocations(mInjector.getAppStandbyInternal()); 960 clearInvocations(mInjector.getNotificationManager()); 961 clearInvocations(mBgRestrictionController); 962 963 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 964 new double[]{bgRestrictedThresholdMah + 1, 0}, 965 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 966 () -> { 967 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 968 doReturn(mCurrentTimeMillis + windowMs) 969 .when(stats).getStatsEndTimestamp(); 970 mCurrentTimeMillis += windowMs + 1; 971 // We won't change restriction level automatically because it needs 972 // user consent. 973 try { 974 listener.verify(timeout, testUid, testPkgName, 975 RESTRICTION_LEVEL_BACKGROUND_RESTRICTED); 976 fail("There shouldn't be level change event like this"); 977 } catch (Exception e) { 978 // Expected. 979 } 980 verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket( 981 eq(testPkgName), 982 eq(STANDBY_BUCKET_RARE), 983 eq(testUser), 984 anyInt(), anyInt()); 985 // We should have requested to goto background restricted level. 986 verify(mBgRestrictionController, times(1)).handleRequestBgRestricted( 987 eq(testPkgName), 988 eq(testUid)); 989 // Verify we have the notification posted now because its FGS is invisible. 990 checkNotificationShown(new String[] {testPkgName}, atLeast(1), true); 991 }); 992 993 // Pretend notification is back on. 994 mAppFGSTracker.onForegroundServiceNotificationUpdated( 995 testPkgName, testUid, notificationId, false); 996 // Now we'll prompt the user even it has a FGS with notification. 997 bgPromptFgsWithNotiToBgRestricted.set(true); 998 clearInvocations(mInjector.getAppStandbyInternal()); 999 clearInvocations(mInjector.getNotificationManager()); 1000 clearInvocations(mBgRestrictionController); 1001 1002 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 1003 new double[]{bgRestrictedThresholdMah + 1, 0}, 1004 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 1005 () -> { 1006 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 1007 doReturn(mCurrentTimeMillis + windowMs) 1008 .when(stats).getStatsEndTimestamp(); 1009 mCurrentTimeMillis += windowMs + 1; 1010 // We won't change restriction level automatically because it needs 1011 // user consent. 1012 try { 1013 listener.verify(timeout, testUid, testPkgName, 1014 RESTRICTION_LEVEL_BACKGROUND_RESTRICTED); 1015 fail("There shouldn't be level change event like this"); 1016 } catch (Exception e) { 1017 // Expected. 1018 } 1019 verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket( 1020 eq(testPkgName), 1021 eq(STANDBY_BUCKET_RARE), 1022 eq(testUser), 1023 anyInt(), anyInt()); 1024 // We should have requested to goto background restricted level. 1025 verify(mBgRestrictionController, times(1)).handleRequestBgRestricted( 1026 eq(testPkgName), 1027 eq(testUid)); 1028 // Verify we have the notification posted. 1029 checkNotificationShown(new String[] {testPkgName}, atLeast(1), true); 1030 }); 1031 1032 // Turn ON the FAS for real. 1033 setBackgroundRestrict(testPkgName, testUid, true, listener); 1034 1035 // Verify it's background restricted now. 1036 verifyRestrictionLevel(RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, testPkgName, testUid); 1037 listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_BACKGROUND_RESTRICTED); 1038 1039 // Trigger user interaction. 1040 mIdleStateListener.onUserInteractionStarted(testPkgName, testUser); 1041 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 1042 1043 listener.mLatchHolder[0] = new CountDownLatch(1); 1044 try { 1045 listener.verify(timeout, testUid, testPkgName, 1046 RESTRICTION_LEVEL_ADAPTIVE_BUCKET); 1047 fail("There shouldn't be level change event like this"); 1048 } catch (Exception e) { 1049 // Expected. 1050 } 1051 1052 // Reset the standby bucket. 1053 doReturn(STANDBY_BUCKET_RARE) 1054 .when(mAppStandbyInternal) 1055 .getAppStandbyBucket(eq(testPkgName), eq(testUser), anyLong(), anyBoolean()); 1056 1057 // Turn OFF the FAS. 1058 listener.mLatchHolder[0] = new CountDownLatch(1); 1059 clearInvocations(mInjector.getAppStandbyInternal()); 1060 clearInvocations(mBgRestrictionController); 1061 setBackgroundRestrict(testPkgName, testUid, false, listener); 1062 1063 // It'll go back to restricted bucket because it used to behave poorly. 1064 listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_RESTRICTED_BUCKET); 1065 verifyRestrictionLevel(RESTRICTION_LEVEL_RESTRICTED_BUCKET, testPkgName, testUid); 1066 1067 clearInvocations(mInjector.getAppStandbyInternal()); 1068 // Trigger user interaction. 1069 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 1070 new double[]{restrictBucketThresholdMah - 1, 0}, 1071 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 1072 () -> { 1073 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 1074 doReturn(mCurrentTimeMillis + windowMs) 1075 .when(stats).getStatsEndTimestamp(); 1076 mCurrentTimeMillis += windowMs + 1; 1077 mIdleStateListener.onUserInteractionStarted(testPkgName, testUser); 1078 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 1079 // It should have been back to normal. 1080 listener.verify(timeout, testUid, testPkgName, 1081 RESTRICTION_LEVEL_ADAPTIVE_BUCKET); 1082 verify(mInjector.getAppStandbyInternal(), atLeast(1)).maybeUnrestrictApp( 1083 eq(testPkgName), 1084 eq(testUser), 1085 eq(REASON_MAIN_USAGE), 1086 eq(REASON_SUB_USAGE_USER_INTERACTION), 1087 eq(REASON_MAIN_USAGE), 1088 eq(REASON_SUB_USAGE_USER_INTERACTION)); 1089 }); 1090 1091 bgCurrentDrainDecoupleThresholds.set(true); 1092 clearInvocations(mInjector.getAppStandbyInternal()); 1093 1094 // Go to the threshold right away. 1095 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 1096 new double[]{0, restrictBucketThresholdMah - 1}, 1097 new double[]{bgRestrictedThresholdMah + 1, 0}, zeros, zeros, 1098 () -> { 1099 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 1100 doReturn(mCurrentTimeMillis + windowMs) 1101 .when(stats).getStatsEndTimestamp(); 1102 mCurrentTimeMillis += windowMs + 1; 1103 // We won't change restriction level automatically because it needs 1104 // user consent. 1105 try { 1106 listener.verify(timeout, testUid, testPkgName, 1107 RESTRICTION_LEVEL_BACKGROUND_RESTRICTED); 1108 fail("There shouldn't be level change event like this"); 1109 } catch (Exception e) { 1110 // Expected. 1111 } 1112 verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket( 1113 eq(testPkgName), 1114 eq(STANDBY_BUCKET_RARE), 1115 eq(testUser), 1116 anyInt(), anyInt()); 1117 // We should have requested to goto background restricted level. 1118 verify(mBgRestrictionController, times(1)).handleRequestBgRestricted( 1119 eq(testPkgName), 1120 eq(testUid)); 1121 // Verify we have the notification posted now because its FGS is invisible. 1122 checkNotificationShown(new String[] {testPkgName}, atLeast(1), true); 1123 }); 1124 1125 bgCurrentDrainDecoupleThresholds.set(false); 1126 clearInvocations(mInjector.getAppStandbyInternal()); 1127 clearInvocations(mBgRestrictionController); 1128 1129 // Go to the threshold right away, but this time, it shouldn't even request to goto 1130 // bg restricted level because it requires to be in restricted bucket before that. 1131 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, 1132 new double[]{0, restrictBucketThresholdMah - 1}, 1133 new double[]{bgRestrictedThresholdMah + 1, 0}, zeros, zeros, 1134 () -> { 1135 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 1136 doReturn(mCurrentTimeMillis + windowMs) 1137 .when(stats).getStatsEndTimestamp(); 1138 mCurrentTimeMillis += windowMs + 1; 1139 // We won't change restriction level automatically because it needs 1140 // user consent. 1141 try { 1142 listener.verify(timeout, testUid, testPkgName, 1143 RESTRICTION_LEVEL_BACKGROUND_RESTRICTED); 1144 fail("There shouldn't be level change event like this"); 1145 } catch (Exception e) { 1146 // Expected. 1147 } 1148 verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket( 1149 eq(testPkgName), 1150 eq(STANDBY_BUCKET_RARE), 1151 eq(testUser), 1152 anyInt(), anyInt()); 1153 // We should NOT have requested to goto background restricted level. 1154 verify(mBgRestrictionController, never()).handleRequestBgRestricted( 1155 eq(testPkgName), 1156 eq(testUid)); 1157 }); 1158 1159 } finally { 1160 closeIfNotNull(bgCurrentDrainMonitor); 1161 closeIfNotNull(bgCurrentDrainWindow); 1162 closeIfNotNull(bgCurrentDrainInteractionGracePeriod); 1163 closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold); 1164 closeIfNotNull(bgCurrentDrainBgRestrictedThreshold); 1165 closeIfNotNull(bgCurrentDrainAutoRestrictAbusiveApps); 1166 closeIfNotNull(bgPromptFgsWithNotiToBgRestricted); 1167 closeIfNotNull(bgPromptAbusiveAppToBgRestricted); 1168 closeIfNotNull(bgNotificationMinInterval); 1169 closeIfNotNull(bgBatteryExemptionTypes); 1170 closeIfNotNull(bgCurrentDrainDecoupleThresholds); 1171 } 1172 } 1173 1174 @Test testLongFGSMonitor()1175 public void testLongFGSMonitor() throws Exception { 1176 final int testPkgIndex1 = 1; 1177 final String testPkgName1 = TEST_PACKAGE_BASE + testPkgIndex1; 1178 final int testUser1 = TEST_USER0; 1179 final int testUid1 = UserHandle.getUid(testUser1, TEST_PACKAGE_APPID_BASE + testPkgIndex1); 1180 final int testPid1 = 1234; 1181 1182 final int testPkgIndex2 = 2; 1183 final String testPkgName2 = TEST_PACKAGE_BASE + testPkgIndex2; 1184 final int testUser2 = TEST_USER0; 1185 final int testUid2 = UserHandle.getUid(testUser2, TEST_PACKAGE_APPID_BASE + testPkgIndex2); 1186 final int testPid2 = 1235; 1187 1188 final int fgsNotificationId = 1000; 1189 1190 final long windowMs = 2_000; 1191 final long thresholdMs = 1_000; 1192 final long shortMs = 100; 1193 1194 DeviceConfigSession<Boolean> longRunningFGSMonitor = null; 1195 DeviceConfigSession<Long> longRunningFGSWindow = null; 1196 DeviceConfigSession<Long> longRunningFGSThreshold = null; 1197 DeviceConfigSession<Boolean> longRunningFGSWithNotification = null; 1198 DeviceConfigSession<Boolean> longRunningFGS = null; 1199 1200 try { 1201 longRunningFGSMonitor = new DeviceConfigSession<>( 1202 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1203 AppFGSPolicy.KEY_BG_FGS_MONITOR_ENABLED, 1204 DeviceConfig::getBoolean, 1205 AppFGSPolicy.DEFAULT_BG_FGS_MONITOR_ENABLED); 1206 longRunningFGSMonitor.set(true); 1207 1208 longRunningFGSWindow = new DeviceConfigSession<>( 1209 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1210 AppFGSPolicy.KEY_BG_FGS_LONG_RUNNING_WINDOW, 1211 DeviceConfig::getLong, 1212 AppFGSPolicy.DEFAULT_BG_FGS_LONG_RUNNING_WINDOW); 1213 longRunningFGSWindow.set(windowMs); 1214 1215 longRunningFGSThreshold = new DeviceConfigSession<>( 1216 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1217 AppFGSPolicy.KEY_BG_FGS_LONG_RUNNING_THRESHOLD, 1218 DeviceConfig::getLong, 1219 AppFGSPolicy.DEFAULT_BG_FGS_LONG_RUNNING_THRESHOLD); 1220 longRunningFGSThreshold.set(thresholdMs); 1221 1222 longRunningFGSWithNotification = new DeviceConfigSession<>( 1223 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1224 ConstantsObserver.KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING, 1225 DeviceConfig::getBoolean, 1226 ConstantsObserver.DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); 1227 longRunningFGSWithNotification.set(true); 1228 1229 longRunningFGS = new DeviceConfigSession<>( 1230 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1231 ConstantsObserver.KEY_BG_PROMPT_FGS_ON_LONG_RUNNING, 1232 DeviceConfig::getBoolean, 1233 ConstantsObserver.DEFAULT_BG_PROMPT_FGS_ON_LONG_RUNNING); 1234 longRunningFGS.set(true); 1235 1236 // Basic case 1237 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, 1238 testPid1, true); 1239 // Verify we have the notification, it'll include the summary notification though. 1240 int notificationId = checkNotificationShown( 1241 new String[] {testPkgName1}, timeout(windowMs * 2).times(2), true)[0]; 1242 1243 clearInvocations(mInjector.getNotificationManager()); 1244 // Sleep a while, verify it won't show another notification. 1245 Thread.sleep(windowMs * 2); 1246 checkNotificationShown( 1247 new String[] {testPkgName1}, timeout(windowMs * 2).times(0), false); 1248 1249 // Stop this FGS 1250 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, 1251 testPid1, false); 1252 checkNotificationGone(testPkgName1, timeout(windowMs), notificationId); 1253 1254 clearInvocations(mInjector.getNotificationManager()); 1255 // Start another one and stop it. 1256 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2, 1257 testPid2, true); 1258 Thread.sleep(shortMs); 1259 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2, 1260 testPid2, false); 1261 1262 // Not long enough, it shouldn't show notification in this case. 1263 checkNotificationShown( 1264 new String[] {testPkgName2}, timeout(windowMs * 2).times(0), false); 1265 1266 clearInvocations(mInjector.getNotificationManager()); 1267 // Start the FGS again. 1268 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2, 1269 testPid2, true); 1270 // Verify we have the notification. 1271 notificationId = checkNotificationShown( 1272 new String[] {testPkgName2}, timeout(windowMs * 2).times(2), true)[0]; 1273 1274 // Stop this FGS 1275 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2, 1276 testPid2, false); 1277 checkNotificationGone(testPkgName2, timeout(windowMs), notificationId); 1278 1279 // Turn OFF the notification. 1280 longRunningFGS.set(false); 1281 clearInvocations(mInjector.getNotificationManager()); 1282 mBgRestrictionController.resetRestrictionSettings(); 1283 // Start the FGS again. 1284 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2, 1285 testPid2, true); 1286 // Verify we do NOT have the notification. 1287 checkNotificationShown( 1288 new String[] {testPkgName2}, timeout(windowMs * 2).times(0), false); 1289 // Stop this FGS 1290 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2, 1291 testPid2, false); 1292 1293 // Turn it back ON. 1294 longRunningFGS.set(true); 1295 1296 // Start over with concurrent cases. 1297 clearInvocations(mInjector.getNotificationManager()); 1298 mBgRestrictionController.resetRestrictionSettings(); 1299 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2, 1300 testPid2, true); 1301 Thread.sleep(shortMs); 1302 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, 1303 testPid1, true); 1304 1305 // Verify we've seen both notifications, and test pkg2 should be shown before test pkg1. 1306 int[] notificationIds = checkNotificationShown( 1307 new String[] {testPkgName2, testPkgName1}, 1308 timeout(windowMs * 2).times(4), true); 1309 1310 // Stop both of them. 1311 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, 1312 testPid1, false); 1313 checkNotificationGone(testPkgName1, timeout(windowMs), notificationIds[1]); 1314 clearInvocations(mInjector.getNotificationManager()); 1315 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2, 1316 testPid2, false); 1317 checkNotificationGone(testPkgName2, timeout(windowMs), notificationIds[0]); 1318 1319 // Test the interlaced case. 1320 clearInvocations(mInjector.getNotificationManager()); 1321 mBgRestrictionController.resetRestrictionSettings(); 1322 mAppFGSTracker.reset(); 1323 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, 1324 testPid1, true); 1325 1326 final long initialWaitMs = thresholdMs / 2; 1327 Thread.sleep(initialWaitMs); 1328 1329 for (long remaining = thresholdMs - initialWaitMs; remaining > 0;) { 1330 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, 1331 testPid1, false); 1332 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2, 1333 testPid2, true); 1334 Thread.sleep(shortMs); 1335 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, 1336 testPid1, true); 1337 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2, 1338 testPid2, false); 1339 Thread.sleep(shortMs); 1340 remaining -= shortMs; 1341 } 1342 1343 // Verify test pkg1 got the notification, but not test pkg2. 1344 notificationId = checkNotificationShown( 1345 new String[] {testPkgName1}, timeout(windowMs).times(2), true)[0]; 1346 1347 clearInvocations(mInjector.getNotificationManager()); 1348 // Stop the FGS. 1349 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, 1350 testPid1, false); 1351 checkNotificationGone(testPkgName1, timeout(windowMs), notificationId); 1352 1353 // Start over with the flag to not show prompt when it has an active notification. 1354 clearInvocations(mInjector.getNotificationManager()); 1355 mBgRestrictionController.resetRestrictionSettings(); 1356 longRunningFGSWithNotification.set(false); 1357 1358 // Start an FGS with notification. 1359 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, 1360 testPid1, true); 1361 mAppFGSTracker.onForegroundServiceNotificationUpdated( 1362 testPkgName1, testUid1, fgsNotificationId, false); 1363 mAppFGSTracker.mNotificationListener.onNotificationPosted(new StatusBarNotification( 1364 testPkgName1, null, fgsNotificationId, null, testUid1, testPid1, 1365 new Notification(), UserHandle.of(testUser1), null, mCurrentTimeMillis), null); 1366 1367 // Verify we won't prompt the user because it has a visible FGS notification. 1368 checkNotificationShown( 1369 new String[] {testPkgName1}, timeout(windowMs * 2).times(0), false); 1370 1371 // Pretend we have the notification dismissed. 1372 mAppFGSTracker.onForegroundServiceNotificationUpdated( 1373 testPkgName1, testUid1, fgsNotificationId, true); 1374 1375 // Verify we have the notification. 1376 notificationId = checkNotificationShown( 1377 new String[] {testPkgName1}, timeout(windowMs * 2).times(2), true)[0]; 1378 1379 // Stop the FGS. 1380 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, 1381 testPid1, false); 1382 checkNotificationGone(testPkgName1, timeout(windowMs), notificationId); 1383 } finally { 1384 closeIfNotNull(longRunningFGSMonitor); 1385 closeIfNotNull(longRunningFGSWindow); 1386 closeIfNotNull(longRunningFGSThreshold); 1387 closeIfNotNull(longRunningFGSWithNotification); 1388 closeIfNotNull(longRunningFGS); 1389 } 1390 } 1391 1392 @Test testLongFGSExemptions()1393 public void testLongFGSExemptions() throws Exception { 1394 final int testPkgIndex1 = 1; 1395 final String testPkgName1 = TEST_PACKAGE_BASE + testPkgIndex1; 1396 final int testUser1 = TEST_USER0; 1397 final int testUid1 = UserHandle.getUid(testUser1, TEST_PACKAGE_APPID_BASE + testPkgIndex1); 1398 final int testPid1 = 1234; 1399 1400 final int testPkgIndex2 = 2; 1401 final String testPkgName2 = TEST_PACKAGE_BASE + testPkgIndex2; 1402 final int testUser2 = TEST_USER0; 1403 final int testUid2 = UserHandle.getUid(testUser2, TEST_PACKAGE_APPID_BASE + testPkgIndex2); 1404 final int testPid2 = 1235; 1405 1406 final long windowMs = 2_000; 1407 final long thresholdMs = 1_000; 1408 1409 DeviceConfigSession<Boolean> longRunningFGSMonitor = null; 1410 DeviceConfigSession<Long> longRunningFGSWindow = null; 1411 DeviceConfigSession<Long> longRunningFGSThreshold = null; 1412 DeviceConfigSession<Long> mediaPlaybackFGSThreshold = null; 1413 DeviceConfigSession<Long> locationFGSThreshold = null; 1414 DeviceConfigSession<Boolean> longRunningFGSWithNotification = null; 1415 DeviceConfigSession<Boolean> longRunningFGS = null; 1416 1417 doReturn(testPkgName1).when(mInjector).getPackageName(testPid1); 1418 doReturn(testPkgName2).when(mInjector).getPackageName(testPid2); 1419 1420 try { 1421 longRunningFGSMonitor = new DeviceConfigSession<>( 1422 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1423 AppFGSPolicy.KEY_BG_FGS_MONITOR_ENABLED, 1424 DeviceConfig::getBoolean, 1425 AppFGSPolicy.DEFAULT_BG_FGS_MONITOR_ENABLED); 1426 longRunningFGSMonitor.set(true); 1427 1428 longRunningFGSWindow = new DeviceConfigSession<>( 1429 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1430 AppFGSPolicy.KEY_BG_FGS_LONG_RUNNING_WINDOW, 1431 DeviceConfig::getLong, 1432 AppFGSPolicy.DEFAULT_BG_FGS_LONG_RUNNING_WINDOW); 1433 longRunningFGSWindow.set(windowMs); 1434 1435 longRunningFGSThreshold = new DeviceConfigSession<>( 1436 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1437 AppFGSPolicy.KEY_BG_FGS_LONG_RUNNING_THRESHOLD, 1438 DeviceConfig::getLong, 1439 AppFGSPolicy.DEFAULT_BG_FGS_LONG_RUNNING_THRESHOLD); 1440 longRunningFGSThreshold.set(thresholdMs); 1441 1442 mediaPlaybackFGSThreshold = new DeviceConfigSession<>( 1443 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1444 AppFGSPolicy.KEY_BG_FGS_MEDIA_PLAYBACK_THRESHOLD, 1445 DeviceConfig::getLong, 1446 AppFGSPolicy.DEFAULT_BG_FGS_MEDIA_PLAYBACK_THRESHOLD); 1447 mediaPlaybackFGSThreshold.set(thresholdMs); 1448 1449 locationFGSThreshold = new DeviceConfigSession<>( 1450 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1451 AppFGSPolicy.KEY_BG_FGS_LOCATION_THRESHOLD, 1452 DeviceConfig::getLong, 1453 AppFGSPolicy.DEFAULT_BG_FGS_LOCATION_THRESHOLD); 1454 locationFGSThreshold.set(thresholdMs); 1455 1456 longRunningFGSWithNotification = new DeviceConfigSession<>( 1457 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1458 ConstantsObserver.KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING, 1459 DeviceConfig::getBoolean, 1460 ConstantsObserver.DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); 1461 longRunningFGSWithNotification.set(true); 1462 1463 longRunningFGS = new DeviceConfigSession<>( 1464 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1465 ConstantsObserver.KEY_BG_PROMPT_FGS_ON_LONG_RUNNING, 1466 DeviceConfig::getBoolean, 1467 ConstantsObserver.DEFAULT_BG_PROMPT_FGS_ON_LONG_RUNNING); 1468 longRunningFGS.set(true); 1469 1470 // Long-running FGS with type "location", but ran for a very short time. 1471 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1472 FOREGROUND_SERVICE_TYPE_LOCATION, 0, null, OP_NONE, null, null, 1473 timeout(windowMs * 2).times(2)); 1474 1475 // Long-running FGS with type "location", and ran for a while. 1476 // We shouldn't see notifications in this case. 1477 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1478 FOREGROUND_SERVICE_TYPE_LOCATION, thresholdMs * 2, null, OP_NONE, null, null, 1479 timeout(windowMs * 2).times(0)); 1480 1481 // Long-running FGS with background location permission. 1482 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1483 FOREGROUND_SERVICE_TYPE_LOCATION, 0, ACCESS_BACKGROUND_LOCATION, OP_NONE, 1484 null, null, timeout(windowMs * 2).times(0)); 1485 1486 // Long-running FGS with type "mediaPlayback", but ran for a very short time. 1487 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1488 FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, 0, null, OP_NONE, null, null, 1489 timeout(windowMs * 2).times(2)); 1490 1491 // Long-running FGS with type "mediaPlayback", and ran for a while. 1492 // We shouldn't see notifications in this case. 1493 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1494 FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, thresholdMs * 2, null, OP_NONE, 1495 null, null, timeout(windowMs * 2).times(0)); 1496 1497 // Long-running FGS with type "camera", and ran for a while. 1498 // We shouldn't see notifications in this case. 1499 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1500 FOREGROUND_SERVICE_TYPE_CAMERA, thresholdMs * 2, null, OP_NONE, null, null, 1501 timeout(windowMs * 2).times(0)); 1502 1503 // Long-running FGS with type "location|mediaPlayback", but ran for a very short time. 1504 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1505 FOREGROUND_SERVICE_TYPE_LOCATION | FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, 1506 0, null, OP_NONE, null, null, timeout(windowMs * 2).times(2)); 1507 1508 // Long-running FGS with type "location|mediaPlayback", and ran for a while. 1509 // We shouldn't see notifications in this case. 1510 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1511 FOREGROUND_SERVICE_TYPE_LOCATION | FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, 1512 thresholdMs * 2, null, OP_NONE, null, null, timeout(windowMs * 2).times(0)); 1513 1514 // Long-running FGS with a media session starts/stops right away. 1515 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1516 FOREGROUND_SERVICE_TYPE_NONE, 0, null, OP_NONE, 1517 List.of(Pair.create(createMediaControllers( 1518 new String[] {testPkgName1}, new int[] {testUid1}), 0L)), null, 1519 timeout(windowMs * 2).times(2)); 1520 1521 // Long-running FGS with media session, and ran for a while. 1522 // We shouldn't see notifications in this case. 1523 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1524 FOREGROUND_SERVICE_TYPE_NONE, thresholdMs * 2, null, OP_NONE, 1525 List.of(Pair.create(createMediaControllers(new String[] {testPkgName1}, 1526 new int[] {testUid1}), thresholdMs * 2)), null, 1527 timeout(windowMs * 2).times(0)); 1528 1529 // Long-running FGS with 2 media sessions start/stop right away 1530 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1531 FOREGROUND_SERVICE_TYPE_NONE, 0, null, OP_NONE, 1532 List.of(Pair.create(createMediaControllers( 1533 new String[] {testPkgName1, testPkgName2}, 1534 new int[] {testUid1, testUid2}), 0L)), null, 1535 timeout(windowMs * 2).times(2)); 1536 1537 // Long-running FGS with 2 media sessions start/stop interlaced. 1538 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1539 FOREGROUND_SERVICE_TYPE_NONE, 0, null, OP_NONE, 1540 List.of(Pair.create(createMediaControllers( 1541 new String[] {testPkgName1, testPkgName2}, 1542 new int[] {testUid1, testUid2}), thresholdMs), 1543 Pair.create(createMediaControllers( 1544 new String[] {testPkgName1}, 1545 new int[] {testUid1}), thresholdMs / 10), 1546 Pair.create(createMediaControllers( 1547 new String[] {testPkgName2}, 1548 new int[] {testUid2}), thresholdMs / 10), 1549 Pair.create(createMediaControllers( 1550 new String[] {testPkgName1}, 1551 new int[] {testUid1}), thresholdMs / 10) 1552 ), null, 1553 timeout(windowMs * 2).times(0)); 1554 1555 // Long-running FGS with top state for a very short time. 1556 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1557 FOREGROUND_SERVICE_TYPE_NONE, 0, null, OP_NONE, null, List.of(0L), 1558 timeout(windowMs * 2).times(2)); 1559 1560 // Long-running FGS with top state for extended time. 1561 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1562 FOREGROUND_SERVICE_TYPE_NONE, 0, null, OP_NONE, null, 1563 List.of(0L, windowMs * 2, 0L), timeout(windowMs * 2).times(0)); 1564 1565 // Long-running FGS with top state, on and off frequently. 1566 runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, 1567 FOREGROUND_SERVICE_TYPE_NONE, 0, null, OP_NONE, null, 1568 List.of(0L, thresholdMs / 10, thresholdMs / 10, thresholdMs / 10, 1569 thresholdMs / 10, thresholdMs / 10, thresholdMs / 10), 1570 timeout(windowMs * 2).times(2)); 1571 } finally { 1572 closeIfNotNull(longRunningFGSMonitor); 1573 closeIfNotNull(longRunningFGSWindow); 1574 closeIfNotNull(longRunningFGSThreshold); 1575 closeIfNotNull(mediaPlaybackFGSThreshold); 1576 closeIfNotNull(locationFGSThreshold); 1577 closeIfNotNull(longRunningFGSWithNotification); 1578 closeIfNotNull(longRunningFGS); 1579 } 1580 } 1581 resetBgRestrictionController()1582 private void resetBgRestrictionController() { 1583 mBgRestrictionController.resetRestrictionSettings(); 1584 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 1585 } 1586 runTestLongFGSExemptionOnce(String packageName, int uid, int pid, int serviceType, long sleepMs, String perm, int op, List<Pair<List<MediaController>, Long>> mediaControllers, List<Long> topStateChanges, VerificationMode mode)1587 private void runTestLongFGSExemptionOnce(String packageName, int uid, int pid, 1588 int serviceType, long sleepMs, String perm, int op, 1589 List<Pair<List<MediaController>, Long>> mediaControllers, List<Long> topStateChanges, 1590 VerificationMode mode) throws Exception { 1591 runExemptionTestOnce( 1592 packageName, uid, pid, serviceType, sleepMs, true, false, perm, op, 1593 mediaControllers, topStateChanges, true, true, 1594 () -> checkNotificationShown(new String[] {packageName}, mode, false) 1595 ); 1596 } 1597 runExemptionTestOnce(String packageName, int uid, int pid, int serviceType, long sleepMs, boolean stopAfterSleep, boolean withNotification, String perm, int op, List<Pair<List<MediaController>, Long>> mediaControllers, List<Long> topStateChanges, boolean resetFGSTracker, boolean resetController, RunnableWithException r)1598 private void runExemptionTestOnce(String packageName, int uid, int pid, 1599 int serviceType, long sleepMs, boolean stopAfterSleep, 1600 boolean withNotification, String perm, int op, 1601 List<Pair<List<MediaController>, Long>> mediaControllers, 1602 List<Long> topStateChanges, boolean resetFGSTracker, boolean resetController, 1603 RunnableWithException r) throws Exception { 1604 if (resetFGSTracker) { 1605 mAppFGSTracker.reset(); 1606 mAppMediaSessionTracker.reset(); 1607 } 1608 if (resetController) { 1609 resetBgRestrictionController(); 1610 } 1611 clearInvocations(mInjector.getNotificationManager()); 1612 1613 Thread topStateThread = null; 1614 if (topStateChanges != null) { 1615 final CountDownLatch latch = new CountDownLatch(1); 1616 topStateThread = new Thread(() -> { 1617 try { 1618 latch.await(); 1619 boolean top = false; 1620 for (long l: topStateChanges) { 1621 mUidObservers.onUidStateChanged(uid, 1622 top ? PROCESS_STATE_TOP : PROCESS_STATE_FOREGROUND_SERVICE, 1623 0, 0); 1624 top = !top; 1625 Thread.sleep(l); 1626 } 1627 mUidObservers.onUidGone(uid, false); 1628 } catch (InterruptedException | RemoteException e) { 1629 } 1630 }); 1631 topStateThread.start(); 1632 latch.countDown(); 1633 } 1634 1635 mAppFGSTracker.onForegroundServiceStateChanged(packageName, uid, pid, true); 1636 if (serviceType != FOREGROUND_SERVICE_TYPE_NONE) { 1637 mAppFGSTracker.mProcessObserver.onForegroundServicesChanged(pid, uid, serviceType); 1638 Thread.sleep(sleepMs); 1639 if (stopAfterSleep) { 1640 // Stop it now. 1641 mAppFGSTracker.mProcessObserver.onForegroundServicesChanged(pid, uid, 1642 FOREGROUND_SERVICE_TYPE_NONE); 1643 } 1644 } 1645 if (withNotification) { 1646 final int notificationId = 1000; 1647 mAppFGSTracker.onForegroundServiceNotificationUpdated( 1648 packageName, uid, notificationId, false); 1649 final StatusBarNotification noti = new StatusBarNotification( 1650 packageName, null, notificationId, null, uid, pid, 1651 new Notification(), UserHandle.of(UserHandle.getUserId(uid)), 1652 null, mCurrentTimeMillis); 1653 mAppFGSTracker.mNotificationListener.onNotificationPosted(noti, null); 1654 Thread.sleep(sleepMs); 1655 if (stopAfterSleep) { 1656 mAppFGSTracker.mNotificationListener.onNotificationRemoved(noti, null, 0); 1657 } 1658 } 1659 if (perm != null) { 1660 setPermissionState(packageName, uid, perm, true); 1661 if (op != OP_NONE) { 1662 setAppOpState(packageName, uid, op, true); 1663 } 1664 mInjector.getAppPermissionTracker().onPermissionsChanged(uid); 1665 } 1666 1667 if (mediaControllers != null) { 1668 for (Pair<List<MediaController>, Long> entry: mediaControllers) { 1669 mActiveSessionListener.onActiveSessionsChanged(entry.first); 1670 Thread.sleep(entry.second); 1671 } 1672 if (stopAfterSleep) { 1673 // Stop it now. 1674 mActiveSessionListener.onActiveSessionsChanged(null); 1675 } 1676 } 1677 1678 r.run(); 1679 1680 // Stop this FGS 1681 mAppFGSTracker.onForegroundServiceStateChanged(packageName, uid, pid, false); 1682 1683 if (perm != null) { 1684 setPermissionState(packageName, uid, perm, false); 1685 if (op != OP_NONE) { 1686 setAppOpState(packageName, uid, op, false); 1687 } 1688 mInjector.getAppPermissionTracker().onPermissionsChanged(uid); 1689 } 1690 if (topStateThread != null) { 1691 topStateThread.join(); 1692 } 1693 } 1694 createMediaControllers(String[] packageNames, int[] uids)1695 private List<MediaController> createMediaControllers(String[] packageNames, int[] uids) { 1696 final ArrayList<MediaController> controllers = new ArrayList<>(); 1697 for (int i = 0; i < packageNames.length; i++) { 1698 controllers.add(createMediaController(packageNames[i], uids[i])); 1699 } 1700 return controllers; 1701 } 1702 createMediaController(String packageName, int uid)1703 private MediaController createMediaController(String packageName, int uid) { 1704 final MediaController controller = mock(MediaController.class); 1705 final MediaSession.Token token = mock(MediaSession.Token.class); 1706 doReturn(packageName).when(controller).getPackageName(); 1707 doReturn(token).when(controller).getSessionToken(); 1708 doReturn(uid).when(token).getUid(); 1709 return controller; 1710 } 1711 1712 @Test testBgCurrentDrainMonitorExemptions()1713 public void testBgCurrentDrainMonitorExemptions() throws Exception { 1714 final BatteryUsageStats stats = mock(BatteryUsageStats.class); 1715 final List<BatteryUsageStats> statsList = Arrays.asList(stats); 1716 final int testPkgIndex1 = 1; 1717 final String testPkgName1 = TEST_PACKAGE_BASE + testPkgIndex1; 1718 final int testUser = TEST_USER0; 1719 final int testUid1 = UserHandle.getUid(testUser, 1720 TEST_PACKAGE_APPID_BASE + testPkgIndex1); 1721 final int testPid1 = 1234; 1722 final int testPkgIndex2 = 2; 1723 final String testPkgName2 = TEST_PACKAGE_BASE + testPkgIndex2; 1724 final int testUid2 = UserHandle.getUid(testUser, 1725 TEST_PACKAGE_APPID_BASE + testPkgIndex2); 1726 final int testPid2 = 1235; 1727 final TestAppRestrictionLevelListener listener = new TestAppRestrictionLevelListener(); 1728 final long timeout = 1729 AppBatteryTracker.BATTERY_USAGE_STATS_POLLING_INTERVAL_MS_DEBUG * 2; 1730 final long windowMs = 2_000; 1731 final float restrictBucketThreshold = 2.0f; 1732 final float restrictBucketThresholdMah = 1733 BATTERY_FULL_CHARGE_MAH * restrictBucketThreshold / 100.0f; 1734 final float bgRestrictedThreshold = 4.0f; 1735 final float bgRestrictedThresholdMah = 1736 BATTERY_FULL_CHARGE_MAH * bgRestrictedThreshold / 100.0f; 1737 final float restrictBucketHighThreshold = 25.0f; 1738 final float restrictBucketHighThresholdMah = 1739 BATTERY_FULL_CHARGE_MAH * restrictBucketHighThreshold / 100.0f; 1740 final float bgRestrictedHighThreshold = 25.0f; 1741 final float bgRestrictedHighThresholdMah = 1742 BATTERY_FULL_CHARGE_MAH * bgRestrictedHighThreshold / 100.0f; 1743 final long bgMediaPlaybackMinDuration = 1_000L; 1744 final long bgLocationMinDuration = 1_000L; 1745 1746 DeviceConfigSession<Boolean> bgCurrentDrainMonitor = null; 1747 DeviceConfigSession<Long> bgCurrentDrainWindow = null; 1748 DeviceConfigSession<Long> bgCurrentDrainInteractionGracePeriod = null; 1749 DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketThreshold = null; 1750 DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null; 1751 DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketHighThreshold = null; 1752 DeviceConfigSession<Float> bgCurrentDrainBgRestrictedHighThreshold = null; 1753 DeviceConfigSession<Boolean> bgCurrentDrainAutoRestrictAbusiveApps = null; 1754 DeviceConfigSession<Long> bgMediaPlaybackMinDurationThreshold = null; 1755 DeviceConfigSession<Long> bgLocationMinDurationThreshold = null; 1756 DeviceConfigSession<Boolean> bgCurrentDrainEventDurationBasedThresholdEnabled = null; 1757 DeviceConfigSession<Boolean> bgBatteryExemptionEnabled = null; 1758 DeviceConfigSession<Integer> bgBatteryExemptionTypes = null; 1759 DeviceConfigSession<Boolean> bgPermissionMonitorEnabled = null; 1760 DeviceConfigSession<String> bgPermissionsInMonitor = null; 1761 DeviceConfigSession<Boolean> bgCurrentDrainHighThresholdByBgLocation = null; 1762 DeviceConfigSession<Boolean> bgCurrentDrainDecoupleThresholds = null; 1763 DeviceConfigSession<Boolean> bgPromptAbusiveAppToBgRestricted = null; 1764 1765 mBgRestrictionController.addAppBackgroundRestrictionListener(listener); 1766 1767 setBackgroundRestrict(testPkgName1, testUid1, false, listener); 1768 1769 // Verify the current settings. 1770 verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName1, testUid1); 1771 1772 final double[] zeros = new double[]{0.0f, 0.0f}; 1773 final int[] uids = new int[]{testUid1, testUid2}; 1774 1775 doReturn(testPkgName1).when(mInjector).getPackageName(testPid1); 1776 doReturn(testPkgName2).when(mInjector).getPackageName(testPid2); 1777 1778 try { 1779 bgCurrentDrainMonitor = new DeviceConfigSession<>( 1780 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1781 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_MONITOR_ENABLED, 1782 DeviceConfig::getBoolean, 1783 mContext.getResources().getBoolean( 1784 R.bool.config_bg_current_drain_monitor_enabled)); 1785 bgCurrentDrainMonitor.set(true); 1786 1787 bgCurrentDrainWindow = new DeviceConfigSession<>( 1788 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1789 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_WINDOW, 1790 DeviceConfig::getLong, 1791 (long) mContext.getResources().getInteger( 1792 R.integer.config_bg_current_drain_window)); 1793 bgCurrentDrainWindow.set(windowMs); 1794 1795 bgCurrentDrainInteractionGracePeriod = new DeviceConfigSession<>( 1796 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1797 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD, 1798 DeviceConfig::getLong, 1799 (long) mContext.getResources().getInteger( 1800 R.integer.config_bg_current_drain_window)); 1801 bgCurrentDrainInteractionGracePeriod.set(windowMs); 1802 1803 bgCurrentDrainRestrictedBucketThreshold = new DeviceConfigSession<>( 1804 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1805 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET, 1806 DeviceConfig::getFloat, 1807 getFloatArray(mContext.getResources().obtainTypedArray( 1808 R.array.config_bg_current_drain_threshold_to_restricted_bucket))[ 1809 isLowRamDeviceStatic() ? 1 : 0]); 1810 bgCurrentDrainRestrictedBucketThreshold.set(restrictBucketThreshold); 1811 1812 bgCurrentDrainBgRestrictedThreshold = new DeviceConfigSession<>( 1813 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1814 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_BG_RESTRICTED, 1815 DeviceConfig::getFloat, 1816 getFloatArray(mContext.getResources().obtainTypedArray( 1817 R.array.config_bg_current_drain_threshold_to_bg_restricted))[ 1818 isLowRamDeviceStatic() ? 1 : 0]); 1819 bgCurrentDrainBgRestrictedThreshold.set(bgRestrictedThreshold); 1820 1821 bgCurrentDrainRestrictedBucketHighThreshold = new DeviceConfigSession<>( 1822 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1823 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_HIGH_THRESHOLD_TO_RESTRICTED_BUCKET, 1824 DeviceConfig::getFloat, 1825 getFloatArray(mContext.getResources().obtainTypedArray( 1826 R.array.config_bg_current_drain_high_threshold_to_restricted_bucket))[ 1827 isLowRamDeviceStatic() ? 1 : 0]); 1828 bgCurrentDrainRestrictedBucketHighThreshold.set(restrictBucketHighThreshold); 1829 1830 bgCurrentDrainBgRestrictedHighThreshold = new DeviceConfigSession<>( 1831 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1832 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_HIGH_THRESHOLD_TO_BG_RESTRICTED, 1833 DeviceConfig::getFloat, 1834 getFloatArray(mContext.getResources().obtainTypedArray( 1835 R.array.config_bg_current_drain_high_threshold_to_bg_restricted))[ 1836 isLowRamDeviceStatic() ? 1 : 0]); 1837 bgCurrentDrainBgRestrictedHighThreshold.set(bgRestrictedHighThreshold); 1838 1839 bgCurrentDrainAutoRestrictAbusiveApps = new DeviceConfigSession<>( 1840 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1841 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_AUTO_RESTRICT_ABUSIVE_APPS_ENABLED, 1842 DeviceConfig::getBoolean, 1843 mContext.getResources().getBoolean( 1844 R.bool.config_bg_current_drain_auto_restrict_abusive_apps)); 1845 bgCurrentDrainAutoRestrictAbusiveApps.set(true); 1846 1847 bgMediaPlaybackMinDurationThreshold = new DeviceConfigSession<>( 1848 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1849 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_MEDIA_PLAYBACK_MIN_DURATION, 1850 DeviceConfig::getLong, 1851 (long) mContext.getResources().getInteger( 1852 R.integer.config_bg_current_drain_media_playback_min_duration)); 1853 bgMediaPlaybackMinDurationThreshold.set(bgMediaPlaybackMinDuration); 1854 1855 bgLocationMinDurationThreshold = new DeviceConfigSession<>( 1856 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1857 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_LOCATION_MIN_DURATION, 1858 DeviceConfig::getLong, 1859 (long) mContext.getResources().getInteger( 1860 R.integer.config_bg_current_drain_location_min_duration)); 1861 bgLocationMinDurationThreshold.set(bgLocationMinDuration); 1862 1863 bgCurrentDrainEventDurationBasedThresholdEnabled = new DeviceConfigSession<>( 1864 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1865 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_EVENT_DURATION_BASED_THRESHOLD_ENABLED, 1866 DeviceConfig::getBoolean, 1867 mContext.getResources().getBoolean( 1868 R.bool.config_bg_current_drain_event_duration_based_threshold_enabled)); 1869 bgCurrentDrainEventDurationBasedThresholdEnabled.set(true); 1870 1871 bgBatteryExemptionEnabled = new DeviceConfigSession<>( 1872 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1873 AppBatteryExemptionPolicy.KEY_BG_BATTERY_EXEMPTION_ENABLED, 1874 DeviceConfig::getBoolean, 1875 AppBatteryExemptionPolicy.DEFAULT_BG_BATTERY_EXEMPTION_ENABLED); 1876 bgBatteryExemptionEnabled.set(false); 1877 1878 bgBatteryExemptionTypes = new DeviceConfigSession<>( 1879 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1880 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_EXEMPTED_TYPES, 1881 DeviceConfig::getInt, 1882 mContext.getResources().getInteger( 1883 R.integer.config_bg_current_drain_exempted_types)); 1884 bgBatteryExemptionTypes.set(STATE_TYPE_MEDIA_SESSION | STATE_TYPE_FGS_MEDIA_PLAYBACK 1885 | STATE_TYPE_FGS_LOCATION | STATE_TYPE_PERMISSION 1886 | STATE_TYPE_FGS_WITH_NOTIFICATION); 1887 1888 bgPermissionMonitorEnabled = new DeviceConfigSession<>( 1889 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1890 AppPermissionPolicy.KEY_BG_PERMISSION_MONITOR_ENABLED, 1891 DeviceConfig::getBoolean, 1892 AppPermissionPolicy.DEFAULT_BG_PERMISSION_MONITOR_ENABLED); 1893 bgPermissionMonitorEnabled.set(true); 1894 1895 bgPermissionsInMonitor = new DeviceConfigSession<>( 1896 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1897 AppPermissionPolicy.KEY_BG_PERMISSION_MONITOR_ENABLED, 1898 DeviceConfig::getString, 1899 Arrays.stream(AppPermissionPolicy.DEFAULT_BG_PERMISSIONS_IN_MONITOR) 1900 .collect(Collectors.joining(","))); 1901 bgPermissionsInMonitor.set(ACCESS_FINE_LOCATION); 1902 1903 bgCurrentDrainHighThresholdByBgLocation = new DeviceConfigSession<>( 1904 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1905 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_HIGH_THRESHOLD_BY_BG_LOCATION, 1906 DeviceConfig::getBoolean, 1907 mContext.getResources().getBoolean( 1908 R.bool.config_bg_current_drain_high_threshold_by_bg_location)); 1909 bgCurrentDrainHighThresholdByBgLocation.set(true); 1910 1911 bgCurrentDrainDecoupleThresholds = new DeviceConfigSession<>( 1912 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1913 AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLDS, 1914 DeviceConfig::getBoolean, 1915 AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLD); 1916 bgCurrentDrainDecoupleThresholds.set(true); 1917 1918 bgPromptAbusiveAppToBgRestricted = new DeviceConfigSession<>( 1919 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 1920 ConstantsObserver.KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED, 1921 DeviceConfig::getBoolean, 1922 mContext.getResources().getBoolean( 1923 R.bool.config_bg_prompt_abusive_apps_to_bg_restricted)); 1924 bgPromptAbusiveAppToBgRestricted.set(true); 1925 1926 mCurrentTimeMillis = 10_000L; 1927 doReturn(mCurrentTimeMillis - windowMs).when(stats).getStatsStartTimestamp(); 1928 doReturn(mCurrentTimeMillis).when(stats).getStatsEndTimestamp(); 1929 doReturn(statsList).when(mBatteryStatsInternal).getBatteryUsageStats(anyObject()); 1930 1931 // Run with a media playback service which starts/stops immediately, we should 1932 // goto the restricted bucket. 1933 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 1934 FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, 0, true, false, 1935 null, OP_NONE, null, null, listener, stats, uids, 1936 new double[]{restrictBucketThresholdMah + 1, 0}, 1937 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 1938 false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 1939 null, windowMs, null, null, null, null); 1940 1941 // Run with a media playback service with extended time. We should be back to normal. 1942 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 1943 FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false, 1944 false, null, OP_NONE, null, null, listener, stats, uids, 1945 new double[]{restrictBucketThresholdMah + 1, 0}, 1946 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 1947 true, RESTRICTION_LEVEL_ADAPTIVE_BUCKET, timeout, false, 1948 () -> { 1949 // A user interaction will bring it back to normal. 1950 mIdleStateListener.onUserInteractionStarted(testPkgName1, 1951 UserHandle.getUserId(testUid1)); 1952 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 1953 // It should have been back to normal. 1954 listener.verify(timeout, testUid1, testPkgName1, 1955 RESTRICTION_LEVEL_ADAPTIVE_BUCKET); 1956 verify(mInjector.getAppStandbyInternal(), times(1)).maybeUnrestrictApp( 1957 eq(testPkgName1), 1958 eq(UserHandle.getUserId(testUid1)), 1959 eq(REASON_MAIN_FORCED_BY_SYSTEM), 1960 eq(REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE), 1961 eq(REASON_MAIN_USAGE), 1962 eq(REASON_SUB_USAGE_USER_INTERACTION)); 1963 }, windowMs, null, null, null, null); 1964 1965 // Start over. 1966 resetBgRestrictionController(); 1967 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 1968 mAppBatteryPolicy.reset(); 1969 1970 // Run with a media playback service with extended time, with higher current drain. 1971 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 1972 FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false, 1973 false, null, OP_NONE, null, null, listener, stats, uids, 1974 new double[]{restrictBucketHighThresholdMah - 1, 0}, 1975 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 1976 true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 1977 null, windowMs, null, null, null, null); 1978 1979 // Run with a media playback service with extended time, with even higher current drain. 1980 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 1981 FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false, 1982 false, null, OP_NONE, null, null, listener, stats, uids, 1983 new double[]{restrictBucketHighThresholdMah + 1, 0}, 1984 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 1985 false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false, 1986 null, windowMs, null, null, null, null); 1987 1988 // Start over. 1989 resetBgRestrictionController(); 1990 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 1991 mAppBatteryPolicy.reset(); 1992 1993 // Run with a media session with extended time, with higher current drain. 1994 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 1995 FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false, 1996 null, OP_NONE, 1997 List.of(Pair.create(createMediaControllers(new String[] {testPkgName1}, 1998 new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)), 1999 null, listener, stats, uids, 2000 new double[]{restrictBucketHighThresholdMah - 1, 0}, 2001 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2002 true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2003 null, windowMs, null, null, null, null); 2004 2005 // Run with a media session with extended time, with even higher current drain. 2006 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2007 FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false, 2008 null, OP_NONE, 2009 List.of(Pair.create(createMediaControllers(new String[] {testPkgName1}, 2010 new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)), 2011 null, listener, stats, uids, 2012 new double[]{restrictBucketHighThresholdMah + 1, 0}, 2013 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2014 false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false, 2015 null, windowMs, null, null, null, null); 2016 2017 // Start over. 2018 resetBgRestrictionController(); 2019 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 2020 mAppBatteryPolicy.reset(); 2021 2022 // Run with a media session with extended time, with moderate current drain, 2023 // but it ran on the top when the location service is active. 2024 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2025 FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false, 2026 null, OP_NONE, 2027 List.of(Pair.create(createMediaControllers(new String[] {testPkgName1}, 2028 new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)), 2029 List.of(0L, timeout * 2), listener, stats, uids, 2030 new double[]{restrictBucketThresholdMah + 1, 0}, 2031 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2032 false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2033 null, windowMs, null, null, null, null); 2034 2035 // Start over. 2036 resetBgRestrictionController(); 2037 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 2038 mAppBatteryPolicy.reset(); 2039 2040 // Run with a location service with extended time, with higher current drain. 2041 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2042 FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false, 2043 null, OP_NONE, null, null, listener, stats, uids, 2044 new double[]{restrictBucketHighThresholdMah - 1, 0}, 2045 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2046 true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2047 null, windowMs, null, null, null, null); 2048 2049 // Run with a location service with extended time, with even higher current drain. 2050 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2051 FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false, 2052 null, OP_NONE, null, null, listener, stats, uids, 2053 new double[]{restrictBucketHighThresholdMah + 1, 0}, 2054 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2055 false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false, 2056 null, windowMs, null, null, null, null); 2057 2058 // Start over. 2059 resetBgRestrictionController(); 2060 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 2061 mAppBatteryPolicy.reset(); 2062 2063 // Run with a location service with extended time, with moderate current drain, 2064 // but it ran on the top when the location service is active. 2065 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2066 FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false, 2067 null, OP_NONE, null, List.of(0L, timeout * 2), listener, stats, uids, 2068 new double[]{restrictBucketThresholdMah + 1, 0}, 2069 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2070 false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2071 null, windowMs, null, null, null, null); 2072 2073 // Start over. 2074 resetBgRestrictionController(); 2075 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 2076 mAppBatteryPolicy.reset(); 2077 2078 // Turn off the higher threshold for bg location access. 2079 bgCurrentDrainHighThresholdByBgLocation.set(false); 2080 2081 // Run with bg location permission, with moderate current drain. 2082 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2083 FOREGROUND_SERVICE_TYPE_NONE, 0, false, false, 2084 ACCESS_BACKGROUND_LOCATION, OP_NONE, null, null, listener, stats, uids, 2085 new double[]{restrictBucketThresholdMah - 1, 0}, 2086 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2087 true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2088 null, windowMs, null, null, null, null); 2089 2090 // Run with bg location permission, with a bit higher current drain. 2091 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2092 FOREGROUND_SERVICE_TYPE_NONE, 0, false, false, 2093 ACCESS_BACKGROUND_LOCATION, OP_NONE, null, null, listener, stats, uids, 2094 new double[]{restrictBucketThresholdMah + 1, 0}, 2095 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2096 false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2097 null, windowMs, null, null, null, null); 2098 2099 // Start over. 2100 resetBgRestrictionController(); 2101 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 2102 mAppBatteryPolicy.reset(); 2103 2104 // Turn on the higher threshold for bg location access. 2105 bgCurrentDrainHighThresholdByBgLocation.set(true); 2106 2107 // Run with bg location permission, with higher current drain. 2108 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2109 FOREGROUND_SERVICE_TYPE_NONE, 0, false, false, 2110 ACCESS_BACKGROUND_LOCATION, OP_NONE, null, null, listener, stats, uids, 2111 new double[]{restrictBucketHighThresholdMah - 1, 0}, 2112 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2113 true , RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false, 2114 null, windowMs, null, null, null, null); 2115 2116 // Run with bg location permission, with even higher current drain. 2117 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2118 FOREGROUND_SERVICE_TYPE_NONE, 0, false, false, 2119 ACCESS_BACKGROUND_LOCATION, OP_NONE, null, null, listener, stats, uids, 2120 new double[]{restrictBucketHighThresholdMah + 1, 0}, 2121 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2122 false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false, 2123 null, windowMs, null, null, null, null); 2124 2125 // Now turn off the event duration based feature flag. 2126 bgCurrentDrainEventDurationBasedThresholdEnabled.set(false); 2127 // Turn on the battery exemption feature flag. 2128 bgBatteryExemptionEnabled.set(true); 2129 2130 // Start over. 2131 resetBgRestrictionController(); 2132 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 2133 mAppBatteryPolicy.reset(); 2134 2135 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 2136 2137 // Run with a media playback service which starts/stops immediately, we should 2138 // goto the restricted bucket. 2139 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2140 FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, 0, true, false, 2141 null, OP_NONE, null, null, listener, stats, uids, 2142 new double[]{restrictBucketThresholdMah + 1, 0}, 2143 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2144 false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2145 null, windowMs, null, null, null, null); 2146 2147 // Run with a media playback service with extended time. We should be back to normal. 2148 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2149 FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false, 2150 false, null, OP_NONE, null, null, listener, stats, uids, 2151 new double[]{restrictBucketThresholdMah + 1, 0}, 2152 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2153 true, RESTRICTION_LEVEL_ADAPTIVE_BUCKET, timeout, false, 2154 () -> { 2155 // A user interaction will bring it back to normal. 2156 mIdleStateListener.onUserInteractionStarted(testPkgName1, 2157 UserHandle.getUserId(testUid1)); 2158 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 2159 // It should have been back to normal. 2160 listener.verify(timeout, testUid1, testPkgName1, 2161 RESTRICTION_LEVEL_ADAPTIVE_BUCKET); 2162 verify(mInjector.getAppStandbyInternal(), times(1)).maybeUnrestrictApp( 2163 eq(testPkgName1), 2164 eq(UserHandle.getUserId(testUid1)), 2165 eq(REASON_MAIN_FORCED_BY_SYSTEM), 2166 eq(REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE), 2167 eq(REASON_MAIN_USAGE), 2168 eq(REASON_SUB_USAGE_USER_INTERACTION)); 2169 }, windowMs, null, null, null, null); 2170 2171 // Start over. 2172 resetBgRestrictionController(); 2173 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 2174 mAppBatteryPolicy.reset(); 2175 2176 final double[] initialBg = {1, 1}, initialFgs = {1, 1}, initialFg = zeros, 2177 initialCached = {1, 1}; 2178 2179 // Run with a media playback service with extended time, with higher current drain. 2180 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2181 FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false, 2182 false, null, OP_NONE, null, null, listener, stats, uids, 2183 new double[]{restrictBucketHighThresholdMah - 1, 0}, 2184 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2185 true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2186 null, windowMs, initialBg, initialFgs, initialFg, initialCached); 2187 2188 // Run with a media playback service with extended time, with even higher current drain, 2189 // it still should stay in the current restriction level as we exempt the media 2190 // playback. 2191 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2192 FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false, 2193 false, null, OP_NONE, null, null, listener, stats, uids, 2194 new double[]{restrictBucketHighThresholdMah + 100, 0}, 2195 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2196 true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false, 2197 null, windowMs, initialBg, initialFgs, initialFg, initialCached); 2198 2199 // Set the policy to exempt media session and permission. 2200 bgBatteryExemptionTypes.set(STATE_TYPE_MEDIA_SESSION | STATE_TYPE_PERMISSION); 2201 // Start over. 2202 resetBgRestrictionController(); 2203 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 2204 mAppBatteryPolicy.reset(); 2205 2206 // Run with coarse location permission, with high current drain. 2207 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2208 FOREGROUND_SERVICE_TYPE_NONE, 0, false, false, 2209 ACCESS_COARSE_LOCATION, OP_NONE, null, null, listener, stats, uids, 2210 new double[]{restrictBucketThresholdMah + 1, 0}, 2211 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2212 false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2213 null, windowMs, initialBg, initialFgs, initialFg, initialCached); 2214 2215 // Start over. 2216 resetBgRestrictionController(); 2217 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 2218 mAppBatteryPolicy.reset(); 2219 2220 // Run with fine location permission, with high current drain. 2221 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2222 FOREGROUND_SERVICE_TYPE_NONE, 0, false, false, 2223 ACCESS_FINE_LOCATION, OP_FINE_LOCATION, null, null, listener, stats, uids, 2224 new double[]{restrictBucketThresholdMah + 1, 0}, 2225 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2226 true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2227 null, windowMs, initialBg, initialFgs, initialFg, initialCached); 2228 2229 // Start over. 2230 resetBgRestrictionController(); 2231 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 2232 mAppBatteryPolicy.reset(); 2233 2234 // Run with a media session with extended time, with higher current drain. 2235 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2236 FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false, 2237 null, OP_NONE, 2238 List.of(Pair.create(createMediaControllers(new String[] {testPkgName1}, 2239 new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)), 2240 null, listener, stats, uids, 2241 new double[]{restrictBucketHighThresholdMah - 1, 0}, 2242 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2243 true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2244 null, windowMs, initialBg, initialFgs, initialFg, initialCached); 2245 2246 // Run with a media session with extended time, with even higher current drain. 2247 // it still should stay in the current restriction level as we exempt the media 2248 // session. 2249 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2250 FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false, 2251 null, OP_NONE, 2252 List.of(Pair.create(createMediaControllers(new String[] {testPkgName1}, 2253 new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)), 2254 null, listener, stats, uids, 2255 new double[]{restrictBucketHighThresholdMah + 100, 0}, 2256 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2257 true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2258 null, windowMs, initialBg, initialFgs, initialFg, initialCached); 2259 2260 // Set the policy to exempt fgs with notifications. 2261 bgBatteryExemptionTypes.set(STATE_TYPE_FGS_WITH_NOTIFICATION); 2262 // Start over. 2263 resetBgRestrictionController(); 2264 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 2265 mAppBatteryPolicy.reset(); 2266 2267 // Run with a FGS with notification posted/removed immediately, we should 2268 // goto the restricted bucket. 2269 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2270 FOREGROUND_SERVICE_TYPE_NONE, 0, true, true, 2271 null, OP_NONE, null, null, listener, stats, uids, 2272 new double[]{restrictBucketThresholdMah + 1, 0}, 2273 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2274 false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2275 null, windowMs, null, null, null, null); 2276 2277 // Run with a service with notification for extended time. We should be back to normal. 2278 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2279 FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, 2280 true, null, OP_NONE, null, null, listener, stats, uids, 2281 new double[]{restrictBucketThresholdMah + 1, 0}, 2282 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2283 true, RESTRICTION_LEVEL_ADAPTIVE_BUCKET, timeout, false, 2284 () -> { 2285 // A user interaction will bring it back to normal. 2286 mIdleStateListener.onUserInteractionStarted(testPkgName1, 2287 UserHandle.getUserId(testUid1)); 2288 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 2289 // It should have been back to normal. 2290 listener.verify(timeout, testUid1, testPkgName1, 2291 RESTRICTION_LEVEL_ADAPTIVE_BUCKET); 2292 verify(mInjector.getAppStandbyInternal(), times(1)).maybeUnrestrictApp( 2293 eq(testPkgName1), 2294 eq(UserHandle.getUserId(testUid1)), 2295 eq(REASON_MAIN_FORCED_BY_SYSTEM), 2296 eq(REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE), 2297 eq(REASON_MAIN_USAGE), 2298 eq(REASON_SUB_USAGE_USER_INTERACTION)); 2299 }, windowMs, null, null, null, null); 2300 2301 // Set the policy to exempt all. 2302 bgBatteryExemptionTypes.set(STATE_TYPE_MEDIA_SESSION | STATE_TYPE_FGS_MEDIA_PLAYBACK 2303 | STATE_TYPE_FGS_LOCATION | STATE_TYPE_PERMISSION 2304 | STATE_TYPE_FGS_WITH_NOTIFICATION); 2305 2306 // Start over. 2307 resetBgRestrictionController(); 2308 setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros); 2309 mAppBatteryPolicy.reset(); 2310 2311 // Run with a location service with extended time, with higher current drain. 2312 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2313 FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false, 2314 null, OP_NONE, null, null, listener, stats, uids, 2315 new double[]{restrictBucketHighThresholdMah - 1, 0}, 2316 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2317 true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true, 2318 null, windowMs, initialBg, initialFgs, initialFg, initialCached); 2319 2320 // Run with a location service with extended time, with even higher current drain. 2321 // it still should stay in the current restriction level as we exempt the location. 2322 runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1, 2323 FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false, 2324 null, OP_NONE, null, null, listener, stats, uids, 2325 new double[]{restrictBucketHighThresholdMah + 100, 0}, 2326 new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros, 2327 true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false, 2328 null, windowMs, initialBg, initialFgs, initialFg, initialCached); 2329 } finally { 2330 closeIfNotNull(bgCurrentDrainMonitor); 2331 closeIfNotNull(bgCurrentDrainWindow); 2332 closeIfNotNull(bgCurrentDrainInteractionGracePeriod); 2333 closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold); 2334 closeIfNotNull(bgCurrentDrainBgRestrictedThreshold); 2335 closeIfNotNull(bgCurrentDrainRestrictedBucketHighThreshold); 2336 closeIfNotNull(bgCurrentDrainBgRestrictedHighThreshold); 2337 closeIfNotNull(bgCurrentDrainAutoRestrictAbusiveApps); 2338 closeIfNotNull(bgMediaPlaybackMinDurationThreshold); 2339 closeIfNotNull(bgLocationMinDurationThreshold); 2340 closeIfNotNull(bgCurrentDrainEventDurationBasedThresholdEnabled); 2341 closeIfNotNull(bgBatteryExemptionEnabled); 2342 closeIfNotNull(bgBatteryExemptionTypes); 2343 closeIfNotNull(bgPermissionMonitorEnabled); 2344 closeIfNotNull(bgPermissionsInMonitor); 2345 closeIfNotNull(bgPromptAbusiveAppToBgRestricted); 2346 closeIfNotNull(bgCurrentDrainHighThresholdByBgLocation); 2347 closeIfNotNull(bgCurrentDrainDecoupleThresholds); 2348 } 2349 } 2350 runTestBgCurrentDrainExemptionOnce(String packageName, int uid, int pid, int serviceType, long sleepMs, boolean stopAfterSleep, boolean withNotification, String perm, int op, List<Pair<List<MediaController>, Long>> mediaControllers, List<Long> topStateChanges, TestAppRestrictionLevelListener listener, BatteryUsageStats stats, int[] uids, double[] bg, double[] fgs, double[] fg, double[] cached, boolean expectingTimeout, int expectingLevel, long timeout, boolean resetFGSTracker, RunnableWithException extraVerifiers, long windowMs, double[] initialBg, double[] initialFgs, double[] initialFg, double[] initialCached)2351 private void runTestBgCurrentDrainExemptionOnce(String packageName, int uid, int pid, 2352 int serviceType, long sleepMs, boolean stopAfterSleep, boolean withNotification, 2353 String perm, int op, List<Pair<List<MediaController>, Long>> mediaControllers, 2354 List<Long> topStateChanges, TestAppRestrictionLevelListener listener, 2355 BatteryUsageStats stats, int[] uids, double[] bg, double[] fgs, double[] fg, 2356 double[] cached, boolean expectingTimeout, int expectingLevel, long timeout, 2357 boolean resetFGSTracker, RunnableWithException extraVerifiers, long windowMs, 2358 double[] initialBg, double[] initialFgs, double[] initialFg, double[] initialCached) 2359 throws Exception { 2360 listener.mLatchHolder[0] = new CountDownLatch(1); 2361 if (initialBg != null) { 2362 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 2363 doReturn(mCurrentTimeMillis + windowMs).when(stats).getStatsEndTimestamp(); 2364 mCurrentTimeMillis += windowMs + 1; 2365 setUidBatteryConsumptions(stats, uids, initialBg, initialFgs, initialFg, initialCached); 2366 mAppBatteryExemptionTracker.reset(); 2367 mAppBatteryPolicy.reset(); 2368 } 2369 if (perm != null) { 2370 setPermissionState(packageName, uid, perm, true); 2371 if (op != OP_NONE) { 2372 setAppOpState(packageName, uid, op, true); 2373 } 2374 mInjector.getAppPermissionTracker().onPermissionsChanged(uid); 2375 } 2376 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 2377 runExemptionTestOnce( 2378 packageName, uid, pid, serviceType, sleepMs, stopAfterSleep, withNotification, 2379 perm, op, mediaControllers, topStateChanges, resetFGSTracker, false, 2380 () -> { 2381 clearInvocations(mInjector.getAppStandbyInternal()); 2382 clearInvocations(mBgRestrictionController); 2383 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, bg, fgs, fg, cached, 2384 false, () -> { 2385 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp(); 2386 doReturn(mCurrentTimeMillis + windowMs) 2387 .when(stats).getStatsEndTimestamp(); 2388 mCurrentTimeMillis += windowMs + 1; 2389 if (expectingTimeout) { 2390 try { 2391 listener.verify(timeout, uid, packageName, expectingLevel); 2392 fail("There shouldn't be any level change events"); 2393 } catch (Exception e) { 2394 // Expected. 2395 } 2396 } else { 2397 listener.verify(timeout, uid, packageName, expectingLevel); 2398 } 2399 if (expectingLevel == RESTRICTION_LEVEL_RESTRICTED_BUCKET) { 2400 verify(mInjector.getAppStandbyInternal(), 2401 expectingTimeout ? never() : atLeast(1)).restrictApp( 2402 eq(packageName), 2403 eq(UserHandle.getUserId(uid)), 2404 anyInt(), anyInt()); 2405 } else if (expectingLevel 2406 == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) { 2407 verify(mBgRestrictionController, 2408 expectingTimeout ? never() : atLeast(1)) 2409 .handleRequestBgRestricted(eq(packageName), eq(uid)); 2410 } else { 2411 verify(mInjector.getAppStandbyInternal(), 2412 expectingTimeout ? never() : atLeast(1)) 2413 .setAppStandbyBucket( 2414 eq(packageName), 2415 eq(STANDBY_BUCKET_RARE), 2416 eq(UserHandle.getUserId(uid)), 2417 anyInt(), anyInt()); 2418 } 2419 if (extraVerifiers != null) { 2420 extraVerifiers.run(); 2421 } 2422 } 2423 ); 2424 } 2425 ); 2426 if (perm != null) { 2427 setPermissionState(packageName, uid, perm, false); 2428 if (op != OP_NONE) { 2429 setAppOpState(packageName, uid, op, false); 2430 } 2431 mInjector.getAppPermissionTracker().onPermissionsChanged(uid); 2432 } 2433 } 2434 setPermissionState(String packageName, int uid, String perm, boolean granted)2435 private void setPermissionState(String packageName, int uid, String perm, boolean granted) { 2436 doReturn(granted ? PERMISSION_GRANTED : PERMISSION_DENIED) 2437 .when(mPermissionManagerServiceInternal) 2438 .checkUidPermission(uid, perm); 2439 doReturn(granted ? PERMISSION_GRANTED : PERMISSION_DENIED) 2440 .when(mPermissionManagerServiceInternal) 2441 .checkPermission(packageName, perm, UserHandle.getUserId(uid)); 2442 } 2443 setAppOpState(String packageName, int uid, int op, boolean granted)2444 private void setAppOpState(String packageName, int uid, int op, boolean granted) { 2445 try { 2446 doReturn(granted ? MODE_ALLOWED : MODE_IGNORED) 2447 .when(mAppOpsManager) 2448 .checkOpNoThrow(op, uid, packageName); 2449 doReturn(granted ? MODE_ALLOWED : MODE_IGNORED) 2450 .when(mIAppOpsService) 2451 .checkOperation(op, uid, packageName); 2452 } catch (RemoteException e) { 2453 // Ignore. 2454 } 2455 } 2456 2457 @Test testExcessiveBroadcasts()2458 public void testExcessiveBroadcasts() throws Exception { 2459 final long windowMs = 5_000; 2460 final int threshold = 10; 2461 runTestExcessiveEvent(AppBroadcastEventsPolicy.KEY_BG_BROADCAST_MONITOR_ENABLED, 2462 AppBroadcastEventsPolicy.DEFAULT_BG_BROADCAST_MONITOR_ENABLED, 2463 AppBroadcastEventsPolicy.KEY_BG_BROADCAST_WINDOW, 2464 AppBroadcastEventsPolicy.DEFAULT_BG_BROADCAST_WINDOW, 2465 AppBroadcastEventsPolicy.KEY_BG_EX_BROADCAST_THRESHOLD, 2466 AppBroadcastEventsPolicy.DEFAULT_BG_EX_BROADCAST_THRESHOLD, 2467 windowMs, threshold, mBroadcastEventListener::onSendingBroadcast, 2468 mAppBroadcastEventsTracker, 2469 new long[][] { 2470 new long[] {1_000L, 2_000L, 2_000L}, 2471 new long[] {2_000L, 2_000L, 1_000L}, 2472 }, 2473 new int[][] { 2474 new int[] {3, 3, 3}, 2475 new int[] {3, 3, 4}, 2476 }, 2477 new boolean[] { 2478 true, 2479 false, 2480 } 2481 ); 2482 } 2483 2484 @Test testExcessiveBindServices()2485 public void testExcessiveBindServices() throws Exception { 2486 final long windowMs = 5_000; 2487 final int threshold = 10; 2488 runTestExcessiveEvent(AppBindServiceEventsPolicy.KEY_BG_BIND_SVC_MONITOR_ENABLED, 2489 AppBindServiceEventsPolicy.DEFAULT_BG_BIND_SVC_MONITOR_ENABLED, 2490 AppBindServiceEventsPolicy.KEY_BG_BIND_SVC_WINDOW, 2491 AppBindServiceEventsPolicy.DEFAULT_BG_BIND_SVC_WINDOW, 2492 AppBindServiceEventsPolicy.KEY_BG_EX_BIND_SVC_THRESHOLD, 2493 AppBindServiceEventsPolicy.DEFAULT_BG_EX_BIND_SVC_THRESHOLD, 2494 windowMs, threshold, mBindServiceEventListener::onBindingService, 2495 mAppBindServiceEventsTracker, 2496 new long[][] { 2497 new long[] {0L, 2_000L, 4_000L, 1_000L}, 2498 new long[] {2_000L, 2_000L, 2_000L, 2_000L}, 2499 }, 2500 new int[][] { 2501 new int[] {8, 3, 1, 0}, // Will goto restricted bucket. 2502 new int[] {3, 3, 3, 3}, 2503 }, 2504 new boolean[] { 2505 false, 2506 true, 2507 } 2508 ); 2509 } 2510 runTestExcessiveEvent(String keyEnable, boolean defaultEnable, String keyWindow, long defaultWindow, String keyThreshold, int defaultThreshold, long windowMs, int threshold, BiConsumer<String, Integer> eventEmitter, BaseAppStateEventsTracker tracker, long[][] waitMs, int[][] events, boolean[] expectingTimeout)2511 private void runTestExcessiveEvent(String keyEnable, boolean defaultEnable, 2512 String keyWindow, long defaultWindow, String keyThreshold, int defaultThreshold, 2513 long windowMs, int threshold, BiConsumer<String, Integer> eventEmitter, 2514 BaseAppStateEventsTracker tracker, long[][] waitMs, int[][] events, 2515 boolean[] expectingTimeout) throws Exception { 2516 final int testPkgIndex = 1; 2517 final String testPkgName = TEST_PACKAGE_BASE + testPkgIndex; 2518 final int testUser = TEST_USER0; 2519 final int testUid = UserHandle.getUid(testUser, TEST_PACKAGE_APPID_BASE + testPkgIndex); 2520 final int testPid = 1234; 2521 2522 final long timeoutMs = 2_000; 2523 2524 final TestAppRestrictionLevelListener listener = new TestAppRestrictionLevelListener(); 2525 2526 mBgRestrictionController.addAppBackgroundRestrictionListener(listener); 2527 setBackgroundRestrict(testPkgName, testUid, false, listener); 2528 2529 DeviceConfigSession<Boolean> enableMonitor = null; 2530 DeviceConfigSession<Long> eventsWindow = null; 2531 DeviceConfigSession<Integer> eventsThreshold = null; 2532 2533 doReturn(testPkgName).when(mInjector).getPackageName(testPid); 2534 2535 verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid); 2536 2537 try { 2538 enableMonitor = new DeviceConfigSession<>( 2539 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 2540 keyEnable, 2541 DeviceConfig::getBoolean, 2542 defaultEnable); 2543 enableMonitor.set(true); 2544 2545 eventsWindow = new DeviceConfigSession<>( 2546 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 2547 keyWindow, 2548 DeviceConfig::getLong, 2549 defaultWindow); 2550 eventsWindow.set(windowMs); 2551 2552 eventsThreshold = new DeviceConfigSession<>( 2553 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, 2554 keyThreshold, 2555 DeviceConfig::getInt, 2556 defaultThreshold); 2557 eventsThreshold.set(threshold); 2558 2559 for (int i = 0; i < waitMs.length; i++) { 2560 resetBgRestrictionController(); 2561 listener.mLatchHolder[0] = new CountDownLatch(1); 2562 tracker.reset(); 2563 clearInvocations(mInjector.getAppStandbyInternal()); 2564 clearInvocations(mBgRestrictionController); 2565 for (int j = 0; j < waitMs[i].length; j++) { 2566 for (int k = 0; k < events[i][j]; k++) { 2567 eventEmitter.accept(testPkgName, testUid); 2568 } 2569 Thread.sleep(waitMs[i][j]); 2570 } 2571 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 2572 if (expectingTimeout[i]) { 2573 verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid); 2574 try { 2575 listener.verify(timeoutMs, testUid, testPkgName, 2576 RESTRICTION_LEVEL_RESTRICTED_BUCKET); 2577 fail("There shouldn't be any level change events"); 2578 } catch (TimeoutException e) { 2579 // expected. 2580 } 2581 } else { 2582 verifyRestrictionLevel(RESTRICTION_LEVEL_RESTRICTED_BUCKET, 2583 testPkgName, testUid); 2584 listener.verify(timeoutMs, testUid, testPkgName, 2585 RESTRICTION_LEVEL_RESTRICTED_BUCKET); 2586 } 2587 } 2588 } finally { 2589 closeIfNotNull(enableMonitor); 2590 closeIfNotNull(eventsWindow); 2591 closeIfNotNull(eventsThreshold); 2592 } 2593 } 2594 checkNotificationShown(String[] packageName, VerificationMode mode, boolean verifyNotification)2595 private int[] checkNotificationShown(String[] packageName, VerificationMode mode, 2596 boolean verifyNotification) throws Exception { 2597 final ArgumentCaptor<Integer> notificationIdCaptor = 2598 ArgumentCaptor.forClass(Integer.class); 2599 final ArgumentCaptor<Notification> notificationCaptor = 2600 ArgumentCaptor.forClass(Notification.class); 2601 verify(mInjector.getNotificationManager(), mode).notifyAsUser(any(), 2602 notificationIdCaptor.capture(), notificationCaptor.capture(), any()); 2603 final int[] notificationId = new int[packageName.length]; 2604 if (verifyNotification) { 2605 for (int i = 0, j = 0; i < packageName.length; j++) { 2606 final int id = notificationIdCaptor.getAllValues().get(j); 2607 if (id == NotificationHelper.SUMMARY_NOTIFICATION_ID) { 2608 continue; 2609 } 2610 final Notification n = notificationCaptor.getAllValues().get(j); 2611 notificationId[i] = id; 2612 assertTrue(NotificationHelper.SUMMARY_NOTIFICATION_ID < notificationId[i]); 2613 assertEquals(NotificationHelper.GROUP_KEY, n.getGroup()); 2614 assertEquals(ABUSIVE_BACKGROUND_APPS, n.getChannelId()); 2615 assertEquals(packageName[i], n.extras.getString(Intent.EXTRA_PACKAGE_NAME)); 2616 i++; 2617 } 2618 } 2619 return notificationId; 2620 } 2621 2622 private void checkNotificationGone(String packageName, VerificationMode mode, 2623 int notificationId) throws Exception { 2624 final ArgumentCaptor<Integer> notificationIdCaptor = 2625 ArgumentCaptor.forClass(Integer.class); 2626 verify(mInjector.getNotificationManager(), mode).cancel(notificationIdCaptor.capture()); 2627 assertEquals(notificationId, notificationIdCaptor.getValue().intValue()); 2628 } 2629 2630 private void closeIfNotNull(DeviceConfigSession<?> config) throws Exception { 2631 if (config != null) { 2632 config.close(); 2633 } 2634 } 2635 2636 private interface RunnableWithException { 2637 void run() throws Exception; 2638 } 2639 2640 private void runTestBgCurrentDrainMonitorOnce(TestAppRestrictionLevelListener listener, 2641 BatteryUsageStats stats, int[] uids, double[] bg, double[] fgs, double[] fg, 2642 double[] cached, RunnableWithException runnable) throws Exception { 2643 runTestBgCurrentDrainMonitorOnce(listener, stats, uids, bg, fgs, fg, cached, true, 2644 runnable); 2645 } 2646 2647 private void runTestBgCurrentDrainMonitorOnce(TestAppRestrictionLevelListener listener, 2648 BatteryUsageStats stats, int[] uids, double[] bg, double[] fgs, double[] fg, 2649 double[] cached, boolean resetListener, RunnableWithException runnable) 2650 throws Exception { 2651 if (resetListener) { 2652 listener.mLatchHolder[0] = new CountDownLatch(1); 2653 } 2654 setUidBatteryConsumptions(stats, uids, bg, fgs, fg, cached); 2655 runnable.run(); 2656 } 2657 2658 private void setUidBatteryConsumptions(BatteryUsageStats stats, int[] uids, double[] bg, 2659 double[] fgs, double[] fg, double[] cached) { 2660 ArrayList<UidBatteryConsumer> consumers = new ArrayList<>(); 2661 for (int i = 0; i < uids.length; i++) { 2662 consumers.add(mockUidBatteryConsumer(uids[i], bg[i], fgs[i], fg[i], cached[i])); 2663 } 2664 doReturn(consumers).when(stats).getUidBatteryConsumers(); 2665 } 2666 2667 private UidBatteryConsumer mockUidBatteryConsumer(int uid, double bg, double fgs, double fg, 2668 double cached) { 2669 UidBatteryConsumer uidConsumer = mock(UidBatteryConsumer.class); 2670 doReturn(uid).when(uidConsumer).getUid(); 2671 doReturn(bg).when(uidConsumer).getConsumedPower( 2672 eq(BATT_DIMENS[BATTERY_USAGE_INDEX_BACKGROUND])); 2673 doReturn(fgs).when(uidConsumer).getConsumedPower( 2674 eq(BATT_DIMENS[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE])); 2675 doReturn(fg).when(uidConsumer).getConsumedPower( 2676 eq(BATT_DIMENS[BATTERY_USAGE_INDEX_FOREGROUND])); 2677 doReturn(cached).when(uidConsumer).getConsumedPower( 2678 eq(BATT_DIMENS[BATTERY_USAGE_INDEX_CACHED])); 2679 return uidConsumer; 2680 } 2681 2682 private void setBackgroundRestrict(String pkgName, int uid, boolean restricted, 2683 TestAppRestrictionLevelListener listener) throws Exception { 2684 Log.i(TAG, "Setting background restrict to " + restricted + " for " + pkgName + " " + uid); 2685 listener.mLatchHolder[0] = new CountDownLatch(1); 2686 doReturn(restricted).when(mAppStateTracker).isAppBackgroundRestricted(uid, pkgName); 2687 mFasListener.updateBackgroundRestrictedForUidPackage(uid, pkgName, restricted); 2688 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 2689 } 2690 2691 private class TestAppRestrictionLevelListener implements AppBackgroundRestrictionListener { 2692 private final CountDownLatch[] mLatchHolder = new CountDownLatch[1]; 2693 final int[] mUidHolder = new int[1]; 2694 final String[] mPkgNameHolder = new String[1]; 2695 final int[] mLevelHolder = new int[1]; 2696 2697 @Override 2698 public void onRestrictionLevelChanged(int uid, String packageName, int newLevel) { 2699 mUidHolder[0] = uid; 2700 mPkgNameHolder[0] = packageName; 2701 mLevelHolder[0] = newLevel; 2702 mLatchHolder[0].countDown(); 2703 }; 2704 2705 void verify(long timeout, int uid, String pkgName, int level) throws Exception { 2706 if (!mLatchHolder[0].await(timeout, TimeUnit.MILLISECONDS)) { 2707 throw new TimeoutException(); 2708 } 2709 assertEquals(uid, mUidHolder[0]); 2710 assertEquals(pkgName, mPkgNameHolder[0]); 2711 assertEquals(level, mLevelHolder[0]); 2712 } 2713 } 2714 2715 private void verifyRestrictionLevel(int level, String pkgName, int uid) { 2716 assertEquals(level, mBgRestrictionController.getRestrictionLevel(uid)); 2717 assertEquals(level, mBgRestrictionController.getRestrictionLevel(uid, pkgName)); 2718 } 2719 2720 private void waitForIdleHandler(Handler handler) { 2721 waitForIdleHandler(handler, Duration.ofSeconds(1)); 2722 } 2723 2724 private void waitForIdleHandler(Handler handler, Duration timeout) { 2725 final MessageQueue queue = handler.getLooper().getQueue(); 2726 final CountDownLatch latch = new CountDownLatch(1); 2727 queue.addIdleHandler(() -> { 2728 latch.countDown(); 2729 // Remove idle handler 2730 return false; 2731 }); 2732 try { 2733 latch.await(timeout.toMillis(), TimeUnit.MILLISECONDS); 2734 } catch (InterruptedException e) { 2735 fail("Interrupted unexpectedly: " + e); 2736 } 2737 } 2738 2739 @Test 2740 public void testMergeAppStateDurations() throws Exception { 2741 final BaseAppStateDurations testObj = new BaseAppStateDurations(0, "", 1, "", null) {}; 2742 assertAppStateDurations(null, testObj.add(null, null)); 2743 assertAppStateDurations(new LinkedList<BaseTimeEvent>(), testObj.add( 2744 null, new LinkedList<BaseTimeEvent>())); 2745 assertAppStateDurations(new LinkedList<BaseTimeEvent>(), testObj.add( 2746 new LinkedList<BaseTimeEvent>(), null)); 2747 assertAppStateDurations(createDurations(1), testObj.add( 2748 createDurations(1), new LinkedList<BaseTimeEvent>())); 2749 assertAppStateDurations(createDurations(1), testObj.add( 2750 new LinkedList<BaseTimeEvent>(), createDurations(1))); 2751 assertAppStateDurations(createDurations(1, 4, 5, 8, 9), testObj.add( 2752 createDurations(1, 3, 5, 7, 9), createDurations(2, 4, 6, 8, 10))); 2753 assertAppStateDurations(createDurations(1, 5), testObj.add( 2754 createDurations(1, 2, 3, 4), createDurations(2, 3, 4, 5))); 2755 assertAppStateDurations(createDurations(1, 4, 6, 9), testObj.add( 2756 createDurations(2, 4, 6, 9), createDurations(1, 4, 7, 8))); 2757 assertAppStateDurations(createDurations(1, 4, 5, 8, 9, 10), testObj.add( 2758 createDurations(1, 4, 6, 8), createDurations(1, 3, 5, 8, 9, 10))); 2759 } 2760 2761 @Test 2762 public void testSubtractAppStateDurations() throws Exception { 2763 final BaseAppStateDurations testObj = new BaseAppStateDurations(0, "", 1, "", null) {}; 2764 assertAppStateDurations(null, testObj.subtract(null, null)); 2765 assertAppStateDurations(null, testObj.subtract(null, new LinkedList<BaseTimeEvent>())); 2766 assertAppStateDurations(new LinkedList<BaseTimeEvent>(), testObj.subtract( 2767 new LinkedList<BaseTimeEvent>(), null)); 2768 assertAppStateDurations(createDurations(1), testObj.subtract( 2769 createDurations(1), new LinkedList<BaseTimeEvent>())); 2770 assertAppStateDurations(new LinkedList<BaseTimeEvent>(), testObj.subtract( 2771 new LinkedList<BaseTimeEvent>(), createDurations(1))); 2772 assertAppStateDurations(new LinkedList<BaseTimeEvent>(), testObj.subtract( 2773 createDurations(1), createDurations(1))); 2774 assertAppStateDurations(createDurations(1, 2, 5, 6, 9, 10), testObj.subtract( 2775 createDurations(1, 3, 5, 7, 9), createDurations(2, 4, 6, 8, 10))); 2776 assertAppStateDurations(createDurations(1, 2, 3, 4), testObj.subtract( 2777 createDurations(1, 4, 6, 7, 9, 10), createDurations(2, 3, 5, 8, 9, 10))); 2778 assertAppStateDurations(createDurations(3, 4, 9, 10), testObj.subtract( 2779 createDurations(1, 4, 6, 8, 9, 10), createDurations(1, 3, 5, 8))); 2780 assertAppStateDurations(createDurations(1, 2, 3, 4, 5, 6, 7, 8), testObj.subtract( 2781 createDurations(1, 6, 7, 8), createDurations(2, 3, 4, 5, 8, 10))); 2782 assertAppStateDurations(createDurations(5, 6), testObj.subtract( 2783 createDurations(2, 3, 5, 6), createDurations(1, 4, 7, 8))); 2784 assertAppStateDurations(createDurations(2, 3, 4, 5, 6, 7, 8), testObj.subtract( 2785 createDurations(1), createDurations(1, 2, 3, 4, 5, 6, 7, 8))); 2786 } 2787 2788 private void assertAppStateDurations(LinkedList<BaseTimeEvent> expected, 2789 LinkedList<BaseTimeEvent> actual) throws Exception { 2790 assertListEquals(expected, actual); 2791 } 2792 2793 private <T> void assertListEquals(LinkedList<T> expected, LinkedList<T> actual) { 2794 assertEquals(expected == null || expected.isEmpty(), actual == null || actual.isEmpty()); 2795 if (expected != null) { 2796 if (expected.size() > 0) { 2797 assertEquals(expected.size(), actual.size()); 2798 } 2799 while (expected.peek() != null) { 2800 assertTrue(expected.poll().equals(actual.poll())); 2801 } 2802 } 2803 } 2804 createDurations(long... timestamps)2805 private LinkedList<BaseTimeEvent> createDurations(long... timestamps) { 2806 return Arrays.stream(timestamps).mapToObj(BaseTimeEvent::new) 2807 .collect(LinkedList<BaseTimeEvent>::new, LinkedList<BaseTimeEvent>::add, 2808 (a, b) -> a.addAll(b)); 2809 } 2810 createIntLinkedList(int[] vals)2811 private LinkedList<Integer> createIntLinkedList(int[] vals) { 2812 return Arrays.stream(vals).collect(LinkedList<Integer>::new, LinkedList<Integer>::add, 2813 (a, b) -> a.addAll(b)); 2814 } 2815 2816 @Test testAppStateTimeSlotEvents()2817 public void testAppStateTimeSlotEvents() throws Exception { 2818 final long maxTrackingDuration = 5_000L; 2819 assertAppStateTimeSlotEvents(new int[] {2, 2, 0, 0, 1}, 2820 new long[] {1_500, 1_500, 2_100, 2_999, 5_999}, 5_000); 2821 assertAppStateTimeSlotEvents(new int[] {2, 2, 0, 0, 1, 1}, 2822 new long[] {1_500, 1_500, 2_100, 2_999, 5_999, 6_000}, 6_000); 2823 assertAppStateTimeSlotEvents(new int[] {2, 0, 0, 1, 1, 1}, 2824 new long[] {1_500, 1_500, 2_100, 2_999, 5_999, 6_000, 7_000}, 7_000); 2825 assertMergeAppStateTimeSlotEvents(new int[] {}, new long[] {}, new long[] {}, 0); 2826 assertMergeAppStateTimeSlotEvents(new int[] {1}, new long[] {}, new long[] {1_500}, 1_000); 2827 assertMergeAppStateTimeSlotEvents(new int[] {1}, new long[] {1_500}, new long[] {}, 1_000); 2828 assertMergeAppStateTimeSlotEvents(new int[] {1, 1}, 2829 new long[] {1_500}, new long[] {2_500}, 2_000); 2830 assertMergeAppStateTimeSlotEvents(new int[] {1, 1}, 2831 new long[] {2_500}, new long[] {1_500}, 2_000); 2832 assertMergeAppStateTimeSlotEvents(new int[] {1, 2, 1}, 2833 new long[] {1_500, 2_500}, new long[] {2_600, 3_000}, 3_000); 2834 assertMergeAppStateTimeSlotEvents(new int[] {2, 1, 1}, 2835 new long[] {2_600, 3_500}, new long[] {1_500, 1_600}, 3_000); 2836 assertMergeAppStateTimeSlotEvents(new int[] {1, 2, 1}, 2837 new long[] {1_500, 3_500}, new long[] {2_600, 2_700}, 3_000); 2838 assertMergeAppStateTimeSlotEvents(new int[] {1, 2, 1}, 2839 new long[] {2_500, 2_600}, new long[] {1_500, 3_700}, 3_000); 2840 assertMergeAppStateTimeSlotEvents(new int[] {1, 0, 0, 0, 0, 1}, 2841 new long[] {2_500, 8_600}, new long[] {1_500, 3_700}, 8_000); 2842 } 2843 createBaseAppStateTimeSlotEvents( long slotSize, long maxTrackingDuration, long[] timestamps)2844 private BaseAppStateTimeSlotEvents createBaseAppStateTimeSlotEvents( 2845 long slotSize, long maxTrackingDuration, long[] timestamps) { 2846 final BaseAppStateTimeSlotEvents testObj = new BaseAppStateTimeSlotEvents( 2847 0, "", 1, slotSize, "", () -> maxTrackingDuration) {}; 2848 for (int i = 0; i < timestamps.length; i++) { 2849 testObj.addEvent(timestamps[i], 0); 2850 } 2851 return testObj; 2852 } 2853 assertAppStateTimeSlotEvents(int[] expectedEvents, long[] timestamps, long expectedCurTimeslot)2854 private void assertAppStateTimeSlotEvents(int[] expectedEvents, long[] timestamps, 2855 long expectedCurTimeslot) { 2856 final BaseAppStateTimeSlotEvents testObj = createBaseAppStateTimeSlotEvents(1_000L, 2857 5_000L, timestamps); 2858 assertEquals(expectedCurTimeslot, testObj.getCurrentSlotStartTime(0)); 2859 assertListEquals(createIntLinkedList(expectedEvents), testObj.getRawEvents(0)); 2860 } 2861 assertMergeAppStateTimeSlotEvents(int[] expectedEvents, long[] timestamps1, long[] timestamps2, long expectedCurTimeslot)2862 private void assertMergeAppStateTimeSlotEvents(int[] expectedEvents, long[] timestamps1, 2863 long[] timestamps2, long expectedCurTimeslot) { 2864 final BaseAppStateTimeSlotEvents testObj1 = createBaseAppStateTimeSlotEvents(1_000L, 2865 5_000L, timestamps1); 2866 final BaseAppStateTimeSlotEvents testObj2 = createBaseAppStateTimeSlotEvents(1_000L, 2867 5_000L, timestamps2); 2868 testObj1.add(testObj2); 2869 assertEquals(expectedCurTimeslot, testObj1.getCurrentSlotStartTime(0)); 2870 assertListEquals(createIntLinkedList(expectedEvents), testObj1.getRawEvents(0)); 2871 } 2872 2873 @Test testMergeUidBatteryUsage()2874 public void testMergeUidBatteryUsage() throws Exception { 2875 final UidBatteryStates testObj = new UidBatteryStates(0, "", null); 2876 assertListEquals(null, testObj.add(null, null)); 2877 assertListEquals(new LinkedList<UidStateEventWithBattery>(), testObj.add( 2878 null, new LinkedList<UidStateEventWithBattery>())); 2879 assertListEquals(new LinkedList<UidStateEventWithBattery>(), testObj.add( 2880 new LinkedList<UidStateEventWithBattery>(), null)); 2881 assertListEquals(createUidStateEventWithBatteryList( 2882 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}), 2883 testObj.add(createUidStateEventWithBatteryList( 2884 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}), 2885 new LinkedList<UidStateEventWithBattery>())); 2886 assertListEquals(createUidStateEventWithBatteryList( 2887 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}), 2888 testObj.add(new LinkedList<UidStateEventWithBattery>(), 2889 createUidStateEventWithBatteryList( 2890 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}))); 2891 assertListEquals(createUidStateEventWithBatteryList( 2892 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}), 2893 testObj.add(createUidStateEventWithBatteryList( 2894 new boolean[] {true}, new long[] {11L}, new double[] {11.0d}), 2895 createUidStateEventWithBatteryList( 2896 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}))); 2897 assertListEquals(createUidStateEventWithBatteryList( 2898 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}), 2899 testObj.add(createUidStateEventWithBatteryList( 2900 new boolean[] {true, false}, new long[] {11L, 12L}, new double[] {11.0d, 1.0d}), 2901 createUidStateEventWithBatteryList( 2902 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}))); 2903 assertListEquals(createUidStateEventWithBatteryList( 2904 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}), 2905 testObj.add(createUidStateEventWithBatteryList( 2906 new boolean[] {true, false, true}, new long[] {11L, 12L, 13L}, 2907 new double[] {11.0d, 1.0d, 13.0d}), 2908 createUidStateEventWithBatteryList( 2909 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}))); 2910 assertListEquals(createUidStateEventWithBatteryList( 2911 new boolean[] {true, false}, new long[] {10L, 13L}, new double[] {10.0d, 3.0d}), 2912 testObj.add(createUidStateEventWithBatteryList( 2913 new boolean[] {true, false}, new long[] {11L, 13L}, new double[] {11.0d, 2.0d}), 2914 createUidStateEventWithBatteryList( 2915 new boolean[] {true, false}, new long[] {10L, 12L}, new double[] {10.0d, 2.0d}))); 2916 assertListEquals(createUidStateEventWithBatteryList( 2917 new boolean[] {true, false, true}, new long[] {10L, 13L, 14L}, 2918 new double[] {10.0d, 3.0d, 14.0d}), 2919 testObj.add(createUidStateEventWithBatteryList( 2920 new boolean[] {true, false, true}, new long[] {11L, 13L, 14L}, 2921 new double[] {11.0d, 2.0d, 14.0d}), 2922 createUidStateEventWithBatteryList( 2923 new boolean[] {true, false}, new long[] {10L, 12L}, new double[] {10.0d, 2.0d}))); 2924 assertListEquals(createUidStateEventWithBatteryList( 2925 new boolean[] {true, false, true, false, true, false}, 2926 new long[] {10L, 13L, 14L, 17L, 18L, 21L}, 2927 new double[] {10.0d, 3.0d, 14.0d, 3.0d, 18.0d, 3.0d}), 2928 testObj.add(createUidStateEventWithBatteryList( 2929 new boolean[] {true, false, true, false, true, false}, 2930 new long[] {11L, 13L, 15L, 17L, 19L, 21L}, 2931 new double[] {11.0d, 2.0d, 15.0d, 2.0d, 19.0d, 2.0d}), 2932 createUidStateEventWithBatteryList( 2933 new boolean[] {true, false, true, false, true, false}, 2934 new long[] {10L, 12L, 14L, 16L, 18L, 20L}, 2935 new double[] {10.0d, 2.0d, 14.0d, 2.0d, 18.0d, 2.0d}))); 2936 assertListEquals(createUidStateEventWithBatteryList( 2937 new boolean[] {true, false, true, false, true, false, true, false, true, false}, 2938 new long[] {10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L}, 2939 new double[] {10.0d, 1.0d, 12.0d, 1.0d, 14.0d, 1.0d, 16.0d, 1.0d, 18.0d, 1.0d}), 2940 testObj.add(createUidStateEventWithBatteryList( 2941 new boolean[] {true, false, true, false}, 2942 new long[] {12L, 13L, 16L, 17L}, 2943 new double[] {12.0d, 1.0d, 16.0d, 1.0d}), 2944 createUidStateEventWithBatteryList( 2945 new boolean[] {true, false, true, false, true, false}, 2946 new long[] {10L, 11L, 14L, 15L, 18L, 19L}, 2947 new double[] {10.0d, 1.0d, 14.0d, 1.0d, 18.0d, 1.0d}))); 2948 assertListEquals(createUidStateEventWithBatteryList( 2949 new boolean[] {true, false, true, false}, 2950 new long[] {10L, 14L, 18L, 19L}, 2951 new double[] {10.0d, 4.0d, 18.0d, 1.0d}), 2952 testObj.add(createUidStateEventWithBatteryList( 2953 new boolean[] {true, false, true, false}, 2954 new long[] {11L, 12L, 13L, 14L}, 2955 new double[] {11.0d, 1.0d, 13.0d, 1.0d}), 2956 createUidStateEventWithBatteryList( 2957 new boolean[] {true, false, true, false, true, false}, 2958 new long[] {10L, 11L, 12L, 13L, 18L, 19L}, 2959 new double[] {10.0d, 1.0d, 12.0d, 1.0d, 18.0d, 1.0d}))); 2960 assertListEquals(createUidStateEventWithBatteryList( 2961 new boolean[] {true, false, true, false}, 2962 new long[] {10L, 14L, 18L, 19L}, 2963 new double[] {10.0d, 4.0d, 18.0d, 1.0d}), 2964 testObj.add(createUidStateEventWithBatteryList( 2965 new boolean[] {true, false, true, false}, 2966 new long[] {10L, 14L, 18L, 19L}, 2967 new double[] {10.0d, 4.0d, 18.0d, 1.0d}), 2968 createUidStateEventWithBatteryList( 2969 new boolean[] {true, false, true, false, true, false}, 2970 new long[] {10L, 11L, 12L, 13L, 18L, 19L}, 2971 new double[] {10.0d, 1.0d, 12.0d, 1.0d, 18.0d, 1.0d}))); 2972 } 2973 2974 @SuppressWarnings("GuardedBy") 2975 @Test testPersistRestrictionSettings()2976 public void testPersistRestrictionSettings() throws Exception { 2977 final RestrictionSettings settings = mBgRestrictionController.mRestrictionSettings; 2978 final String testPkg0 = TEST_PACKAGE_BASE + 0; 2979 final String testPkg1 = TEST_PACKAGE_BASE + 1; 2980 final String testPkg2 = TEST_PACKAGE_BASE + 2; 2981 final String testPkg3 = TEST_PACKAGE_BASE + 3; 2982 final int testUid0 = UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 0); 2983 final int testUid1 = UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 1); 2984 final int testUid2 = UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 2); 2985 final int testUid3 = UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 3); 2986 settings.reset(); 2987 setRestrictionSettings(settings, testPkg0, testUid0, 2988 RESTRICTION_LEVEL_ADAPTIVE_BUCKET, 2989 10_000L, REASON_MAIN_DEFAULT | REASON_SUB_DEFAULT_UNDEFINED, 2990 new long[] {0L, 0L}, false); 2991 setRestrictionSettings(settings, testPkg1, testUid1, 2992 RESTRICTION_LEVEL_RESTRICTED_BUCKET, 2993 20_000L, REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE, 2994 new long[] {10_000L, 0L}, false); 2995 setRestrictionSettings(settings, testPkg2, testUid2, 2996 RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, 2997 25_000L, REASON_MAIN_FORCED_BY_USER | REASON_SUB_FORCED_USER_FLAG_INTERACTION, 2998 new long[] {0L, 15_000L}, false); 2999 setRestrictionSettings(settings, testPkg3, testUid3, 3000 RESTRICTION_LEVEL_RESTRICTED_BUCKET, 3001 30_000L, REASON_MAIN_DEFAULT | REASON_SUB_DEFAULT_UNDEFINED, 3002 new long[] {0L, 0L}, false); 3003 RestrictionSettings test = (RestrictionSettings) settings.clone(); 3004 3005 // Verify our clone works correctly. 3006 assertTrue(settings.equals(test)); 3007 3008 // Reset the test object. 3009 test.resetToDefault(); 3010 3011 // Save the original data into xml. 3012 settings.persistToXml(TEST_USER0); 3013 settings.persistToXml(TEST_USER1); 3014 3015 // Load it to our test object. 3016 test.loadFromXml(false); 3017 // Verify we restored it correctly. 3018 assertTrue(settings.equals(test)); 3019 3020 // Remove one package. 3021 settings.removePackage(testPkg3, testUid3); 3022 // Verify it. 3023 verifyLoadedSettings(settings); 3024 3025 // Add it back. 3026 setRestrictionSettings(settings, testPkg3, testUid3, 3027 RESTRICTION_LEVEL_RESTRICTED_BUCKET, 3028 30_000L, REASON_MAIN_DEFAULT | REASON_SUB_DEFAULT_UNDEFINED, 3029 new long[] {0L, 1_000L}, true); 3030 // Verify it. 3031 verifyLoadedSettings(settings); 3032 3033 // Remove one user. 3034 settings.removeUser(TEST_USER1); 3035 // Verify it. 3036 verifyLoadedSettings(settings); 3037 } 3038 3039 @Test testCarrierPrivilegedAppListener()3040 public void testCarrierPrivilegedAppListener() throws Exception { 3041 final long shortMs = 1_000L; 3042 for (int i = 0; i < MOCK_PRIVILEGED_PACKAGES.length; i++) { 3043 verifyPotentialSystemExemptionReason(REASON_CARRIER_PRIVILEGED_APP, 3044 MOCK_PRIVILEGED_PACKAGES[i], 3045 MOCK_PRIVILEGED_UIDS[i]); 3046 } 3047 verifyPotentialSystemExemptionReason(REASON_DENIED, 3048 MOCK_PRIVILEGED_PACKAGES_2, 3049 MOCK_PRIVILEGED_UIDS_2); 3050 3051 mPhoneCarrierPrivileges.addNewPrivilegePackages(0, 3052 MOCK_PRIVILEGED_PACKAGES_2, 3053 MOCK_PRIVILEGED_UIDS_2); 3054 Thread.sleep(shortMs); 3055 3056 verifyPotentialSystemExemptionReason(REASON_CARRIER_PRIVILEGED_APP, 3057 MOCK_PRIVILEGED_PACKAGES_2, 3058 MOCK_PRIVILEGED_UIDS_2); 3059 3060 verifyPotentialSystemExemptionReason(REASON_DENIED, 3061 MOCK_PRIVILEGED_PACKAGES_0, 3062 MOCK_PRIVILEGED_UIDS_0); 3063 3064 verifyPotentialSystemExemptionReason(REASON_CARRIER_PRIVILEGED_APP, 3065 MOCK_PRIVILEGED_PACKAGES_1, 3066 MOCK_PRIVILEGED_UIDS_1); 3067 3068 mPhoneCarrierPrivileges.addNewPrivilegePackages(1, 3069 new String[0], new int[0]); 3070 Thread.sleep(shortMs); 3071 3072 verifyPotentialSystemExemptionReason(REASON_CARRIER_PRIVILEGED_APP, 3073 MOCK_PRIVILEGED_PACKAGES_2, 3074 MOCK_PRIVILEGED_UIDS_2); 3075 3076 verifyPotentialSystemExemptionReason(REASON_DENIED, 3077 MOCK_PRIVILEGED_PACKAGES_0, 3078 MOCK_PRIVILEGED_UIDS_0); 3079 3080 verifyPotentialSystemExemptionReason(REASON_DENIED, 3081 MOCK_PRIVILEGED_PACKAGES_1, 3082 MOCK_PRIVILEGED_UIDS_1); 3083 3084 mPhoneCarrierPrivileges.addNewPrivilegePackages(0, 3085 MOCK_PRIVILEGED_PACKAGES_0, 3086 MOCK_PRIVILEGED_UIDS_0); 3087 Thread.sleep(shortMs); 3088 3089 verifyPotentialSystemExemptionReason(REASON_DENIED, 3090 MOCK_PRIVILEGED_PACKAGES_2, 3091 MOCK_PRIVILEGED_UIDS_2); 3092 3093 verifyPotentialSystemExemptionReason(REASON_CARRIER_PRIVILEGED_APP, 3094 MOCK_PRIVILEGED_PACKAGES_0, 3095 MOCK_PRIVILEGED_UIDS_0); 3096 3097 verifyPotentialSystemExemptionReason(REASON_DENIED, 3098 MOCK_PRIVILEGED_PACKAGES_1, 3099 MOCK_PRIVILEGED_UIDS_1); 3100 } 3101 verifyPotentialSystemExemptionReason(int expectedReason, String[] packages, int[] uids)3102 private void verifyPotentialSystemExemptionReason(int expectedReason, 3103 String[] packages, int[] uids) throws Exception { 3104 for (int i = 0; i < packages.length; i++) { 3105 assertEquals(expectedReason, 3106 mBgRestrictionController.getPotentialSystemExemptionReason( 3107 uids[i], packages[i])); 3108 } 3109 } 3110 verifyLoadedSettings(RestrictionSettings settings)3111 private void verifyLoadedSettings(RestrictionSettings settings) throws Exception { 3112 // Make a new copy and reset it. 3113 RestrictionSettings test = (RestrictionSettings) settings.clone(); 3114 test.resetToDefault(); 3115 3116 // Wait for the idleness so the data is persisted. 3117 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); 3118 // Load it to our test object. 3119 test.loadFromXml(false); 3120 // Verify we restored it correctly. 3121 assertTrue(settings.equals(test)); 3122 } 3123 3124 @SuppressWarnings("GuardedBy") setRestrictionSettings(RestrictionSettings settings, String pkgName, int uid, int level, long levelTs, int reason, long[] notificationTime, boolean persist)3125 private void setRestrictionSettings(RestrictionSettings settings, String pkgName, int uid, 3126 int level, long levelTs, int reason, long[] notificationTime, boolean persist) { 3127 mCurrentTimeMillis = levelTs; 3128 settings.update(pkgName, uid, level, reason & REASON_MAIN_MASK, reason & REASON_SUB_MASK); 3129 final RestrictionSettings.PkgSettings pkgSettings = settings.getRestrictionSettingsLocked( 3130 uid, pkgName); 3131 for (int i = 0; i < notificationTime.length; i++) { 3132 pkgSettings.setLastNotificationTime(i, notificationTime[i], persist); 3133 } 3134 } 3135 createUidStateEventWithBatteryList( boolean[] isStart, long[] timestamps, double[] batteryUsage)3136 private LinkedList<UidStateEventWithBattery> createUidStateEventWithBatteryList( 3137 boolean[] isStart, long[] timestamps, double[] batteryUsage) { 3138 final LinkedList<UidStateEventWithBattery> result = new LinkedList<>(); 3139 for (int i = 0; i < isStart.length; i++) { 3140 result.add(new UidStateEventWithBattery(isStart[i], timestamps[i], 3141 new ImmutableBatteryUsage(0.0d, 0.0d, batteryUsage[i], 0.0d, 0.0d), null)); 3142 } 3143 return result; 3144 } 3145 3146 private class PhoneCarrierPrivileges { 3147 private final SparseArray<Pair<String[], int[]>> mPackages = new SparseArray<>(); 3148 private final SparseArray<Pair<Executor, CarrierPrivilegesCallback>> mListeners = 3149 new SparseArray<>(); 3150 PhoneCarrierPrivileges(TelephonyManager telephonyManager, int phoneIds)3151 PhoneCarrierPrivileges(TelephonyManager telephonyManager, int phoneIds) { 3152 doReturn(phoneIds).when(telephonyManager).getActiveModemCount(); 3153 doAnswer(inv -> { 3154 registerCarrierPrivilegesCallback( 3155 inv.getArgument(0), 3156 inv.getArgument(1), 3157 inv.getArgument(2)); 3158 return null; 3159 }).when(telephonyManager).registerCarrierPrivilegesCallback( 3160 anyInt(), anyObject(), anyObject()); 3161 } 3162 registerCarrierPrivilegesCallback(int phoneId, Executor executor, CarrierPrivilegesCallback callback)3163 public void registerCarrierPrivilegesCallback(int phoneId, Executor executor, 3164 CarrierPrivilegesCallback callback) { 3165 mListeners.put(phoneId, Pair.create(executor, callback)); 3166 final Pair<String[], int[]> pkgs = mPackages.get(phoneId); 3167 final Set<String> pkgNames = pkgs != null 3168 ? Arrays.stream(pkgs.first).collect(Collectors.toUnmodifiableSet()) 3169 : Collections.emptySet(); 3170 final Set<Integer> uids = pkgs != null 3171 ? Arrays.stream(pkgs.second).boxed().collect(Collectors.toUnmodifiableSet()) 3172 : Collections.emptySet(); 3173 executor.execute(() -> callback.onCarrierPrivilegesChanged(pkgNames, uids)); 3174 } 3175 addNewPrivilegePackages(int phoneId, String[] pkgNames, int[] uids)3176 public void addNewPrivilegePackages(int phoneId, String[] pkgNames, int[] uids) { 3177 mPackages.put(phoneId, Pair.create(pkgNames, uids)); 3178 final Pair<Executor, CarrierPrivilegesCallback> callback = mListeners.get(phoneId); 3179 if (callback != null) { 3180 callback.first.execute(() -> callback.second.onCarrierPrivilegesChanged( 3181 Arrays.stream(pkgNames).collect(Collectors.toUnmodifiableSet()), 3182 Arrays.stream(uids).boxed().collect(Collectors.toUnmodifiableSet()))); 3183 } 3184 } 3185 } 3186 3187 private class TestBgRestrictionInjector extends AppRestrictionController.Injector { 3188 private Context mContext; 3189 TestBgRestrictionInjector(Context context)3190 TestBgRestrictionInjector(Context context) { 3191 super(context); 3192 mContext = context; 3193 } 3194 3195 @Override initAppStateTrackers(AppRestrictionController controller)3196 void initAppStateTrackers(AppRestrictionController controller) { 3197 try { 3198 mAppBatteryTracker = new AppBatteryTracker(mContext, controller, 3199 TestAppBatteryTrackerInjector.class.getDeclaredConstructor( 3200 BackgroundRestrictionTest.class), 3201 BackgroundRestrictionTest.this); 3202 controller.addAppStateTracker(mAppBatteryTracker); 3203 mAppBatteryExemptionTracker = new AppBatteryExemptionTracker(mContext, controller, 3204 TestAppBatteryExemptionTrackerInjector.class.getDeclaredConstructor( 3205 BackgroundRestrictionTest.class), 3206 BackgroundRestrictionTest.this); 3207 controller.addAppStateTracker(mAppBatteryExemptionTracker); 3208 mAppFGSTracker = new AppFGSTracker(mContext, controller, 3209 TestAppFGSTrackerInjector.class.getDeclaredConstructor( 3210 BackgroundRestrictionTest.class), 3211 BackgroundRestrictionTest.this); 3212 controller.addAppStateTracker(mAppFGSTracker); 3213 mAppMediaSessionTracker = new AppMediaSessionTracker(mContext, controller, 3214 TestAppMediaSessionTrackerInjector.class.getDeclaredConstructor( 3215 BackgroundRestrictionTest.class), 3216 BackgroundRestrictionTest.this); 3217 controller.addAppStateTracker(mAppMediaSessionTracker); 3218 mAppBroadcastEventsTracker = new AppBroadcastEventsTracker(mContext, controller, 3219 TestAppBroadcastEventsTrackerInjector.class.getDeclaredConstructor( 3220 BackgroundRestrictionTest.class), 3221 BackgroundRestrictionTest.this); 3222 controller.addAppStateTracker(mAppBroadcastEventsTracker); 3223 mAppBindServiceEventsTracker = new AppBindServiceEventsTracker(mContext, controller, 3224 TestAppBindServiceEventsTrackerInjector.class.getDeclaredConstructor( 3225 BackgroundRestrictionTest.class), 3226 BackgroundRestrictionTest.this); 3227 controller.addAppStateTracker(mAppBindServiceEventsTracker); 3228 mAppPermissionTracker = new AppPermissionTracker(mContext, controller, 3229 TestAppPermissionTrackerInjector.class.getDeclaredConstructor( 3230 BackgroundRestrictionTest.class), 3231 BackgroundRestrictionTest.this); 3232 controller.addAppStateTracker(mAppPermissionTracker); 3233 } catch (NoSuchMethodException e) { 3234 // Won't happen. 3235 } 3236 } 3237 3238 @Override getActivityManagerInternal()3239 ActivityManagerInternal getActivityManagerInternal() { 3240 return mActivityManagerInternal; 3241 } 3242 3243 @Override getAppRestrictionController()3244 AppRestrictionController getAppRestrictionController() { 3245 return mBgRestrictionController; 3246 } 3247 3248 @Override getAppOpsManager()3249 AppOpsManager getAppOpsManager() { 3250 return mAppOpsManager; 3251 } 3252 3253 @Override getAppStandbyInternal()3254 AppStandbyInternal getAppStandbyInternal() { 3255 return mAppStandbyInternal; 3256 } 3257 3258 @Override getAppHibernationInternal()3259 AppHibernationManagerInternal getAppHibernationInternal() { 3260 return mAppHibernationInternal; 3261 } 3262 3263 @Override getAppStateTracker()3264 AppStateTracker getAppStateTracker() { 3265 return mAppStateTracker; 3266 } 3267 3268 @Override getIActivityManager()3269 IActivityManager getIActivityManager() { 3270 return mIActivityManager; 3271 } 3272 3273 @Override getUserManagerInternal()3274 UserManagerInternal getUserManagerInternal() { 3275 return mUserManagerInternal; 3276 } 3277 3278 @Override getPackageManagerInternal()3279 PackageManagerInternal getPackageManagerInternal() { 3280 return mPackageManagerInternal; 3281 } 3282 3283 @Override getPackageManager()3284 PackageManager getPackageManager() { 3285 return mPackageManager; 3286 } 3287 3288 @Override getNotificationManager()3289 NotificationManager getNotificationManager() { 3290 return mNotificationManager; 3291 } 3292 3293 @Override getRoleManager()3294 RoleManager getRoleManager() { 3295 return mRoleManager; 3296 } 3297 3298 @Override getTelephonyManager()3299 TelephonyManager getTelephonyManager() { 3300 return mTelephonyManager; 3301 } 3302 3303 @Override getAppFGSTracker()3304 AppFGSTracker getAppFGSTracker() { 3305 return mAppFGSTracker; 3306 } 3307 3308 @Override getAppMediaSessionTracker()3309 AppMediaSessionTracker getAppMediaSessionTracker() { 3310 return mAppMediaSessionTracker; 3311 } 3312 3313 @Override getActivityManagerService()3314 ActivityManagerService getActivityManagerService() { 3315 return mActivityManagerService; 3316 } 3317 3318 @Override getUidBatteryUsageProvider()3319 UidBatteryUsageProvider getUidBatteryUsageProvider() { 3320 return mAppBatteryTracker; 3321 } 3322 3323 @Override getAppBatteryExemptionTracker()3324 AppBatteryExemptionTracker getAppBatteryExemptionTracker() { 3325 return mAppBatteryExemptionTracker; 3326 } 3327 3328 @Override getAppPermissionTracker()3329 AppPermissionTracker getAppPermissionTracker() { 3330 return mAppPermissionTracker; 3331 } 3332 3333 @Override scheduleInitTrackers(Handler handler, Runnable initializers)3334 void scheduleInitTrackers(Handler handler, Runnable initializers) { 3335 initializers.run(); 3336 } 3337 3338 @Override getDataSystemDeDirectory(@serIdInt int userId)3339 File getDataSystemDeDirectory(@UserIdInt int userId) { 3340 return new File(mContext.getFilesDir(), Integer.toString(userId)); 3341 } 3342 3343 @Override currentTimeMillis()3344 long currentTimeMillis() { 3345 return mCurrentTimeMillis; 3346 } 3347 3348 @Override isTest()3349 boolean isTest() { 3350 return true; 3351 } 3352 } 3353 3354 private class TestBaseTrackerInjector<T extends BaseAppStatePolicy> 3355 extends BaseAppStateTracker.Injector<T> { 3356 @Override onSystemReady()3357 void onSystemReady() { 3358 getPolicy().onSystemReady(); 3359 } 3360 3361 @Override getActivityManagerInternal()3362 ActivityManagerInternal getActivityManagerInternal() { 3363 return BackgroundRestrictionTest.this.mActivityManagerInternal; 3364 } 3365 3366 @Override getBatteryManagerInternal()3367 BatteryManagerInternal getBatteryManagerInternal() { 3368 return BackgroundRestrictionTest.this.mBatteryManagerInternal; 3369 } 3370 3371 @Override getBatteryStatsInternal()3372 BatteryStatsInternal getBatteryStatsInternal() { 3373 return BackgroundRestrictionTest.this.mBatteryStatsInternal; 3374 } 3375 3376 @Override getDeviceIdleInternal()3377 DeviceIdleInternal getDeviceIdleInternal() { 3378 return BackgroundRestrictionTest.this.mDeviceIdleInternal; 3379 } 3380 3381 @Override getUserManagerInternal()3382 UserManagerInternal getUserManagerInternal() { 3383 return BackgroundRestrictionTest.this.mUserManagerInternal; 3384 } 3385 3386 @Override currentTimeMillis()3387 long currentTimeMillis() { 3388 return BackgroundRestrictionTest.this.mCurrentTimeMillis; 3389 } 3390 3391 @Override getPackageManager()3392 PackageManager getPackageManager() { 3393 return BackgroundRestrictionTest.this.mPackageManager; 3394 } 3395 3396 @Override getPermissionManagerServiceInternal()3397 PermissionManagerServiceInternal getPermissionManagerServiceInternal() { 3398 return BackgroundRestrictionTest.this.mPermissionManagerServiceInternal; 3399 } 3400 3401 @Override getAppOpsManager()3402 AppOpsManager getAppOpsManager() { 3403 return BackgroundRestrictionTest.this.mAppOpsManager; 3404 } 3405 3406 @Override getMediaSessionManager()3407 MediaSessionManager getMediaSessionManager() { 3408 return BackgroundRestrictionTest.this.mMediaSessionManager; 3409 } 3410 3411 @Override getNotificationManagerInternal()3412 NotificationManagerInternal getNotificationManagerInternal() { 3413 return BackgroundRestrictionTest.this.mNotificationManagerInternal; 3414 } 3415 getPackageManagerInternal()3416 PackageManagerInternal getPackageManagerInternal() { 3417 return BackgroundRestrictionTest.this.mPackageManagerInternal; 3418 } 3419 getPermissionManager()3420 PermissionManager getPermissionManager() { 3421 return BackgroundRestrictionTest.this.mPermissionManager; 3422 } 3423 3424 @Override getServiceStartForegroundTimeout()3425 long getServiceStartForegroundTimeout() { 3426 return 1_000; // ms 3427 } 3428 3429 @Override getRoleManager()3430 RoleManager getRoleManager() { 3431 return BackgroundRestrictionTest.this.mRoleManager; 3432 } 3433 3434 @Override getIAppOpsService()3435 IAppOpsService getIAppOpsService() { 3436 return BackgroundRestrictionTest.this.mIAppOpsService; 3437 } 3438 } 3439 3440 private class TestAppBatteryTrackerInjector extends TestBaseTrackerInjector<AppBatteryPolicy> { 3441 @Override setPolicy(AppBatteryPolicy policy)3442 void setPolicy(AppBatteryPolicy policy) { 3443 super.setPolicy(policy); 3444 BackgroundRestrictionTest.this.mAppBatteryPolicy = policy; 3445 } 3446 } 3447 3448 private class TestAppBatteryExemptionTrackerInjector 3449 extends TestBaseTrackerInjector<AppBatteryExemptionPolicy> { 3450 } 3451 3452 private class TestAppFGSTrackerInjector extends TestBaseTrackerInjector<AppFGSPolicy> { 3453 } 3454 3455 private class TestAppMediaSessionTrackerInjector 3456 extends TestBaseTrackerInjector<AppMediaSessionPolicy> { 3457 } 3458 3459 private class TestAppPermissionTrackerInjector 3460 extends TestBaseTrackerInjector<AppPermissionPolicy> { 3461 } 3462 3463 private class TestAppBroadcastEventsTrackerInjector 3464 extends TestBaseTrackerInjector<AppBroadcastEventsPolicy> { 3465 @Override setPolicy(AppBroadcastEventsPolicy policy)3466 void setPolicy(AppBroadcastEventsPolicy policy) { 3467 super.setPolicy(policy); 3468 policy.setTimeSlotSize(1_000L); 3469 } 3470 } 3471 3472 private class TestAppBindServiceEventsTrackerInjector 3473 extends TestBaseTrackerInjector<AppBindServiceEventsPolicy> { 3474 @Override setPolicy(AppBindServiceEventsPolicy policy)3475 void setPolicy(AppBindServiceEventsPolicy policy) { 3476 super.setPolicy(policy); 3477 policy.setTimeSlotSize(1_000L); 3478 } 3479 } 3480 } 3481