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