1 /* 2 * Copyright (C) 2020 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.car.watchdog; 18 19 import static android.app.StatsManager.PULL_SKIP; 20 import static android.app.StatsManager.PULL_SUCCESS; 21 import static android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_BASELINE; 22 import static android.car.test.mocks.AndroidMockitoHelper.mockAmGetCurrentUser; 23 import static android.car.test.mocks.AndroidMockitoHelper.mockUmGetAllUsers; 24 import static android.car.test.mocks.AndroidMockitoHelper.mockUmGetUserHandles; 25 import static android.car.test.mocks.AndroidMockitoHelper.mockUmIsUserRunning; 26 import static android.car.watchdog.CarWatchdogManager.TIMEOUT_CRITICAL; 27 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; 28 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 29 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 30 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED; 31 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 32 import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS; 33 34 import static com.android.car.CarStatsLog.CAR_WATCHDOG_KILL_STATS_REPORTED__KILL_REASON__KILLED_ON_IO_OVERUSE; 35 import static com.android.car.CarStatsLog.CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__GARAGE_MODE; 36 import static com.android.car.CarStatsLog.CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE; 37 import static com.android.car.CarStatsLog.CAR_WATCHDOG_KILL_STATS_REPORTED__UID_STATE__UNKNOWN_UID_STATE; 38 import static com.android.car.CarStatsLog.CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY; 39 import static com.android.car.CarStatsLog.CAR_WATCHDOG_UID_IO_USAGE_SUMMARY; 40 import static com.android.car.admin.NotificationHelper.RESOURCE_OVERUSE_NOTIFICATION_BASE_ID; 41 import static com.android.car.watchdog.CarWatchdogService.ACTION_DISMISS_RESOURCE_OVERUSE_NOTIFICATION; 42 import static com.android.car.watchdog.CarWatchdogService.ACTION_LAUNCH_APP_SETTINGS; 43 import static com.android.car.watchdog.CarWatchdogService.ACTION_RESOURCE_OVERUSE_DISABLE_APP; 44 import static com.android.car.watchdog.CarWatchdogService.MISSING_ARG_VALUE; 45 import static com.android.car.watchdog.TimeSource.ZONE_OFFSET; 46 import static com.android.car.watchdog.WatchdogPerfHandler.INTENT_EXTRA_ID; 47 import static com.android.car.watchdog.WatchdogPerfHandler.UID_IO_USAGE_SUMMARY_MIN_SYSTEM_TOTAL_WEEKLY_WRITTEN_BYTES; 48 import static com.android.car.watchdog.WatchdogStorage.RETENTION_PERIOD; 49 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; 50 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 51 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; 52 53 import static com.google.common.truth.Truth.assertThat; 54 import static com.google.common.truth.Truth.assertWithMessage; 55 56 import static org.junit.Assert.assertThrows; 57 import static org.mockito.AdditionalMatchers.or; 58 import static org.mockito.ArgumentMatchers.anyBoolean; 59 import static org.mockito.ArgumentMatchers.anyLong; 60 import static org.mockito.Mockito.any; 61 import static org.mockito.Mockito.anyInt; 62 import static org.mockito.Mockito.anyList; 63 import static org.mockito.Mockito.anyString; 64 import static org.mockito.Mockito.atLeastOnce; 65 import static org.mockito.Mockito.eq; 66 import static org.mockito.Mockito.mock; 67 import static org.mockito.Mockito.never; 68 import static org.mockito.Mockito.spy; 69 import static org.mockito.Mockito.timeout; 70 import static org.mockito.Mockito.times; 71 import static org.mockito.Mockito.verifyNoMoreInteractions; 72 import static org.mockito.Mockito.when; 73 74 import android.app.ActivityManager; 75 import android.app.ActivityThread; 76 import android.app.NotificationManager; 77 import android.app.StatsManager; 78 import android.app.StatsManager.PullAtomMetadata; 79 import android.app.StatsManager.StatsPullAtomCallback; 80 import android.automotive.watchdog.internal.ApplicationCategoryType; 81 import android.automotive.watchdog.internal.ComponentType; 82 import android.automotive.watchdog.internal.GarageMode; 83 import android.automotive.watchdog.internal.ICarWatchdog; 84 import android.automotive.watchdog.internal.ICarWatchdogServiceForSystem; 85 import android.automotive.watchdog.internal.IoUsageStats; 86 import android.automotive.watchdog.internal.PackageIdentifier; 87 import android.automotive.watchdog.internal.PackageInfo; 88 import android.automotive.watchdog.internal.PackageIoOveruseStats; 89 import android.automotive.watchdog.internal.PackageMetadata; 90 import android.automotive.watchdog.internal.PerStateIoOveruseThreshold; 91 import android.automotive.watchdog.internal.PowerCycle; 92 import android.automotive.watchdog.internal.ResourceSpecificConfiguration; 93 import android.automotive.watchdog.internal.StateType; 94 import android.automotive.watchdog.internal.UidType; 95 import android.automotive.watchdog.internal.UserPackageIoUsageStats; 96 import android.automotive.watchdog.internal.UserState; 97 import android.car.drivingstate.CarUxRestrictions; 98 import android.car.drivingstate.ICarUxRestrictionsChangeListener; 99 import android.car.hardware.power.CarPowerManager.CarPowerStateListener; 100 import android.car.hardware.power.CarPowerPolicy; 101 import android.car.hardware.power.ICarPowerPolicyListener; 102 import android.car.hardware.power.ICarPowerStateListener; 103 import android.car.hardware.power.PowerComponent; 104 import android.car.test.mocks.AbstractExtendedMockitoTestCase; 105 import android.car.watchdog.CarWatchdogManager; 106 import android.car.watchdog.ICarWatchdogServiceCallback; 107 import android.car.watchdog.IResourceOveruseListener; 108 import android.car.watchdog.IoOveruseAlertThreshold; 109 import android.car.watchdog.IoOveruseConfiguration; 110 import android.car.watchdog.IoOveruseStats; 111 import android.car.watchdog.PackageKillableState; 112 import android.car.watchdog.PerStateBytes; 113 import android.car.watchdog.ResourceOveruseConfiguration; 114 import android.car.watchdog.ResourceOveruseStats; 115 import android.content.BroadcastReceiver; 116 import android.content.Context; 117 import android.content.Intent; 118 import android.content.pm.ApplicationInfo; 119 import android.content.pm.IPackageManager; 120 import android.content.pm.PackageManager; 121 import android.content.pm.UserInfo; 122 import android.content.res.Resources; 123 import android.os.Binder; 124 import android.os.FileUtils; 125 import android.os.Handler; 126 import android.os.IBinder; 127 import android.os.Looper; 128 import android.os.RemoteException; 129 import android.os.ServiceManager; 130 import android.os.SystemClock; 131 import android.os.UserHandle; 132 import android.os.UserManager; 133 import android.util.ArrayMap; 134 import android.util.ArraySet; 135 import android.util.SparseArray; 136 import android.util.StatsEvent; 137 import android.view.Display; 138 139 import com.android.car.CarLocalServices; 140 import com.android.car.CarServiceUtils; 141 import com.android.car.CarStatsLog; 142 import com.android.car.CarUxRestrictionsManagerService; 143 import com.android.car.power.CarPowerManagementService; 144 import com.android.car.systeminterface.SystemInterface; 145 146 import com.google.common.truth.Correspondence; 147 148 import org.junit.After; 149 import org.junit.Before; 150 import org.junit.Test; 151 import org.junit.runner.RunWith; 152 import org.mockito.ArgumentCaptor; 153 import org.mockito.Captor; 154 import org.mockito.Mock; 155 import org.mockito.junit.MockitoJUnitRunner; 156 157 import java.io.File; 158 import java.nio.file.Files; 159 import java.time.Instant; 160 import java.time.ZonedDateTime; 161 import java.time.temporal.ChronoField; 162 import java.time.temporal.ChronoUnit; 163 import java.util.ArrayList; 164 import java.util.Arrays; 165 import java.util.Collections; 166 import java.util.Comparator; 167 import java.util.List; 168 import java.util.Map; 169 import java.util.Set; 170 import java.util.concurrent.CountDownLatch; 171 import java.util.concurrent.Executor; 172 import java.util.concurrent.TimeUnit; 173 import java.util.concurrent.atomic.AtomicBoolean; 174 import java.util.function.BiConsumer; 175 176 /** 177 * <p>This class contains unit tests for the {@link CarWatchdogService}. 178 */ 179 @RunWith(MockitoJUnitRunner.class) 180 public final class CarWatchdogServiceUnitTest extends AbstractExtendedMockitoTestCase { 181 private static final String CAR_WATCHDOG_DAEMON_INTERFACE = "carwatchdogd_system"; 182 private static final int MAX_WAIT_TIME_MS = 3000; 183 private static final int INVALID_SESSION_ID = -1; 184 private static final int OVERUSE_HANDLING_DELAY_MILLS = 1000; 185 private static final int RECURRING_OVERUSE_TIMES = 2; 186 private static final int RECURRING_OVERUSE_PERIOD_IN_DAYS = 2; 187 private static final int UID_IO_USAGE_SUMMARY_TOP_COUNT = 3; 188 private static final long STATS_DURATION_SECONDS = 3 * 60 * 60; 189 private static final long SYSTEM_DAILY_IO_USAGE_SUMMARY_MULTIPLIER = 10_000; 190 191 @Mock private Context mMockContext; 192 @Mock private NotificationManager mMockNotificationManager; 193 @Mock private PackageManager mMockPackageManager; 194 @Mock private StatsManager mMockStatsManager; 195 @Mock private UserManager mMockUserManager; 196 @Mock private SystemInterface mMockSystemInterface; 197 @Mock private CarPowerManagementService mMockCarPowerManagementService; 198 @Mock private CarUxRestrictionsManagerService mMockCarUxRestrictionsManagerService; 199 @Mock private Resources mMockResources; 200 @Mock private IBinder mMockBinder; 201 @Mock private ICarWatchdog mMockCarWatchdogDaemon; 202 @Mock private WatchdogStorage mMockWatchdogStorage; 203 @Mock private UserNotificationHelper mMockUserNotificationHelper; 204 205 @Captor private ArgumentCaptor<ICarPowerStateListener> mICarPowerStateListenerCaptor; 206 @Captor private ArgumentCaptor<ICarPowerPolicyListener> mICarPowerPolicyListenerCaptor; 207 @Captor private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor; 208 @Captor private ArgumentCaptor<ICarUxRestrictionsChangeListener> 209 mICarUxRestrictionsChangeListener; 210 @Captor private ArgumentCaptor<IBinder.DeathRecipient> mDeathRecipientCaptor; 211 @Captor private ArgumentCaptor<ICarWatchdogServiceForSystem> 212 mICarWatchdogServiceForSystemCaptor; 213 @Captor private ArgumentCaptor<List< 214 android.automotive.watchdog.internal.ResourceOveruseConfiguration>> 215 mResourceOveruseConfigurationsCaptor; 216 @Captor private ArgumentCaptor<SparseArray<List<String>>> mPackagesByUserIdCaptor; 217 @Captor private ArgumentCaptor<StatsPullAtomCallback> mStatsPullAtomCallbackCaptor; 218 @Captor private ArgumentCaptor<List<UserNotificationHelper.PackageNotificationInfo>> 219 mPackageNotificationInfosCaptor; 220 @Captor private ArgumentCaptor<UserHandle> mUserHandleCaptor; 221 @Captor private ArgumentCaptor<Intent> mIntentCaptor; 222 @Captor private ArgumentCaptor<int[]> mIntArrayCaptor; 223 @Captor private ArgumentCaptor<byte[]> mOveruseStatsCaptor; 224 @Captor private ArgumentCaptor<byte[]> mKilledStatsCaptor; 225 @Captor private ArgumentCaptor<Integer> mOverusingUidCaptor; 226 @Captor private ArgumentCaptor<Integer> mKilledUidCaptor; 227 @Captor private ArgumentCaptor<Integer> mUidStateCaptor; 228 @Captor private ArgumentCaptor<Integer> mSystemStateCaptor; 229 @Captor private ArgumentCaptor<Integer> mKillReasonCaptor; 230 231 private CarWatchdogService mCarWatchdogService; 232 private ICarWatchdogServiceForSystem mWatchdogServiceForSystemImpl; 233 private IBinder.DeathRecipient mCarWatchdogDaemonBinderDeathRecipient; 234 private BroadcastReceiver mBroadcastReceiver; 235 private boolean mIsDaemonCrashed; 236 private ICarPowerStateListener mCarPowerStateListener; 237 private ICarPowerPolicyListener mCarPowerPolicyListener; 238 private ICarUxRestrictionsChangeListener mCarUxRestrictionsChangeListener; 239 private StatsPullAtomCallback mStatsPullAtomCallback; 240 private File mTempSystemCarDir; 241 242 private final TestTimeSource mTimeSource = new TestTimeSource(); 243 private final SparseArray<String> mGenericPackageNameByUid = new SparseArray<>(); 244 private final SparseArray<List<String>> mPackagesBySharedUid = new SparseArray<>(); 245 private final ArrayMap<String, android.content.pm.PackageInfo> mPmPackageInfoByUserPackage = 246 new ArrayMap<>(); 247 private final ArraySet<String> mDisabledUserPackages = new ArraySet<>(); 248 private final List<WatchdogStorage.UserPackageSettingsEntry> mUserPackageSettingsEntries = 249 new ArrayList<>(); 250 private final List<WatchdogStorage.IoUsageStatsEntry> mIoUsageStatsEntries = new ArrayList<>(); 251 private final List<AtomsProto.CarWatchdogSystemIoUsageSummary> mPulledSystemIoUsageSummaries = 252 new ArrayList<>(); 253 private final List<AtomsProto.CarWatchdogUidIoUsageSummary> mPulledUidIoUsageSummaries = 254 new ArrayList<>(); 255 private final IPackageManager mSpiedPackageManager = spy(ActivityThread.getPackageManager()); 256 257 @Override onSessionBuilder(CustomMockitoSessionBuilder builder)258 protected void onSessionBuilder(CustomMockitoSessionBuilder builder) { 259 builder 260 .spyStatic(ServiceManager.class) 261 .spyStatic(Binder.class) 262 .spyStatic(ActivityManager.class) 263 .spyStatic(ActivityThread.class) 264 .spyStatic(CarLocalServices.class) 265 .spyStatic(CarStatsLog.class); 266 } 267 268 /** 269 * Initialize all of the objects with the @Mock annotation. 270 */ 271 @Before setUp()272 public void setUp() throws Exception { 273 when(mMockContext.getSystemService(NotificationManager.class)) 274 .thenReturn(mMockNotificationManager); 275 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); 276 when(mMockContext.getSystemService(StatsManager.class)).thenReturn(mMockStatsManager); 277 when(mMockContext.getPackageName()).thenReturn( 278 CarWatchdogServiceUnitTest.class.getCanonicalName()); 279 when(mMockContext.getResources()).thenReturn(mMockResources); 280 when(mMockResources.getInteger( 281 eq(com.android.car.R.integer.recurringResourceOverusePeriodInDays))) 282 .thenReturn(RECURRING_OVERUSE_PERIOD_IN_DAYS); 283 when(mMockResources.getInteger( 284 eq(com.android.car.R.integer.recurringResourceOveruseTimes))) 285 .thenReturn(RECURRING_OVERUSE_TIMES); 286 doReturn(mMockSystemInterface) 287 .when(() -> CarLocalServices.getService(SystemInterface.class)); 288 doReturn(mMockCarPowerManagementService) 289 .when(() -> CarLocalServices.getService(CarPowerManagementService.class)); 290 doReturn(mMockCarUxRestrictionsManagerService) 291 .when(() -> CarLocalServices.getService(CarUxRestrictionsManagerService.class)); 292 doReturn(mSpiedPackageManager).when(() -> ActivityThread.getPackageManager()); 293 294 when(mMockCarUxRestrictionsManagerService.getCurrentUxRestrictions()) 295 .thenReturn(new CarUxRestrictions.Builder(/* reqOpt= */ false, 296 UX_RESTRICTIONS_BASELINE, /* time= */ 0).build()); 297 298 mTempSystemCarDir = Files.createTempDirectory("watchdog_test").toFile(); 299 when(mMockSystemInterface.getSystemCarDir()).thenReturn(mTempSystemCarDir); 300 301 setupUsers(); 302 mockWatchdogDaemon(); 303 mockWatchdogStorage(); 304 mockPackageManager(); 305 mockBuildStatsEventCalls(); 306 307 mCarWatchdogService = new CarWatchdogService(mMockContext, mMockWatchdogStorage, 308 mMockUserNotificationHelper, mTimeSource); 309 initService(/* wantedInvocations= */ 1); 310 } 311 312 /** 313 * Releases resources. 314 */ 315 @After tearDown()316 public void tearDown() throws Exception { 317 if (mIsDaemonCrashed) { 318 /* Note: On daemon crash, CarWatchdogService retries daemon connection on the main 319 * thread. This retry outlives the test and impacts other test runs. Thus always call 320 * restartWatchdogDaemonAndAwait after crashing the daemon and before completing 321 * teardown. 322 */ 323 restartWatchdogDaemonAndAwait(); 324 } 325 if (mTempSystemCarDir != null) { 326 FileUtils.deleteContentsAndDir(mTempSystemCarDir); 327 } 328 } 329 330 @Test testCarWatchdogServiceHealthCheck()331 public void testCarWatchdogServiceHealthCheck() throws Exception { 332 mWatchdogServiceForSystemImpl.checkIfAlive(123456, TIMEOUT_CRITICAL); 333 verify(mMockCarWatchdogDaemon, 334 timeout(MAX_WAIT_TIME_MS)).tellCarWatchdogServiceAlive( 335 eq(mWatchdogServiceForSystemImpl), any(int[].class), eq(123456)); 336 } 337 338 @Test testRegisterClient()339 public void testRegisterClient() throws Exception { 340 TestClient client = new TestClient(); 341 mCarWatchdogService.registerClient(client, TIMEOUT_CRITICAL); 342 mWatchdogServiceForSystemImpl.checkIfAlive(123456, TIMEOUT_CRITICAL); 343 // Checking client health is asynchronous, so wait at most 1 second. 344 int repeat = 10; 345 while (repeat > 0) { 346 int sessionId = client.getLastSessionId(); 347 if (sessionId != INVALID_SESSION_ID) { 348 return; 349 } 350 SystemClock.sleep(100L); 351 repeat--; 352 } 353 assertThat(client.getLastSessionId()).isNotEqualTo(INVALID_SESSION_ID); 354 } 355 356 @Test testUnregisterUnregisteredClient()357 public void testUnregisterUnregisteredClient() throws Exception { 358 TestClient client = new TestClient(); 359 mCarWatchdogService.registerClient(client, TIMEOUT_CRITICAL); 360 mCarWatchdogService.unregisterClient(client); 361 mWatchdogServiceForSystemImpl.checkIfAlive(123456, TIMEOUT_CRITICAL); 362 assertThat(client.getLastSessionId()).isEqualTo(INVALID_SESSION_ID); 363 } 364 365 @Test testGoodClientHealthCheck()366 public void testGoodClientHealthCheck() throws Exception { 367 testClientHealthCheck(new TestClient(), 0); 368 } 369 370 @Test testBadClientHealthCheck()371 public void testBadClientHealthCheck() throws Exception { 372 testClientHealthCheck(new BadTestClient(), 1); 373 } 374 375 @Test testGarageModeStateChangeToOn()376 public void testGarageModeStateChangeToOn() throws Exception { 377 mBroadcastReceiver.onReceive(mMockContext, 378 new Intent().setAction(CarWatchdogService.ACTION_GARAGE_MODE_ON)); 379 verify(mMockCarWatchdogDaemon).notifySystemStateChange(StateType.GARAGE_MODE, 380 GarageMode.GARAGE_MODE_ON, MISSING_ARG_VALUE); 381 verify(mMockWatchdogStorage).shrinkDatabase(); 382 } 383 384 @Test testGarageModeStateChangeToOff()385 public void testGarageModeStateChangeToOff() throws Exception { 386 mBroadcastReceiver.onReceive(mMockContext, 387 new Intent().setAction(CarWatchdogService.ACTION_GARAGE_MODE_OFF)); 388 // GARAGE_MODE_OFF is notified twice: Once during the initial daemon connect and once when 389 // the ACTION_GARAGE_MODE_OFF intent is received. 390 verify(mMockCarWatchdogDaemon, times(2)).notifySystemStateChange(StateType.GARAGE_MODE, 391 GarageMode.GARAGE_MODE_OFF, MISSING_ARG_VALUE); 392 verify(mMockWatchdogStorage, never()).shrinkDatabase(); 393 } 394 395 @Test testWatchdogDaemonRestart()396 public void testWatchdogDaemonRestart() throws Exception { 397 crashWatchdogDaemon(); 398 399 mockUmGetAllUsers(mMockUserManager, new UserInfo(101, "", 0), new UserInfo(102, "", 0)); 400 mockUmIsUserRunning(mMockUserManager, /* userId= */ 101, /* isRunning= */ false); 401 mockUmIsUserRunning(mMockUserManager, /* userId= */ 102, /* isRunning= */ true); 402 setCarPowerState(CarPowerStateListener.SHUTDOWN_ENTER); 403 mBroadcastReceiver.onReceive(mMockContext, 404 new Intent().setAction(CarWatchdogService.ACTION_GARAGE_MODE_ON)); 405 406 restartWatchdogDaemonAndAwait(); 407 408 verify(mMockCarWatchdogDaemon).notifySystemStateChange(StateType.USER_STATE, 101, 409 UserState.USER_STATE_STOPPED); 410 verify(mMockCarWatchdogDaemon).notifySystemStateChange(StateType.USER_STATE, 102, 411 UserState.USER_STATE_STARTED); 412 verify(mMockCarWatchdogDaemon).notifySystemStateChange(StateType.POWER_CYCLE, 413 PowerCycle.POWER_CYCLE_SHUTDOWN_ENTER, MISSING_ARG_VALUE); 414 verify(mMockCarWatchdogDaemon).notifySystemStateChange(StateType.GARAGE_MODE, 415 GarageMode.GARAGE_MODE_ON, MISSING_ARG_VALUE); 416 } 417 418 @Test testUserRemovedBroadcast()419 public void testUserRemovedBroadcast() throws Exception { 420 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 101, 102); 421 mBroadcastReceiver.onReceive(mMockContext, 422 new Intent().setAction(Intent.ACTION_USER_REMOVED) 423 .putExtra(Intent.EXTRA_USER, UserHandle.of(100))); 424 verify(mMockCarWatchdogDaemon).notifySystemStateChange(StateType.USER_STATE, 100, 425 UserState.USER_STATE_REMOVED); 426 verify(mMockWatchdogStorage).syncUsers(new int[] {101, 102}); 427 } 428 429 @Test testDisableAppBroadcast()430 public void testDisableAppBroadcast() throws Exception { 431 String packageName = "system_package"; 432 UserHandle userHandle = UserHandle.of(100); 433 int id = 150; 434 435 mBroadcastReceiver.onReceive(mMockContext, new Intent(ACTION_RESOURCE_OVERUSE_DISABLE_APP) 436 .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName) 437 .putExtra(Intent.EXTRA_USER, userHandle) 438 .putExtra(INTENT_EXTRA_ID, id)); 439 440 verify(mSpiedPackageManager).getApplicationEnabledSetting(packageName, 441 userHandle.getIdentifier()); 442 443 verify(mSpiedPackageManager).setApplicationEnabledSetting(eq(packageName), 444 eq(COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED), eq(0), 445 eq(userHandle.getIdentifier()), anyString()); 446 447 verify(mMockNotificationManager).cancelAsUser(CarWatchdogService.TAG, id, userHandle); 448 449 verifyNoMoreInteractions(mSpiedPackageManager); 450 verifyNoMoreInteractions(mMockNotificationManager); 451 } 452 453 @Test testDisableAppBroadcastWithDisabledPackage()454 public void testDisableAppBroadcastWithDisabledPackage() throws Exception { 455 String packageName = "system_package"; 456 UserHandle userHandle = UserHandle.of(100); 457 458 doReturn(COMPONENT_ENABLED_STATE_DISABLED).when(mSpiedPackageManager) 459 .getApplicationEnabledSetting(packageName, userHandle.getIdentifier()); 460 461 mBroadcastReceiver.onReceive(mMockContext, new Intent(ACTION_RESOURCE_OVERUSE_DISABLE_APP) 462 .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName) 463 .putExtra(Intent.EXTRA_USER, userHandle) 464 .putExtra(INTENT_EXTRA_ID, RESOURCE_OVERUSE_NOTIFICATION_BASE_ID)); 465 466 verify(mSpiedPackageManager).getApplicationEnabledSetting(packageName, 467 userHandle.getIdentifier()); 468 469 verify(mMockNotificationManager).cancelAsUser(CarWatchdogService.TAG, 470 RESOURCE_OVERUSE_NOTIFICATION_BASE_ID, userHandle); 471 472 verifyNoMoreInteractions(mSpiedPackageManager); 473 verifyNoMoreInteractions(mMockNotificationManager); 474 } 475 476 @Test testLaunchAppSettingsBroadcast()477 public void testLaunchAppSettingsBroadcast() throws Exception { 478 String packageName = "system_package"; 479 UserHandle userHandle = UserHandle.of(100); 480 481 mBroadcastReceiver.onReceive(mMockContext, new Intent(ACTION_LAUNCH_APP_SETTINGS) 482 .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName) 483 .putExtra(Intent.EXTRA_USER, userHandle) 484 .putExtra(INTENT_EXTRA_ID, RESOURCE_OVERUSE_NOTIFICATION_BASE_ID)); 485 486 verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(userHandle)); 487 488 Intent actualIntent = mIntentCaptor.getValue(); 489 490 assertWithMessage("Launch app settings intent action").that(actualIntent.getAction()) 491 .isEqualTo(ACTION_APPLICATION_DETAILS_SETTINGS); 492 493 assertWithMessage("Launch app settings intent data string") 494 .that(actualIntent.getDataString()).contains(packageName); 495 496 assertWithMessage("Launch app settings intent flags") 497 .that(actualIntent.getFlags()) 498 .isEqualTo(FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK); 499 500 verify(mMockNotificationManager).cancelAsUser(CarWatchdogService.TAG, 501 RESOURCE_OVERUSE_NOTIFICATION_BASE_ID, userHandle); 502 503 verifyNoMoreInteractions(mSpiedPackageManager); 504 verifyNoMoreInteractions(mMockNotificationManager); 505 } 506 507 @Test testDismissUserNotificationBroadcast()508 public void testDismissUserNotificationBroadcast() throws Exception { 509 String packageName = "system_package"; 510 UserHandle userHandle = UserHandle.of(100); 511 512 mBroadcastReceiver.onReceive(mMockContext, 513 new Intent(ACTION_DISMISS_RESOURCE_OVERUSE_NOTIFICATION) 514 .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName) 515 .putExtra(Intent.EXTRA_USER, userHandle) 516 .putExtra(INTENT_EXTRA_ID, RESOURCE_OVERUSE_NOTIFICATION_BASE_ID)); 517 518 verify(mMockNotificationManager).cancelAsUser(CarWatchdogService.TAG, 519 RESOURCE_OVERUSE_NOTIFICATION_BASE_ID, userHandle); 520 521 verifyNoMoreInteractions(mSpiedPackageManager); 522 verifyNoMoreInteractions(mMockNotificationManager); 523 } 524 525 @Test testUserNotificationActionBroadcastsWithNullPackageName()526 public void testUserNotificationActionBroadcastsWithNullPackageName() throws Exception { 527 List<String> actions = Arrays.asList(ACTION_RESOURCE_OVERUSE_DISABLE_APP, 528 ACTION_LAUNCH_APP_SETTINGS, ACTION_DISMISS_RESOURCE_OVERUSE_NOTIFICATION); 529 530 for (String action : actions) { 531 mBroadcastReceiver.onReceive(mMockContext, new Intent(action) 532 .putExtra(Intent.EXTRA_USER, UserHandle.of(100)) 533 .putExtra(INTENT_EXTRA_ID, RESOURCE_OVERUSE_NOTIFICATION_BASE_ID)); 534 } 535 536 verify(mMockContext, never()).startActivityAsUser(any(), any()); 537 verifyNoMoreInteractions(mSpiedPackageManager); 538 verifyNoMoreInteractions(mMockNotificationManager); 539 } 540 541 @Test testUserNotificationActionBroadcastsWithInvalidUserId()542 public void testUserNotificationActionBroadcastsWithInvalidUserId() throws Exception { 543 List<String> actions = Arrays.asList(ACTION_RESOURCE_OVERUSE_DISABLE_APP, 544 ACTION_LAUNCH_APP_SETTINGS, ACTION_DISMISS_RESOURCE_OVERUSE_NOTIFICATION); 545 546 for (String action : actions) { 547 mBroadcastReceiver.onReceive(mMockContext, new Intent(action) 548 .putExtra(Intent.EXTRA_PACKAGE_NAME, "system_package") 549 .putExtra(Intent.EXTRA_USER, UserHandle.of(-1)) 550 .putExtra(INTENT_EXTRA_ID, RESOURCE_OVERUSE_NOTIFICATION_BASE_ID)); 551 } 552 553 verify(mMockContext, never()).startActivityAsUser(any(), any()); 554 verifyNoMoreInteractions(mSpiedPackageManager); 555 verifyNoMoreInteractions(mMockNotificationManager); 556 } 557 558 @Test testUserNotificationActionBroadcastsWithMissingNotificationId()559 public void testUserNotificationActionBroadcastsWithMissingNotificationId() throws Exception { 560 String packageName = "system_package"; 561 UserHandle userHandle = UserHandle.of(100); 562 563 List<String> actions = Arrays.asList(ACTION_RESOURCE_OVERUSE_DISABLE_APP, 564 ACTION_LAUNCH_APP_SETTINGS, ACTION_DISMISS_RESOURCE_OVERUSE_NOTIFICATION); 565 566 for (String action : actions) { 567 mBroadcastReceiver.onReceive(mMockContext, new Intent(action) 568 .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName) 569 .putExtra(Intent.EXTRA_USER, userHandle)); 570 } 571 572 verify(mSpiedPackageManager).getApplicationEnabledSetting(packageName, 573 userHandle.getIdentifier()); 574 575 verify(mSpiedPackageManager).setApplicationEnabledSetting(eq(packageName), 576 eq(COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED), eq(0), 577 eq(userHandle.getIdentifier()), anyString()); 578 579 verify(mMockContext).startActivityAsUser(any(), any()); 580 581 verifyNoMoreInteractions(mSpiedPackageManager); 582 verifyNoMoreInteractions(mMockNotificationManager); 583 } 584 585 @Test testGetResourceOveruseStats()586 public void testGetResourceOveruseStats() throws Exception { 587 int uid = Binder.getCallingUid(); 588 injectPackageInfos(Collections.singletonList( 589 constructPackageManagerPackageInfo( 590 mMockContext.getPackageName(), uid, null, ApplicationInfo.FLAG_SYSTEM, 0))); 591 592 SparseArray<PackageIoOveruseStats> packageIoOveruseStatsByUid = 593 injectIoOveruseStatsForPackages( 594 mGenericPackageNameByUid, /* killablePackages= */ new ArraySet<>(), 595 /* shouldNotifyPackages= */ new ArraySet<>()); 596 597 ResourceOveruseStats expectedStats = 598 constructResourceOveruseStats(uid, mMockContext.getPackageName(), 599 packageIoOveruseStatsByUid.get(uid).ioOveruseStats); 600 601 ResourceOveruseStats actualStats = mCarWatchdogService.getResourceOveruseStats( 602 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 603 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY); 604 605 ResourceOveruseStatsSubject.assertEquals(actualStats, expectedStats); 606 607 verifyNoMoreInteractions(mMockWatchdogStorage); 608 } 609 610 @Test testGetResourceOveruseStatsForPast7days()611 public void testGetResourceOveruseStatsForPast7days() throws Exception { 612 int uid = Binder.getCallingUid(); 613 String packageName = mMockContext.getPackageName(); 614 injectPackageInfos(Collections.singletonList(constructPackageManagerPackageInfo( 615 packageName, uid, null, ApplicationInfo.FLAG_SYSTEM, 0))); 616 617 long startTime = mTimeSource.getCurrentDateTime().minusDays(4).toEpochSecond(); 618 long duration = mTimeSource.now().getEpochSecond() - startTime; 619 when(mMockWatchdogStorage.getHistoricalIoOveruseStats( 620 UserHandle.getUserId(uid), packageName, 6)) 621 .thenReturn(new IoOveruseStats.Builder(startTime, duration).setTotalOveruses(5) 622 .setTotalTimesKilled(2).setTotalBytesWritten(24_000).build()); 623 624 injectIoOveruseStatsForPackages(mGenericPackageNameByUid, 625 /* killablePackages= */ Collections.singleton(packageName), 626 /* shouldNotifyPackages= */ new ArraySet<>()); 627 628 ResourceOveruseStats actualStats = mCarWatchdogService.getResourceOveruseStats( 629 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 630 CarWatchdogManager.STATS_PERIOD_PAST_7_DAYS); 631 632 IoOveruseStats ioOveruseStats = 633 new IoOveruseStats.Builder(startTime, duration + STATS_DURATION_SECONDS) 634 .setKillableOnOveruse(true).setTotalOveruses(8).setTotalBytesWritten(24_600) 635 .setTotalTimesKilled(2) 636 .setRemainingWriteBytes(new PerStateBytes(20, 20, 20)).build(); 637 638 ResourceOveruseStats expectedStats = 639 new ResourceOveruseStats.Builder(packageName, UserHandle.getUserHandleForUid(uid)) 640 .setIoOveruseStats(ioOveruseStats).build(); 641 642 ResourceOveruseStatsSubject.assertEquals(actualStats, expectedStats); 643 } 644 645 @Test testGetResourceOveruseStatsForPast7daysWithNoHistory()646 public void testGetResourceOveruseStatsForPast7daysWithNoHistory() throws Exception { 647 int uid = Binder.getCallingUid(); 648 String packageName = mMockContext.getPackageName(); 649 injectPackageInfos(Collections.singletonList(constructPackageManagerPackageInfo( 650 packageName, uid, null, ApplicationInfo.FLAG_SYSTEM, 0))); 651 652 when(mMockWatchdogStorage.getHistoricalIoOveruseStats( 653 UserHandle.getUserId(uid), packageName, 6)).thenReturn(null); 654 655 injectIoOveruseStatsForPackages(mGenericPackageNameByUid, 656 /* killablePackages= */ Collections.singleton(packageName), 657 /* shouldNotifyPackages= */ new ArraySet<>()); 658 659 ResourceOveruseStats actualStats = mCarWatchdogService.getResourceOveruseStats( 660 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 661 CarWatchdogManager.STATS_PERIOD_PAST_7_DAYS); 662 663 ResourceOveruseStats expectedStats = 664 new ResourceOveruseStats.Builder(packageName, UserHandle.getUserHandleForUid(uid)) 665 .setIoOveruseStats(new IoOveruseStats.Builder( 666 mTimeSource.now().getEpochSecond(), STATS_DURATION_SECONDS) 667 .setKillableOnOveruse(true).setTotalOveruses(3) 668 .setTotalBytesWritten(600) 669 .setRemainingWriteBytes(new PerStateBytes(20, 20, 20)).build()) 670 .build(); 671 672 ResourceOveruseStatsSubject.assertEquals(actualStats, expectedStats); 673 } 674 675 @Test testGetResourceOveruseStatsForPast7daysWithNoCurrentStats()676 public void testGetResourceOveruseStatsForPast7daysWithNoCurrentStats() throws Exception { 677 int uid = Binder.getCallingUid(); 678 String packageName = mMockContext.getPackageName(); 679 injectPackageInfos(Collections.singletonList(constructPackageManagerPackageInfo( 680 packageName, uid, null, ApplicationInfo.FLAG_SYSTEM, 0))); 681 682 long startTime = mTimeSource.getCurrentDateTime().minusDays(4).toEpochSecond(); 683 long duration = mTimeSource.now().getEpochSecond() - startTime; 684 when(mMockWatchdogStorage.getHistoricalIoOveruseStats( 685 UserHandle.getUserId(uid), packageName, 6)) 686 .thenReturn(new IoOveruseStats.Builder(startTime, duration).setTotalOveruses(5) 687 .setTotalTimesKilled(2).setTotalBytesWritten(24_000).build()); 688 689 ResourceOveruseStats actualStats = mCarWatchdogService.getResourceOveruseStats( 690 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 691 CarWatchdogManager.STATS_PERIOD_PAST_7_DAYS); 692 693 ResourceOveruseStats expectedStats = 694 new ResourceOveruseStats.Builder(packageName, UserHandle.getUserHandleForUid(uid)) 695 .build(); 696 697 ResourceOveruseStatsSubject.assertEquals(actualStats, expectedStats); 698 } 699 700 @Test testGetResourceOveruseStatsForSharedUid()701 public void testGetResourceOveruseStatsForSharedUid() throws Exception { 702 int sharedUid = Binder.getCallingUid(); 703 injectPackageInfos(Collections.singletonList( 704 constructPackageManagerPackageInfo( 705 mMockContext.getPackageName(), sharedUid, "system_shared_package", 706 ApplicationInfo.FLAG_SYSTEM, 0))); 707 708 SparseArray<PackageIoOveruseStats> packageIoOveruseStatsByUid = 709 injectIoOveruseStatsForPackages( 710 mGenericPackageNameByUid, /* killablePackages= */ new ArraySet<>(), 711 /* shouldNotifyPackages= */ new ArraySet<>()); 712 713 ResourceOveruseStats expectedStats = 714 constructResourceOveruseStats(sharedUid, "shared:system_shared_package", 715 packageIoOveruseStatsByUid.get(sharedUid).ioOveruseStats); 716 717 ResourceOveruseStats actualStats = mCarWatchdogService.getResourceOveruseStats( 718 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 719 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY); 720 721 ResourceOveruseStatsSubject.assertEquals(actualStats, expectedStats); 722 } 723 724 @Test testFailsGetResourceOveruseStatsWithInvalidArgs()725 public void testFailsGetResourceOveruseStatsWithInvalidArgs() throws Exception { 726 assertThrows(IllegalArgumentException.class, 727 () -> mCarWatchdogService.getResourceOveruseStats(/* resourceOveruseFlag= */ 0, 728 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY)); 729 730 assertThrows(IllegalArgumentException.class, 731 () -> mCarWatchdogService.getResourceOveruseStats( 732 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, /* maxStatsPeriod= */ 0)); 733 } 734 735 @Test testGetAllResourceOveruseStatsWithNoMinimum()736 public void testGetAllResourceOveruseStatsWithNoMinimum() throws Exception { 737 injectPackageInfos(Arrays.asList( 738 constructPackageManagerPackageInfo("third_party_package", 1103456, null), 739 constructPackageManagerPackageInfo("vendor_package.critical", 1201278, null))); 740 741 List<PackageIoOveruseStats> packageIoOveruseStats = Arrays.asList( 742 constructPackageIoOveruseStats(1103456, 743 /* shouldNotify= */ true, 744 /* forgivenWriteBytes= */ constructPerStateBytes(100, 200, 300), 745 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 746 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 747 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 748 /* totalOveruses= */ 3)), 749 constructPackageIoOveruseStats(1201278, 750 /* shouldNotify= */ false, 751 /* forgivenWriteBytes= */ constructPerStateBytes(5000, 6000, 9000), 752 constructInternalIoOveruseStats(/* killableOnOveruse= */ false, 753 /* remainingWriteBytes= */ constructPerStateBytes(450, 120, 340), 754 /* writtenBytes= */ constructPerStateBytes(5000, 6000, 9000), 755 /* totalOveruses= */ 3))); 756 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 757 758 List<ResourceOveruseStats> expectedStats = Arrays.asList( 759 constructResourceOveruseStats(1103456, "third_party_package", 760 packageIoOveruseStats.get(0).ioOveruseStats), 761 constructResourceOveruseStats(1201278, "vendor_package.critical", 762 packageIoOveruseStats.get(1).ioOveruseStats)); 763 764 List<ResourceOveruseStats> actualStats = mCarWatchdogService.getAllResourceOveruseStats( 765 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, /* minimumStatsFlag= */ 0, 766 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY); 767 768 ResourceOveruseStatsSubject.assertThat(actualStats) 769 .containsExactlyElementsIn(expectedStats); 770 771 verifyNoMoreInteractions(mMockWatchdogStorage); 772 } 773 774 @Test testGetAllResourceOveruseStatsWithNoMinimumForPast7days()775 public void testGetAllResourceOveruseStatsWithNoMinimumForPast7days() throws Exception { 776 injectPackageInfos(Arrays.asList( 777 constructPackageManagerPackageInfo("third_party_package", 1103456, null), 778 constructPackageManagerPackageInfo("vendor_package.critical", 1201278, null))); 779 780 List<PackageIoOveruseStats> packageIoOveruseStats = Arrays.asList( 781 constructPackageIoOveruseStats(1103456, 782 /* shouldNotify= */ true, 783 /* forgivenWriteBytes= */ constructPerStateBytes(100, 200, 300), 784 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 785 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 786 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 787 /* totalOveruses= */ 3)), 788 constructPackageIoOveruseStats(1201278, 789 /* shouldNotify= */ false, 790 /* forgivenWriteBytes= */ constructPerStateBytes(0, 0, 0), 791 constructInternalIoOveruseStats(/* killableOnOveruse= */ false, 792 /* remainingWriteBytes= */ constructPerStateBytes(450, 120, 340), 793 /* writtenBytes= */ constructPerStateBytes(5000, 6000, 9000), 794 /* totalOveruses= */ 0))); 795 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 796 797 ZonedDateTime now = mTimeSource.getCurrentDateTime(); 798 long startTime = now.minusDays(4).toEpochSecond(); 799 IoOveruseStats thirdPartyPkgOldStats = new IoOveruseStats.Builder( 800 startTime, now.toEpochSecond() - startTime).setTotalOveruses(5) 801 .setTotalTimesKilled(2).setTotalBytesWritten(24_000).build(); 802 when(mMockWatchdogStorage.getHistoricalIoOveruseStats(11, "third_party_package", 6)) 803 .thenReturn(thirdPartyPkgOldStats); 804 805 startTime = now.minusDays(6).toEpochSecond(); 806 IoOveruseStats vendorPkgOldStats = new IoOveruseStats.Builder( 807 startTime, now.toEpochSecond() - startTime).setTotalOveruses(2) 808 .setTotalTimesKilled(0).setTotalBytesWritten(35_000).build(); 809 when(mMockWatchdogStorage.getHistoricalIoOveruseStats(12, "vendor_package.critical", 6)) 810 .thenReturn(vendorPkgOldStats); 811 812 813 List<ResourceOveruseStats> actualStats = mCarWatchdogService.getAllResourceOveruseStats( 814 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, /* minimumStatsFlag= */ 0, 815 CarWatchdogManager.STATS_PERIOD_PAST_7_DAYS); 816 817 IoOveruseStats thirdPartyIoStats = new IoOveruseStats.Builder( 818 thirdPartyPkgOldStats.getStartTime(), 819 thirdPartyPkgOldStats.getDurationInSeconds() + STATS_DURATION_SECONDS) 820 .setKillableOnOveruse(true).setTotalOveruses(8).setTotalBytesWritten(24_600) 821 .setTotalTimesKilled(2).setRemainingWriteBytes(new PerStateBytes(0, 0, 0)) 822 .build(); 823 IoOveruseStats vendorIoStats = new IoOveruseStats.Builder( 824 vendorPkgOldStats.getStartTime(), 825 vendorPkgOldStats.getDurationInSeconds() + STATS_DURATION_SECONDS) 826 .setKillableOnOveruse(false).setTotalOveruses(2).setTotalBytesWritten(55_000) 827 .setTotalTimesKilled(0).setRemainingWriteBytes(new PerStateBytes(450, 120, 340)) 828 .build(); 829 830 List<ResourceOveruseStats> expectedStats = Arrays.asList( 831 new ResourceOveruseStats.Builder("third_party_package", new UserHandle(11)) 832 .setIoOveruseStats(thirdPartyIoStats).build(), 833 new ResourceOveruseStats.Builder("vendor_package.critical", new UserHandle(12)) 834 .setIoOveruseStats(vendorIoStats).build()); 835 836 ResourceOveruseStatsSubject.assertThat(actualStats) 837 .containsExactlyElementsIn(expectedStats); 838 } 839 840 @Test testGetAllResourceOveruseStatsForSharedPackage()841 public void testGetAllResourceOveruseStatsForSharedPackage() throws Exception { 842 injectPackageInfos(Arrays.asList( 843 constructPackageManagerPackageInfo( 844 "vendor_package.A", 1103456, "vendor_shared_package"), 845 constructPackageManagerPackageInfo( 846 "third_party_package.B", 1103456, "vendor_shared_package"), 847 constructPackageManagerPackageInfo( 848 "system_package.C", 1201000, "system_shared_package"), 849 constructPackageManagerPackageInfo( 850 "system_package.D", 1201000, "system_shared_package"), 851 constructPackageManagerPackageInfo( 852 "third_party_package.A", 1303456, "vendor_shared_package"), 853 constructPackageManagerPackageInfo( 854 "vendor_package.B", 1303456, "vendor_shared_package"))); 855 856 List<PackageIoOveruseStats> packageIoOveruseStats = Arrays.asList( 857 constructPackageIoOveruseStats(1103456, 858 /* shouldNotify= */ false, 859 /* forgivenWriteBytes= */ constructPerStateBytes(50, 100, 150), 860 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 861 /* remainingWriteBytes= */ constructPerStateBytes(20, 20, 20), 862 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 863 /* totalOveruses= */ 3)), 864 constructPackageIoOveruseStats(1201000, 865 /* shouldNotify= */ false, 866 /* forgivenWriteBytes= */ constructPerStateBytes(0, 0, 0), 867 constructInternalIoOveruseStats(/* killableOnOveruse= */ false, 868 /* remainingWriteBytes= */ constructPerStateBytes(450, 120, 340), 869 /* writtenBytes= */ constructPerStateBytes(5000, 6000, 9000), 870 /* totalOveruses= */ 0)), 871 constructPackageIoOveruseStats(1303456, 872 /* shouldNotify= */ true, 873 /* forgivenWriteBytes= */ constructPerStateBytes(80, 170, 260), 874 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 875 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 876 /* writtenBytes= */ constructPerStateBytes(80, 170, 260), 877 /* totalOveruses= */ 1))); 878 879 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 880 881 List<ResourceOveruseStats> expectedStats = Arrays.asList( 882 constructResourceOveruseStats(1103456, "shared:vendor_shared_package", 883 packageIoOveruseStats.get(0).ioOveruseStats), 884 constructResourceOveruseStats(1201278, "shared:system_shared_package", 885 packageIoOveruseStats.get(1).ioOveruseStats), 886 constructResourceOveruseStats(1303456, "shared:vendor_shared_package", 887 packageIoOveruseStats.get(2).ioOveruseStats)); 888 889 List<ResourceOveruseStats> actualStats = mCarWatchdogService.getAllResourceOveruseStats( 890 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, /* minimumStatsFlag= */ 0, 891 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY); 892 893 ResourceOveruseStatsSubject.assertThat(actualStats) 894 .containsExactlyElementsIn(expectedStats); 895 896 verifyNoMoreInteractions(mMockWatchdogStorage); 897 } 898 899 @Test testFailsGetAllResourceOveruseStatsWithInvalidArgs()900 public void testFailsGetAllResourceOveruseStatsWithInvalidArgs() throws Exception { 901 assertThrows(IllegalArgumentException.class, 902 () -> mCarWatchdogService.getAllResourceOveruseStats(0, /* minimumStatsFlag= */ 0, 903 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY)); 904 905 assertThrows(IllegalArgumentException.class, 906 () -> mCarWatchdogService.getAllResourceOveruseStats( 907 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 908 CarWatchdogManager.FLAG_MINIMUM_STATS_IO_1_MB 909 | CarWatchdogManager.FLAG_MINIMUM_STATS_IO_100_MB, 910 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY)); 911 912 assertThrows(IllegalArgumentException.class, 913 () -> mCarWatchdogService.getAllResourceOveruseStats( 914 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, /* minimumStatsFlag= */ 1 << 5, 915 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY)); 916 917 assertThrows(IllegalArgumentException.class, 918 () -> mCarWatchdogService.getAllResourceOveruseStats( 919 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, /* minimumStatsFlag= */ 0, 920 /* maxStatsPeriod= */ 0)); 921 } 922 923 @Test testGetAllResourceOveruseStatsWithMinimum()924 public void testGetAllResourceOveruseStatsWithMinimum() throws Exception { 925 injectPackageInfos(Arrays.asList( 926 constructPackageManagerPackageInfo("third_party_package", 1103456, null), 927 constructPackageManagerPackageInfo("vendor_package.critical", 1201278, null))); 928 929 List<PackageIoOveruseStats> packageIoOveruseStats = Arrays.asList( 930 constructPackageIoOveruseStats(1103456, /* shouldNotify= */ false, 931 /* forgivenWriteBytes= */ constructPerStateBytes(80, 170, 260), 932 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 933 /* remainingWriteBytes= */ constructPerStateBytes(20, 20, 20), 934 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 935 /* totalOveruses= */ 3)), 936 constructPackageIoOveruseStats(1201278, /* shouldNotify= */ false, 937 /* forgivenWriteBytes= */ constructPerStateBytes(5_070_000, 4500, 7000), 938 constructInternalIoOveruseStats(/* killableOnOveruse= */ false, 939 /* remainingWriteBytes= */ constructPerStateBytes(450, 120, 340), 940 /* writtenBytes= */ constructPerStateBytes(7_000_000, 6000, 9000), 941 /* totalOveruses= */ 3))); 942 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 943 944 List<ResourceOveruseStats> expectedStats = Collections.singletonList( 945 constructResourceOveruseStats(1201278, "vendor_package.critical", 946 packageIoOveruseStats.get(1).ioOveruseStats)); 947 948 List<ResourceOveruseStats> actualStats = mCarWatchdogService.getAllResourceOveruseStats( 949 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 950 CarWatchdogManager.FLAG_MINIMUM_STATS_IO_1_MB, 951 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY); 952 953 ResourceOveruseStatsSubject.assertThat(actualStats) 954 .containsExactlyElementsIn(expectedStats); 955 956 verifyNoMoreInteractions(mMockWatchdogStorage); 957 } 958 959 @Test testGetAllResourceOveruseStatsWithMinimumForPast7days()960 public void testGetAllResourceOveruseStatsWithMinimumForPast7days() throws Exception { 961 injectPackageInfos(Arrays.asList( 962 constructPackageManagerPackageInfo("third_party_package", 1103456, null), 963 constructPackageManagerPackageInfo("vendor_package.critical", 1201278, null))); 964 965 List<PackageIoOveruseStats> packageIoOveruseStats = Arrays.asList( 966 constructPackageIoOveruseStats(1103456, 967 /* shouldNotify= */ true, 968 /* forgivenWriteBytes= */ constructPerStateBytes(80, 170, 260), 969 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 970 /* remainingWriteBytes= */ constructPerStateBytes(20, 20, 20), 971 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 972 /* totalOveruses= */ 3)), 973 constructPackageIoOveruseStats(1201278, 974 /* shouldNotify= */ false, 975 /* forgivenWriteBytes= */ constructPerStateBytes(0, 0, 0), 976 constructInternalIoOveruseStats(/* killableOnOveruse= */ false, 977 /* remainingWriteBytes= */ constructPerStateBytes(450, 120, 340), 978 /* writtenBytes= */ constructPerStateBytes(100_000, 6000, 9000), 979 /* totalOveruses= */ 0))); 980 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 981 982 ZonedDateTime now = mTimeSource.getCurrentDateTime(); 983 long startTime = now.minusDays(4).toEpochSecond(); 984 IoOveruseStats thirdPartyPkgOldStats = new IoOveruseStats.Builder( 985 startTime, now.toEpochSecond() - startTime).setTotalOveruses(5) 986 .setTotalTimesKilled(2).setTotalBytesWritten(24_000).build(); 987 when(mMockWatchdogStorage.getHistoricalIoOveruseStats(11, "third_party_package", 6)) 988 .thenReturn(thirdPartyPkgOldStats); 989 990 startTime = now.minusDays(6).toEpochSecond(); 991 IoOveruseStats vendorPkgOldStats = new IoOveruseStats.Builder( 992 startTime, now.toEpochSecond() - startTime).setTotalOveruses(2) 993 .setTotalTimesKilled(0).setTotalBytesWritten(6_900_000).build(); 994 when(mMockWatchdogStorage.getHistoricalIoOveruseStats(12, "vendor_package.critical", 6)) 995 .thenReturn(vendorPkgOldStats); 996 997 List<ResourceOveruseStats> actualStats = mCarWatchdogService.getAllResourceOveruseStats( 998 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 999 CarWatchdogManager.FLAG_MINIMUM_STATS_IO_1_MB, 1000 CarWatchdogManager.STATS_PERIOD_PAST_7_DAYS); 1001 1002 IoOveruseStats vendorIoStats = new IoOveruseStats.Builder( 1003 vendorPkgOldStats.getStartTime(), 1004 vendorPkgOldStats.getDurationInSeconds() + STATS_DURATION_SECONDS) 1005 .setKillableOnOveruse(false).setTotalOveruses(2).setTotalBytesWritten(7_015_000) 1006 .setTotalTimesKilled(0).setRemainingWriteBytes(new PerStateBytes(450, 120, 340)) 1007 .build(); 1008 1009 List<ResourceOveruseStats> expectedStats = Collections.singletonList( 1010 new ResourceOveruseStats.Builder("vendor_package.critical", new UserHandle(12)) 1011 .setIoOveruseStats(vendorIoStats).build()); 1012 1013 ResourceOveruseStatsSubject.assertThat(actualStats) 1014 .containsExactlyElementsIn(expectedStats); 1015 } 1016 1017 @Test testGetResourceOveruseStatsForUserPackage()1018 public void testGetResourceOveruseStatsForUserPackage() throws Exception { 1019 injectPackageInfos(Arrays.asList( 1020 constructPackageManagerPackageInfo("third_party_package", 1103456, null), 1021 constructPackageManagerPackageInfo("vendor_package.critical", 1201278, null))); 1022 1023 List<PackageIoOveruseStats> packageIoOveruseStats = Arrays.asList( 1024 constructPackageIoOveruseStats(1103456, 1025 /* shouldNotify= */ false, 1026 /* forgivenWriteBytes= */ constructPerStateBytes(80, 170, 260), 1027 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 1028 /* remainingWriteBytes= */ constructPerStateBytes(20, 20, 20), 1029 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 1030 /* totalOveruses= */ 3)), 1031 constructPackageIoOveruseStats(1201278, 1032 /* shouldNotify= */ false, 1033 /* forgivenWriteBytes= */ constructPerStateBytes(300, 400, 700), 1034 constructInternalIoOveruseStats(/* killableOnOveruse= */ false, 1035 /* remainingWriteBytes= */ constructPerStateBytes(450, 120, 340), 1036 /* writtenBytes= */ constructPerStateBytes(500, 600, 900), 1037 /* totalOveruses= */ 3))); 1038 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 1039 1040 ResourceOveruseStats expectedStats = 1041 constructResourceOveruseStats(1201278, "vendor_package.critical", 1042 packageIoOveruseStats.get(1).ioOveruseStats); 1043 1044 ResourceOveruseStats actualStats = 1045 mCarWatchdogService.getResourceOveruseStatsForUserPackage( 1046 "vendor_package.critical", new UserHandle(12), 1047 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 1048 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY); 1049 1050 ResourceOveruseStatsSubject.assertEquals(actualStats, expectedStats); 1051 } 1052 1053 @Test testGetResourceOveruseStatsForUserPackageForPast7days()1054 public void testGetResourceOveruseStatsForUserPackageForPast7days() throws Exception { 1055 injectPackageInfos(Arrays.asList( 1056 constructPackageManagerPackageInfo("third_party_package", 1103456, null), 1057 constructPackageManagerPackageInfo("vendor_package.critical", 1201278, null))); 1058 1059 List<PackageIoOveruseStats> packageIoOveruseStats = Arrays.asList( 1060 constructPackageIoOveruseStats(1103456, 1061 /* shouldNotify= */ false, 1062 /* forgivenWriteBytes= */ constructPerStateBytes(80, 170, 260), 1063 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 1064 /* remainingWriteBytes= */ constructPerStateBytes(20, 20, 20), 1065 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 1066 /* totalOveruses= */ 3)), 1067 constructPackageIoOveruseStats(1201278, 1068 /* shouldNotify= */ false, 1069 /* forgivenWriteBytes= */ constructPerStateBytes(300, 400, 700), 1070 constructInternalIoOveruseStats(/* killableOnOveruse= */ false, 1071 /* remainingWriteBytes= */ constructPerStateBytes(450, 120, 340), 1072 /* writtenBytes= */ constructPerStateBytes(500, 600, 900), 1073 /* totalOveruses= */ 3))); 1074 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 1075 1076 ZonedDateTime now = mTimeSource.getCurrentDateTime(); 1077 long startTime = now.minusDays(4).toEpochSecond(); 1078 IoOveruseStats vendorPkgOldStats = new IoOveruseStats.Builder( 1079 startTime, now.toEpochSecond() - startTime).setTotalOveruses(2) 1080 .setTotalTimesKilled(0).setTotalBytesWritten(6_900_000).build(); 1081 when(mMockWatchdogStorage.getHistoricalIoOveruseStats(12, "vendor_package.critical", 6)) 1082 .thenReturn(vendorPkgOldStats); 1083 1084 ResourceOveruseStats actualStats = 1085 mCarWatchdogService.getResourceOveruseStatsForUserPackage( 1086 "vendor_package.critical", new UserHandle(12), 1087 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 1088 CarWatchdogManager.STATS_PERIOD_PAST_7_DAYS); 1089 1090 IoOveruseStats vendorIoStats = new IoOveruseStats.Builder( 1091 vendorPkgOldStats.getStartTime(), 1092 vendorPkgOldStats.getDurationInSeconds() + STATS_DURATION_SECONDS) 1093 .setKillableOnOveruse(false).setTotalOveruses(5).setTotalBytesWritten(6_902_000) 1094 .setTotalTimesKilled(0).setRemainingWriteBytes(new PerStateBytes(450, 120, 340)) 1095 .build(); 1096 1097 ResourceOveruseStats expectedStats = new ResourceOveruseStats.Builder( 1098 "vendor_package.critical", new UserHandle(12)).setIoOveruseStats(vendorIoStats) 1099 .build(); 1100 1101 ResourceOveruseStatsSubject.assertEquals(actualStats, expectedStats); 1102 } 1103 1104 @Test testGetResourceOveruseStatsForUserPackageWithSharedUids()1105 public void testGetResourceOveruseStatsForUserPackageWithSharedUids() throws Exception { 1106 injectPackageInfos(Arrays.asList( 1107 constructPackageManagerPackageInfo( 1108 "third_party_package", 1103456, "vendor_shared_package"), 1109 constructPackageManagerPackageInfo( 1110 "vendor_package", 1103456, "vendor_shared_package"), 1111 constructPackageManagerPackageInfo("system_package", 1101100, 1112 "shared_system_package"))); 1113 1114 SparseArray<PackageIoOveruseStats> packageIoOveruseStatsByUid = 1115 injectIoOveruseStatsForPackages( 1116 mGenericPackageNameByUid, /* killablePackages= */ new ArraySet<>( 1117 Collections.singleton("shared:vendor_shared_package")), 1118 /* shouldNotifyPackages= */ new ArraySet<>()); 1119 1120 ResourceOveruseStats expectedStats = 1121 constructResourceOveruseStats(1103456, "shared:vendor_shared_package", 1122 packageIoOveruseStatsByUid.get(1103456).ioOveruseStats); 1123 1124 ResourceOveruseStats actualStats = 1125 mCarWatchdogService.getResourceOveruseStatsForUserPackage( 1126 "vendor_package", new UserHandle(11), 1127 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 1128 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY); 1129 1130 ResourceOveruseStatsSubject.assertEquals(actualStats, expectedStats); 1131 } 1132 1133 @Test testFailsGetResourceOveruseStatsForUserPackageWithInvalidArgs()1134 public void testFailsGetResourceOveruseStatsForUserPackageWithInvalidArgs() throws Exception { 1135 assertThrows(NullPointerException.class, 1136 () -> mCarWatchdogService.getResourceOveruseStatsForUserPackage( 1137 /* packageName= */ null, new UserHandle(10), 1138 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 1139 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY)); 1140 1141 assertThrows(NullPointerException.class, 1142 () -> mCarWatchdogService.getResourceOveruseStatsForUserPackage("some.package", 1143 /* userHandle= */ null, CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 1144 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY)); 1145 1146 assertThrows(IllegalArgumentException.class, 1147 () -> mCarWatchdogService.getResourceOveruseStatsForUserPackage("some.package", 1148 UserHandle.ALL, CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 1149 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY)); 1150 1151 assertThrows(IllegalArgumentException.class, 1152 () -> mCarWatchdogService.getResourceOveruseStatsForUserPackage("some.package", 1153 new UserHandle(10), /* resourceOveruseFlag= */ 0, 1154 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY)); 1155 1156 assertThrows(IllegalArgumentException.class, 1157 () -> mCarWatchdogService.getResourceOveruseStatsForUserPackage("some.package", 1158 new UserHandle(10), CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 1159 /* maxStatsPeriod= */ 0)); 1160 } 1161 1162 @Test testAddResourceOveruseListenerThrowsWithInvalidFlag()1163 public void testAddResourceOveruseListenerThrowsWithInvalidFlag() throws Exception { 1164 IResourceOveruseListener mockListener = createMockResourceOveruseListener(); 1165 assertThrows(IllegalArgumentException.class, () -> { 1166 mCarWatchdogService.addResourceOveruseListener(0, mockListener); 1167 }); 1168 } 1169 1170 @Test testResourceOveruseListener()1171 public void testResourceOveruseListener() throws Exception { 1172 mGenericPackageNameByUid.put(Binder.getCallingUid(), mMockContext.getPackageName()); 1173 1174 IResourceOveruseListener mockListener = createMockResourceOveruseListener(); 1175 IBinder mockBinder = mockListener.asBinder(); 1176 1177 mCarWatchdogService.addResourceOveruseListener(CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 1178 mockListener); 1179 1180 verify(mockBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 1181 1182 injectIoOveruseStatsForPackages( 1183 mGenericPackageNameByUid, /* killablePackages= */ new ArraySet<>(), 1184 /* shouldNotifyPackages= */ new ArraySet<>( 1185 Collections.singleton(mMockContext.getPackageName()))); 1186 1187 verify(mockListener).onOveruse(any()); 1188 1189 mCarWatchdogService.removeResourceOveruseListener(mockListener); 1190 1191 verify(mockListener, atLeastOnce()).asBinder(); 1192 verify(mockBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 1193 1194 injectIoOveruseStatsForPackages( 1195 mGenericPackageNameByUid, /* killablePackages= */ new ArraySet<>(), 1196 /* shouldNotifyPackages= */ new ArraySet<>( 1197 Collections.singletonList(mMockContext.getPackageName()))); 1198 1199 verifyNoMoreInteractions(mockListener); 1200 } 1201 1202 @Test testDuplicateAddResourceOveruseListener()1203 public void testDuplicateAddResourceOveruseListener() throws Exception { 1204 mGenericPackageNameByUid.put(Binder.getCallingUid(), mMockContext.getPackageName()); 1205 1206 IResourceOveruseListener mockListener = createMockResourceOveruseListener(); 1207 IBinder mockBinder = mockListener.asBinder(); 1208 1209 mCarWatchdogService.addResourceOveruseListener(CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 1210 mockListener); 1211 1212 assertThrows(IllegalStateException.class, 1213 () -> mCarWatchdogService.addResourceOveruseListener( 1214 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, mockListener)); 1215 1216 verify(mockBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 1217 1218 mCarWatchdogService.removeResourceOveruseListener(mockListener); 1219 1220 verify(mockListener, atLeastOnce()).asBinder(); 1221 verify(mockBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 1222 1223 verifyNoMoreInteractions(mockListener); 1224 } 1225 1226 @Test testAddMultipleResourceOveruseListeners()1227 public void testAddMultipleResourceOveruseListeners() throws Exception { 1228 mGenericPackageNameByUid.put(Binder.getCallingUid(), mMockContext.getPackageName()); 1229 1230 IResourceOveruseListener firstMockListener = createMockResourceOveruseListener(); 1231 IBinder firstMockBinder = firstMockListener.asBinder(); 1232 IResourceOveruseListener secondMockListener = createMockResourceOveruseListener(); 1233 IBinder secondMockBinder = secondMockListener.asBinder(); 1234 1235 mCarWatchdogService.addResourceOveruseListener(CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 1236 firstMockListener); 1237 mCarWatchdogService.addResourceOveruseListener(CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 1238 secondMockListener); 1239 1240 verify(firstMockBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 1241 verify(secondMockBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 1242 1243 injectIoOveruseStatsForPackages( 1244 mGenericPackageNameByUid, /* killablePackages= */ new ArraySet<>(), 1245 /* shouldNotifyPackages= */ new ArraySet<>( 1246 Collections.singleton(mMockContext.getPackageName()))); 1247 1248 verify(firstMockListener).onOveruse(any()); 1249 1250 mCarWatchdogService.removeResourceOveruseListener(firstMockListener); 1251 1252 verify(firstMockListener, atLeastOnce()).asBinder(); 1253 verify(firstMockBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 1254 1255 injectIoOveruseStatsForPackages( 1256 mGenericPackageNameByUid, /* killablePackages= */ new ArraySet<>(), 1257 /* shouldNotifyPackages= */ new ArraySet<>( 1258 Collections.singletonList(mMockContext.getPackageName()))); 1259 1260 verify(secondMockListener, times(2)).onOveruse(any()); 1261 1262 mCarWatchdogService.removeResourceOveruseListener(secondMockListener); 1263 1264 verify(secondMockListener, atLeastOnce()).asBinder(); 1265 verify(secondMockBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 1266 1267 injectIoOveruseStatsForPackages( 1268 mGenericPackageNameByUid, /* killablePackages= */ new ArraySet<>(), 1269 /* shouldNotifyPackages= */ new ArraySet<>( 1270 Collections.singletonList(mMockContext.getPackageName()))); 1271 1272 verifyNoMoreInteractions(firstMockListener); 1273 verifyNoMoreInteractions(secondMockListener); 1274 } 1275 1276 @Test testAddResourceOveruseListenerForSystemThrowsWithInvalidFlag()1277 public void testAddResourceOveruseListenerForSystemThrowsWithInvalidFlag() throws Exception { 1278 IResourceOveruseListener mockListener = createMockResourceOveruseListener(); 1279 assertThrows(IllegalArgumentException.class, () -> { 1280 mCarWatchdogService.addResourceOveruseListenerForSystem(0, mockListener); 1281 }); 1282 } 1283 1284 @Test testResourceOveruseListenerForSystem()1285 public void testResourceOveruseListenerForSystem() throws Exception { 1286 int callingUid = Binder.getCallingUid(); 1287 mGenericPackageNameByUid.put(callingUid, "system_package.critical"); 1288 1289 IResourceOveruseListener mockListener = createMockResourceOveruseListener(); 1290 mCarWatchdogService.addResourceOveruseListenerForSystem( 1291 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, mockListener); 1292 1293 IBinder mockBinder = mockListener.asBinder(); 1294 verify(mockBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 1295 1296 List<PackageIoOveruseStats> packageIoOveruseStats = Collections.singletonList( 1297 constructPackageIoOveruseStats(callingUid, /* shouldNotify= */ true, 1298 /* forgivenWriteBytes= */ constructPerStateBytes(80, 170, 260), 1299 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 1300 /* remainingWriteBytes= */ constructPerStateBytes(20, 20, 20), 1301 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 1302 /* totalOveruses= */ 3))); 1303 1304 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 1305 1306 verify(mockListener).onOveruse(any()); 1307 1308 mCarWatchdogService.removeResourceOveruseListenerForSystem(mockListener); 1309 1310 verify(mockListener, atLeastOnce()).asBinder(); 1311 verify(mockBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 1312 1313 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 1314 1315 verifyNoMoreInteractions(mockListener); 1316 } 1317 1318 @Test testSetKillablePackageAsUser()1319 public void testSetKillablePackageAsUser() throws Exception { 1320 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12); 1321 injectPackageInfos(Arrays.asList( 1322 constructPackageManagerPackageInfo("third_party_package", 1103456, null), 1323 constructPackageManagerPackageInfo("vendor_package.critical", 1101278, null), 1324 constructPackageManagerPackageInfo("third_party_package", 1203456, null), 1325 constructPackageManagerPackageInfo("vendor_package.critical", 1201278, null))); 1326 1327 UserHandle userHandle = new UserHandle(11); 1328 mCarWatchdogService.setKillablePackageAsUser("third_party_package", userHandle, 1329 /* isKillable= */ false); 1330 mCarWatchdogService.setKillablePackageAsUser("vendor_package.critical", 1331 userHandle, /* isKillable= */ false); 1332 1333 PackageKillableStateSubject.assertThat( 1334 mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL)).containsExactly( 1335 new PackageKillableState("third_party_package", 11, 1336 PackageKillableState.KILLABLE_STATE_NO), 1337 new PackageKillableState("vendor_package.critical", 11, 1338 PackageKillableState.KILLABLE_STATE_NEVER), 1339 new PackageKillableState("third_party_package", 12, 1340 PackageKillableState.KILLABLE_STATE_YES), 1341 new PackageKillableState("vendor_package.critical", 12, 1342 PackageKillableState.KILLABLE_STATE_NEVER)); 1343 1344 assertThrows(IllegalArgumentException.class, 1345 () -> mCarWatchdogService.setKillablePackageAsUser("vendor_package.critical", 1346 userHandle, /* isKillable= */ true)); 1347 1348 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12, 13); 1349 injectPackageInfos(Collections.singletonList( 1350 constructPackageManagerPackageInfo("third_party_package", 1303456, null))); 1351 1352 PackageKillableStateSubject.assertThat( 1353 mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL)).containsExactly( 1354 new PackageKillableState("third_party_package", 11, 1355 PackageKillableState.KILLABLE_STATE_NO), 1356 new PackageKillableState("vendor_package.critical", 11, 1357 PackageKillableState.KILLABLE_STATE_NEVER), 1358 new PackageKillableState("third_party_package", 12, 1359 PackageKillableState.KILLABLE_STATE_YES), 1360 new PackageKillableState("vendor_package.critical", 12, 1361 PackageKillableState.KILLABLE_STATE_NEVER), 1362 new PackageKillableState("third_party_package", 13, 1363 PackageKillableState.KILLABLE_STATE_YES)); 1364 } 1365 1366 @Test testSetKillablePackageAsUserWithSharedUids()1367 public void testSetKillablePackageAsUserWithSharedUids() throws Exception { 1368 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12); 1369 injectPackageInfos(Arrays.asList( 1370 constructPackageManagerPackageInfo( 1371 "third_party_package.A", 1103456, "third_party_shared_package.A"), 1372 constructPackageManagerPackageInfo( 1373 "third_party_package.B", 1103456, "third_party_shared_package.A"), 1374 constructPackageManagerPackageInfo( 1375 "third_party_package.C", 1101356, "third_party_shared_package.B"), 1376 constructPackageManagerPackageInfo( 1377 "third_party_package.D", 1101356, "third_party_shared_package.B"))); 1378 1379 UserHandle userHandle = new UserHandle(11); 1380 mCarWatchdogService.setKillablePackageAsUser("third_party_package.A", userHandle, 1381 /* isKillable= */ false); 1382 1383 PackageKillableStateSubject.assertThat( 1384 mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL)).containsExactly( 1385 new PackageKillableState("third_party_package.A", 11, 1386 PackageKillableState.KILLABLE_STATE_NO), 1387 new PackageKillableState("third_party_package.B", 11, 1388 PackageKillableState.KILLABLE_STATE_NO), 1389 new PackageKillableState("third_party_package.C", 11, 1390 PackageKillableState.KILLABLE_STATE_YES), 1391 new PackageKillableState("third_party_package.D", 11, 1392 PackageKillableState.KILLABLE_STATE_YES)); 1393 1394 mCarWatchdogService.setKillablePackageAsUser("third_party_package.B", userHandle, 1395 /* isKillable= */ true); 1396 mCarWatchdogService.setKillablePackageAsUser("third_party_package.C", userHandle, 1397 /* isKillable= */ false); 1398 1399 PackageKillableStateSubject.assertThat( 1400 mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL)).containsExactly( 1401 new PackageKillableState("third_party_package.A", 11, 1402 PackageKillableState.KILLABLE_STATE_YES), 1403 new PackageKillableState("third_party_package.B", 11, 1404 PackageKillableState.KILLABLE_STATE_YES), 1405 new PackageKillableState("third_party_package.C", 11, 1406 PackageKillableState.KILLABLE_STATE_NO), 1407 new PackageKillableState("third_party_package.D", 11, 1408 PackageKillableState.KILLABLE_STATE_NO)); 1409 } 1410 1411 @Test testSetKillablePackageAsUserForAllUsers()1412 public void testSetKillablePackageAsUserForAllUsers() throws Exception { 1413 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12); 1414 injectPackageInfos(Arrays.asList( 1415 constructPackageManagerPackageInfo("third_party_package", 1103456, null), 1416 constructPackageManagerPackageInfo("vendor_package.critical", 1101278, null), 1417 constructPackageManagerPackageInfo("third_party_package", 1203456, null), 1418 constructPackageManagerPackageInfo("vendor_package.critical", 1201278, null))); 1419 1420 mCarWatchdogService.setKillablePackageAsUser("third_party_package", UserHandle.ALL, 1421 /* isKillable= */ false); 1422 mCarWatchdogService.setKillablePackageAsUser("vendor_package.critical", 1423 UserHandle.ALL, /* isKillable= */ false); 1424 1425 PackageKillableStateSubject.assertThat( 1426 mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL)).containsExactly( 1427 new PackageKillableState("third_party_package", 11, 1428 PackageKillableState.KILLABLE_STATE_NO), 1429 new PackageKillableState("vendor_package.critical", 11, 1430 PackageKillableState.KILLABLE_STATE_NEVER), 1431 new PackageKillableState("third_party_package", 12, 1432 PackageKillableState.KILLABLE_STATE_NO), 1433 new PackageKillableState("vendor_package.critical", 12, 1434 PackageKillableState.KILLABLE_STATE_NEVER)); 1435 1436 assertThrows(IllegalArgumentException.class, 1437 () -> mCarWatchdogService.setKillablePackageAsUser("vendor_package.critical", 1438 UserHandle.ALL, /* isKillable= */ true)); 1439 1440 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12, 13); 1441 injectPackageInfos(Collections.singletonList( 1442 constructPackageManagerPackageInfo("third_party_package", 1303456, null))); 1443 1444 PackageKillableStateSubject.assertThat( 1445 mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL)).containsExactly( 1446 new PackageKillableState("third_party_package", 11, 1447 PackageKillableState.KILLABLE_STATE_NO), 1448 new PackageKillableState("vendor_package.critical", 11, 1449 PackageKillableState.KILLABLE_STATE_NEVER), 1450 new PackageKillableState("third_party_package", 12, 1451 PackageKillableState.KILLABLE_STATE_NO), 1452 new PackageKillableState("vendor_package.critical", 12, 1453 PackageKillableState.KILLABLE_STATE_NEVER), 1454 new PackageKillableState("third_party_package", 13, 1455 PackageKillableState.KILLABLE_STATE_NO)); 1456 } 1457 1458 @Test testSetKillablePackageAsUsersForAllUsersWithSharedUids()1459 public void testSetKillablePackageAsUsersForAllUsersWithSharedUids() throws Exception { 1460 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12); 1461 injectPackageInfos(Arrays.asList( 1462 constructPackageManagerPackageInfo( 1463 "third_party_package.A", 1103456, "third_party_shared_package.A"), 1464 constructPackageManagerPackageInfo( 1465 "third_party_package.B", 1103456, "third_party_shared_package.A"), 1466 constructPackageManagerPackageInfo( 1467 "third_party_package.C", 1101356, "third_party_shared_package.B"), 1468 constructPackageManagerPackageInfo( 1469 "third_party_package.D", 1101356, "third_party_shared_package.B"), 1470 constructPackageManagerPackageInfo( 1471 "third_party_package.A", 1203456, "third_party_shared_package.A"), 1472 constructPackageManagerPackageInfo( 1473 "third_party_package.B", 1203456, "third_party_shared_package.A"))); 1474 1475 mCarWatchdogService.setKillablePackageAsUser("third_party_package.A", UserHandle.ALL, 1476 /* isKillable= */ false); 1477 1478 PackageKillableStateSubject.assertThat( 1479 mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL)).containsExactly( 1480 new PackageKillableState("third_party_package.A", 11, 1481 PackageKillableState.KILLABLE_STATE_NO), 1482 new PackageKillableState("third_party_package.B", 11, 1483 PackageKillableState.KILLABLE_STATE_NO), 1484 new PackageKillableState("third_party_package.C", 11, 1485 PackageKillableState.KILLABLE_STATE_YES), 1486 new PackageKillableState("third_party_package.D", 11, 1487 PackageKillableState.KILLABLE_STATE_YES), 1488 new PackageKillableState("third_party_package.A", 12, 1489 PackageKillableState.KILLABLE_STATE_NO), 1490 new PackageKillableState("third_party_package.B", 12, 1491 PackageKillableState.KILLABLE_STATE_NO)); 1492 1493 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12, 13); 1494 injectPackageInfos(Arrays.asList( 1495 constructPackageManagerPackageInfo( 1496 "third_party_package.A", 1303456, "third_party_shared_package.A"), 1497 constructPackageManagerPackageInfo( 1498 "third_party_package.B", 1303456, "third_party_shared_package.A"))); 1499 1500 PackageKillableStateSubject.assertThat( 1501 mCarWatchdogService.getPackageKillableStatesAsUser(new UserHandle(13))) 1502 .containsExactly( 1503 new PackageKillableState("third_party_package.A", 13, 1504 PackageKillableState.KILLABLE_STATE_NO), 1505 new PackageKillableState("third_party_package.B", 13, 1506 PackageKillableState.KILLABLE_STATE_NO)); 1507 } 1508 1509 @Test testGetPackageKillableStatesAsUser()1510 public void testGetPackageKillableStatesAsUser() throws Exception { 1511 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12); 1512 injectPackageInfos(Arrays.asList( 1513 constructPackageManagerPackageInfo("third_party_package", 1103456, null), 1514 constructPackageManagerPackageInfo("vendor_package.critical", 1101278, null), 1515 constructPackageManagerPackageInfo("third_party_package", 1203456, null), 1516 constructPackageManagerPackageInfo("vendor_package.critical", 1201278, null))); 1517 1518 PackageKillableStateSubject.assertThat( 1519 mCarWatchdogService.getPackageKillableStatesAsUser(new UserHandle(11))) 1520 .containsExactly( 1521 new PackageKillableState("third_party_package", 11, 1522 PackageKillableState.KILLABLE_STATE_YES), 1523 new PackageKillableState("vendor_package.critical", 11, 1524 PackageKillableState.KILLABLE_STATE_NEVER)); 1525 } 1526 1527 @Test testGetPackageKillableStatesAsUserWithSafeToKillPackages()1528 public void testGetPackageKillableStatesAsUserWithSafeToKillPackages() throws Exception { 1529 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 100, 101); 1530 injectPackageInfos(Arrays.asList( 1531 constructPackageManagerPackageInfo("system_package.non_critical.A", 10002459, null), 1532 constructPackageManagerPackageInfo("third_party_package", 10003456, null), 1533 constructPackageManagerPackageInfo("vendor_package.critical.B", 10001278, null), 1534 constructPackageManagerPackageInfo("vendor_package.non_critical.A", 10005573, null), 1535 constructPackageManagerPackageInfo("third_party_package", 10103456, null), 1536 constructPackageManagerPackageInfo("vendor_package.critical.B", 10101278, null))); 1537 1538 PackageKillableStateSubject.assertThat( 1539 mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL)) 1540 .containsExactly( 1541 new PackageKillableState("system_package.non_critical.A", 100, 1542 PackageKillableState.KILLABLE_STATE_YES), 1543 new PackageKillableState("third_party_package", 100, 1544 PackageKillableState.KILLABLE_STATE_YES), 1545 new PackageKillableState("vendor_package.critical.B", 100, 1546 PackageKillableState.KILLABLE_STATE_NEVER), 1547 new PackageKillableState("vendor_package.non_critical.A", 100, 1548 PackageKillableState.KILLABLE_STATE_YES), 1549 new PackageKillableState("third_party_package", 101, 1550 PackageKillableState.KILLABLE_STATE_YES), 1551 new PackageKillableState("vendor_package.critical.B", 101, 1552 PackageKillableState.KILLABLE_STATE_NEVER)); 1553 } 1554 1555 @Test testGetPackageKillableStatesAsUserWithVendorPackagePrefixes()1556 public void testGetPackageKillableStatesAsUserWithVendorPackagePrefixes() throws Exception { 1557 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 100); 1558 injectPackageInfos(Collections.singletonList(constructPackageManagerPackageInfo( 1559 "some_pkg_as_vendor_pkg", 10002459, /* sharedUserId= */ null, /* flags= */ 0, 1560 ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT))); 1561 1562 List<PackageKillableState> killableStates = 1563 mCarWatchdogService.getPackageKillableStatesAsUser(new UserHandle(100)); 1564 1565 // The vendor package prefixes in the resource overuse configs help identify vendor 1566 // packages. The safe-to-kill list in the vendor configs helps identify safe-to-kill vendor 1567 // packages. |system_package_as_vendor| is a critical system package by default but with 1568 // the resource overuse configs, this package should be classified as a safe-to-kill vendor 1569 // package. 1570 PackageKillableStateSubject.assertThat(killableStates) 1571 .containsExactly(new PackageKillableState("some_pkg_as_vendor_pkg", 100, 1572 PackageKillableState.KILLABLE_STATE_YES)); 1573 } 1574 1575 @Test testGetPackageKillableStatesAsUserWithSharedUids()1576 public void testGetPackageKillableStatesAsUserWithSharedUids() throws Exception { 1577 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12); 1578 injectPackageInfos(Arrays.asList( 1579 constructPackageManagerPackageInfo( 1580 "system_package.A", 1103456, "vendor_shared_package.A"), 1581 constructPackageManagerPackageInfo( 1582 "vendor_package.B", 1103456, "vendor_shared_package.A"), 1583 constructPackageManagerPackageInfo( 1584 "third_party_package.C", 1105678, "third_party_shared_package"), 1585 constructPackageManagerPackageInfo( 1586 "third_party_package.D", 1105678, "third_party_shared_package"), 1587 constructPackageManagerPackageInfo( 1588 "system_package.A", 1203456, "vendor_shared_package.A"), 1589 constructPackageManagerPackageInfo( 1590 "vendor_package.B", 1203456, "vendor_shared_package.A"))); 1591 1592 PackageKillableStateSubject.assertThat( 1593 mCarWatchdogService.getPackageKillableStatesAsUser(new UserHandle(11))) 1594 .containsExactly( 1595 new PackageKillableState("system_package.A", 11, 1596 PackageKillableState.KILLABLE_STATE_NEVER), 1597 new PackageKillableState("vendor_package.B", 11, 1598 PackageKillableState.KILLABLE_STATE_NEVER), 1599 new PackageKillableState("third_party_package.C", 11, 1600 PackageKillableState.KILLABLE_STATE_YES), 1601 new PackageKillableState("third_party_package.D", 11, 1602 PackageKillableState.KILLABLE_STATE_YES)); 1603 } 1604 1605 @Test testGetPackageKillableStatesAsUserWithSharedUidsAndSafeToKillPackages()1606 public void testGetPackageKillableStatesAsUserWithSharedUidsAndSafeToKillPackages() 1607 throws Exception { 1608 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 100); 1609 injectPackageInfos(Arrays.asList( 1610 constructPackageManagerPackageInfo( 1611 "vendor_package.non_critical.A", 10003456, "vendor_shared_package.A"), 1612 constructPackageManagerPackageInfo( 1613 "system_package.A", 10003456, "vendor_shared_package.A"), 1614 constructPackageManagerPackageInfo( 1615 "vendor_package.B", 10003456, "vendor_shared_package.A"), 1616 constructPackageManagerPackageInfo( 1617 "third_party_package.C", 10005678, "third_party_shared_package"), 1618 constructPackageManagerPackageInfo( 1619 "third_party_package.D", 10005678, "third_party_shared_package"))); 1620 1621 PackageKillableStateSubject.assertThat( 1622 mCarWatchdogService.getPackageKillableStatesAsUser(new UserHandle(100))) 1623 .containsExactly( 1624 new PackageKillableState("vendor_package.non_critical.A", 100, 1625 PackageKillableState.KILLABLE_STATE_YES), 1626 new PackageKillableState("system_package.A", 100, 1627 PackageKillableState.KILLABLE_STATE_YES), 1628 new PackageKillableState("vendor_package.B", 100, 1629 PackageKillableState.KILLABLE_STATE_YES), 1630 new PackageKillableState("third_party_package.C", 100, 1631 PackageKillableState.KILLABLE_STATE_YES), 1632 new PackageKillableState("third_party_package.D", 100, 1633 PackageKillableState.KILLABLE_STATE_YES)); 1634 } 1635 1636 @Test testGetPackageKillableStatesAsUserWithSharedUidsAndSafeToKillSharedPackage()1637 public void testGetPackageKillableStatesAsUserWithSharedUidsAndSafeToKillSharedPackage() 1638 throws Exception { 1639 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 100); 1640 injectPackageInfos(Arrays.asList( 1641 constructPackageManagerPackageInfo( 1642 "vendor_package.A", 10003456, "vendor_shared_package.non_critical.B"), 1643 constructPackageManagerPackageInfo( 1644 "system_package.A", 10003456, "vendor_shared_package.non_critical.B"), 1645 constructPackageManagerPackageInfo( 1646 "vendor_package.B", 10003456, "vendor_shared_package.non_critical.B"))); 1647 1648 1649 PackageKillableStateSubject.assertThat( 1650 mCarWatchdogService.getPackageKillableStatesAsUser(new UserHandle(100))) 1651 .containsExactly( 1652 new PackageKillableState("vendor_package.A", 100, 1653 PackageKillableState.KILLABLE_STATE_YES), 1654 new PackageKillableState("system_package.A", 100, 1655 PackageKillableState.KILLABLE_STATE_YES), 1656 new PackageKillableState("vendor_package.B", 100, 1657 PackageKillableState.KILLABLE_STATE_YES)); 1658 } 1659 1660 @Test testGetPackageKillableStatesAsUserForAllUsers()1661 public void testGetPackageKillableStatesAsUserForAllUsers() throws Exception { 1662 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12); 1663 injectPackageInfos(Arrays.asList( 1664 constructPackageManagerPackageInfo("third_party_package", 1103456, null), 1665 constructPackageManagerPackageInfo("vendor_package.critical", 1101278, null), 1666 constructPackageManagerPackageInfo("third_party_package", 1203456, null), 1667 constructPackageManagerPackageInfo("vendor_package.critical", 1201278, null))); 1668 1669 PackageKillableStateSubject.assertThat( 1670 mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL)).containsExactly( 1671 new PackageKillableState("third_party_package", 11, 1672 PackageKillableState.KILLABLE_STATE_YES), 1673 new PackageKillableState("vendor_package.critical", 11, 1674 PackageKillableState.KILLABLE_STATE_NEVER), 1675 new PackageKillableState("third_party_package", 12, 1676 PackageKillableState.KILLABLE_STATE_YES), 1677 new PackageKillableState("vendor_package.critical", 12, 1678 PackageKillableState.KILLABLE_STATE_NEVER)); 1679 } 1680 1681 @Test testGetPackageKillableStatesAsUserForAllUsersWithSharedUids()1682 public void testGetPackageKillableStatesAsUserForAllUsersWithSharedUids() throws Exception { 1683 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 11, 12); 1684 injectPackageInfos(Arrays.asList( 1685 constructPackageManagerPackageInfo( 1686 "system_package.A", 1103456, "vendor_shared_package.A"), 1687 constructPackageManagerPackageInfo( 1688 "vendor_package.B", 1103456, "vendor_shared_package.A"), 1689 constructPackageManagerPackageInfo( 1690 "third_party_package.C", 1105678, "third_party_shared_package"), 1691 constructPackageManagerPackageInfo( 1692 "third_party_package.D", 1105678, "third_party_shared_package"), 1693 constructPackageManagerPackageInfo( 1694 "system_package.A", 1203456, "vendor_shared_package.A"), 1695 constructPackageManagerPackageInfo( 1696 "vendor_package.B", 1203456, "vendor_shared_package.A"))); 1697 1698 PackageKillableStateSubject.assertThat( 1699 mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL)) 1700 .containsExactly( 1701 new PackageKillableState("system_package.A", 11, 1702 PackageKillableState.KILLABLE_STATE_NEVER), 1703 new PackageKillableState("vendor_package.B", 11, 1704 PackageKillableState.KILLABLE_STATE_NEVER), 1705 new PackageKillableState("third_party_package.C", 11, 1706 PackageKillableState.KILLABLE_STATE_YES), 1707 new PackageKillableState("third_party_package.D", 11, 1708 PackageKillableState.KILLABLE_STATE_YES), 1709 new PackageKillableState("system_package.A", 12, 1710 PackageKillableState.KILLABLE_STATE_NEVER), 1711 new PackageKillableState("vendor_package.B", 12, 1712 PackageKillableState.KILLABLE_STATE_NEVER)); 1713 } 1714 1715 @Test testSetResourceOveruseConfigurations()1716 public void testSetResourceOveruseConfigurations() throws Exception { 1717 assertThat(mCarWatchdogService.setResourceOveruseConfigurations( 1718 sampleResourceOveruseConfigurations(), CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)) 1719 .isEqualTo(CarWatchdogManager.RETURN_CODE_SUCCESS); 1720 1721 InternalResourceOveruseConfigurationSubject 1722 .assertThat(captureOnSetResourceOveruseConfigurations()) 1723 .containsExactlyElementsIn(sampleInternalResourceOveruseConfigurations()); 1724 1725 // CarService fetches and syncs resource overuse configuration on the main thread by posting 1726 // a new message. Wait until this completes. 1727 CarServiceUtils.runOnMainSync(() -> {}); 1728 1729 /* Expect two calls, the first is made at car watchdog service init */ 1730 verify(mMockCarWatchdogDaemon, times(2)).getResourceOveruseConfigurations(); 1731 } 1732 1733 @Test testSetResourceOveruseConfigurationsRetriedWithDisconnectedDaemon()1734 public void testSetResourceOveruseConfigurationsRetriedWithDisconnectedDaemon() 1735 throws Exception { 1736 crashWatchdogDaemon(); 1737 1738 assertThat(mCarWatchdogService.setResourceOveruseConfigurations( 1739 sampleResourceOveruseConfigurations(), CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)) 1740 .isEqualTo(CarWatchdogManager.RETURN_CODE_SUCCESS); 1741 1742 restartWatchdogDaemonAndAwait(); 1743 1744 InternalResourceOveruseConfigurationSubject 1745 .assertThat(captureOnSetResourceOveruseConfigurations()) 1746 .containsExactlyElementsIn(sampleInternalResourceOveruseConfigurations()); 1747 } 1748 1749 @Test testSetResourceOveruseConfigurationsRetriedWithRepeatedRemoteException()1750 public void testSetResourceOveruseConfigurationsRetriedWithRepeatedRemoteException() 1751 throws Exception { 1752 CountDownLatch crashLatch = new CountDownLatch(2); 1753 doAnswer(args -> { 1754 crashWatchdogDaemon(); 1755 crashLatch.countDown(); 1756 throw new RemoteException(); 1757 }).when(mMockCarWatchdogDaemon).updateResourceOveruseConfigurations(anyList()); 1758 1759 assertThat(mCarWatchdogService.setResourceOveruseConfigurations( 1760 sampleResourceOveruseConfigurations(), CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)) 1761 .isEqualTo(CarWatchdogManager.RETURN_CODE_SUCCESS); 1762 1763 restartWatchdogDaemonAndAwait(); 1764 1765 /* 1766 * Wait until the daemon is crashed again during the latest 1767 * updateResourceOveruseConfigurations call so the test is deterministic. 1768 */ 1769 crashLatch.await(MAX_WAIT_TIME_MS, TimeUnit.MILLISECONDS); 1770 1771 /* The below final restart should set the resource overuse configurations successfully. */ 1772 List<android.automotive.watchdog.internal.ResourceOveruseConfiguration> actualConfigs = 1773 new ArrayList<>(); 1774 doAnswer(args -> { 1775 List<android.automotive.watchdog.internal.ResourceOveruseConfiguration> configs = 1776 args.getArgument(0); 1777 synchronized (actualConfigs) { 1778 actualConfigs.addAll(configs); 1779 actualConfigs.notify(); 1780 } 1781 return null; 1782 }).when(mMockCarWatchdogDaemon).updateResourceOveruseConfigurations(anyList()); 1783 1784 restartWatchdogDaemonAndAwait(); 1785 1786 /* Wait until latest updateResourceOveruseConfigurations call is issued on reconnection. */ 1787 synchronized (actualConfigs) { 1788 actualConfigs.wait(MAX_WAIT_TIME_MS); 1789 InternalResourceOveruseConfigurationSubject.assertThat(actualConfigs) 1790 .containsExactlyElementsIn(sampleInternalResourceOveruseConfigurations()); 1791 } 1792 1793 verify(mMockCarWatchdogDaemon, times(3)).updateResourceOveruseConfigurations(anyList()); 1794 } 1795 1796 @Test testFailsSetResourceOveruseConfigurationsWithPendingRequest()1797 public void testFailsSetResourceOveruseConfigurationsWithPendingRequest() 1798 throws Exception { 1799 crashWatchdogDaemon(); 1800 1801 assertThat(mCarWatchdogService.setResourceOveruseConfigurations( 1802 sampleResourceOveruseConfigurations(), CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)) 1803 .isEqualTo(CarWatchdogManager.RETURN_CODE_SUCCESS); 1804 1805 assertThrows(IllegalStateException.class, 1806 () -> mCarWatchdogService.setResourceOveruseConfigurations( 1807 sampleResourceOveruseConfigurations(), 1808 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)); 1809 } 1810 1811 @Test testFailsSetResourceOveruseConfigurationsOnInvalidArgs()1812 public void testFailsSetResourceOveruseConfigurationsOnInvalidArgs() throws Exception { 1813 assertThrows(NullPointerException.class, 1814 () -> mCarWatchdogService.setResourceOveruseConfigurations(null, 1815 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)); 1816 1817 assertThrows(IllegalArgumentException.class, 1818 () -> mCarWatchdogService.setResourceOveruseConfigurations(new ArrayList<>(), 1819 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)); 1820 1821 List<ResourceOveruseConfiguration> resourceOveruseConfigs = Collections.singletonList( 1822 sampleResourceOveruseConfigurationBuilder(ComponentType.SYSTEM, 1823 sampleIoOveruseConfigurationBuilder(ComponentType.SYSTEM).build()) 1824 .build()); 1825 assertThrows(IllegalArgumentException.class, 1826 () -> mCarWatchdogService.setResourceOveruseConfigurations(resourceOveruseConfigs, 1827 0)); 1828 } 1829 1830 @Test testFailsSetResourceOveruseConfigurationsOnDuplicateComponents()1831 public void testFailsSetResourceOveruseConfigurationsOnDuplicateComponents() throws Exception { 1832 ResourceOveruseConfiguration config = 1833 sampleResourceOveruseConfigurationBuilder(ComponentType.SYSTEM, 1834 sampleIoOveruseConfigurationBuilder(ComponentType.SYSTEM).build()).build(); 1835 List<ResourceOveruseConfiguration> resourceOveruseConfigs = Arrays.asList(config, config); 1836 assertThrows(IllegalArgumentException.class, 1837 () -> mCarWatchdogService.setResourceOveruseConfigurations(resourceOveruseConfigs, 1838 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)); 1839 } 1840 1841 @Test testFailsSetResourceOveruseConfigurationsOnZeroComponentLevelIoOveruseThresholds()1842 public void testFailsSetResourceOveruseConfigurationsOnZeroComponentLevelIoOveruseThresholds() 1843 throws Exception { 1844 List<ResourceOveruseConfiguration> resourceOveruseConfigs = 1845 Collections.singletonList( 1846 sampleResourceOveruseConfigurationBuilder(ComponentType.SYSTEM, 1847 sampleIoOveruseConfigurationBuilder(ComponentType.SYSTEM) 1848 .setComponentLevelThresholds(new PerStateBytes(200, 0, 200)) 1849 .build()) 1850 .build()); 1851 assertThrows(IllegalArgumentException.class, 1852 () -> mCarWatchdogService.setResourceOveruseConfigurations(resourceOveruseConfigs, 1853 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)); 1854 } 1855 1856 @Test testFailsSetResourceOveruseConfigurationsOnEmptyIoOveruseSystemWideThresholds()1857 public void testFailsSetResourceOveruseConfigurationsOnEmptyIoOveruseSystemWideThresholds() 1858 throws Exception { 1859 List<ResourceOveruseConfiguration> resourceOveruseConfigs = 1860 Collections.singletonList( 1861 sampleResourceOveruseConfigurationBuilder(ComponentType.SYSTEM, 1862 sampleIoOveruseConfigurationBuilder(ComponentType.SYSTEM) 1863 .setSystemWideThresholds(new ArrayList<>()) 1864 .build()) 1865 .build()); 1866 assertThrows(IllegalArgumentException.class, 1867 () -> mCarWatchdogService.setResourceOveruseConfigurations(resourceOveruseConfigs, 1868 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)); 1869 } 1870 1871 @Test testFailsSetResourceOveruseConfigurationsOnIoOveruseInvalidSystemWideThreshold()1872 public void testFailsSetResourceOveruseConfigurationsOnIoOveruseInvalidSystemWideThreshold() 1873 throws Exception { 1874 List<ResourceOveruseConfiguration> resourceOveruseConfigs = new ArrayList<>(); 1875 resourceOveruseConfigs.add(sampleResourceOveruseConfigurationBuilder(ComponentType.SYSTEM, 1876 sampleIoOveruseConfigurationBuilder(ComponentType.SYSTEM) 1877 .setSystemWideThresholds(Collections.singletonList( 1878 new IoOveruseAlertThreshold(30, 0))) 1879 .build()) 1880 .build()); 1881 assertThrows(IllegalArgumentException.class, 1882 () -> mCarWatchdogService.setResourceOveruseConfigurations( 1883 resourceOveruseConfigs, 1884 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)); 1885 1886 resourceOveruseConfigs.set(0, 1887 sampleResourceOveruseConfigurationBuilder(ComponentType.SYSTEM, 1888 sampleIoOveruseConfigurationBuilder(ComponentType.SYSTEM) 1889 .setSystemWideThresholds(Collections.singletonList( 1890 new IoOveruseAlertThreshold(0, 300))) 1891 .build()) 1892 .build()); 1893 assertThrows(IllegalArgumentException.class, 1894 () -> mCarWatchdogService.setResourceOveruseConfigurations( 1895 resourceOveruseConfigs, 1896 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)); 1897 } 1898 1899 @Test testFailsSetResourceOveruseConfigurationsOnNullIoOveruseConfiguration()1900 public void testFailsSetResourceOveruseConfigurationsOnNullIoOveruseConfiguration() 1901 throws Exception { 1902 List<ResourceOveruseConfiguration> resourceOveruseConfigs = Collections.singletonList( 1903 sampleResourceOveruseConfigurationBuilder(ComponentType.SYSTEM, null).build()); 1904 assertThrows(IllegalArgumentException.class, 1905 () -> mCarWatchdogService.setResourceOveruseConfigurations(resourceOveruseConfigs, 1906 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)); 1907 } 1908 1909 @Test testGetResourceOveruseConfigurations()1910 public void testGetResourceOveruseConfigurations() throws Exception { 1911 List<ResourceOveruseConfiguration> actualConfigs = 1912 mCarWatchdogService.getResourceOveruseConfigurations( 1913 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO); 1914 1915 ResourceOveruseConfigurationSubject.assertThat(actualConfigs) 1916 .containsExactlyElementsIn(sampleResourceOveruseConfigurations()); 1917 } 1918 1919 @Test testGetResourceOveruseConfigurationsWithDisconnectedDaemon()1920 public void testGetResourceOveruseConfigurationsWithDisconnectedDaemon() throws Exception { 1921 crashWatchdogDaemon(); 1922 1923 assertThrows(IllegalStateException.class, 1924 () -> mCarWatchdogService.getResourceOveruseConfigurations( 1925 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)); 1926 1927 /* Method initially called in CarWatchdogService init */ 1928 verify(mMockCarWatchdogDaemon).getResourceOveruseConfigurations(); 1929 } 1930 1931 @Test testGetResourceOveruseConfigurationsWithReconnectedDaemon()1932 public void testGetResourceOveruseConfigurationsWithReconnectedDaemon() throws Exception { 1933 /* 1934 * Emulate daemon crash and restart during the get request. The below get request should be 1935 * waiting for daemon connection before the first call to ServiceManager.getService. But to 1936 * make sure the test is deterministic emulate daemon restart only on the second call to 1937 * ServiceManager.getService. 1938 */ 1939 doReturn(null) 1940 .doReturn(mMockBinder) 1941 .when(() -> ServiceManager.getService(CAR_WATCHDOG_DAEMON_INTERFACE)); 1942 mCarWatchdogDaemonBinderDeathRecipient.binderDied(); 1943 1944 List<ResourceOveruseConfiguration> actualConfigs = 1945 mCarWatchdogService.getResourceOveruseConfigurations( 1946 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO); 1947 1948 ResourceOveruseConfigurationSubject.assertThat(actualConfigs) 1949 .containsExactlyElementsIn(sampleResourceOveruseConfigurations()); 1950 } 1951 1952 @Test testConcurrentSetGetResourceOveruseConfigurationsWithReconnectedDaemon()1953 public void testConcurrentSetGetResourceOveruseConfigurationsWithReconnectedDaemon() 1954 throws Exception { 1955 /* 1956 * Emulate daemon crash and restart during the get and set requests. The below get request 1957 * should be waiting for daemon connection before the first call to 1958 * ServiceManager.getService. But to make sure the test is deterministic emulate daemon 1959 * restart only on the second call to ServiceManager.getService. 1960 */ 1961 doReturn(null) 1962 .doReturn(mMockBinder) 1963 .when(() -> ServiceManager.getService(CAR_WATCHDOG_DAEMON_INTERFACE)); 1964 mCarWatchdogDaemonBinderDeathRecipient.binderDied(); 1965 1966 /* Capture and respond with the configuration received in the set request. */ 1967 List<android.automotive.watchdog.internal.ResourceOveruseConfiguration> internalConfigs = 1968 new ArrayList<>(); 1969 doAnswer(args -> { 1970 List<android.automotive.watchdog.internal.ResourceOveruseConfiguration> configs = 1971 args.getArgument(0); 1972 internalConfigs.addAll(configs); 1973 return null; 1974 }).when(mMockCarWatchdogDaemon).updateResourceOveruseConfigurations(anyList()); 1975 when(mMockCarWatchdogDaemon.getResourceOveruseConfigurations()).thenReturn(internalConfigs); 1976 1977 /* Start a set request that will become pending and a blocking get request. */ 1978 List<ResourceOveruseConfiguration> setConfigs = sampleResourceOveruseConfigurations(); 1979 assertThat(mCarWatchdogService.setResourceOveruseConfigurations( 1980 setConfigs, CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO)) 1981 .isEqualTo(CarWatchdogManager.RETURN_CODE_SUCCESS); 1982 1983 List<ResourceOveruseConfiguration> getConfigs = 1984 mCarWatchdogService.getResourceOveruseConfigurations( 1985 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO); 1986 1987 ResourceOveruseConfigurationSubject.assertThat(getConfigs) 1988 .containsExactlyElementsIn(setConfigs); 1989 } 1990 1991 @Test testFailsGetResourceOveruseConfigurationsOnInvalidArgs()1992 public void testFailsGetResourceOveruseConfigurationsOnInvalidArgs() throws Exception { 1993 assertThrows(IllegalArgumentException.class, 1994 () -> mCarWatchdogService.getResourceOveruseConfigurations(0)); 1995 } 1996 1997 @Test testLatestIoOveruseStats()1998 public void testLatestIoOveruseStats() throws Exception { 1999 setRequiresDistractionOptimization(true); 2000 setDisplayStateEnabled(false); 2001 int criticalSysPkgUid = Binder.getCallingUid(); 2002 int nonCriticalSysPkgUid = 1001056; 2003 int nonCriticalVndrPkgUid = 1002564; 2004 int thirdPartyPkgUid = 1002044; 2005 2006 injectPackageInfos(Arrays.asList( 2007 constructPackageManagerPackageInfo( 2008 "system_package.critical", criticalSysPkgUid, null), 2009 constructPackageManagerPackageInfo( 2010 "system_package.non_critical", nonCriticalSysPkgUid, null), 2011 constructPackageManagerPackageInfo( 2012 "vendor_package.non_critical", nonCriticalVndrPkgUid, null), 2013 constructPackageManagerPackageInfo( 2014 "third_party_package", thirdPartyPkgUid, null))); 2015 2016 IResourceOveruseListener mockSystemListener = createMockResourceOveruseListener(); 2017 mCarWatchdogService.addResourceOveruseListenerForSystem( 2018 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, mockSystemListener); 2019 2020 IResourceOveruseListener mockListener = createMockResourceOveruseListener(); 2021 mCarWatchdogService.addResourceOveruseListener( 2022 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, mockListener); 2023 2024 List<PackageIoOveruseStats> packageIoOveruseStats = Arrays.asList( 2025 /* Overuse occurred but cannot be killed/disabled. */ 2026 constructPackageIoOveruseStats(criticalSysPkgUid, /* shouldNotify= */ true, 2027 /* forgivenWriteBytes= */ constructPerStateBytes(100, 200, 300), 2028 constructInternalIoOveruseStats(/* killableOnOveruse= */ false, 2029 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 2030 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 2031 /* totalOveruses= */ 3)), 2032 /* No overuse occurred but should be notified. */ 2033 constructPackageIoOveruseStats(nonCriticalSysPkgUid, /* shouldNotify= */ true, 2034 /* forgivenWriteBytes= */ constructPerStateBytes(50, 100, 150), 2035 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2036 /* remainingWriteBytes= */ constructPerStateBytes(20, 30, 40), 2037 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 2038 /* totalOveruses= */ 3)), 2039 /* Neither overuse occurred nor be notified. */ 2040 constructPackageIoOveruseStats(nonCriticalVndrPkgUid, /* shouldNotify= */ false, 2041 /* forgivenWriteBytes= */ constructPerStateBytes(25, 50, 75), 2042 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2043 /* remainingWriteBytes= */ constructPerStateBytes(200, 300, 400), 2044 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 2045 /* totalOveruses= */ 3)), 2046 /* Overuse occurred and can be killed/disabled. */ 2047 constructPackageIoOveruseStats(thirdPartyPkgUid, /* shouldNotify= */ true, 2048 /* forgivenWriteBytes= */ constructPerStateBytes(100, 200, 300), 2049 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2050 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 2051 /* writtenBytes= */ constructPerStateBytes(300, 600, 900), 2052 /* totalOveruses= */ 3))); 2053 2054 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 2055 2056 assertThat(mDisabledUserPackages).containsExactlyElementsIn(Collections.singleton( 2057 "10:third_party_package")); 2058 2059 List<ResourceOveruseStats> expectedStats = new ArrayList<>(); 2060 2061 expectedStats.add(constructResourceOveruseStats(criticalSysPkgUid, 2062 "system_package.critical", packageIoOveruseStats.get(0).ioOveruseStats)); 2063 2064 verifyOnOveruseCalled(expectedStats, mockListener); 2065 2066 expectedStats.add(constructResourceOveruseStats(nonCriticalSysPkgUid, 2067 "system_package.non_critical", packageIoOveruseStats.get(1).ioOveruseStats)); 2068 2069 /* 2070 * When the package receives overuse notification, the package is not yet killed so the 2071 * totalTimesKilled counter is not yet incremented. 2072 */ 2073 expectedStats.add(constructResourceOveruseStats(thirdPartyPkgUid, "third_party_package", 2074 packageIoOveruseStats.get(3).ioOveruseStats)); 2075 2076 verifyOnOveruseCalled(expectedStats, mockSystemListener); 2077 2078 List<AtomsProto.CarWatchdogIoOveruseStatsReported> expectedReportedOveruseStats = 2079 new ArrayList<>(); 2080 expectedReportedOveruseStats.add(constructIoOveruseStatsReported(criticalSysPkgUid, 2081 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(10, 20, 30), 2082 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(100, 200, 300))); 2083 expectedReportedOveruseStats.add(constructIoOveruseStatsReported(thirdPartyPkgUid, 2084 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(30, 60, 90), 2085 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(300, 600, 900))); 2086 2087 captureAndVerifyIoOveruseStatsReported(expectedReportedOveruseStats); 2088 2089 List<AtomsProto.CarWatchdogKillStatsReported> expectedReportedKillStats = 2090 Collections.singletonList(constructIoOveruseKillStatsReported(thirdPartyPkgUid, 2091 CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE, 2092 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(30, 60, 90), 2093 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(300, 600, 900))); 2094 2095 captureAndVerifyKillStatsReported(expectedReportedKillStats); 2096 } 2097 2098 @Test testLatestIoOveruseStatsWithSharedUid()2099 public void testLatestIoOveruseStatsWithSharedUid() throws Exception { 2100 setRequiresDistractionOptimization(true); 2101 setDisplayStateEnabled(false); 2102 int criticalSysSharedUid = Binder.getCallingUid(); 2103 int nonCriticalVndrSharedUid = 1002564; 2104 int thirdPartySharedUid = 1002044; 2105 2106 injectPackageInfos(Arrays.asList( 2107 constructPackageManagerPackageInfo( 2108 "system_package.A", criticalSysSharedUid, "system_shared_package"), 2109 constructPackageManagerPackageInfo( 2110 "system_package.B", criticalSysSharedUid, "system_shared_package"), 2111 constructPackageManagerPackageInfo("vendor_package.non_critical", 2112 nonCriticalVndrSharedUid, "vendor_shared_package"), 2113 constructPackageManagerPackageInfo( 2114 "third_party_package.A", thirdPartySharedUid, "third_party_shared_package"), 2115 constructPackageManagerPackageInfo( 2116 "third_party_package.B", thirdPartySharedUid, "third_party_shared_package") 2117 )); 2118 2119 IResourceOveruseListener mockSystemListener = createMockResourceOveruseListener(); 2120 mCarWatchdogService.addResourceOveruseListenerForSystem( 2121 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, mockSystemListener); 2122 2123 IResourceOveruseListener mockListener = createMockResourceOveruseListener(); 2124 mCarWatchdogService.addResourceOveruseListener( 2125 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, mockListener); 2126 2127 List<PackageIoOveruseStats> packageIoOveruseStats = Arrays.asList( 2128 /* Overuse occurred but cannot be killed/disabled. */ 2129 constructPackageIoOveruseStats(criticalSysSharedUid, /* shouldNotify= */ true, 2130 /* forgivenWriteBytes= */ constructPerStateBytes(100, 200, 300), 2131 constructInternalIoOveruseStats(/* killableOnOveruse= */ false, 2132 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 2133 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 2134 /* totalOveruses= */ 3)), 2135 /* No overuse occurred but should be notified. */ 2136 constructPackageIoOveruseStats(nonCriticalVndrSharedUid, /* shouldNotify= */ true, 2137 /* forgivenWriteBytes= */ constructPerStateBytes(50, 100, 150), 2138 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2139 /* remainingWriteBytes= */ constructPerStateBytes(200, 300, 400), 2140 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 2141 /* totalOveruses= */ 3)), 2142 /* Overuse occurred and can be killed/disabled. */ 2143 constructPackageIoOveruseStats(thirdPartySharedUid, /* shouldNotify= */ true, 2144 /* forgivenWriteBytes= */ constructPerStateBytes(100, 200, 300), 2145 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2146 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 2147 /* writtenBytes= */ constructPerStateBytes(300, 600, 900), 2148 /* totalOveruses= */ 3))); 2149 2150 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 2151 2152 assertThat(mDisabledUserPackages).containsExactlyElementsIn(Arrays.asList( 2153 "10:third_party_package.A", "10:third_party_package.B")); 2154 2155 List<ResourceOveruseStats> expectedStats = new ArrayList<>(); 2156 2157 expectedStats.add(constructResourceOveruseStats(criticalSysSharedUid, 2158 "shared:system_shared_package", packageIoOveruseStats.get(0).ioOveruseStats)); 2159 2160 verifyOnOveruseCalled(expectedStats, mockListener); 2161 2162 expectedStats.add(constructResourceOveruseStats(nonCriticalVndrSharedUid, 2163 "shared:vendor_shared_package", packageIoOveruseStats.get(1).ioOveruseStats)); 2164 2165 /* 2166 * When the package receives overuse notification, the package is not yet killed so the 2167 * totalTimesKilled counter is not yet incremented. 2168 */ 2169 expectedStats.add(constructResourceOveruseStats(thirdPartySharedUid, 2170 "shared:third_party_shared_package", packageIoOveruseStats.get(2).ioOveruseStats)); 2171 2172 verifyOnOveruseCalled(expectedStats, mockSystemListener); 2173 2174 List<AtomsProto.CarWatchdogIoOveruseStatsReported> expectedReportedOveruseStats = 2175 new ArrayList<>(); 2176 expectedReportedOveruseStats.add(constructIoOveruseStatsReported(criticalSysSharedUid, 2177 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(10, 20, 30), 2178 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(100, 200, 300))); 2179 expectedReportedOveruseStats.add(constructIoOveruseStatsReported(thirdPartySharedUid, 2180 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(30, 60, 90), 2181 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(300, 600, 900))); 2182 2183 captureAndVerifyIoOveruseStatsReported(expectedReportedOveruseStats); 2184 2185 List<AtomsProto.CarWatchdogKillStatsReported> expectedReportedKillStats = 2186 Collections.singletonList(constructIoOveruseKillStatsReported(thirdPartySharedUid, 2187 CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE, 2188 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(30, 60, 90), 2189 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(300, 600, 900))); 2190 2191 captureAndVerifyKillStatsReported(expectedReportedKillStats); 2192 } 2193 2194 @Test testGetTodayIoUsageStats()2195 public void testGetTodayIoUsageStats() throws Exception { 2196 List<WatchdogStorage.IoUsageStatsEntry> ioUsageStatsEntries = Arrays.asList( 2197 WatchdogStorageUnitTest.constructIoUsageStatsEntry( 2198 /* userId= */ 10, "system_package", /* startTime */ 0, /* duration= */ 1234, 2199 /* remainingWriteBytes= */ constructPerStateBytes(200, 300, 400), 2200 /* writtenBytes= */ constructPerStateBytes(1000, 2000, 3000), 2201 /* forgivenWriteBytes= */ constructPerStateBytes(100, 100, 100), 2202 /* totalOveruses= */ 2, /* forgivenOveruses= */ 0, 2203 /* totalTimesKilled= */ 1), 2204 WatchdogStorageUnitTest.constructIoUsageStatsEntry( 2205 /* userId= */ 11, "vendor_package", /* startTime */ 0, /* duration= */ 1234, 2206 /* remainingWriteBytes= */ constructPerStateBytes(500, 600, 700), 2207 /* writtenBytes= */ constructPerStateBytes(1100, 2300, 4300), 2208 /* forgivenWriteBytes= */ constructPerStateBytes(100, 100, 100), 2209 /* totalOveruses= */ 4, /* forgivenOveruses= */ 1, 2210 /* totalTimesKilled= */ 10)); 2211 when(mMockWatchdogStorage.getTodayIoUsageStats()).thenReturn(ioUsageStatsEntries); 2212 2213 List<UserPackageIoUsageStats> actualStats = 2214 mWatchdogServiceForSystemImpl.getTodayIoUsageStats(); 2215 2216 List<UserPackageIoUsageStats> expectedStats = Arrays.asList( 2217 constructUserPackageIoUsageStats(/* userId= */ 10, "system_package", 2218 /* writtenBytes= */ constructPerStateBytes(1000, 2000, 3000), 2219 /* forgivenWriteBytes= */ constructPerStateBytes(100, 100, 100), 2220 /* totalOveruses= */ 2), 2221 constructUserPackageIoUsageStats(/* userId= */ 11, "vendor_package", 2222 /* writtenBytes= */ constructPerStateBytes(1100, 2300, 4300), 2223 /* forgivenWriteBytes= */ constructPerStateBytes(100, 100, 100), 2224 /* totalOveruses= */ 4)); 2225 2226 assertThat(actualStats).comparingElementsUsing(Correspondence.from( 2227 CarWatchdogServiceUnitTest::isUserPackageIoUsageStatsEquals, 2228 "is user package I/O usage stats equal to")) 2229 .containsExactlyElementsIn(expectedStats); 2230 } 2231 2232 @Test testPersistStatsOnShutdownEnter()2233 public void testPersistStatsOnShutdownEnter() throws Exception { 2234 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 10, 11, 12); 2235 injectPackageInfos(Arrays.asList( 2236 constructPackageManagerPackageInfo( 2237 "third_party_package", 1103456, "vendor_shared_package.critical"), 2238 constructPackageManagerPackageInfo( 2239 "vendor_package", 1103456, "vendor_shared_package.critical"), 2240 constructPackageManagerPackageInfo("third_party_package.A", 1001100, null), 2241 constructPackageManagerPackageInfo("third_party_package.A", 1201100, null))); 2242 2243 SparseArray<PackageIoOveruseStats> packageIoOveruseStatsByUid = 2244 injectIoOveruseStatsForPackages( 2245 mGenericPackageNameByUid, 2246 /* killablePackages= */ new ArraySet<>(Collections.singletonList( 2247 "third_party_package.A")), 2248 /* shouldNotifyPackages= */ new ArraySet<>()); 2249 2250 mCarWatchdogService.setKillablePackageAsUser( 2251 "third_party_package.A", new UserHandle(12), /* isKillable= */ false); 2252 2253 restartService(/* totalRestarts= */ 1); 2254 2255 List<ResourceOveruseStats> actualStats = mCarWatchdogService.getAllResourceOveruseStats( 2256 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, /* minimumStatsFlag= */ 0, 2257 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY); 2258 2259 List<ResourceOveruseStats> expectedStats = Arrays.asList( 2260 constructResourceOveruseStats( 2261 /* uid= */ 1103456, "shared:vendor_shared_package.critical", 2262 packageIoOveruseStatsByUid.get(1103456).ioOveruseStats), 2263 constructResourceOveruseStats(/* uid= */ 1001100, "third_party_package.A", 2264 packageIoOveruseStatsByUid.get(1001100).ioOveruseStats), 2265 constructResourceOveruseStats(/* uid= */ 1201100, "third_party_package.A", 2266 packageIoOveruseStatsByUid.get(1201100).ioOveruseStats)); 2267 2268 PackageKillableStateSubject.assertThat( 2269 mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL)) 2270 .containsExactly( 2271 new PackageKillableState("third_party_package", 11, 2272 PackageKillableState.KILLABLE_STATE_NEVER), 2273 new PackageKillableState("vendor_package", 11, 2274 PackageKillableState.KILLABLE_STATE_NEVER), 2275 new PackageKillableState("third_party_package.A", 10, 2276 PackageKillableState.KILLABLE_STATE_YES), 2277 new PackageKillableState("third_party_package.A", 12, 2278 PackageKillableState.KILLABLE_STATE_NO)); 2279 2280 ResourceOveruseStatsSubject.assertThat(actualStats) 2281 .containsExactlyElementsIn(expectedStats); 2282 2283 verifyNoMoreInteractions(mMockWatchdogStorage); 2284 } 2285 2286 @Test testPersistIoOveruseStatsOnDateChange()2287 public void testPersistIoOveruseStatsOnDateChange() throws Exception { 2288 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 10); 2289 injectPackageInfos(Arrays.asList( 2290 constructPackageManagerPackageInfo("system_package", 1011200, null), 2291 constructPackageManagerPackageInfo("third_party_package", 1001100, null))); 2292 2293 setDisplayStateEnabled(false); 2294 mTimeSource.updateNow(/* numDaysAgo= */ 1); 2295 List<PackageIoOveruseStats> prevDayStats = Arrays.asList( 2296 constructPackageIoOveruseStats(1011200, /* shouldNotify= */ false, 2297 /* forgivenWriteBytes= */ constructPerStateBytes(600, 700, 800), 2298 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2299 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 2300 /* writtenBytes= */ constructPerStateBytes(600, 700, 800), 2301 /* totalOveruses= */ 3)), 2302 constructPackageIoOveruseStats(1001100, /* shouldNotify= */ false, 2303 /* forgivenWriteBytes= */ constructPerStateBytes(1050, 1100, 1200), 2304 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2305 /* remainingWriteBytes= */ constructPerStateBytes(50, 60, 70), 2306 /* writtenBytes= */ constructPerStateBytes(1100, 1200, 1300), 2307 /* totalOveruses= */ 5))); 2308 pushLatestIoOveruseStatsAndWait(prevDayStats); 2309 2310 List<WatchdogStorage.IoUsageStatsEntry> expectedSavedEntries = Arrays.asList( 2311 new WatchdogStorage.IoUsageStatsEntry(/* userId= */ 10, "system_package", 2312 new WatchdogPerfHandler.PackageIoUsage(prevDayStats.get(0).ioOveruseStats, 2313 /* forgivenWriteBytes= */ constructPerStateBytes(600, 700, 800), 2314 /* forgivenOveruses= */ 3, /* totalTimesKilled= */ 1)), 2315 new WatchdogStorage.IoUsageStatsEntry(/* userId= */ 10, "third_party_package", 2316 new WatchdogPerfHandler.PackageIoUsage(prevDayStats.get(1).ioOveruseStats, 2317 /* forgivenWriteBytes= */ constructPerStateBytes(1050, 1100, 1200), 2318 /* forgivenOveruses= */ 0, /* totalTimesKilled= */ 0))); 2319 2320 setDisplayStateEnabled(true); 2321 mTimeSource.updateNow(/* numDaysAgo= */ 0); 2322 List<PackageIoOveruseStats> currentDayStats = Arrays.asList( 2323 constructPackageIoOveruseStats(1011200, /* shouldNotify= */ false, 2324 /* forgivenWriteBytes= */ constructPerStateBytes(0, 0, 0), 2325 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2326 /* remainingWriteBytes= */ constructPerStateBytes(500, 550, 600), 2327 /* writtenBytes= */ constructPerStateBytes(100, 150, 200), 2328 /* totalOveruses= */ 0)), 2329 constructPackageIoOveruseStats(1001100, /* shouldNotify= */ false, 2330 /* forgivenWriteBytes= */ constructPerStateBytes(0, 0, 0), 2331 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2332 /* remainingWriteBytes= */ constructPerStateBytes(250, 360, 470), 2333 /* writtenBytes= */ constructPerStateBytes(900, 900, 900), 2334 /* totalOveruses= */ 0))); 2335 pushLatestIoOveruseStatsAndWait(currentDayStats); 2336 2337 IoUsageStatsEntrySubject.assertThat(mIoUsageStatsEntries) 2338 .containsExactlyElementsIn(expectedSavedEntries); 2339 2340 List<ResourceOveruseStats> actualCurrentDayStats = 2341 mCarWatchdogService.getAllResourceOveruseStats( 2342 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, /* minimumStatsFlag= */ 0, 2343 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY); 2344 2345 List<ResourceOveruseStats> expectedCurrentDayStats = Arrays.asList( 2346 constructResourceOveruseStats(/* uid= */ 1011200, "system_package", 2347 currentDayStats.get(0).ioOveruseStats), 2348 constructResourceOveruseStats(/* uid= */ 1001100, "third_party_package", 2349 currentDayStats.get(1).ioOveruseStats)); 2350 2351 ResourceOveruseStatsSubject.assertThat(actualCurrentDayStats) 2352 .containsExactlyElementsIn(expectedCurrentDayStats); 2353 } 2354 2355 @Test testNoUserNotificationWithNoRecurrentOveruse()2356 public void testNoUserNotificationWithNoRecurrentOveruse() throws Exception { 2357 mockAmGetCurrentUser(100); 2358 setDisplayStateEnabled(true); 2359 setRequiresDistractionOptimization(false); 2360 2361 setUpSampleUserAndPackages(); 2362 2363 pushLatestIoOveruseStatsAndWait( 2364 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ false)); 2365 2366 // Verify no notification is sent 2367 captureAndVerifyUserNotifications(Collections.emptyList()); 2368 } 2369 2370 @Test testNoUserNotificationOnRecurrentOveruseWithDistractionOptimization()2371 public void testNoUserNotificationOnRecurrentOveruseWithDistractionOptimization() 2372 throws Exception { 2373 mockAmGetCurrentUser(100); 2374 setDisplayStateEnabled(true); 2375 setRequiresDistractionOptimization(true); 2376 2377 setUpSampleUserAndPackages(); 2378 2379 pushLatestIoOveruseStatsAndWait( 2380 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true)); 2381 2382 // Verify no notification is sent 2383 captureAndVerifyUserNotifications(Collections.emptyList()); 2384 } 2385 2386 @Test testUserNotificationOnRecurrentOveruseAfterNoDistractionOptimization()2387 public void testUserNotificationOnRecurrentOveruseAfterNoDistractionOptimization() 2388 throws Exception { 2389 mockAmGetCurrentUser(100); 2390 setDisplayStateEnabled(true); 2391 setRequiresDistractionOptimization(true); 2392 2393 setUpSampleUserAndPackages(); 2394 2395 pushLatestIoOveruseStatsAndWait( 2396 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true)); 2397 2398 setRequiresDistractionOptimization(false); 2399 2400 captureAndVerifyUserNotifications(Collections.singletonList( 2401 new UserNotificationCall(UserHandle.of(100), 2402 Arrays.asList("vendor_package.non_critical", "third_party_package.A", 2403 "third_party_package.B"), /* hasHeadsUpNotification= */ true, 2404 /* notificationIds= */ Arrays.asList(150, 151, 152)))); 2405 } 2406 2407 @Test testNoDuplicateUserNotificationOnRepeatedRecurrentOveruse()2408 public void testNoDuplicateUserNotificationOnRepeatedRecurrentOveruse() 2409 throws Exception { 2410 mockAmGetCurrentUser(100); 2411 setDisplayStateEnabled(true); 2412 setRequiresDistractionOptimization(false); 2413 2414 setUpSampleUserAndPackages(); 2415 2416 pushLatestIoOveruseStatsAndWait( 2417 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true)); 2418 2419 captureAndVerifyUserNotifications(Collections.singletonList( 2420 new UserNotificationCall(UserHandle.of(100), 2421 Arrays.asList("vendor_package.non_critical", "third_party_package.A", 2422 "third_party_package.B"), /* hasHeadsUpNotification= */ true, 2423 /* notificationIds= */ Arrays.asList(150, 151, 152)))); 2424 2425 pushLatestIoOveruseStatsAndWait( 2426 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true)); 2427 2428 verifyNoMoreInteractions(mMockUserNotificationHelper); 2429 } 2430 2431 @Test testImmediateUserNotificationOnRecurrentOveruseWhenNoDistractionOptimization()2432 public void testImmediateUserNotificationOnRecurrentOveruseWhenNoDistractionOptimization() 2433 throws Exception { 2434 mockAmGetCurrentUser(100); 2435 setDisplayStateEnabled(true); 2436 setRequiresDistractionOptimization(false); 2437 2438 setUpSampleUserAndPackages(); 2439 2440 pushLatestIoOveruseStatsAndWait( 2441 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true)); 2442 2443 pushLatestIoOveruseStatsAndWait(Collections.singletonList( 2444 constructPackageIoOveruseStats(/* uid= */ 10010002, /* shouldNotify= */ true, 2445 /* forgivenWriteBytes= */ constructPerStateBytes(100, 200, 300), 2446 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2447 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 2448 /* writtenBytes= */ constructPerStateBytes(300, 600, 900), 2449 /* totalOveruses= */ 3)))); 2450 2451 List<UserNotificationCall> userNotificationCalls = Arrays.asList( 2452 new UserNotificationCall(UserHandle.of(100), 2453 Arrays.asList("vendor_package.non_critical", "third_party_package.A", 2454 "third_party_package.B"), /* hasHeadsUpNotification= */ true, 2455 /* notificationIds= */ Arrays.asList(150, 151, 152)), 2456 new UserNotificationCall(UserHandle.of(100), 2457 Collections.singletonList("system_package.non_critical"), 2458 /* hasHeadsUpNotification= */ false, 2459 /* notificationIds= */ Arrays.asList(153))); 2460 2461 captureAndVerifyUserNotifications(userNotificationCalls); 2462 } 2463 2464 @Test testNoUserNotificationOnRecurrentOveruseByPrePrioritizedApp()2465 public void testNoUserNotificationOnRecurrentOveruseByPrePrioritizedApp() throws Exception { 2466 mockAmGetCurrentUser(100); 2467 setDisplayStateEnabled(true); 2468 setRequiresDistractionOptimization(true); 2469 2470 setUpSampleUserAndPackages(); 2471 2472 mCarWatchdogService.setKillablePackageAsUser("third_party_package.A", UserHandle.of(100), 2473 /* isKillable= */ false); 2474 2475 pushLatestIoOveruseStatsAndWait(Collections.singletonList( 2476 constructPackageIoOveruseStats(/* uid= */ 10010005, /* shouldNotify= */ true, 2477 /* forgivenWriteBytes= */ constructPerStateBytes(100, 200, 300), 2478 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2479 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 2480 /* writtenBytes= */ constructPerStateBytes(300, 600, 900), 2481 /* totalOveruses= */ 3)))); 2482 2483 setRequiresDistractionOptimization(false); 2484 2485 // Verify no notification is sent 2486 captureAndVerifyUserNotifications(Collections.emptyList()); 2487 } 2488 2489 @Test testNoUserNotificationOnRecurrentOveruseByPostPrioritizedApp()2490 public void testNoUserNotificationOnRecurrentOveruseByPostPrioritizedApp() throws Exception { 2491 mockAmGetCurrentUser(100); 2492 setDisplayStateEnabled(true); 2493 setRequiresDistractionOptimization(true); 2494 2495 setUpSampleUserAndPackages(); 2496 2497 pushLatestIoOveruseStatsAndWait(Collections.singletonList( 2498 constructPackageIoOveruseStats(/* uid= */ 10010005, /* shouldNotify= */ true, 2499 /* forgivenWriteBytes= */ constructPerStateBytes(100, 200, 300), 2500 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2501 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 2502 /* writtenBytes= */ constructPerStateBytes(300, 600, 900), 2503 /* totalOveruses= */ 3)))); 2504 2505 mCarWatchdogService.setKillablePackageAsUser("third_party_package.A", 2506 UserHandle.of(100), /* isKillable= */ false); 2507 2508 setRequiresDistractionOptimization(false); 2509 2510 // Verify no notification is sent 2511 captureAndVerifyUserNotifications(Collections.emptyList()); 2512 } 2513 2514 @Test testUserNotificationOnRecurrentOveruseByPriorityResettedApp()2515 public void testUserNotificationOnRecurrentOveruseByPriorityResettedApp() throws Exception { 2516 mockAmGetCurrentUser(100); 2517 setDisplayStateEnabled(true); 2518 setRequiresDistractionOptimization(true); 2519 2520 setUpSampleUserAndPackages(); 2521 2522 mCarWatchdogService.setKillablePackageAsUser("third_party_package.A", 2523 UserHandle.of(100), /* isKillable= */ false); 2524 2525 pushLatestIoOveruseStatsAndWait(Collections.singletonList( 2526 constructPackageIoOveruseStats(/* uid= */ 10010005, /* shouldNotify= */ true, 2527 /* forgivenWriteBytes= */ constructPerStateBytes(100, 200, 300), 2528 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2529 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 2530 /* writtenBytes= */ constructPerStateBytes(300, 600, 900), 2531 /* totalOveruses= */ 3)))); 2532 2533 mCarWatchdogService.setKillablePackageAsUser("third_party_package.A", UserHandle.of(100), 2534 /* isKillable= */ true); 2535 2536 setRequiresDistractionOptimization(false); 2537 2538 captureAndVerifyUserNotifications(Collections.singletonList( 2539 new UserNotificationCall(UserHandle.of(100), 2540 Arrays.asList("third_party_package.A", "third_party_package.B"), 2541 /* hasHeadsUpNotification= */ true, 2542 /* notificationIds= */ Arrays.asList(150, 151)))); 2543 } 2544 2545 @Test testUserNotificationOnHistoricalRecurrentOveruse()2546 public void testUserNotificationOnHistoricalRecurrentOveruse() throws Exception { 2547 when(mMockWatchdogStorage 2548 .getNotForgivenHistoricalIoOveruses(RECURRING_OVERUSE_PERIOD_IN_DAYS)) 2549 .thenReturn(Arrays.asList(new WatchdogStorage.NotForgivenOverusesEntry(100, 2550 "system_package.non_critical", 2))); 2551 2552 // Force CarWatchdogService to fetch historical not forgiven overuses. 2553 restartService(/* totalRestarts= */ 1); 2554 mockAmGetCurrentUser(100); 2555 setDisplayStateEnabled(true); 2556 setRequiresDistractionOptimization(false); 2557 2558 setUpSampleUserAndPackages(); 2559 2560 pushLatestIoOveruseStatsAndWait(Collections.singletonList( 2561 constructPackageIoOveruseStats(/* uid= */ 10010002, /* shouldNotify= */ true, 2562 /* forgivenWriteBytes= */ constructPerStateBytes(100, 200, 300), 2563 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2564 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 2565 /* writtenBytes= */ constructPerStateBytes(300, 600, 900), 2566 /* totalOveruses= */ 1)))); 2567 2568 captureAndVerifyUserNotifications(Collections.singletonList( 2569 new UserNotificationCall(UserHandle.of(100), 2570 Collections.singletonList("system_package.non_critical"), 2571 /* hasHeadsUpNotification= */ true, 2572 /* notificationIds= */ Collections.singletonList(150)))); 2573 } 2574 2575 @Test testUserNotificationWithDisabledDisplay()2576 public void testUserNotificationWithDisabledDisplay() throws Exception { 2577 mockAmGetCurrentUser(100); 2578 setDisplayStateEnabled(false); 2579 setRequiresDistractionOptimization(false); 2580 2581 setUpSampleUserAndPackages(); 2582 2583 pushLatestIoOveruseStatsAndWait(Collections.singletonList( 2584 constructPackageIoOveruseStats(/* uid= */ 10010002, /* shouldNotify= */ true, 2585 /* forgivenWriteBytes= */ constructPerStateBytes(100, 200, 300), 2586 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2587 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 2588 /* writtenBytes= */ constructPerStateBytes(300, 600, 900), 2589 /* totalOveruses= */ 3)))); 2590 2591 captureAndVerifyUserNotifications(Collections.singletonList( 2592 new UserNotificationCall(UserHandle.of(100), 2593 Collections.singletonList("system_package.non_critical"), 2594 /* hasHeadsUpNotification= */ false, 2595 /* notificationIds= */ Collections.singletonList(150)))); 2596 } 2597 2598 @Test testNoDisableWithNoRecurrentOveruse()2599 public void testNoDisableWithNoRecurrentOveruse() throws Exception { 2600 setUpSampleUserAndPackages(); 2601 setRequiresDistractionOptimization(false); 2602 setDisplayStateEnabled(false); 2603 2604 List<PackageIoOveruseStats> packageIoOveruseStats = 2605 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ false); 2606 2607 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 2608 2609 captureAndVerifyIoOveruseStatsReported(sampleReportedOveruseStats()); 2610 2611 verify(() -> CarStatsLog.write(eq(CarStatsLog.CAR_WATCHDOG_KILL_STATS_REPORTED), 2612 anyInt(), anyInt(), anyInt(), anyInt(), any(), any()), never()); 2613 2614 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).isEmpty(); 2615 } 2616 2617 @Test testNoDisableRecurrentlyOverusingAppWithDistractionOptimization()2618 public void testNoDisableRecurrentlyOverusingAppWithDistractionOptimization() throws Exception { 2619 setUpSampleUserAndPackages(); 2620 setRequiresDistractionOptimization(true); 2621 setDisplayStateEnabled(true); 2622 2623 List<PackageIoOveruseStats> packageIoOveruseStats = 2624 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true); 2625 2626 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 2627 2628 captureAndVerifyIoOveruseStatsReported(sampleReportedOveruseStats()); 2629 2630 verify(() -> CarStatsLog.write(eq(CarStatsLog.CAR_WATCHDOG_KILL_STATS_REPORTED), 2631 anyInt(), anyInt(), anyInt(), anyInt(), any(), any()), never()); 2632 2633 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).isEmpty(); 2634 } 2635 2636 @Test testNoDisableRecurrentlyOverusingAppWhenDisplayEnabled()2637 public void testNoDisableRecurrentlyOverusingAppWhenDisplayEnabled() throws Exception { 2638 setUpSampleUserAndPackages(); 2639 setRequiresDistractionOptimization(false); 2640 setDisplayStateEnabled(true); 2641 2642 List<PackageIoOveruseStats> packageIoOveruseStats = 2643 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true); 2644 2645 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 2646 2647 captureAndVerifyIoOveruseStatsReported(sampleReportedOveruseStats()); 2648 2649 verify(() -> CarStatsLog.write(eq(CarStatsLog.CAR_WATCHDOG_KILL_STATS_REPORTED), 2650 anyInt(), anyInt(), anyInt(), anyInt(), any(), any()), never()); 2651 2652 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).isEmpty(); 2653 } 2654 2655 @Test testDisableRecurrentlyOverusingAppAfterDisplayDisabled()2656 public void testDisableRecurrentlyOverusingAppAfterDisplayDisabled() throws Exception { 2657 setUpSampleUserAndPackages(); 2658 setRequiresDistractionOptimization(true); 2659 setDisplayStateEnabled(true); 2660 2661 List<PackageIoOveruseStats> packageIoOveruseStats = 2662 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true); 2663 2664 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 2665 2666 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).isEmpty(); 2667 2668 setRequiresDistractionOptimization(false); 2669 2670 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).isEmpty(); 2671 2672 setDisplayStateEnabled(false); 2673 2674 captureAndVerifyIoOveruseStatsReported(sampleReportedOveruseStats()); 2675 2676 captureAndVerifyKillStatsReported(sampleReportedKillStats( 2677 CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE, 2678 /* killedUids= */ new int[]{10010004, 10110004, 10010005, 10110005})); 2679 2680 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).containsExactly( 2681 "100:vendor_package.non_critical", "101:vendor_package.non_critical", 2682 "100:third_party_package.A", "101:third_party_package.A", 2683 "100:third_party_package.B", "101:third_party_package.B"); 2684 } 2685 2686 @Test testImmediateDisableRecurrentlyOverusingAppDuringDisabledDisplay()2687 public void testImmediateDisableRecurrentlyOverusingAppDuringDisabledDisplay() 2688 throws Exception { 2689 setUpSampleUserAndPackages(); 2690 setRequiresDistractionOptimization(false); 2691 setDisplayStateEnabled(false); 2692 2693 List<PackageIoOveruseStats> packageIoOveruseStats = 2694 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true); 2695 2696 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 2697 2698 captureAndVerifyIoOveruseStatsReported(sampleReportedOveruseStats()); 2699 2700 captureAndVerifyKillStatsReported(sampleReportedKillStats( 2701 CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE, 2702 /* killedUids= */ new int[]{10010004, 10110004, 10010005, 10110005})); 2703 2704 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).containsExactly( 2705 "100:vendor_package.non_critical", "101:vendor_package.non_critical", 2706 "100:third_party_package.A", "101:third_party_package.A", 2707 "100:third_party_package.B", "101:third_party_package.B"); 2708 } 2709 2710 @Test testDisableRecurrentlyOverusingAppWhenDisplayDisabledAfterDateChange()2711 public void testDisableRecurrentlyOverusingAppWhenDisplayDisabledAfterDateChange() 2712 throws Exception { 2713 mTimeSource.updateNow(/* numDaysAgo= */ 1); 2714 setUpSampleUserAndPackages(); 2715 setRequiresDistractionOptimization(true); 2716 setDisplayStateEnabled(true); 2717 2718 List<PackageIoOveruseStats> packageIoOveruseStats = 2719 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true); 2720 2721 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 2722 2723 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).isEmpty(); 2724 2725 mTimeSource.updateNow(/* numDaysAgo= */ 0); 2726 2727 pushLatestIoOveruseStatsAndWait(new ArrayList<>()); 2728 2729 setRequiresDistractionOptimization(false); 2730 setDisplayStateEnabled(false); 2731 2732 captureAndVerifyIoOveruseStatsReported(sampleReportedOveruseStats()); 2733 2734 captureAndVerifyKillStatsReported(sampleReportedKillStats( 2735 CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE, 2736 /* killedUids= */ new int[]{10010004, 10110004, 10010005, 10110005})); 2737 2738 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).containsExactly( 2739 "100:vendor_package.non_critical", "101:vendor_package.non_critical", 2740 "100:third_party_package.A", "101:third_party_package.A", 2741 "100:third_party_package.B", "101:third_party_package.B"); 2742 } 2743 2744 @Test testNoDisableRecurrentlyOverusingPrePrioritizedApp()2745 public void testNoDisableRecurrentlyOverusingPrePrioritizedApp() throws Exception { 2746 setUpSampleUserAndPackages(); 2747 setRequiresDistractionOptimization(true); 2748 setDisplayStateEnabled(true); 2749 2750 mCarWatchdogService.setKillablePackageAsUser( 2751 "vendor_package.non_critical", new UserHandle(100), /* isKillable= */ false); 2752 mCarWatchdogService.setKillablePackageAsUser( 2753 "third_party_package.A", new UserHandle(101), /* isKillable= */ false); 2754 2755 List<PackageIoOveruseStats> packageIoOveruseStats = 2756 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true); 2757 2758 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 2759 2760 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).isEmpty(); 2761 2762 setRequiresDistractionOptimization(false); 2763 setDisplayStateEnabled(false); 2764 2765 captureAndVerifyIoOveruseStatsReported(sampleReportedOveruseStats()); 2766 2767 captureAndVerifyKillStatsReported(sampleReportedKillStats( 2768 CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE, 2769 /* killedUids= */ new int[]{10110004, 10010005})); 2770 2771 assertWithMessage("Disabled user packages").that(mDisabledUserPackages) 2772 .containsExactly("101:vendor_package.non_critical", "100:third_party_package.A", 2773 "100:third_party_package.B"); 2774 } 2775 2776 @Test testNoDisableRecurrentlyOverusingPostPrioritizedApp()2777 public void testNoDisableRecurrentlyOverusingPostPrioritizedApp() throws Exception { 2778 setUpSampleUserAndPackages(); 2779 setRequiresDistractionOptimization(true); 2780 setDisplayStateEnabled(true); 2781 2782 List<PackageIoOveruseStats> packageIoOveruseStats = 2783 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true); 2784 2785 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 2786 2787 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).isEmpty(); 2788 2789 mCarWatchdogService.setKillablePackageAsUser( 2790 "vendor_package.non_critical", new UserHandle(100), /* isKillable= */ false); 2791 mCarWatchdogService.setKillablePackageAsUser( 2792 "third_party_package.A", new UserHandle(101), /* isKillable= */ false); 2793 2794 setRequiresDistractionOptimization(false); 2795 setDisplayStateEnabled(false); 2796 2797 captureAndVerifyIoOveruseStatsReported(sampleReportedOveruseStats()); 2798 2799 captureAndVerifyKillStatsReported(sampleReportedKillStats( 2800 CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE, 2801 /* killedUids= */ new int[]{10110004, 10010005})); 2802 2803 assertWithMessage("Disabled user packages").that(mDisabledUserPackages) 2804 .containsExactly("101:vendor_package.non_critical", "100:third_party_package.A", 2805 "100:third_party_package.B"); 2806 } 2807 2808 @Test testDisableRecurrentlyOverusingPriorityResettedApp()2809 public void testDisableRecurrentlyOverusingPriorityResettedApp() throws Exception { 2810 setUpSampleUserAndPackages(); 2811 setRequiresDistractionOptimization(true); 2812 setDisplayStateEnabled(true); 2813 2814 mCarWatchdogService.setKillablePackageAsUser( 2815 "vendor_package.non_critical", new UserHandle(100), /* isKillable= */ false); 2816 2817 List<PackageIoOveruseStats> packageIoOveruseStats = 2818 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true); 2819 2820 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 2821 2822 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).isEmpty(); 2823 2824 mCarWatchdogService.setKillablePackageAsUser( 2825 "vendor_package.non_critical", new UserHandle(100), /* isKillable= */ true); 2826 2827 setRequiresDistractionOptimization(false); 2828 setDisplayStateEnabled(false); 2829 2830 captureAndVerifyIoOveruseStatsReported(sampleReportedOveruseStats()); 2831 2832 captureAndVerifyKillStatsReported(sampleReportedKillStats( 2833 CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__USER_NO_INTERACTION_MODE, 2834 /* killedUids= */ new int[]{10010004, 10110004, 10010005, 10110005})); 2835 2836 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).containsExactly( 2837 "100:vendor_package.non_critical", "101:vendor_package.non_critical", 2838 "100:third_party_package.A", "101:third_party_package.A", 2839 "100:third_party_package.B", "101:third_party_package.B"); 2840 } 2841 2842 @Test testImmediateDisableRecurrentlyOverusingAppDuringGarageMode()2843 public void testImmediateDisableRecurrentlyOverusingAppDuringGarageMode() 2844 throws Exception { 2845 setUpSampleUserAndPackages(); 2846 setRequiresDistractionOptimization(false); 2847 setDisplayStateEnabled(false); 2848 mBroadcastReceiver.onReceive(mMockContext, 2849 new Intent().setAction(CarWatchdogService.ACTION_GARAGE_MODE_ON)); 2850 2851 List<PackageIoOveruseStats> packageIoOveruseStats = 2852 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ true); 2853 2854 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 2855 2856 captureAndVerifyIoOveruseStatsReported(sampleReportedOveruseStats()); 2857 2858 captureAndVerifyKillStatsReported(sampleReportedKillStats( 2859 CAR_WATCHDOG_KILL_STATS_REPORTED__SYSTEM_STATE__GARAGE_MODE, 2860 /* killedUids= */ new int[]{10010004, 10110004, 10010005, 10110005})); 2861 2862 assertWithMessage("Disabled user packages").that(mDisabledUserPackages).containsExactly( 2863 "100:vendor_package.non_critical", "101:vendor_package.non_critical", 2864 "100:third_party_package.A", "101:third_party_package.A", 2865 "100:third_party_package.B", "101:third_party_package.B"); 2866 } 2867 2868 @Test testDisableHistoricalRecurrentlyOverusingApp()2869 public void testDisableHistoricalRecurrentlyOverusingApp() throws Exception { 2870 when(mMockWatchdogStorage 2871 .getNotForgivenHistoricalIoOveruses(RECURRING_OVERUSE_PERIOD_IN_DAYS)) 2872 .thenReturn(Arrays.asList(new WatchdogStorage.NotForgivenOverusesEntry(100, 2873 "third_party_package", 2))); 2874 2875 // Force CarWatchdogService to fetch historical not forgiven overuses. 2876 restartService(/* totalRestarts= */ 1); 2877 setRequiresDistractionOptimization(true); 2878 setDisplayStateEnabled(false); 2879 int thirdPartyPkgUid = UserHandle.getUid(100, 10005); 2880 2881 injectPackageInfos(Collections.singletonList(constructPackageManagerPackageInfo( 2882 "third_party_package", thirdPartyPkgUid, null))); 2883 2884 pushLatestIoOveruseStatsAndWait( 2885 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ false)); 2886 2887 // Third party package is disabled given the two historical overuses and one current 2888 // overuse. 2889 assertWithMessage("Disabled packages after recurring overuse with history") 2890 .that(mDisabledUserPackages) 2891 .containsExactlyElementsIn(Collections.singleton("100:third_party_package")); 2892 2893 // Package was enabled again. 2894 mDisabledUserPackages.clear(); 2895 2896 PackageIoOveruseStats packageIoOveruseStats = 2897 constructPackageIoOveruseStats(thirdPartyPkgUid, /* shouldNotify= */ true, 2898 /* forgivenWriteBytes= */ constructPerStateBytes(200, 400, 600), 2899 constructInternalIoOveruseStats(/* killableOnOveruse= */ true, 2900 /* remainingWriteBytes= */ constructPerStateBytes(0, 0, 0), 2901 /* writtenBytes= */ constructPerStateBytes(200, 400, 600), 2902 /* totalOveruses= */ 3)); 2903 2904 pushLatestIoOveruseStatsAndWait(Collections.singletonList(packageIoOveruseStats)); 2905 2906 // From the 3 total overuses, one overuse was forgiven previously. 2907 assertWithMessage("Disabled packages after non-recurring overuse") 2908 .that(mDisabledUserPackages).isEmpty(); 2909 2910 // Add one overuse. 2911 packageIoOveruseStats.ioOveruseStats.totalOveruses = 4; 2912 2913 pushLatestIoOveruseStatsAndWait(Collections.singletonList(packageIoOveruseStats)); 2914 2915 // Third party package is disabled again given the three current overuses. From the 4 total 2916 // overuses, one overuse was forgiven previously. 2917 assertWithMessage("Disabled packages after recurring overuse from the same day") 2918 .that(mDisabledUserPackages) 2919 .containsExactlyElementsIn(Collections.singleton("100:third_party_package")); 2920 2921 // Force write to database 2922 restartService(/* totalRestarts= */ 2); 2923 2924 verify(mMockWatchdogStorage).forgiveHistoricalOveruses(mPackagesByUserIdCaptor.capture(), 2925 eq(RECURRING_OVERUSE_PERIOD_IN_DAYS)); 2926 2927 assertWithMessage("Forgiven packages") 2928 .that(mPackagesByUserIdCaptor.getValue().get(100)) 2929 .containsExactlyElementsIn(Arrays.asList("third_party_package")); 2930 } 2931 2932 @Test testDisableHistoricalRecurrentlyOverusingAppAfterDateChange()2933 public void testDisableHistoricalRecurrentlyOverusingAppAfterDateChange() throws Exception { 2934 when(mMockWatchdogStorage.getNotForgivenHistoricalIoOveruses( 2935 eq(RECURRING_OVERUSE_PERIOD_IN_DAYS))) 2936 .thenReturn(Arrays.asList(new WatchdogStorage.NotForgivenOverusesEntry(100, 2937 "third_party_package", 2))); 2938 2939 mTimeSource.updateNow(/* numDaysAgo= */ 1); 2940 setRequiresDistractionOptimization(true); 2941 setDisplayStateEnabled(false); 2942 int thirdPartyPkgUid = UserHandle.getUid(100, 10005); 2943 2944 injectPackageInfos(Collections.singletonList(constructPackageManagerPackageInfo( 2945 "third_party_package", thirdPartyPkgUid, null))); 2946 2947 List<PackageIoOveruseStats> ioOveruseStats = 2948 sampleIoOveruseStats(/* requireRecurrentOveruseStats= */ false); 2949 pushLatestIoOveruseStatsAndWait(ioOveruseStats); 2950 2951 // Third party package is disabled given the two historical overuses and one current 2952 // overuse. 2953 assertThat(mDisabledUserPackages) 2954 .containsExactlyElementsIn(Collections.singleton("100:third_party_package")); 2955 2956 // Force write to database by pushing non-overusing I/O overuse stats. 2957 mTimeSource.updateNow(/* numDaysAgo= */ 0); 2958 pushLatestIoOveruseStatsAndWait(Collections.singletonList(ioOveruseStats.get(0))); 2959 2960 verify(mMockWatchdogStorage).forgiveHistoricalOveruses(mPackagesByUserIdCaptor.capture(), 2961 eq(RECURRING_OVERUSE_PERIOD_IN_DAYS)); 2962 2963 assertWithMessage("Forgiven packages") 2964 .that(mPackagesByUserIdCaptor.getValue().get(100)) 2965 .containsExactlyElementsIn(Arrays.asList("third_party_package")); 2966 } 2967 2968 2969 @Test testResetResourceOveruseStatsResetsStats()2970 public void testResetResourceOveruseStatsResetsStats() throws Exception { 2971 UserHandle user = UserHandle.getUserHandleForUid(10003346); 2972 String packageName = mMockContext.getPackageName(); 2973 mGenericPackageNameByUid.put(10003346, packageName); 2974 mGenericPackageNameByUid.put(10101278, "vendor_package.critical"); 2975 injectIoOveruseStatsForPackages( 2976 mGenericPackageNameByUid, /* killablePackages= */ new ArraySet<>(), 2977 /* shouldNotifyPackages= */ new ArraySet<>()); 2978 2979 mWatchdogServiceForSystemImpl.resetResourceOveruseStats( 2980 Collections.singletonList(packageName)); 2981 2982 ResourceOveruseStats actualStats = 2983 mCarWatchdogService.getResourceOveruseStatsForUserPackage( 2984 packageName, user, 2985 CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, 2986 CarWatchdogManager.STATS_PERIOD_CURRENT_DAY); 2987 2988 ResourceOveruseStats expectedStats = new ResourceOveruseStats.Builder( 2989 packageName, user).build(); 2990 2991 ResourceOveruseStatsSubject.assertEquals(actualStats, expectedStats); 2992 2993 verify(mMockWatchdogStorage).deleteUserPackage(eq(user.getIdentifier()), eq(packageName)); 2994 } 2995 2996 @Test testResetResourceOveruseStatsEnablesPackage()2997 public void testResetResourceOveruseStatsEnablesPackage() throws Exception { 2998 injectPackageInfos(Arrays.asList( 2999 constructPackageManagerPackageInfo("third_party_package.A", 10012345, 3000 /* sharedUserId= */ null), 3001 constructPackageManagerPackageInfo("vendor_package.critical.A", 10014567, 3002 "vendor_shared_package.A"), 3003 constructPackageManagerPackageInfo("vendor_package.critical.B", 10014567, 3004 "vendor_shared_package.A"), 3005 constructPackageManagerPackageInfo("system_package.critical.A", 10001278, 3006 "system_shared_package.A"), 3007 constructPackageManagerPackageInfo("third_party_package.B", 10056790, 3008 /* sharedUserId= */ null), 3009 constructPackageManagerPackageInfo("system_package.non_critical.B", 10007345, 3010 "system_shared_package.B"))); 3011 3012 injectIoOveruseStatsForPackages( 3013 mGenericPackageNameByUid, /* killablePackages= */ new ArraySet<>(), 3014 /* shouldNotifyPackages= */ new ArraySet<>()); 3015 3016 doReturn(COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED).when(mSpiedPackageManager) 3017 .getApplicationEnabledSetting( 3018 or(or(eq("third_party_package.A"), eq("vendor_package.critical.A")), 3019 eq("vendor_package.critical.B")), eq(100)); 3020 3021 mWatchdogServiceForSystemImpl.resetResourceOveruseStats( 3022 Arrays.asList("third_party_package.A", "shared:vendor_shared_package.A", 3023 "shared:system_shared_package.A", "third_party_package.B")); 3024 3025 verify(mSpiedPackageManager).getApplicationEnabledSetting("third_party_package.A", 100); 3026 verify(mSpiedPackageManager).getApplicationEnabledSetting("vendor_package.critical.A", 100); 3027 verify(mSpiedPackageManager).getApplicationEnabledSetting("vendor_package.critical.B", 100); 3028 verify(mSpiedPackageManager).getApplicationEnabledSetting("system_package.critical.A", 100); 3029 verify(mSpiedPackageManager).getApplicationEnabledSetting("third_party_package.B", 100); 3030 3031 verify(mSpiedPackageManager).setApplicationEnabledSetting(eq("third_party_package.A"), 3032 eq(COMPONENT_ENABLED_STATE_ENABLED), anyInt(), eq(100), anyString()); 3033 verify(mSpiedPackageManager).setApplicationEnabledSetting(eq("vendor_package.critical.A"), 3034 eq(COMPONENT_ENABLED_STATE_ENABLED), anyInt(), eq(100), anyString()); 3035 verify(mSpiedPackageManager).setApplicationEnabledSetting(eq("vendor_package.critical.B"), 3036 eq(COMPONENT_ENABLED_STATE_ENABLED), anyInt(), eq(100), anyString()); 3037 3038 verifyNoMoreInteractions(mSpiedPackageManager); 3039 } 3040 3041 @Test testResetResourceOveruseStatsResetsUserPackageSettings()3042 public void testResetResourceOveruseStatsResetsUserPackageSettings() throws Exception { 3043 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 100, 101); 3044 injectPackageInfos(Arrays.asList( 3045 constructPackageManagerPackageInfo("third_party_package.A", 10001278, null), 3046 constructPackageManagerPackageInfo("third_party_package.A", 10101278, null), 3047 constructPackageManagerPackageInfo("third_party_package.B", 10003346, null), 3048 constructPackageManagerPackageInfo("third_party_package.B", 10103346, null))); 3049 injectIoOveruseStatsForPackages(mGenericPackageNameByUid, 3050 /* killablePackages= */ Set.of("third_party_package.A", "third_party_package.B"), 3051 /* shouldNotifyPackages= */ new ArraySet<>()); 3052 3053 mCarWatchdogService.setKillablePackageAsUser("third_party_package.A", 3054 UserHandle.ALL, /* isKillable= */false); 3055 mCarWatchdogService.setKillablePackageAsUser("third_party_package.B", 3056 UserHandle.ALL, /* isKillable= */false); 3057 3058 mWatchdogServiceForSystemImpl.resetResourceOveruseStats( 3059 Collections.singletonList("third_party_package.A")); 3060 3061 PackageKillableStateSubject.assertThat( 3062 mCarWatchdogService.getPackageKillableStatesAsUser(UserHandle.ALL)).containsExactly( 3063 new PackageKillableState("third_party_package.A", 100, 3064 PackageKillableState.KILLABLE_STATE_YES), 3065 new PackageKillableState("third_party_package.A", 101, 3066 PackageKillableState.KILLABLE_STATE_YES), 3067 new PackageKillableState("third_party_package.B", 100, 3068 PackageKillableState.KILLABLE_STATE_NO), 3069 new PackageKillableState("third_party_package.B", 101, 3070 PackageKillableState.KILLABLE_STATE_NO) 3071 ); 3072 3073 verify(mMockWatchdogStorage, times(2)).deleteUserPackage(anyInt(), 3074 eq("third_party_package.A")); 3075 } 3076 3077 @Test testPullSystemIoUsageSummaryAtomsWithRestart()3078 public void testPullSystemIoUsageSummaryAtomsWithRestart() throws Exception { 3079 List<StatsEvent> events = new ArrayList<>(); 3080 assertWithMessage("Stats pull atom callback status") 3081 .that(mStatsPullAtomCallback.onPullAtom(CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY, 3082 events)).isEqualTo(PULL_SUCCESS); 3083 3084 List<AtomsProto.CarWatchdogSystemIoUsageSummary> expectedSummaries = 3085 verifyAndGetSystemIoUsageSummaries( 3086 mTimeSource.getCurrentDate().minus(RETENTION_PERIOD)); 3087 3088 assertWithMessage("First pulled system I/O usage summary atoms") 3089 .that(mPulledSystemIoUsageSummaries).containsExactlyElementsIn(expectedSummaries); 3090 mPulledSystemIoUsageSummaries.clear(); 3091 3092 restartService(/* totalRestarts= */ 1); 3093 3094 assertWithMessage("Status of stats pull atom callback after restart") 3095 .that(mStatsPullAtomCallback.onPullAtom(CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY, 3096 events)).isEqualTo(PULL_SUCCESS); 3097 3098 assertWithMessage("Pulled system I/O usage summary atoms after restart") 3099 .that(mPulledSystemIoUsageSummaries).isEmpty(); 3100 3101 verifyNoMoreInteractions(mMockWatchdogStorage); 3102 } 3103 3104 @Test testPullSystemIoUsageSummaryAtomsWithDateChange()3105 public void testPullSystemIoUsageSummaryAtomsWithDateChange() throws Exception { 3106 mTimeSource.updateNow(/* numDaysAgo= */ 7); 3107 3108 List<StatsEvent> events = new ArrayList<>(); 3109 assertWithMessage("Stats pull atom callback status") 3110 .that(mStatsPullAtomCallback.onPullAtom(CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY, 3111 events)).isEqualTo(PULL_SUCCESS); 3112 3113 List<AtomsProto.CarWatchdogSystemIoUsageSummary> expectedSummaries = 3114 verifyAndGetSystemIoUsageSummaries( 3115 mTimeSource.getCurrentDate().minus(RETENTION_PERIOD)); 3116 3117 assertWithMessage("First pulled system I/O usage summary atoms") 3118 .that(mPulledSystemIoUsageSummaries).containsExactlyElementsIn(expectedSummaries); 3119 mPulledSystemIoUsageSummaries.clear(); 3120 3121 mTimeSource.updateNow(/* numDaysAgo= */ 6); 3122 3123 assertWithMessage("Status of stats pull atom callback within the same week") 3124 .that(mStatsPullAtomCallback.onPullAtom(CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY, 3125 events)).isEqualTo(PULL_SUCCESS); 3126 3127 assertWithMessage("Pulled system I/O usage summary atoms within the same week") 3128 .that(mPulledSystemIoUsageSummaries).isEmpty(); 3129 3130 mTimeSource.updateNow(/* numDaysAgo= */ 0); 3131 3132 assertWithMessage("Status of stats pull atom callback after a week") 3133 .that(mStatsPullAtomCallback.onPullAtom(CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY, 3134 events)).isEqualTo(PULL_SUCCESS); 3135 3136 expectedSummaries = verifyAndGetSystemIoUsageSummaries( 3137 mTimeSource.getCurrentDate().minus(1, ChronoUnit.WEEKS)); 3138 3139 assertWithMessage("Pulled system I/O usage summary atoms after a week") 3140 .that(mPulledSystemIoUsageSummaries).containsExactlyElementsIn(expectedSummaries); 3141 3142 verifyNoMoreInteractions(mMockWatchdogStorage); 3143 } 3144 3145 @Test testPullUidIoUsageSummaryAtomsForTopUids()3146 public void testPullUidIoUsageSummaryAtomsForTopUids() throws Exception { 3147 injectPackageInfos(Arrays.asList( 3148 constructPackageManagerPackageInfo("system_package.critical.A", 10000345, null), 3149 constructPackageManagerPackageInfo("third_party_package.B", 10004675, null), 3150 constructPackageManagerPackageInfo("system_package.critical.B", 10010001, null), 3151 constructPackageManagerPackageInfo("vendor_package.non_critical", 10110004, null), 3152 constructPackageManagerPackageInfo("third_party_package.A", 10110005, 3153 "third_party_shared_package"))); 3154 3155 List<StatsEvent> events = new ArrayList<>(); 3156 assertWithMessage("Stats pull atom callback status") 3157 .that(mStatsPullAtomCallback.onPullAtom(CAR_WATCHDOG_UID_IO_USAGE_SUMMARY, 3158 events)).isEqualTo(PULL_SUCCESS); 3159 3160 List<AtomsProto.CarWatchdogUidIoUsageSummary> expectedSummaries = 3161 verifyAndGetUidIoUsageSummaries( 3162 mTimeSource.getCurrentDate().minus(RETENTION_PERIOD), 3163 /* expectUids= */ Arrays.asList(10010001, 10110004, 10110005)); 3164 3165 assertWithMessage(String.format("Pulled uid I/O usage summary atoms for top %d UIDs", 3166 UID_IO_USAGE_SUMMARY_TOP_COUNT)).that(mPulledUidIoUsageSummaries) 3167 .containsExactlyElementsIn(expectedSummaries); 3168 } 3169 3170 @Test testPullUidIoUsageSummaryAtomsWithRestart()3171 public void testPullUidIoUsageSummaryAtomsWithRestart() throws Exception { 3172 injectPackageInfos(Arrays.asList( 3173 constructPackageManagerPackageInfo("system_package.critical", 10010001, null), 3174 constructPackageManagerPackageInfo("vendor_package.non_critical", 10110004, null), 3175 constructPackageManagerPackageInfo("third_party_package.A", 10110005, 3176 "third_party_shared_package"))); 3177 3178 List<StatsEvent> events = new ArrayList<>(); 3179 assertWithMessage("Stats pull atom callback status") 3180 .that(mStatsPullAtomCallback.onPullAtom(CAR_WATCHDOG_UID_IO_USAGE_SUMMARY, 3181 events)).isEqualTo(PULL_SUCCESS); 3182 3183 List<AtomsProto.CarWatchdogUidIoUsageSummary> expectedSummaries = 3184 verifyAndGetUidIoUsageSummaries( 3185 mTimeSource.getCurrentDate().minus(RETENTION_PERIOD), 3186 /* expectUids= */ Arrays.asList(10010001, 10110004, 10110005)); 3187 3188 assertWithMessage("First pulled uid I/O usage summary atoms") 3189 .that(mPulledUidIoUsageSummaries).containsExactlyElementsIn(expectedSummaries); 3190 mPulledUidIoUsageSummaries.clear(); 3191 3192 restartService(/* totalRestarts= */ 1); 3193 3194 assertWithMessage("Status of stats pull atom callback after restart") 3195 .that(mStatsPullAtomCallback.onPullAtom(CAR_WATCHDOG_UID_IO_USAGE_SUMMARY, 3196 events)).isEqualTo(PULL_SUCCESS); 3197 3198 assertWithMessage("Pulled uid I/O usage summary atoms after restart") 3199 .that(mPulledUidIoUsageSummaries).isEmpty(); 3200 3201 verifyNoMoreInteractions(mMockWatchdogStorage); 3202 } 3203 3204 @Test testPullUidIoUsageSummaryAtomsWithDateChange()3205 public void testPullUidIoUsageSummaryAtomsWithDateChange() throws Exception { 3206 injectPackageInfos(Arrays.asList( 3207 constructPackageManagerPackageInfo("system_package.critical", 10010001, null), 3208 constructPackageManagerPackageInfo("vendor_package.non_critical", 10110004, null), 3209 constructPackageManagerPackageInfo("third_party_package.A", 10110005, 3210 "third_party_shared_package"))); 3211 3212 mTimeSource.updateNow(/* numDaysAgo= */ 7); 3213 3214 List<StatsEvent> events = new ArrayList<>(); 3215 assertWithMessage("Stats pull atom callback status") 3216 .that(mStatsPullAtomCallback.onPullAtom(CAR_WATCHDOG_UID_IO_USAGE_SUMMARY, 3217 events)).isEqualTo(PULL_SUCCESS); 3218 3219 List<AtomsProto.CarWatchdogUidIoUsageSummary> expectedSummaries = 3220 verifyAndGetUidIoUsageSummaries( 3221 mTimeSource.getCurrentDate().minus(RETENTION_PERIOD), 3222 /* expectUids= */ Arrays.asList(10010001, 10110004, 10110005)); 3223 3224 assertWithMessage("First pulled uid I/O usage summary atoms") 3225 .that(mPulledUidIoUsageSummaries).containsExactlyElementsIn(expectedSummaries); 3226 mPulledUidIoUsageSummaries.clear(); 3227 3228 mTimeSource.updateNow(/* numDaysAgo= */ 6); 3229 3230 assertWithMessage("Status of stats pull atom callback within the same week") 3231 .that(mStatsPullAtomCallback.onPullAtom(CAR_WATCHDOG_UID_IO_USAGE_SUMMARY, 3232 events)).isEqualTo(PULL_SUCCESS); 3233 3234 assertWithMessage("Pulled uid I/O usage summary atoms within the same week") 3235 .that(mPulledUidIoUsageSummaries).isEmpty(); 3236 3237 mTimeSource.updateNow(/* numDaysAgo= */ 0); 3238 3239 assertWithMessage("Status of stats pull atom callback after a week") 3240 .that(mStatsPullAtomCallback.onPullAtom(CAR_WATCHDOG_UID_IO_USAGE_SUMMARY, 3241 events)).isEqualTo(PULL_SUCCESS); 3242 3243 expectedSummaries = verifyAndGetUidIoUsageSummaries( 3244 mTimeSource.getCurrentDate().minus(1, ChronoUnit.WEEKS), 3245 /* expectUids= */ Arrays.asList(10010001, 10110004, 10110005)); 3246 3247 assertWithMessage("Pulled uid I/O usage summary atoms after a week") 3248 .that(mPulledUidIoUsageSummaries).containsExactlyElementsIn(expectedSummaries); 3249 3250 verifyNoMoreInteractions(mMockWatchdogStorage); 3251 } 3252 3253 @Test testPullInvalidAtoms()3254 public void testPullInvalidAtoms() throws Exception { 3255 List<StatsEvent> actualEvents = new ArrayList<>(); 3256 assertWithMessage("Stats pull atom callback status").that(mStatsPullAtomCallback.onPullAtom( 3257 0, actualEvents)).isEqualTo(PULL_SKIP); 3258 assertWithMessage("Pulled stats events").that(actualEvents).isEmpty(); 3259 } 3260 3261 @Test testGetPackageInfosForUids()3262 public void testGetPackageInfosForUids() throws Exception { 3263 injectPackageInfos(Arrays.asList( 3264 constructPackageManagerPackageInfo( 3265 "system_package.A", 6001, null, ApplicationInfo.FLAG_SYSTEM, 0), 3266 constructPackageManagerPackageInfo( 3267 "vendor_package.B", 5100, null, 0, ApplicationInfo.PRIVATE_FLAG_OEM), 3268 constructPackageManagerPackageInfo( 3269 "vendor_package.C", 1345678, null, 0, ApplicationInfo.PRIVATE_FLAG_ODM), 3270 constructPackageManagerPackageInfo("third_party_package.D", 120056, null))); 3271 3272 int[] uids = new int[]{6001, 5100, 120056, 1345678}; 3273 List<PackageInfo> actualPackageInfos = mWatchdogServiceForSystemImpl.getPackageInfosForUids( 3274 uids, new ArrayList<>()); 3275 3276 List<PackageInfo> expectedPackageInfos = Arrays.asList( 3277 constructPackageInfo("system_package.A", 6001, new ArrayList<>(), 3278 UidType.NATIVE, ComponentType.SYSTEM, ApplicationCategoryType.OTHERS), 3279 constructPackageInfo("vendor_package.B", 5100, new ArrayList<>(), 3280 UidType.NATIVE, ComponentType.VENDOR, ApplicationCategoryType.OTHERS), 3281 constructPackageInfo("third_party_package.D", 120056, new ArrayList<>(), 3282 UidType.APPLICATION, ComponentType.THIRD_PARTY, 3283 ApplicationCategoryType.OTHERS), 3284 constructPackageInfo("vendor_package.C", 1345678, new ArrayList<>(), 3285 UidType.APPLICATION, ComponentType.VENDOR, 3286 ApplicationCategoryType.OTHERS)); 3287 3288 assertPackageInfoEquals(actualPackageInfos, expectedPackageInfos); 3289 } 3290 3291 @Test testGetPackageInfosWithSharedUids()3292 public void testGetPackageInfosWithSharedUids() throws Exception { 3293 injectPackageInfos(Arrays.asList( 3294 constructPackageManagerPackageInfo("system_package.A", 6050, 3295 "system_shared_package", ApplicationInfo.FLAG_UPDATED_SYSTEM_APP, 0), 3296 constructPackageManagerPackageInfo("system_package.B", 110035, 3297 "vendor_shared_package", 0, ApplicationInfo.PRIVATE_FLAG_PRODUCT), 3298 constructPackageManagerPackageInfo("vendor_package.C", 110035, 3299 "vendor_shared_package", 0, ApplicationInfo.PRIVATE_FLAG_VENDOR), 3300 constructPackageManagerPackageInfo( 3301 "third_party_package.D", 6050, "system_shared_package"), 3302 constructPackageManagerPackageInfo( 3303 "third_party_package.E", 110035, "vendor_shared_package"), 3304 constructPackageManagerPackageInfo( 3305 "third_party_package.F", 120078, "third_party_shared_package"))); 3306 3307 int[] uids = new int[]{6050, 110035, 120056, 120078}; 3308 List<PackageInfo> actualPackageInfos = mWatchdogServiceForSystemImpl.getPackageInfosForUids( 3309 uids, new ArrayList<>()); 3310 3311 List<PackageInfo> expectedPackageInfos = Arrays.asList( 3312 constructPackageInfo("shared:system_shared_package", 6050, 3313 Arrays.asList("system_package.A", "third_party_package.D"), 3314 UidType.NATIVE, ComponentType.SYSTEM, ApplicationCategoryType.OTHERS), 3315 constructPackageInfo("shared:vendor_shared_package", 110035, 3316 Arrays.asList("vendor_package.C", "system_package.B", 3317 "third_party_package.E"), UidType.APPLICATION, 3318 ComponentType.VENDOR, ApplicationCategoryType.OTHERS), 3319 constructPackageInfo("shared:third_party_shared_package", 120078, 3320 Collections.singletonList("third_party_package.F"), 3321 UidType.APPLICATION, ComponentType.THIRD_PARTY, 3322 ApplicationCategoryType.OTHERS)); 3323 3324 assertPackageInfoEquals(actualPackageInfos, expectedPackageInfos); 3325 } 3326 3327 @Test testGetPackageInfosForUidsWithVendorPackagePrefixes()3328 public void testGetPackageInfosForUidsWithVendorPackagePrefixes() throws Exception { 3329 injectPackageInfos(Arrays.asList( 3330 constructPackageManagerPackageInfo( 3331 "vendor_package.A", 110034, null, 0, ApplicationInfo.PRIVATE_FLAG_PRODUCT), 3332 constructPackageManagerPackageInfo("vendor_pkg.B", 110035, 3333 "vendor_shared_package", ApplicationInfo.FLAG_SYSTEM, 0), 3334 constructPackageManagerPackageInfo( 3335 "third_party_package.C", 110035, "vendor_shared_package"), 3336 constructPackageManagerPackageInfo( 3337 "third_party_package.D", 110035, "vendor_shared_package"), 3338 constructPackageManagerPackageInfo( 3339 "third_party_package.F", 120078, "third_party_shared_package"), 3340 constructPackageManagerPackageInfo("vndr_pkg.G", 126345, "vendor_package.shared", 3341 ApplicationInfo.FLAG_SYSTEM, 0), 3342 /* 3343 * A 3p package pretending to be a vendor package because 3p packages won't have the 3344 * required flags. 3345 */ 3346 constructPackageManagerPackageInfo("vendor_package.imposter", 123456, null, 0, 0))); 3347 3348 int[] uids = new int[]{110034, 110035, 120078, 126345, 123456}; 3349 List<PackageInfo> actualPackageInfos = mWatchdogServiceForSystemImpl.getPackageInfosForUids( 3350 uids, Arrays.asList("vendor_package.", "vendor_pkg.", "shared:vendor_package.")); 3351 3352 List<PackageInfo> expectedPackageInfos = Arrays.asList( 3353 constructPackageInfo("vendor_package.A", 110034, new ArrayList<>(), 3354 UidType.APPLICATION, ComponentType.VENDOR, ApplicationCategoryType.OTHERS), 3355 constructPackageInfo("shared:vendor_shared_package", 110035, 3356 Arrays.asList("vendor_pkg.B", "third_party_package.C", 3357 "third_party_package.D"), UidType.APPLICATION, 3358 ComponentType.VENDOR, ApplicationCategoryType.OTHERS), 3359 constructPackageInfo("shared:third_party_shared_package", 120078, 3360 Collections.singletonList("third_party_package.F"), UidType.APPLICATION, 3361 ComponentType.THIRD_PARTY, ApplicationCategoryType.OTHERS), 3362 constructPackageInfo("shared:vendor_package.shared", 126345, 3363 Collections.singletonList("vndr_pkg.G"), UidType.APPLICATION, 3364 ComponentType.VENDOR, ApplicationCategoryType.OTHERS), 3365 constructPackageInfo("vendor_package.imposter", 123456, 3366 new ArrayList<>(), UidType.APPLICATION, ComponentType.THIRD_PARTY, 3367 ApplicationCategoryType.OTHERS)); 3368 3369 assertPackageInfoEquals(actualPackageInfos, expectedPackageInfos); 3370 } 3371 3372 @Test testGetPackageInfosForUidsWithMissingApplicationInfos()3373 public void testGetPackageInfosForUidsWithMissingApplicationInfos() throws Exception { 3374 injectPackageInfos(Arrays.asList( 3375 constructPackageManagerPackageInfo( 3376 "vendor_package.A", 110034, null, 0, ApplicationInfo.PRIVATE_FLAG_OEM), 3377 constructPackageManagerPackageInfo("vendor_package.B", 110035, 3378 "vendor_shared_package", 0, ApplicationInfo.PRIVATE_FLAG_VENDOR), 3379 constructPackageManagerPackageInfo( 3380 "third_party_package.C", 110035, "vendor_shared_package"))); 3381 3382 BiConsumer<Integer, String> addPackageToSharedUid = (uid, packageName) -> { 3383 List<String> packages = mPackagesBySharedUid.get(uid); 3384 if (packages == null) { 3385 packages = new ArrayList<>(); 3386 } 3387 packages.add(packageName); 3388 mPackagesBySharedUid.put(uid, packages); 3389 }; 3390 3391 addPackageToSharedUid.accept(110035, "third_party.package.G"); 3392 mGenericPackageNameByUid.put(120056, "third_party.package.H"); 3393 mGenericPackageNameByUid.put(120078, "shared:third_party_shared_package"); 3394 addPackageToSharedUid.accept(120078, "third_party_package.I"); 3395 3396 3397 int[] uids = new int[]{110034, 110035, 120056, 120078}; 3398 3399 List<PackageInfo> actualPackageInfos = mWatchdogServiceForSystemImpl.getPackageInfosForUids( 3400 uids, new ArrayList<>()); 3401 3402 List<PackageInfo> expectedPackageInfos = Arrays.asList( 3403 constructPackageInfo("vendor_package.A", 110034, new ArrayList<>(), 3404 UidType.APPLICATION, ComponentType.VENDOR, ApplicationCategoryType.OTHERS), 3405 constructPackageInfo("shared:vendor_shared_package", 110035, 3406 Arrays.asList("vendor_package.B", "third_party_package.C", 3407 "third_party.package.G"), 3408 UidType.APPLICATION, ComponentType.VENDOR, ApplicationCategoryType.OTHERS), 3409 constructPackageInfo("third_party.package.H", 120056, new ArrayList<>(), 3410 UidType.APPLICATION, ComponentType.UNKNOWN, 3411 ApplicationCategoryType.OTHERS), 3412 constructPackageInfo("shared:third_party_shared_package", 120078, 3413 Collections.singletonList("third_party_package.I"), 3414 UidType.APPLICATION, ComponentType.UNKNOWN, 3415 ApplicationCategoryType.OTHERS)); 3416 3417 assertPackageInfoEquals(actualPackageInfos, expectedPackageInfos); 3418 } 3419 3420 @Test testSetProcessHealthCheckEnabled()3421 public void testSetProcessHealthCheckEnabled() throws Exception { 3422 mCarWatchdogService.controlProcessHealthCheck(true); 3423 3424 verify(mMockCarWatchdogDaemon).controlProcessHealthCheck(eq(true)); 3425 } 3426 3427 @Test testSetProcessHealthCheckEnabledWithDisconnectedDaemon()3428 public void testSetProcessHealthCheckEnabledWithDisconnectedDaemon() throws Exception { 3429 crashWatchdogDaemon(); 3430 3431 assertThrows(IllegalStateException.class, 3432 () -> mCarWatchdogService.controlProcessHealthCheck(false)); 3433 3434 verify(mMockCarWatchdogDaemon, never()).controlProcessHealthCheck(anyBoolean()); 3435 } 3436 3437 @Test testOveruseConfigurationCacheGetVendorPackagePrefixes()3438 public void testOveruseConfigurationCacheGetVendorPackagePrefixes() throws Exception { 3439 OveruseConfigurationCache cache = new OveruseConfigurationCache(); 3440 3441 cache.set(sampleInternalResourceOveruseConfigurations()); 3442 3443 assertWithMessage("Vendor package prefixes").that(cache.getVendorPackagePrefixes()) 3444 .containsExactly("vendor_package", "some_pkg_as_vendor_pkg"); 3445 } 3446 3447 @Test testOveruseConfigurationCacheFetchThreshold()3448 public void testOveruseConfigurationCacheFetchThreshold() throws Exception { 3449 OveruseConfigurationCache cache = new OveruseConfigurationCache(); 3450 3451 cache.set(sampleInternalResourceOveruseConfigurations()); 3452 3453 InternalPerStateBytesSubject.assertWithMessage( 3454 cache.fetchThreshold("system_package.non_critical.A", ComponentType.SYSTEM), 3455 "System package with generic threshold") 3456 .isEqualTo(constructPerStateBytes(10, 20, 30)); 3457 3458 InternalPerStateBytesSubject.assertWithMessage( 3459 cache.fetchThreshold("system_package.A", ComponentType.SYSTEM), 3460 "System package with package specific threshold") 3461 .isEqualTo(constructPerStateBytes(40, 50, 60)); 3462 3463 InternalPerStateBytesSubject.assertWithMessage( 3464 cache.fetchThreshold("system_package.MEDIA", ComponentType.SYSTEM), 3465 "System package with media category threshold") 3466 .isEqualTo(constructPerStateBytes(200, 400, 600)); 3467 3468 InternalPerStateBytesSubject.assertWithMessage( 3469 cache.fetchThreshold("vendor_package.non_critical.A", ComponentType.VENDOR), 3470 "Vendor package with generic threshold") 3471 .isEqualTo(constructPerStateBytes(20, 40, 60)); 3472 3473 InternalPerStateBytesSubject.assertWithMessage( 3474 cache.fetchThreshold("vendor_package.A", ComponentType.VENDOR), 3475 "Vendor package with package specific threshold") 3476 .isEqualTo(constructPerStateBytes(80, 100, 120)); 3477 3478 InternalPerStateBytesSubject.assertWithMessage( 3479 cache.fetchThreshold("vendor_package.MEDIA", ComponentType.VENDOR), 3480 "Vendor package with media category threshold") 3481 .isEqualTo(constructPerStateBytes(200, 400, 600)); 3482 3483 InternalPerStateBytesSubject.assertWithMessage( 3484 cache.fetchThreshold("third_party_package.A", 3485 ComponentType.THIRD_PARTY), 3486 "3p package with generic threshold").isEqualTo(constructPerStateBytes(30, 60, 90)); 3487 3488 InternalPerStateBytesSubject.assertWithMessage( 3489 cache.fetchThreshold("third_party_package.MAPS", ComponentType.VENDOR), 3490 "3p package with maps category threshold") 3491 .isEqualTo(constructPerStateBytes(2200, 4400, 6600)); 3492 } 3493 3494 @Test testOveruseConfigurationCacheIsSafeToKill()3495 public void testOveruseConfigurationCacheIsSafeToKill() throws Exception { 3496 OveruseConfigurationCache cache = new OveruseConfigurationCache(); 3497 3498 cache.set(sampleInternalResourceOveruseConfigurations()); 3499 3500 assertWithMessage("isSafeToKill non-critical system package").that(cache.isSafeToKill( 3501 "system_package.non_critical.A", ComponentType.SYSTEM, null)).isTrue(); 3502 3503 assertWithMessage("isSafeToKill shared non-critical system package") 3504 .that(cache.isSafeToKill("system_package.A", ComponentType.SYSTEM, 3505 Collections.singletonList("system_package.non_critical.A"))).isTrue(); 3506 3507 assertWithMessage("isSafeToKill non-critical vendor package").that(cache.isSafeToKill( 3508 "vendor_package.non_critical.A", ComponentType.VENDOR, null)).isTrue(); 3509 3510 assertWithMessage("isSafeToKill shared non-critical vendor package") 3511 .that(cache.isSafeToKill("vendor_package.A", ComponentType.VENDOR, 3512 Collections.singletonList("vendor_package.non_critical.A"))).isTrue(); 3513 3514 assertWithMessage("isSafeToKill 3p package").that(cache.isSafeToKill( 3515 "third_party_package.A", ComponentType.THIRD_PARTY, null)).isTrue(); 3516 3517 assertWithMessage("isSafeToKill critical system package").that(cache.isSafeToKill( 3518 "system_package.A", ComponentType.SYSTEM, null)).isFalse(); 3519 3520 assertWithMessage("isSafeToKill critical vendor package").that(cache.isSafeToKill( 3521 "vendor_package.A", ComponentType.VENDOR, null)).isFalse(); 3522 } 3523 3524 @Test testOverwriteOveruseConfigurationCache()3525 public void testOverwriteOveruseConfigurationCache() throws Exception { 3526 OveruseConfigurationCache cache = new OveruseConfigurationCache(); 3527 3528 cache.set(sampleInternalResourceOveruseConfigurations()); 3529 3530 cache.set(new ArrayList<>()); 3531 3532 assertWithMessage("Vendor package prefixes").that(cache.getVendorPackagePrefixes()) 3533 .isEmpty(); 3534 3535 InternalPerStateBytesSubject.assertWithMessage( 3536 cache.fetchThreshold("system_package.A", ComponentType.SYSTEM), 3537 "System package with default threshold") 3538 .isEqualTo(OveruseConfigurationCache.DEFAULT_THRESHOLD); 3539 3540 InternalPerStateBytesSubject.assertWithMessage( 3541 cache.fetchThreshold("vendor_package.A", ComponentType.VENDOR), 3542 "Vendor package with default threshold") 3543 .isEqualTo(OveruseConfigurationCache.DEFAULT_THRESHOLD); 3544 3545 InternalPerStateBytesSubject.assertWithMessage( 3546 cache.fetchThreshold("third_party_package.A", ComponentType.THIRD_PARTY), 3547 "3p package with default threshold") 3548 .isEqualTo(OveruseConfigurationCache.DEFAULT_THRESHOLD); 3549 3550 assertWithMessage("isSafeToKill any system package").that(cache.isSafeToKill( 3551 "system_package.non_critical.A", ComponentType.SYSTEM, null)).isFalse(); 3552 3553 assertWithMessage("isSafeToKill any vendor package").that(cache.isSafeToKill( 3554 "vendor_package.non_critical.A", ComponentType.VENDOR, null)).isFalse(); 3555 } 3556 constructPerStateBytes( long fgBytes, long bgBytes, long gmBytes)3557 public static android.automotive.watchdog.PerStateBytes constructPerStateBytes( 3558 long fgBytes, long bgBytes, long gmBytes) { 3559 android.automotive.watchdog.PerStateBytes perStateBytes = 3560 new android.automotive.watchdog.PerStateBytes(); 3561 perStateBytes.foregroundBytes = fgBytes; 3562 perStateBytes.backgroundBytes = bgBytes; 3563 perStateBytes.garageModeBytes = gmBytes; 3564 return perStateBytes; 3565 } 3566 mockWatchdogDaemon()3567 private void mockWatchdogDaemon() throws Exception { 3568 when(mMockBinder.queryLocalInterface(anyString())).thenReturn(mMockCarWatchdogDaemon); 3569 when(mMockCarWatchdogDaemon.asBinder()).thenReturn(mMockBinder); 3570 doReturn(mMockBinder).when(() -> ServiceManager.getService(CAR_WATCHDOG_DAEMON_INTERFACE)); 3571 when(mMockCarWatchdogDaemon.getResourceOveruseConfigurations()).thenReturn( 3572 sampleInternalResourceOveruseConfigurations()); 3573 mIsDaemonCrashed = false; 3574 } 3575 mockWatchdogStorage()3576 private void mockWatchdogStorage() { 3577 when(mMockWatchdogStorage.saveUserPackageSettings(any())).thenAnswer((args) -> { 3578 mUserPackageSettingsEntries.addAll(args.getArgument(0)); 3579 return true; 3580 }); 3581 when(mMockWatchdogStorage.saveIoUsageStats(any())).thenAnswer((args) -> { 3582 List<WatchdogStorage.IoUsageStatsEntry> ioUsageStatsEntries = args.getArgument(0); 3583 for (WatchdogStorage.IoUsageStatsEntry entry : ioUsageStatsEntries) { 3584 mIoUsageStatsEntries.add( 3585 new WatchdogStorage.IoUsageStatsEntry(entry.userId, entry.packageName, 3586 new WatchdogPerfHandler.PackageIoUsage( 3587 entry.ioUsage.getInternalIoOveruseStats(), 3588 entry.ioUsage.getForgivenWriteBytes(), 3589 entry.ioUsage.getForgivenOveruses(), 3590 entry.ioUsage.getTotalTimesKilled()))); 3591 } 3592 return true; 3593 }); 3594 when(mMockWatchdogStorage.getUserPackageSettings()).thenReturn(mUserPackageSettingsEntries); 3595 when(mMockWatchdogStorage.getTodayIoUsageStats()).thenReturn(mIoUsageStatsEntries); 3596 when(mMockWatchdogStorage.getDailySystemIoUsageSummaries(anyLong(), anyLong())).thenAnswer( 3597 args -> sampleDailyIoUsageSummariesForAWeek(args.getArgument(0), 3598 SYSTEM_DAILY_IO_USAGE_SUMMARY_MULTIPLIER)); 3599 when(mMockWatchdogStorage.getTopUsersDailyIoUsageSummaries( 3600 anyInt(), anyLong(), anyLong(), anyLong())).thenAnswer(args -> { 3601 ArrayList<WatchdogStorage.UserPackageDailySummaries> summaries = 3602 new ArrayList<>(); 3603 for (int i = 0; i < mGenericPackageNameByUid.size(); ++i) { 3604 int uid = mGenericPackageNameByUid.keyAt(i); 3605 summaries.add(new WatchdogStorage.UserPackageDailySummaries( 3606 UserHandle.getUserId(uid), mGenericPackageNameByUid.valueAt(i), 3607 sampleDailyIoUsageSummariesForAWeek(args.getArgument(2), 3608 /* sysOrUidMultiplier= */ uid))); 3609 } 3610 summaries.sort(Comparator.comparingLong(WatchdogStorage 3611 .UserPackageDailySummaries::getTotalWrittenBytes).reversed()); 3612 return summaries; 3613 }); 3614 } 3615 setupUsers()3616 private void setupUsers() { 3617 when(mMockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager); 3618 mockUmGetAllUsers(mMockUserManager, new UserInfo[0]); 3619 } 3620 initService(int wantedInvocations)3621 private void initService(int wantedInvocations) throws Exception { 3622 mTimeSource.updateNow(/* numDaysAgo= */ 0); 3623 mCarWatchdogService.setOveruseHandlingDelay(OVERUSE_HANDLING_DELAY_MILLS); 3624 mCarWatchdogService.setUidIoUsageSummaryTopCount( 3625 UID_IO_USAGE_SUMMARY_TOP_COUNT); 3626 mCarWatchdogService.init(); 3627 captureCarPowerListeners(wantedInvocations); 3628 captureBroadcastReceiver(wantedInvocations); 3629 captureCarUxRestrictionsChangeListener(wantedInvocations); 3630 captureAndVerifyRegistrationWithDaemon(/* waitOnMain= */ true); 3631 verifyDatabaseInit(wantedInvocations); 3632 captureStatsPullAtomCallback(wantedInvocations); 3633 } 3634 restartService(int totalRestarts)3635 private void restartService(int totalRestarts) throws Exception { 3636 setCarPowerState(CarPowerStateListener.SHUTDOWN_PREPARE); 3637 setCarPowerState(CarPowerStateListener.SHUTDOWN_ENTER); 3638 mCarWatchdogService.release(); 3639 verify(mMockWatchdogStorage, times(totalRestarts)).saveIoUsageStats(any()); 3640 verify(mMockWatchdogStorage, times(totalRestarts)).saveUserPackageSettings(any()); 3641 verify(mMockWatchdogStorage, times(totalRestarts)).release(); 3642 mCarWatchdogService = new CarWatchdogService(mMockContext, mMockWatchdogStorage, 3643 mMockUserNotificationHelper, mTimeSource); 3644 initService(/* wantedInvocations= */ totalRestarts + 1); 3645 } 3646 captureCarPowerListeners(int wantedInvocations)3647 private void captureCarPowerListeners(int wantedInvocations) { 3648 verify(mMockCarPowerManagementService, times(wantedInvocations)).registerListener( 3649 mICarPowerStateListenerCaptor.capture()); 3650 mCarPowerStateListener = mICarPowerStateListenerCaptor.getValue(); 3651 assertWithMessage("Car power state listener").that(mCarPowerStateListener).isNotNull(); 3652 3653 verify(mMockCarPowerManagementService, times(wantedInvocations)).addPowerPolicyListener( 3654 any(), mICarPowerPolicyListenerCaptor.capture()); 3655 mCarPowerPolicyListener = mICarPowerPolicyListenerCaptor.getValue(); 3656 assertWithMessage("Car power policy listener").that(mCarPowerPolicyListener).isNotNull(); 3657 } 3658 captureBroadcastReceiver(int wantedInvocations)3659 private void captureBroadcastReceiver(int wantedInvocations) { 3660 verify(mMockContext, times(wantedInvocations)) 3661 .registerReceiverForAllUsers(mBroadcastReceiverCaptor.capture(), any(), any(), 3662 any()); 3663 mBroadcastReceiver = mBroadcastReceiverCaptor.getValue(); 3664 assertWithMessage("Broadcast receiver").that(mBroadcastReceiver).isNotNull(); 3665 } 3666 captureCarUxRestrictionsChangeListener(int wantedInvocations)3667 private void captureCarUxRestrictionsChangeListener(int wantedInvocations) { 3668 verify(mMockCarUxRestrictionsManagerService, times(wantedInvocations)) 3669 .getCurrentUxRestrictions(); 3670 verify(mMockCarUxRestrictionsManagerService, times(wantedInvocations)) 3671 .registerUxRestrictionsChangeListener(mICarUxRestrictionsChangeListener.capture(), 3672 eq(Display.DEFAULT_DISPLAY)); 3673 mCarUxRestrictionsChangeListener = mICarUxRestrictionsChangeListener.getValue(); 3674 assertWithMessage("UX restrictions change listener").that(mCarUxRestrictionsChangeListener) 3675 .isNotNull(); 3676 } 3677 captureAndVerifyRegistrationWithDaemon(boolean waitOnMain)3678 private void captureAndVerifyRegistrationWithDaemon(boolean waitOnMain) throws Exception { 3679 if (waitOnMain) { 3680 // Registering to daemon is done on the main thread. To ensure the registration 3681 // completes before verification, execute an empty block on the main thread. 3682 CarServiceUtils.runOnMainSync(() -> {}); 3683 } 3684 3685 verify(mMockCarWatchdogDaemon, atLeastOnce()).asBinder(); 3686 3687 verify(mMockBinder, atLeastOnce()).linkToDeath(mDeathRecipientCaptor.capture(), anyInt()); 3688 mCarWatchdogDaemonBinderDeathRecipient = mDeathRecipientCaptor.getValue(); 3689 assertWithMessage("Watchdog daemon binder death recipient") 3690 .that(mCarWatchdogDaemonBinderDeathRecipient).isNotNull(); 3691 3692 verify(mMockCarWatchdogDaemon, atLeastOnce()).registerCarWatchdogService( 3693 mICarWatchdogServiceForSystemCaptor.capture()); 3694 mWatchdogServiceForSystemImpl = mICarWatchdogServiceForSystemCaptor.getValue(); 3695 assertWithMessage("Car watchdog service for system") 3696 .that(mWatchdogServiceForSystemImpl).isNotNull(); 3697 3698 verify(mMockCarWatchdogDaemon, atLeastOnce()).notifySystemStateChange( 3699 StateType.GARAGE_MODE, GarageMode.GARAGE_MODE_OFF, MISSING_ARG_VALUE); 3700 3701 // Once registration with daemon completes, the service post a new message on the main 3702 // thread to fetch and sync resource overuse configs. 3703 CarServiceUtils.runOnMainSync(() -> {}); 3704 3705 verify(mMockCarWatchdogDaemon, atLeastOnce()).getResourceOveruseConfigurations(); 3706 } 3707 verifyDatabaseInit(int wantedInvocations)3708 private void verifyDatabaseInit(int wantedInvocations) throws Exception { 3709 /* 3710 * Database read is posted on a separate handler thread. Wait until the handler thread has 3711 * processed the database read request before verifying. 3712 */ 3713 CarServiceUtils.getHandlerThread(CarWatchdogService.class.getSimpleName()) 3714 .getThreadHandler().post(() -> {}); 3715 verify(mMockWatchdogStorage, times(wantedInvocations)).syncUsers(any()); 3716 verify(mMockWatchdogStorage, times(wantedInvocations)).getUserPackageSettings(); 3717 verify(mMockWatchdogStorage, times(wantedInvocations)).getTodayIoUsageStats(); 3718 verify(mMockWatchdogStorage, times(wantedInvocations)).getNotForgivenHistoricalIoOveruses( 3719 RECURRING_OVERUSE_PERIOD_IN_DAYS); 3720 } 3721 captureStatsPullAtomCallback(int wantedInvocations)3722 private void captureStatsPullAtomCallback(int wantedInvocations) { 3723 verify(mMockStatsManager, times(wantedInvocations)).setPullAtomCallback( 3724 eq(CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY), any(PullAtomMetadata.class), 3725 any(Executor.class), mStatsPullAtomCallbackCaptor.capture()); 3726 verify(mMockStatsManager, times(wantedInvocations)).setPullAtomCallback( 3727 eq(CAR_WATCHDOG_UID_IO_USAGE_SUMMARY), any(PullAtomMetadata.class), 3728 any(Executor.class), mStatsPullAtomCallbackCaptor.capture()); 3729 3730 // The same callback is set in the above calls, so fetch the latest captured callback. 3731 mStatsPullAtomCallback = mStatsPullAtomCallbackCaptor.getValue(); 3732 assertWithMessage("Stats pull atom callback").that(mStatsPullAtomCallback).isNotNull(); 3733 } 3734 mockBuildStatsEventCalls()3735 private void mockBuildStatsEventCalls() { 3736 when(CarStatsLog.buildStatsEvent(eq(CAR_WATCHDOG_SYSTEM_IO_USAGE_SUMMARY), 3737 any(byte[].class))).thenAnswer(args -> { 3738 mPulledSystemIoUsageSummaries.add(AtomsProto.CarWatchdogSystemIoUsageSummary 3739 .newBuilder() 3740 .setIoUsageSummary(AtomsProto.CarWatchdogIoUsageSummary.parseFrom( 3741 (byte[]) args.getArgument(1))) 3742 .build()); 3743 // Returned event is not used in tests, so return an empty event. 3744 return StatsEvent.newBuilder().build(); 3745 }); 3746 3747 when(CarStatsLog.buildStatsEvent(eq(CAR_WATCHDOG_UID_IO_USAGE_SUMMARY), anyInt(), 3748 any(byte[].class))).thenAnswer(args -> { 3749 mPulledUidIoUsageSummaries.add(AtomsProto.CarWatchdogUidIoUsageSummary 3750 .newBuilder() 3751 .setUid(args.getArgument(1)) 3752 .setIoUsageSummary(AtomsProto.CarWatchdogIoUsageSummary.parseFrom( 3753 (byte[]) args.getArgument(2))) 3754 .build()); 3755 // Returned event is not used in tests, so return an empty event. 3756 return StatsEvent.newBuilder().build(); 3757 }); 3758 } 3759 mockPackageManager()3760 private void mockPackageManager() throws Exception { 3761 when(mMockPackageManager.getNamesForUids(any())).thenAnswer(args -> { 3762 int[] uids = args.getArgument(0); 3763 String[] names = new String[uids.length]; 3764 for (int i = 0; i < uids.length; ++i) { 3765 names[i] = mGenericPackageNameByUid.get(uids[i], null); 3766 } 3767 return names; 3768 }); 3769 when(mMockPackageManager.getPackagesForUid(anyInt())).thenAnswer(args -> { 3770 int uid = args.getArgument(0); 3771 List<String> packages = mPackagesBySharedUid.get(uid); 3772 return packages.toArray(new String[0]); 3773 }); 3774 when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), 3775 any(UserHandle.class))).thenAnswer(args -> { 3776 int userId = ((UserHandle) args.getArgument(2)).getIdentifier(); 3777 String userPackageId = userId + ":" + args.getArgument(0); 3778 android.content.pm.PackageInfo packageInfo = 3779 mPmPackageInfoByUserPackage.get(userPackageId); 3780 if (packageInfo == null) { 3781 throw new PackageManager.NameNotFoundException( 3782 "User package id '" + userPackageId + "' not found"); 3783 } 3784 return packageInfo.applicationInfo; 3785 }); 3786 when(mMockPackageManager.getPackageInfoAsUser(anyString(), anyInt(), anyInt())) 3787 .thenAnswer(args -> { 3788 String userPackageId = args.getArgument(2) + ":" + args.getArgument(0); 3789 android.content.pm.PackageInfo packageInfo = 3790 mPmPackageInfoByUserPackage.get(userPackageId); 3791 if (packageInfo == null) { 3792 throw new PackageManager.NameNotFoundException( 3793 "User package id '" + userPackageId + "' not found"); 3794 } 3795 return packageInfo; 3796 }); 3797 when(mMockPackageManager.getInstalledPackagesAsUser(anyInt(), anyInt())) 3798 .thenAnswer(args -> { 3799 int userId = args.getArgument(1); 3800 List<android.content.pm.PackageInfo> packageInfos = new ArrayList<>(); 3801 for (android.content.pm.PackageInfo packageInfo : 3802 mPmPackageInfoByUserPackage.values()) { 3803 if (UserHandle.getUserId(packageInfo.applicationInfo.uid) == userId) { 3804 packageInfos.add(packageInfo); 3805 } 3806 } 3807 return packageInfos; 3808 }); 3809 when(mMockPackageManager.getPackageUidAsUser(anyString(), anyInt())) 3810 .thenAnswer(args -> { 3811 String userPackageId = args.getArgument(1) + ":" + args.getArgument(0); 3812 android.content.pm.PackageInfo packageInfo = 3813 mPmPackageInfoByUserPackage.get(userPackageId); 3814 if (packageInfo == null) { 3815 throw new PackageManager.NameNotFoundException( 3816 "User package id '" + userPackageId + "' not found"); 3817 } 3818 return packageInfo.applicationInfo.uid; 3819 }); 3820 3821 doAnswer((args) -> { 3822 String value = args.getArgument(3) + ":" + args.getArgument(0); 3823 mDisabledUserPackages.add(value); 3824 return null; 3825 }).when(mSpiedPackageManager).setApplicationEnabledSetting( 3826 anyString(), eq(COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED), anyInt(), 3827 anyInt(), anyString()); 3828 doReturn(COMPONENT_ENABLED_STATE_ENABLED).when(mSpiedPackageManager) 3829 .getApplicationEnabledSetting(anyString(), anyInt()); 3830 } 3831 setCarPowerState(int powerState)3832 private void setCarPowerState(int powerState) throws Exception { 3833 when(mMockCarPowerManagementService.getPowerState()).thenReturn(powerState); 3834 mCarPowerStateListener.onStateChanged(powerState); 3835 } 3836 setDisplayStateEnabled(boolean isEnabled)3837 private void setDisplayStateEnabled(boolean isEnabled) throws Exception { 3838 int[] enabledComponents = new int[]{}; 3839 int[] disabledComponents = new int[]{}; 3840 if (isEnabled) { 3841 enabledComponents = new int[]{PowerComponent.DISPLAY}; 3842 } else { 3843 disabledComponents = new int[]{PowerComponent.DISPLAY}; 3844 } 3845 mCarPowerPolicyListener.onPolicyChanged( 3846 new CarPowerPolicy(/* policyId= */ "", enabledComponents, disabledComponents), 3847 /* accumulatedPolicy= */ null); 3848 } 3849 setRequiresDistractionOptimization(boolean isRequires)3850 private void setRequiresDistractionOptimization(boolean isRequires) throws Exception { 3851 CarUxRestrictions.Builder builder = new CarUxRestrictions.Builder( 3852 isRequires, UX_RESTRICTIONS_BASELINE, /* time= */ 0); 3853 mCarUxRestrictionsChangeListener.onUxRestrictionsChanged(builder.build()); 3854 } 3855 crashWatchdogDaemon()3856 private void crashWatchdogDaemon() { 3857 doReturn(null).when(() -> ServiceManager.getService(CAR_WATCHDOG_DAEMON_INTERFACE)); 3858 mCarWatchdogDaemonBinderDeathRecipient.binderDied(); 3859 mIsDaemonCrashed = true; 3860 } 3861 restartWatchdogDaemonAndAwait()3862 private void restartWatchdogDaemonAndAwait() throws Exception { 3863 CountDownLatch latch = new CountDownLatch(1); 3864 doAnswer(args -> { 3865 latch.countDown(); 3866 return null; 3867 }).when(mMockBinder).linkToDeath(any(), anyInt()); 3868 mockWatchdogDaemon(); 3869 latch.await(MAX_WAIT_TIME_MS, TimeUnit.MILLISECONDS); 3870 captureAndVerifyRegistrationWithDaemon(/* waitOnMain= */ false); 3871 } 3872 testClientHealthCheck(TestClient client, int badClientCount)3873 private void testClientHealthCheck(TestClient client, int badClientCount) throws Exception { 3874 mCarWatchdogService.registerClient(client, TIMEOUT_CRITICAL); 3875 mWatchdogServiceForSystemImpl.checkIfAlive(123456, TIMEOUT_CRITICAL); 3876 verify(mMockCarWatchdogDaemon, timeout(MAX_WAIT_TIME_MS)).tellCarWatchdogServiceAlive( 3877 eq(mWatchdogServiceForSystemImpl), mIntArrayCaptor.capture(), eq(123456)); 3878 assertThat(mIntArrayCaptor.getValue()).isEmpty(); 3879 mWatchdogServiceForSystemImpl.checkIfAlive(987654, TIMEOUT_CRITICAL); 3880 verify(mMockCarWatchdogDaemon, timeout(MAX_WAIT_TIME_MS)).tellCarWatchdogServiceAlive( 3881 eq(mWatchdogServiceForSystemImpl), mIntArrayCaptor.capture(), eq(987654)); 3882 assertThat(mIntArrayCaptor.getValue().length).isEqualTo(badClientCount); 3883 } 3884 3885 private List<android.automotive.watchdog.internal.ResourceOveruseConfiguration> captureOnSetResourceOveruseConfigurations()3886 captureOnSetResourceOveruseConfigurations() throws Exception { 3887 verify(mMockCarWatchdogDaemon, timeout(MAX_WAIT_TIME_MS)) 3888 .updateResourceOveruseConfigurations( 3889 mResourceOveruseConfigurationsCaptor.capture()); 3890 return mResourceOveruseConfigurationsCaptor.getValue(); 3891 } 3892 injectIoOveruseStatsForPackages( SparseArray<String> genericPackageNameByUid, Set<String> killablePackages, Set<String> shouldNotifyPackages)3893 private SparseArray<PackageIoOveruseStats> injectIoOveruseStatsForPackages( 3894 SparseArray<String> genericPackageNameByUid, Set<String> killablePackages, 3895 Set<String> shouldNotifyPackages) throws Exception { 3896 SparseArray<PackageIoOveruseStats> packageIoOveruseStatsByUid = new SparseArray<>(); 3897 List<PackageIoOveruseStats> packageIoOveruseStats = new ArrayList<>(); 3898 for (int i = 0; i < genericPackageNameByUid.size(); ++i) { 3899 String name = genericPackageNameByUid.valueAt(i); 3900 int uid = genericPackageNameByUid.keyAt(i); 3901 PackageIoOveruseStats stats = constructPackageIoOveruseStats(uid, 3902 shouldNotifyPackages.contains(name), 3903 constructPerStateBytes(80, 147, 213), 3904 constructInternalIoOveruseStats(killablePackages.contains(name), 3905 /* remainingWriteBytes= */ constructPerStateBytes(20, 20, 20), 3906 /* writtenBytes= */ constructPerStateBytes(100, 200, 300), 3907 /* totalOveruses= */ 3)); 3908 packageIoOveruseStatsByUid.put(uid, stats); 3909 packageIoOveruseStats.add(stats); 3910 } 3911 pushLatestIoOveruseStatsAndWait(packageIoOveruseStats); 3912 return packageIoOveruseStatsByUid; 3913 } 3914 injectPackageInfos(List<android.content.pm.PackageInfo> packageInfos)3915 private void injectPackageInfos(List<android.content.pm.PackageInfo> packageInfos) { 3916 for (android.content.pm.PackageInfo packageInfo : packageInfos) { 3917 String genericPackageName = packageInfo.packageName; 3918 int uid = packageInfo.applicationInfo.uid; 3919 int userId = UserHandle.getUserId(uid); 3920 if (packageInfo.sharedUserId != null) { 3921 genericPackageName = 3922 PackageInfoHandler.SHARED_PACKAGE_PREFIX + packageInfo.sharedUserId; 3923 List<String> packages = mPackagesBySharedUid.get(uid); 3924 if (packages == null) { 3925 packages = new ArrayList<>(); 3926 } 3927 packages.add(packageInfo.packageName); 3928 mPackagesBySharedUid.put(uid, packages); 3929 } 3930 String userPackageId = userId + ":" + packageInfo.packageName; 3931 assertWithMessage("Duplicate package infos provided for user package id: %s", 3932 userPackageId).that(mPmPackageInfoByUserPackage.containsKey(userPackageId)) 3933 .isFalse(); 3934 assertWithMessage("Mismatch generic package names for the same uid '%s'", 3935 uid).that(mGenericPackageNameByUid.get(uid, genericPackageName)) 3936 .isEqualTo(genericPackageName); 3937 mPmPackageInfoByUserPackage.put(userPackageId, packageInfo); 3938 mGenericPackageNameByUid.put(uid, genericPackageName); 3939 } 3940 } 3941 pushLatestIoOveruseStatsAndWait(List<PackageIoOveruseStats> packageIoOveruseStats)3942 private void pushLatestIoOveruseStatsAndWait(List<PackageIoOveruseStats> packageIoOveruseStats) 3943 throws Exception { 3944 mWatchdogServiceForSystemImpl.latestIoOveruseStats(packageIoOveruseStats); 3945 3946 // Resource overuse handling is done on the main thread by posting a new message with 3947 // OVERUSE_HANDLING_DELAY_MILLS delay. Wait until the below message is processed before 3948 // returning, so the resource overuse handling is completed. 3949 delayedRunOnMainSync(() -> {}, OVERUSE_HANDLING_DELAY_MILLS * 2); 3950 } 3951 setUpSampleUserAndPackages()3952 private void setUpSampleUserAndPackages() { 3953 mockUmGetUserHandles(mMockUserManager, /* excludeDying= */ true, 100, 101); 3954 int[] users = new int[]{100, 101}; 3955 List<android.content.pm.PackageInfo> packageInfos = new ArrayList<>(); 3956 for (int i = 0; i < users.length; ++i) { 3957 packageInfos.add(constructPackageManagerPackageInfo( 3958 "system_package.critical", UserHandle.getUid(users[i], 10001), null)); 3959 packageInfos.add(constructPackageManagerPackageInfo( 3960 "system_package.non_critical", UserHandle.getUid(users[i], 10002), null)); 3961 packageInfos.add(constructPackageManagerPackageInfo( 3962 "vendor_package.critical", UserHandle.getUid(users[i], 10003), null)); 3963 packageInfos.add(constructPackageManagerPackageInfo( 3964 "vendor_package.non_critical", UserHandle.getUid(users[i], 10004), null)); 3965 packageInfos.add(constructPackageManagerPackageInfo( 3966 "third_party_package.A", UserHandle.getUid(users[i], 10005), 3967 "third_party_shared_package")); 3968 packageInfos.add(constructPackageManagerPackageInfo( 3969 "third_party_package.B", UserHandle.getUid(users[i], 10005), 3970 "third_party_shared_package")); 3971 } 3972 injectPackageInfos(packageInfos); 3973 } 3974 sampleIoOveruseStats(boolean requireRecurrentOveruseStats)3975 private List<PackageIoOveruseStats> sampleIoOveruseStats(boolean requireRecurrentOveruseStats) 3976 throws Exception { 3977 int[] users = new int[]{100, 101}; 3978 int totalOveruses = requireRecurrentOveruseStats ? RECURRING_OVERUSE_TIMES + 1 : 1; 3979 List<PackageIoOveruseStats> packageIoOveruseStats = new ArrayList<>(); 3980 android.automotive.watchdog.PerStateBytes zeroRemainingBytes = 3981 constructPerStateBytes(0, 0, 0); 3982 android.automotive.watchdog.PerStateBytes nonZeroRemainingBytes = 3983 constructPerStateBytes(20, 30, 40); 3984 android.automotive.watchdog.PerStateBytes writtenBytes = 3985 constructPerStateBytes(100, 200, 300); 3986 for (int i = 0; i < users.length; ++i) { 3987 // Overuse occurred but cannot be killed/disabled. 3988 packageIoOveruseStats.add(constructPackageIoOveruseStats( 3989 UserHandle.getUid(users[i], 10001), /* shouldNotify= */ true, 3990 /* forgivenWriteBytes= */ writtenBytes, 3991 constructInternalIoOveruseStats( 3992 /* killableOnOveruse= */ false, zeroRemainingBytes, writtenBytes, 3993 totalOveruses))); 3994 // No overuse occurred but the package should be notified. 3995 packageIoOveruseStats.add(constructPackageIoOveruseStats( 3996 UserHandle.getUid(users[i], 10002), /* shouldNotify= */ true, 3997 /* forgivenWriteBytes= */ constructPerStateBytes(0, 0, 0), 3998 constructInternalIoOveruseStats( 3999 /* killableOnOveruse= */ true, nonZeroRemainingBytes, writtenBytes, 4000 totalOveruses))); 4001 // Neither overuse occurred nor be notified. 4002 packageIoOveruseStats.add(constructPackageIoOveruseStats( 4003 UserHandle.getUid(users[i], 10003), /* shouldNotify= */ false, 4004 /* forgivenWriteBytes= */ constructPerStateBytes(0, 0, 0), 4005 constructInternalIoOveruseStats( 4006 /* killableOnOveruse= */ false, nonZeroRemainingBytes, writtenBytes, 4007 totalOveruses))); 4008 // Overuse occurred and can be killed/disabled. 4009 packageIoOveruseStats.add(constructPackageIoOveruseStats( 4010 UserHandle.getUid(users[i], 10004), /* shouldNotify= */ false, 4011 /* forgivenWriteBytes= */ writtenBytes, 4012 constructInternalIoOveruseStats( 4013 /* killableOnOveruse= */ true, zeroRemainingBytes, writtenBytes, 4014 totalOveruses))); 4015 // Overuse occurred and can be killed/disabled. 4016 packageIoOveruseStats.add(constructPackageIoOveruseStats( 4017 UserHandle.getUid(users[i], 10005), /* shouldNotify= */ true, 4018 /* forgivenWriteBytes= */ writtenBytes, 4019 constructInternalIoOveruseStats( 4020 /* killableOnOveruse= */ true, zeroRemainingBytes, writtenBytes, 4021 totalOveruses))); 4022 } 4023 return packageIoOveruseStats; 4024 } 4025 captureAndVerifyUserNotifications( List<UserNotificationCall> expectedUserNotificationCalls)4026 private void captureAndVerifyUserNotifications( 4027 List<UserNotificationCall> expectedUserNotificationCalls) { 4028 // Recurring overuse notification handling task is posted on the service thread and this 4029 // task sends the user notifications. Wait for this task to complete. 4030 CarServiceUtils.runOnLooperSync( 4031 CarServiceUtils.getHandlerThread(CarWatchdogService.class.getSimpleName()) 4032 .getLooper(), () -> {}); 4033 4034 verify(mMockUserNotificationHelper, times(expectedUserNotificationCalls.size())) 4035 .showResourceOveruseNotificationsAsUser(mPackageNotificationInfosCaptor.capture(), 4036 mUserHandleCaptor.capture()); 4037 4038 List<List<UserNotificationHelper.PackageNotificationInfo>> allPackageNotificationInfos = 4039 mPackageNotificationInfosCaptor.getAllValues(); 4040 List<UserHandle> allUserHandles = mUserHandleCaptor.getAllValues(); 4041 4042 for (int i = 0; i < expectedUserNotificationCalls.size(); ++i) { 4043 UserNotificationCall expectedUserNotificationCall = 4044 expectedUserNotificationCalls.get(i); 4045 expectedUserNotificationCall.verifyCall(allPackageNotificationInfos.get(i), 4046 allUserHandles.get(i)); 4047 } 4048 } 4049 sampleReportedOveruseStats()4050 private static List<AtomsProto.CarWatchdogIoOveruseStatsReported> sampleReportedOveruseStats() { 4051 // The below thresholds are from {@link sampleInternalResourceOveruseConfiguration} and 4052 // UID/stat are from {@link sampleIoOveruseStats}. 4053 AtomsProto.CarWatchdogPerStateBytes systemThreshold = 4054 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(10, 20, 30); 4055 AtomsProto.CarWatchdogPerStateBytes vendorThreshold = 4056 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(20, 40, 60); 4057 AtomsProto.CarWatchdogPerStateBytes thirdPartyThreshold = 4058 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(30, 60, 90); 4059 AtomsProto.CarWatchdogPerStateBytes writtenBytes = 4060 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(100, 200, 300); 4061 List<AtomsProto.CarWatchdogIoOveruseStatsReported> reportedOveruseStats = new ArrayList<>(); 4062 reportedOveruseStats.add(constructIoOveruseStatsReported( 4063 10010001, systemThreshold, writtenBytes)); 4064 reportedOveruseStats.add(constructIoOveruseStatsReported( 4065 10110001, systemThreshold, writtenBytes)); 4066 reportedOveruseStats.add(constructIoOveruseStatsReported( 4067 10010004, vendorThreshold, writtenBytes)); 4068 reportedOveruseStats.add(constructIoOveruseStatsReported( 4069 10110004, vendorThreshold, writtenBytes)); 4070 reportedOveruseStats.add(constructIoOveruseStatsReported( 4071 10010005, thirdPartyThreshold, writtenBytes)); 4072 reportedOveruseStats.add(constructIoOveruseStatsReported( 4073 10110005, thirdPartyThreshold, writtenBytes)); 4074 return reportedOveruseStats; 4075 } 4076 sampleReportedKillStats( int systemState, int[] killedUids)4077 private static List<AtomsProto.CarWatchdogKillStatsReported> sampleReportedKillStats( 4078 int systemState, int[] killedUids) { 4079 // The below thresholds are from {@link sampleInternalResourceOveruseConfiguration} and 4080 // UID/stat are from {@link sampleIoOveruseStats}. 4081 AtomsProto.CarWatchdogPerStateBytes vendorThreshold = 4082 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(20, 40, 60); 4083 AtomsProto.CarWatchdogPerStateBytes thirdPartyThreshold = 4084 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(30, 60, 90); 4085 AtomsProto.CarWatchdogPerStateBytes writtenBytes = 4086 WatchdogPerfHandler.constructCarWatchdogPerStateBytes(100, 200, 300); 4087 List<AtomsProto.CarWatchdogKillStatsReported> reportedKillStats = new ArrayList<>(); 4088 for (int uid : killedUids) { 4089 AtomsProto.CarWatchdogPerStateBytes threshold = 4090 UserHandle.getAppId(uid) == 10004 ? vendorThreshold : thirdPartyThreshold; 4091 reportedKillStats.add(constructIoOveruseKillStatsReported( 4092 uid, systemState, threshold, writtenBytes)); 4093 } 4094 return reportedKillStats; 4095 } 4096 verifyOnOveruseCalled(List<ResourceOveruseStats> expectedStats, IResourceOveruseListener mockListener)4097 private static void verifyOnOveruseCalled(List<ResourceOveruseStats> expectedStats, 4098 IResourceOveruseListener mockListener) throws Exception { 4099 ArgumentCaptor<ResourceOveruseStats> resourceOveruseStatsCaptor = 4100 ArgumentCaptor.forClass(ResourceOveruseStats.class); 4101 4102 verify(mockListener, times(expectedStats.size())) 4103 .onOveruse(resourceOveruseStatsCaptor.capture()); 4104 4105 ResourceOveruseStatsSubject.assertThat(resourceOveruseStatsCaptor.getAllValues()) 4106 .containsExactlyElementsIn(expectedStats); 4107 } 4108 sampleResourceOveruseConfigurations()4109 private static List<ResourceOveruseConfiguration> sampleResourceOveruseConfigurations() { 4110 return Arrays.asList( 4111 sampleResourceOveruseConfigurationBuilder(ComponentType.SYSTEM, 4112 sampleIoOveruseConfigurationBuilder(ComponentType.SYSTEM).build()).build(), 4113 sampleResourceOveruseConfigurationBuilder(ComponentType.VENDOR, 4114 sampleIoOveruseConfigurationBuilder(ComponentType.VENDOR).build()).build(), 4115 sampleResourceOveruseConfigurationBuilder(ComponentType.THIRD_PARTY, 4116 sampleIoOveruseConfigurationBuilder(ComponentType.THIRD_PARTY).build()) 4117 .build()); 4118 } 4119 4120 private static List<android.automotive.watchdog.internal.ResourceOveruseConfiguration> sampleInternalResourceOveruseConfigurations()4121 sampleInternalResourceOveruseConfigurations() { 4122 return Arrays.asList( 4123 sampleInternalResourceOveruseConfiguration(ComponentType.SYSTEM, 4124 sampleInternalIoOveruseConfiguration(ComponentType.SYSTEM)), 4125 sampleInternalResourceOveruseConfiguration(ComponentType.VENDOR, 4126 sampleInternalIoOveruseConfiguration(ComponentType.VENDOR)), 4127 sampleInternalResourceOveruseConfiguration(ComponentType.THIRD_PARTY, 4128 sampleInternalIoOveruseConfiguration(ComponentType.THIRD_PARTY))); 4129 } 4130 sampleResourceOveruseConfigurationBuilder( @omponentType int componentType, IoOveruseConfiguration ioOveruseConfig)4131 private static ResourceOveruseConfiguration.Builder sampleResourceOveruseConfigurationBuilder( 4132 @ComponentType int componentType, IoOveruseConfiguration ioOveruseConfig) { 4133 String prefix = WatchdogPerfHandler.toComponentTypeStr(componentType).toLowerCase(); 4134 List<String> safeToKill = Arrays.asList(prefix + "_package.non_critical.A", 4135 prefix + "_pkg.non_critical.B", 4136 "shared:" + prefix + "_shared_package.non_critical.B", 4137 "some_pkg_as_" + prefix + "_pkg"); 4138 List<String> vendorPrefixes = Arrays.asList( 4139 prefix + "_package", "some_pkg_as_" + prefix + "_pkg"); 4140 Map<String, String> pkgToAppCategory = new ArrayMap<>(); 4141 pkgToAppCategory.put("system_package.MEDIA", "android.car.watchdog.app.category.MEDIA"); 4142 pkgToAppCategory.put("system_package.A", "android.car.watchdog.app.category.MAPS"); 4143 pkgToAppCategory.put("vendor_package.MEDIA", "android.car.watchdog.app.category.MEDIA"); 4144 pkgToAppCategory.put("vendor_package.A", "android.car.watchdog.app.category.MAPS"); 4145 pkgToAppCategory.put("third_party_package.MAPS", "android.car.watchdog.app.category.MAPS"); 4146 ResourceOveruseConfiguration.Builder configBuilder = 4147 new ResourceOveruseConfiguration.Builder(componentType, safeToKill, 4148 vendorPrefixes, pkgToAppCategory); 4149 configBuilder.setIoOveruseConfiguration(ioOveruseConfig); 4150 return configBuilder; 4151 } 4152 sampleIoOveruseConfigurationBuilder( @omponentType int componentType)4153 private static IoOveruseConfiguration.Builder sampleIoOveruseConfigurationBuilder( 4154 @ComponentType int componentType) { 4155 String prefix = WatchdogPerfHandler.toComponentTypeStr(componentType).toLowerCase(); 4156 PerStateBytes componentLevelThresholds = new PerStateBytes( 4157 /* foregroundModeBytes= */ componentType * 10L, 4158 /* backgroundModeBytes= */ componentType * 20L, 4159 /* garageModeBytes= */ componentType * 30L); 4160 Map<String, PerStateBytes> packageSpecificThresholds = new ArrayMap<>(); 4161 packageSpecificThresholds.put(prefix + "_package.A", new PerStateBytes( 4162 /* foregroundModeBytes= */ componentType * 40L, 4163 /* backgroundModeBytes= */ componentType * 50L, 4164 /* garageModeBytes= */ componentType * 60L)); 4165 4166 Map<String, PerStateBytes> appCategorySpecificThresholds = new ArrayMap<>(); 4167 appCategorySpecificThresholds.put( 4168 ResourceOveruseConfiguration.APPLICATION_CATEGORY_TYPE_MEDIA, 4169 new PerStateBytes(/* foregroundModeBytes= */ componentType * 100L, 4170 /* backgroundModeBytes= */ componentType * 200L, 4171 /* garageModeBytes= */ componentType * 300L)); 4172 appCategorySpecificThresholds.put( 4173 ResourceOveruseConfiguration.APPLICATION_CATEGORY_TYPE_MAPS, 4174 new PerStateBytes(/* foregroundModeBytes= */ componentType * 1100L, 4175 /* backgroundModeBytes= */ componentType * 2200L, 4176 /* garageModeBytes= */ componentType * 3300L)); 4177 4178 List<IoOveruseAlertThreshold> systemWideThresholds = Collections.singletonList( 4179 new IoOveruseAlertThreshold(/* durationInSeconds= */ componentType * 10L, 4180 /* writtenBytesPerSecond= */ componentType * 200L)); 4181 4182 return new IoOveruseConfiguration.Builder(componentLevelThresholds, 4183 packageSpecificThresholds, appCategorySpecificThresholds, systemWideThresholds); 4184 } 4185 4186 private static android.automotive.watchdog.internal.ResourceOveruseConfiguration sampleInternalResourceOveruseConfiguration(@omponentType int componentType, android.automotive.watchdog.internal.IoOveruseConfiguration ioOveruseConfig)4187 sampleInternalResourceOveruseConfiguration(@ComponentType int componentType, 4188 android.automotive.watchdog.internal.IoOveruseConfiguration ioOveruseConfig) { 4189 String prefix = WatchdogPerfHandler.toComponentTypeStr(componentType).toLowerCase(); 4190 android.automotive.watchdog.internal.ResourceOveruseConfiguration config = 4191 new android.automotive.watchdog.internal.ResourceOveruseConfiguration(); 4192 config.componentType = componentType; 4193 config.safeToKillPackages = Arrays.asList(prefix + "_package.non_critical.A", 4194 prefix + "_pkg.non_critical.B", 4195 "shared:" + prefix + "_shared_package.non_critical.B", 4196 "some_pkg_as_" + prefix + "_pkg"); 4197 config.vendorPackagePrefixes = Arrays.asList( 4198 prefix + "_package", "some_pkg_as_" + prefix + "_pkg"); 4199 config.packageMetadata = Arrays.asList( 4200 constructPackageMetadata("system_package.MEDIA", ApplicationCategoryType.MEDIA), 4201 constructPackageMetadata("system_package.A", ApplicationCategoryType.MAPS), 4202 constructPackageMetadata("vendor_package.MEDIA", ApplicationCategoryType.MEDIA), 4203 constructPackageMetadata("vendor_package.A", ApplicationCategoryType.MAPS), 4204 constructPackageMetadata("third_party_package.MAPS", ApplicationCategoryType.MAPS)); 4205 4206 ResourceSpecificConfiguration resourceSpecificConfig = new ResourceSpecificConfiguration(); 4207 resourceSpecificConfig.setIoOveruseConfiguration(ioOveruseConfig); 4208 config.resourceSpecificConfigurations = Collections.singletonList(resourceSpecificConfig); 4209 4210 return config; 4211 } 4212 4213 private static android.automotive.watchdog.internal.IoOveruseConfiguration sampleInternalIoOveruseConfiguration(@omponentType int componentType)4214 sampleInternalIoOveruseConfiguration(@ComponentType int componentType) { 4215 String prefix = WatchdogPerfHandler.toComponentTypeStr(componentType).toLowerCase(); 4216 android.automotive.watchdog.internal.IoOveruseConfiguration config = 4217 new android.automotive.watchdog.internal.IoOveruseConfiguration(); 4218 config.componentLevelThresholds = constructPerStateIoOveruseThreshold( 4219 WatchdogPerfHandler.toComponentTypeStr(componentType), 4220 /* fgBytes= */ componentType * 10L, /* bgBytes= */ componentType * 20L, 4221 /*gmBytes= */ componentType * 30L); 4222 config.packageSpecificThresholds = Collections.singletonList( 4223 constructPerStateIoOveruseThreshold(prefix + "_package.A", 4224 /* fgBytes= */ componentType * 40L, /* bgBytes= */ componentType * 50L, 4225 /* gmBytes= */ componentType * 60L)); 4226 config.categorySpecificThresholds = Arrays.asList( 4227 constructPerStateIoOveruseThreshold( 4228 WatchdogPerfHandler.INTERNAL_APPLICATION_CATEGORY_TYPE_MEDIA, 4229 /* fgBytes= */ componentType * 100L, /* bgBytes= */ componentType * 200L, 4230 /* gmBytes= */ componentType * 300L), 4231 constructPerStateIoOveruseThreshold( 4232 WatchdogPerfHandler.INTERNAL_APPLICATION_CATEGORY_TYPE_MAPS, 4233 /* fgBytes= */ componentType * 1100L, /* bgBytes= */ componentType * 2200L, 4234 /* gmBytes= */ componentType * 3300L)); 4235 config.systemWideThresholds = Collections.singletonList( 4236 constructInternalIoOveruseAlertThreshold( 4237 /* duration= */ componentType * 10L, /* writeBPS= */ componentType * 200L)); 4238 return config; 4239 } 4240 constructPackageMetadata( String packageName, @ApplicationCategoryType int appCategoryType)4241 private static PackageMetadata constructPackageMetadata( 4242 String packageName, @ApplicationCategoryType int appCategoryType) { 4243 PackageMetadata metadata = new PackageMetadata(); 4244 metadata.packageName = packageName; 4245 metadata.appCategoryType = appCategoryType; 4246 return metadata; 4247 } 4248 constructPerStateIoOveruseThreshold(String name, long fgBytes, long bgBytes, long gmBytes)4249 private static PerStateIoOveruseThreshold constructPerStateIoOveruseThreshold(String name, 4250 long fgBytes, long bgBytes, long gmBytes) { 4251 PerStateIoOveruseThreshold threshold = new PerStateIoOveruseThreshold(); 4252 threshold.name = name; 4253 threshold.perStateWriteBytes = new android.automotive.watchdog.PerStateBytes(); 4254 threshold.perStateWriteBytes.foregroundBytes = fgBytes; 4255 threshold.perStateWriteBytes.backgroundBytes = bgBytes; 4256 threshold.perStateWriteBytes.garageModeBytes = gmBytes; 4257 return threshold; 4258 } 4259 4260 private static android.automotive.watchdog.internal.IoOveruseAlertThreshold constructInternalIoOveruseAlertThreshold(long duration, long writeBPS)4261 constructInternalIoOveruseAlertThreshold(long duration, long writeBPS) { 4262 android.automotive.watchdog.internal.IoOveruseAlertThreshold threshold = 4263 new android.automotive.watchdog.internal.IoOveruseAlertThreshold(); 4264 threshold.durationInSeconds = duration; 4265 threshold.writtenBytesPerSecond = writeBPS; 4266 return threshold; 4267 } 4268 constructPackageIoOveruseStats(int uid, boolean shouldNotify, android.automotive.watchdog.PerStateBytes forgivenWriteBytes, android.automotive.watchdog.IoOveruseStats ioOveruseStats)4269 private static PackageIoOveruseStats constructPackageIoOveruseStats(int uid, 4270 boolean shouldNotify, android.automotive.watchdog.PerStateBytes forgivenWriteBytes, 4271 android.automotive.watchdog.IoOveruseStats ioOveruseStats) { 4272 PackageIoOveruseStats stats = new PackageIoOveruseStats(); 4273 stats.uid = uid; 4274 stats.shouldNotify = shouldNotify; 4275 stats.forgivenWriteBytes = forgivenWriteBytes; 4276 stats.ioOveruseStats = ioOveruseStats; 4277 return stats; 4278 } 4279 constructResourceOveruseStats(int uid, String packageName, android.automotive.watchdog.IoOveruseStats internalIoOveruseStats)4280 private static ResourceOveruseStats constructResourceOveruseStats(int uid, String packageName, 4281 android.automotive.watchdog.IoOveruseStats internalIoOveruseStats) { 4282 IoOveruseStats ioOveruseStats = WatchdogPerfHandler.toIoOveruseStatsBuilder( 4283 internalIoOveruseStats, /* totalTimesKilled= */ 0, 4284 internalIoOveruseStats.killableOnOveruse).build(); 4285 4286 return new ResourceOveruseStats.Builder(packageName, UserHandle.getUserHandleForUid(uid)) 4287 .setIoOveruseStats(ioOveruseStats).build(); 4288 } 4289 constructUserPackageIoUsageStats( int userId, String packageName, android.automotive.watchdog.PerStateBytes writtenBytes, android.automotive.watchdog.PerStateBytes forgivenWriteBytes, int totalOveruses)4290 private static UserPackageIoUsageStats constructUserPackageIoUsageStats( 4291 int userId, String packageName, android.automotive.watchdog.PerStateBytes writtenBytes, 4292 android.automotive.watchdog.PerStateBytes forgivenWriteBytes, int totalOveruses) { 4293 UserPackageIoUsageStats stats = new UserPackageIoUsageStats(); 4294 stats.userId = userId; 4295 stats.packageName = packageName; 4296 stats.ioUsageStats = new IoUsageStats(); 4297 stats.ioUsageStats.writtenBytes = writtenBytes; 4298 stats.ioUsageStats.forgivenWriteBytes = forgivenWriteBytes; 4299 stats.ioUsageStats.totalOveruses = totalOveruses; 4300 return stats; 4301 } 4302 isUserPackageIoUsageStatsEquals(UserPackageIoUsageStats actual, UserPackageIoUsageStats expected)4303 public static boolean isUserPackageIoUsageStatsEquals(UserPackageIoUsageStats actual, 4304 UserPackageIoUsageStats expected) { 4305 return actual.userId == expected.userId && actual.packageName.equals(expected.packageName) 4306 && isInternalPerStateBytesEquals( 4307 actual.ioUsageStats.writtenBytes, expected.ioUsageStats.writtenBytes) 4308 && isInternalPerStateBytesEquals(actual.ioUsageStats.forgivenWriteBytes, 4309 expected.ioUsageStats.forgivenWriteBytes) 4310 && actual.ioUsageStats.totalOveruses == expected.ioUsageStats.totalOveruses; 4311 } 4312 isInternalPerStateBytesEquals( android.automotive.watchdog.PerStateBytes actual, android.automotive.watchdog.PerStateBytes expected)4313 public static boolean isInternalPerStateBytesEquals( 4314 android.automotive.watchdog.PerStateBytes actual, 4315 android.automotive.watchdog.PerStateBytes expected) { 4316 return actual.foregroundBytes == expected.foregroundBytes 4317 && actual.backgroundBytes == expected.backgroundBytes 4318 && actual.garageModeBytes == expected.garageModeBytes; 4319 } 4320 constructInternalIoOveruseStats( boolean killableOnOveruse, android.automotive.watchdog.PerStateBytes remainingWriteBytes, android.automotive.watchdog.PerStateBytes writtenBytes, int totalOveruses)4321 private android.automotive.watchdog.IoOveruseStats constructInternalIoOveruseStats( 4322 boolean killableOnOveruse, 4323 android.automotive.watchdog.PerStateBytes remainingWriteBytes, 4324 android.automotive.watchdog.PerStateBytes writtenBytes, int totalOveruses) { 4325 return constructInternalIoOveruseStats(killableOnOveruse, STATS_DURATION_SECONDS, 4326 remainingWriteBytes, writtenBytes, totalOveruses); 4327 } 4328 constructInternalIoOveruseStats( boolean killableOnOveruse, long durationInSecs, android.automotive.watchdog.PerStateBytes remainingWriteBytes, android.automotive.watchdog.PerStateBytes writtenBytes, int totalOveruses)4329 private android.automotive.watchdog.IoOveruseStats constructInternalIoOveruseStats( 4330 boolean killableOnOveruse, long durationInSecs, 4331 android.automotive.watchdog.PerStateBytes remainingWriteBytes, 4332 android.automotive.watchdog.PerStateBytes writtenBytes, int totalOveruses) { 4333 android.automotive.watchdog.IoOveruseStats stats = 4334 new android.automotive.watchdog.IoOveruseStats(); 4335 stats.startTime = mTimeSource.now().getEpochSecond(); 4336 stats.durationInSeconds = durationInSecs; 4337 stats.killableOnOveruse = killableOnOveruse; 4338 stats.remainingWriteBytes = remainingWriteBytes; 4339 stats.writtenBytes = writtenBytes; 4340 stats.totalOveruses = totalOveruses; 4341 return stats; 4342 } 4343 delayedRunOnMainSync(Runnable action, long delayMillis)4344 private static void delayedRunOnMainSync(Runnable action, long delayMillis) 4345 throws InterruptedException { 4346 AtomicBoolean isComplete = new AtomicBoolean(); 4347 Handler handler = new Handler(Looper.getMainLooper()); 4348 handler.postDelayed(() -> { 4349 action.run(); 4350 synchronized (action) { 4351 isComplete.set(true); 4352 action.notifyAll(); 4353 } 4354 }, delayMillis); 4355 synchronized (action) { 4356 while (!isComplete.get()) { 4357 action.wait(); 4358 } 4359 } 4360 } 4361 4362 private static AtomsProto.CarWatchdogIoOveruseStatsReported constructIoOveruseStatsReported(int uid, AtomsProto.CarWatchdogPerStateBytes threshold, AtomsProto.CarWatchdogPerStateBytes writtenBytes)4363 constructIoOveruseStatsReported(int uid, AtomsProto.CarWatchdogPerStateBytes threshold, 4364 AtomsProto.CarWatchdogPerStateBytes writtenBytes) { 4365 return constructCarWatchdogIoOveruseStatsReported( 4366 uid, WatchdogPerfHandler.constructCarWatchdogIoOveruseStats( 4367 AtomsProto.CarWatchdogIoOveruseStats.Period.DAILY, threshold, writtenBytes) 4368 ); 4369 } 4370 4371 private static AtomsProto.CarWatchdogIoOveruseStatsReported constructCarWatchdogIoOveruseStatsReported( int uid, AtomsProto.CarWatchdogIoOveruseStats ioOveruseStats)4372 constructCarWatchdogIoOveruseStatsReported( 4373 int uid, AtomsProto.CarWatchdogIoOveruseStats ioOveruseStats) { 4374 return AtomsProto.CarWatchdogIoOveruseStatsReported.newBuilder() 4375 .setUid(uid) 4376 .setIoOveruseStats(ioOveruseStats) 4377 .build(); 4378 } 4379 constructIoOveruseKillStatsReported( int uid, int systemState, AtomsProto.CarWatchdogPerStateBytes threshold, AtomsProto.CarWatchdogPerStateBytes writtenBytes)4380 private static AtomsProto.CarWatchdogKillStatsReported constructIoOveruseKillStatsReported( 4381 int uid, int systemState, AtomsProto.CarWatchdogPerStateBytes threshold, 4382 AtomsProto.CarWatchdogPerStateBytes writtenBytes) { 4383 return constructCarWatchdogKillStatsReported(uid, 4384 CAR_WATCHDOG_KILL_STATS_REPORTED__UID_STATE__UNKNOWN_UID_STATE, systemState, 4385 CAR_WATCHDOG_KILL_STATS_REPORTED__KILL_REASON__KILLED_ON_IO_OVERUSE, 4386 WatchdogPerfHandler.constructCarWatchdogIoOveruseStats( 4387 AtomsProto.CarWatchdogIoOveruseStats.Period.DAILY, threshold, writtenBytes) 4388 ); 4389 } 4390 constructCarWatchdogKillStatsReported( int uid, int uidState, int systemState, int killReason, AtomsProto.CarWatchdogIoOveruseStats ioOveruseStats)4391 private static AtomsProto.CarWatchdogKillStatsReported constructCarWatchdogKillStatsReported( 4392 int uid, int uidState, int systemState, int killReason, 4393 AtomsProto.CarWatchdogIoOveruseStats ioOveruseStats) { 4394 return AtomsProto.CarWatchdogKillStatsReported.newBuilder() 4395 .setUid(uid) 4396 .setUidState(AtomsProto.CarWatchdogKillStatsReported.UidState.forNumber(uidState)) 4397 .setSystemState(AtomsProto.CarWatchdogKillStatsReported.SystemState.forNumber( 4398 systemState)) 4399 .setKillReason(AtomsProto.CarWatchdogKillStatsReported.KillReason.forNumber( 4400 killReason)) 4401 .setIoOveruseStats(ioOveruseStats) 4402 .build(); 4403 } 4404 captureAndVerifyIoOveruseStatsReported( List<AtomsProto.CarWatchdogIoOveruseStatsReported> expected)4405 private void captureAndVerifyIoOveruseStatsReported( 4406 List<AtomsProto.CarWatchdogIoOveruseStatsReported> expected) throws Exception { 4407 verify(() -> CarStatsLog.write(eq(CarStatsLog.CAR_WATCHDOG_IO_OVERUSE_STATS_REPORTED), 4408 mOverusingUidCaptor.capture(), mOveruseStatsCaptor.capture()), 4409 times(expected.size())); 4410 4411 List<Integer> allUidValues = mOverusingUidCaptor.getAllValues(); 4412 List<byte[]> allOveruseStatsValues = mOveruseStatsCaptor.getAllValues(); 4413 List<AtomsProto.CarWatchdogIoOveruseStatsReported> actual = new ArrayList<>(); 4414 for (int i = 0; i < expected.size(); ++i) { 4415 actual.add(constructCarWatchdogIoOveruseStatsReported(allUidValues.get(i), 4416 AtomsProto.CarWatchdogIoOveruseStats.parseFrom(allOveruseStatsValues.get(i)))); 4417 } 4418 assertWithMessage("I/O overuse stats reported to statsd").that(actual) 4419 .containsExactlyElementsIn(expected); 4420 } 4421 captureAndVerifyKillStatsReported( List<AtomsProto.CarWatchdogKillStatsReported> expected)4422 private void captureAndVerifyKillStatsReported( 4423 List<AtomsProto.CarWatchdogKillStatsReported> expected) throws Exception { 4424 // Overuse handling task is posted on the main thread and this task performs disabling and 4425 // uploading metrics. Wait for this task to complete. 4426 CarServiceUtils.runOnMainSync(() -> {}); 4427 4428 verify(() -> CarStatsLog.write(eq(CarStatsLog.CAR_WATCHDOG_KILL_STATS_REPORTED), 4429 mKilledUidCaptor.capture(), mUidStateCaptor.capture(), 4430 mSystemStateCaptor.capture(), mKillReasonCaptor.capture(), eq(null), 4431 mKilledStatsCaptor.capture()), times(expected.size())); 4432 4433 List<Integer> allUidValues = mKilledUidCaptor.getAllValues(); 4434 List<Integer> allUidStateValues = mUidStateCaptor.getAllValues(); 4435 List<Integer> allSystemStateValues = mSystemStateCaptor.getAllValues(); 4436 List<Integer> allKillReasonValues = mKillReasonCaptor.getAllValues(); 4437 List<byte[]> allIoOveruseStatsValues = mKilledStatsCaptor.getAllValues(); 4438 List<AtomsProto.CarWatchdogKillStatsReported> actual = new ArrayList<>(); 4439 for (int i = 0; i < expected.size(); ++i) { 4440 actual.add(constructCarWatchdogKillStatsReported(allUidValues.get(i), 4441 allUidStateValues.get(i), allSystemStateValues.get(i), 4442 allKillReasonValues.get(i), 4443 AtomsProto.CarWatchdogIoOveruseStats.parseFrom( 4444 allIoOveruseStatsValues.get(i)))); 4445 } 4446 assertWithMessage("I/O overuse kill stats reported to statsd").that(actual) 4447 .containsExactlyElementsIn(expected); 4448 } 4449 verifyAndGetSystemIoUsageSummaries( ZonedDateTime beginReportDate)4450 private List<AtomsProto.CarWatchdogSystemIoUsageSummary> verifyAndGetSystemIoUsageSummaries( 4451 ZonedDateTime beginReportDate) { 4452 ZonedDateTime beginWeekStartDate = beginReportDate.with(ChronoField.DAY_OF_WEEK, 1); 4453 ZonedDateTime endWeekStartDate = mTimeSource.getCurrentDate() 4454 .with(ChronoField.DAY_OF_WEEK, 1); 4455 List<AtomsProto.CarWatchdogSystemIoUsageSummary> expectedSummaries = new ArrayList<>(); 4456 while (!beginWeekStartDate.equals(endWeekStartDate)) { 4457 long startEpochSecond = beginWeekStartDate.toEpochSecond(); 4458 verify(mMockWatchdogStorage).getDailySystemIoUsageSummaries(startEpochSecond, 4459 beginWeekStartDate.plusWeeks(1).toEpochSecond()); 4460 expectedSummaries.add(AtomsProto.CarWatchdogSystemIoUsageSummary.newBuilder() 4461 .setIoUsageSummary(constructCarWatchdogIoUsageSummary(startEpochSecond, 4462 sampleDailyIoUsageSummariesForAWeek(startEpochSecond, 4463 SYSTEM_DAILY_IO_USAGE_SUMMARY_MULTIPLIER))) 4464 .build()); 4465 beginWeekStartDate = beginWeekStartDate.plusWeeks(1); 4466 } 4467 return expectedSummaries; 4468 } 4469 verifyAndGetUidIoUsageSummaries( ZonedDateTime beginReportDate, List<Integer> expectUids)4470 private List<AtomsProto.CarWatchdogUidIoUsageSummary> verifyAndGetUidIoUsageSummaries( 4471 ZonedDateTime beginReportDate, List<Integer> expectUids) { 4472 ZonedDateTime beginWeekStartDate = beginReportDate.with(ChronoField.DAY_OF_WEEK, 1); 4473 ZonedDateTime endWeekStartDate = mTimeSource.getCurrentDate() 4474 .with(ChronoField.DAY_OF_WEEK, 1); 4475 List<AtomsProto.CarWatchdogUidIoUsageSummary> expectedSummaries = new ArrayList<>(); 4476 while (!beginWeekStartDate.equals(endWeekStartDate)) { 4477 long startEpochSecond = beginWeekStartDate.toEpochSecond(); 4478 verify(mMockWatchdogStorage).getTopUsersDailyIoUsageSummaries( 4479 UID_IO_USAGE_SUMMARY_TOP_COUNT * 2, 4480 UID_IO_USAGE_SUMMARY_MIN_SYSTEM_TOTAL_WEEKLY_WRITTEN_BYTES, startEpochSecond, 4481 beginWeekStartDate.plusWeeks(1).toEpochSecond()); 4482 for (Integer uid : expectUids) { 4483 expectedSummaries.add(AtomsProto.CarWatchdogUidIoUsageSummary.newBuilder() 4484 .setUid(uid) 4485 .setIoUsageSummary(constructCarWatchdogIoUsageSummary(startEpochSecond, 4486 sampleDailyIoUsageSummariesForAWeek(startEpochSecond, 4487 uid))) 4488 .build()); 4489 } 4490 beginWeekStartDate = beginWeekStartDate.plusWeeks(1); 4491 } 4492 return expectedSummaries; 4493 } 4494 constructCarWatchdogIoUsageSummary( long startTimeMillis, List<AtomsProto.CarWatchdogDailyIoUsageSummary> dailySummaries)4495 private static AtomsProto.CarWatchdogIoUsageSummary constructCarWatchdogIoUsageSummary( 4496 long startTimeMillis, List<AtomsProto.CarWatchdogDailyIoUsageSummary> dailySummaries) { 4497 return AtomsProto.CarWatchdogIoUsageSummary.newBuilder() 4498 .setEventTimePeriod(AtomsProto.CarWatchdogEventTimePeriod.newBuilder() 4499 .setPeriod(AtomsProto.CarWatchdogEventTimePeriod.Period.WEEKLY) 4500 .setStartTimeMillis(startTimeMillis).build()) 4501 .addAllDailyIoUsageSummary(dailySummaries) 4502 .build(); 4503 } 4504 sampleDailyIoUsageSummariesForAWeek( long startEpochSeconds, long sysOrUidMultiplier)4505 private List<AtomsProto.CarWatchdogDailyIoUsageSummary> sampleDailyIoUsageSummariesForAWeek( 4506 long startEpochSeconds, long sysOrUidMultiplier) { 4507 List<AtomsProto.CarWatchdogDailyIoUsageSummary> summaries = new ArrayList<>(); 4508 long weekMultiplier = ChronoUnit.WEEKS.between( 4509 ZonedDateTime.ofInstant(Instant.ofEpochSecond(startEpochSeconds), ZONE_OFFSET), 4510 mTimeSource.getCurrentDate()); 4511 for (int i = 1; i < 8; ++i) { 4512 summaries.add(constructCarWatchdogDailyIoUsageSummary( 4513 /* fgWrBytes= */ 100 * i * weekMultiplier * sysOrUidMultiplier, 4514 /* bgWrBytes= */ 200 * i * weekMultiplier * sysOrUidMultiplier, 4515 /* gmWrBytes= */ 300 * i * weekMultiplier * sysOrUidMultiplier, 4516 /* overuseCount= */ 2 * i)); 4517 } 4518 return summaries; 4519 } 4520 constructCarWatchdogDailyIoUsageSummary( long fgWrBytes, long bgWrBytes, long gmWrBytes, int overuseCount)4521 static AtomsProto.CarWatchdogDailyIoUsageSummary constructCarWatchdogDailyIoUsageSummary( 4522 long fgWrBytes, long bgWrBytes, long gmWrBytes, int overuseCount) { 4523 return AtomsProto.CarWatchdogDailyIoUsageSummary.newBuilder() 4524 .setWrittenBytes(WatchdogPerfHandler 4525 .constructCarWatchdogPerStateBytes(fgWrBytes, bgWrBytes, gmWrBytes)) 4526 .setOveruseCount(overuseCount) 4527 .build(); 4528 } 4529 4530 private class TestClient extends ICarWatchdogServiceCallback.Stub { 4531 protected int mLastSessionId = INVALID_SESSION_ID; 4532 4533 @Override onCheckHealthStatus(int sessionId, int timeout)4534 public void onCheckHealthStatus(int sessionId, int timeout) { 4535 mLastSessionId = sessionId; 4536 mCarWatchdogService.tellClientAlive(this, sessionId); 4537 } 4538 4539 @Override onPrepareProcessTermination()4540 public void onPrepareProcessTermination() { 4541 } 4542 getLastSessionId()4543 public int getLastSessionId() { 4544 return mLastSessionId; 4545 } 4546 } 4547 4548 private final class BadTestClient extends TestClient { 4549 @Override onCheckHealthStatus(int sessionId, int timeout)4550 public void onCheckHealthStatus(int sessionId, int timeout) { 4551 mLastSessionId = sessionId; 4552 // This client doesn't respond to CarWatchdogService. 4553 } 4554 } 4555 createMockResourceOveruseListener()4556 private static IResourceOveruseListener createMockResourceOveruseListener() { 4557 IResourceOveruseListener listener = mock(IResourceOveruseListener.Stub.class); 4558 when(listener.asBinder()).thenCallRealMethod(); 4559 return listener; 4560 } 4561 constructPackageInfo(String packageName, int uid, List<String> sharedUidPackages, int uidType, int componentType, int appCategoryType)4562 private static PackageInfo constructPackageInfo(String packageName, int uid, 4563 List<String> sharedUidPackages, int uidType, int componentType, int appCategoryType) { 4564 PackageInfo packageInfo = new PackageInfo(); 4565 packageInfo.packageIdentifier = new PackageIdentifier(); 4566 packageInfo.packageIdentifier.name = packageName; 4567 packageInfo.packageIdentifier.uid = uid; 4568 packageInfo.uidType = uidType; 4569 packageInfo.sharedUidPackages = sharedUidPackages; 4570 packageInfo.componentType = componentType; 4571 packageInfo.appCategoryType = appCategoryType; 4572 4573 return packageInfo; 4574 } 4575 toPackageInfosString(List<PackageInfo> packageInfos)4576 private static String toPackageInfosString(List<PackageInfo> packageInfos) { 4577 StringBuilder builder = new StringBuilder(); 4578 for (PackageInfo packageInfo : packageInfos) { 4579 builder = packageInfoStringBuilder(builder, packageInfo).append('\n'); 4580 } 4581 return builder.toString(); 4582 } 4583 packageInfoStringBuilder( StringBuilder builder, PackageInfo packageInfo)4584 private static StringBuilder packageInfoStringBuilder( 4585 StringBuilder builder, PackageInfo packageInfo) { 4586 if (packageInfo == null) { 4587 return builder.append("Null package info\n"); 4588 } 4589 builder.append("Package name: '").append(packageInfo.packageIdentifier.name) 4590 .append("', UID: ").append(packageInfo.packageIdentifier.uid).append('\n') 4591 .append("Owned packages: "); 4592 if (packageInfo.sharedUidPackages != null) { 4593 for (int i = 0; i < packageInfo.sharedUidPackages.size(); ++i) { 4594 builder.append('\'').append(packageInfo.sharedUidPackages.get(i)).append('\''); 4595 if (i < packageInfo.sharedUidPackages.size() - 1) { 4596 builder.append(", "); 4597 } 4598 } 4599 builder.append('\n'); 4600 } else { 4601 builder.append("Null"); 4602 } 4603 builder.append("Component type: ").append(packageInfo.componentType).append('\n') 4604 .append("Application category type: ").append(packageInfo.appCategoryType).append( 4605 '\n'); 4606 4607 return builder; 4608 } 4609 assertPackageInfoEquals(List<PackageInfo> actual, List<PackageInfo> expected)4610 private static void assertPackageInfoEquals(List<PackageInfo> actual, 4611 List<PackageInfo> expected) throws Exception { 4612 assertWithMessage("Package infos for UIDs:\nExpected: %s\nActual: %s", 4613 CarWatchdogServiceUnitTest.toPackageInfosString(expected), 4614 CarWatchdogServiceUnitTest.toPackageInfosString(actual)) 4615 .that(actual) 4616 .comparingElementsUsing( 4617 Correspondence.from(CarWatchdogServiceUnitTest::isPackageInfoEquals, 4618 "is package info equal to")).containsExactlyElementsIn(expected); 4619 } 4620 isPackageInfoEquals(PackageInfo lhs, PackageInfo rhs)4621 private static boolean isPackageInfoEquals(PackageInfo lhs, PackageInfo rhs) { 4622 return isEquals(lhs.packageIdentifier, rhs.packageIdentifier) 4623 && lhs.sharedUidPackages.containsAll(rhs.sharedUidPackages) 4624 && lhs.componentType == rhs.componentType 4625 && lhs.appCategoryType == rhs.appCategoryType; 4626 } 4627 isEquals(PackageIdentifier lhs, PackageIdentifier rhs)4628 private static boolean isEquals(PackageIdentifier lhs, PackageIdentifier rhs) { 4629 return lhs.name.equals(rhs.name) && lhs.uid == rhs.uid; 4630 } 4631 constructPackageManagerPackageInfo( String packageName, int uid, String sharedUserId)4632 private static android.content.pm.PackageInfo constructPackageManagerPackageInfo( 4633 String packageName, int uid, String sharedUserId) { 4634 if (packageName.startsWith("system")) { 4635 return constructPackageManagerPackageInfo( 4636 packageName, uid, sharedUserId, ApplicationInfo.FLAG_SYSTEM, 0); 4637 } 4638 if (packageName.startsWith("vendor")) { 4639 return constructPackageManagerPackageInfo( 4640 packageName, uid, sharedUserId, ApplicationInfo.FLAG_SYSTEM, 4641 ApplicationInfo.PRIVATE_FLAG_OEM); 4642 } 4643 return constructPackageManagerPackageInfo(packageName, uid, sharedUserId, 0, 0); 4644 } 4645 constructPackageManagerPackageInfo( String packageName, int uid, String sharedUserId, int flags, int privateFlags)4646 private static android.content.pm.PackageInfo constructPackageManagerPackageInfo( 4647 String packageName, int uid, String sharedUserId, int flags, int privateFlags) { 4648 android.content.pm.PackageInfo packageInfo = new android.content.pm.PackageInfo(); 4649 packageInfo.packageName = packageName; 4650 packageInfo.sharedUserId = sharedUserId; 4651 packageInfo.applicationInfo = new ApplicationInfo(); 4652 packageInfo.applicationInfo.packageName = packageName; 4653 packageInfo.applicationInfo.uid = uid; 4654 packageInfo.applicationInfo.flags = flags; 4655 packageInfo.applicationInfo.privateFlags = privateFlags; 4656 return packageInfo; 4657 } 4658 4659 private static final class TestTimeSource extends TimeSource { 4660 private static final Instant TEST_DATE_TIME = Instant.parse("2021-11-12T13:14:15.16Z"); 4661 private Instant mNow; TestTimeSource()4662 TestTimeSource() { 4663 mNow = TEST_DATE_TIME; 4664 } 4665 4666 @Override now()4667 public Instant now() { 4668 /* Return the same time, so the tests are deterministic. */ 4669 return mNow; 4670 } 4671 4672 @Override toString()4673 public String toString() { 4674 return "Mocked date to " + now(); 4675 } 4676 updateNow(int numDaysAgo)4677 void updateNow(int numDaysAgo) { 4678 mNow = TEST_DATE_TIME.minus(numDaysAgo, ChronoUnit.DAYS); 4679 } 4680 } 4681 4682 private static final class UserNotificationCall { 4683 public final UserHandle userHandle; 4684 public final List<String> packages; 4685 public final boolean hasHeadsUpNotification; 4686 public final List<Integer> notificationIds; 4687 UserNotificationCall(UserHandle userHandle, List<String> packages, boolean hasHeadsUpNotification, List<Integer> notificationIds)4688 UserNotificationCall(UserHandle userHandle, List<String> packages, 4689 boolean hasHeadsUpNotification, List<Integer> notificationIds) { 4690 this.userHandle = userHandle; 4691 this.packages = packages; 4692 this.hasHeadsUpNotification = hasHeadsUpNotification; 4693 this.notificationIds = notificationIds; 4694 } 4695 verifyCall( List<UserNotificationHelper.PackageNotificationInfo> actualPackageNotificationInfos, UserHandle actualUserHandle)4696 void verifyCall( 4697 List<UserNotificationHelper.PackageNotificationInfo> actualPackageNotificationInfos, 4698 UserHandle actualUserHandle) { 4699 assertWithMessage("User handle").that(actualUserHandle).isEqualTo(userHandle); 4700 List<String> actualPackages = new ArrayList<>(); 4701 List<Integer> actualNotificationIds = new ArrayList<>(); 4702 int numHeadsUpNotification = 0; 4703 for (UserNotificationHelper.PackageNotificationInfo info 4704 : actualPackageNotificationInfos) { 4705 actualPackages.add(info.packageName); 4706 numHeadsUpNotification += info.importance == NotificationManager.IMPORTANCE_HIGH ? 1 4707 : 0; 4708 actualNotificationIds.add(info.notificationId); 4709 } 4710 assertWithMessage("Packages").that(actualPackages).isEqualTo(packages); 4711 assertWithMessage("Notification ids").that(actualNotificationIds) 4712 .containsExactlyElementsIn(notificationIds); 4713 assertWithMessage("Number of heads up notifications").that(numHeadsUpNotification) 4714 .isEqualTo(hasHeadsUpNotification ? 1 : 0); 4715 } 4716 } 4717 } 4718