1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.server.alarm; 17 18 import static android.Manifest.permission.SCHEDULE_EXACT_ALARM; 19 import static android.app.AlarmManager.ELAPSED_REALTIME; 20 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; 21 import static android.app.AlarmManager.EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED; 22 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE; 23 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_COMPAT; 24 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; 25 import static android.app.AlarmManager.FLAG_IDLE_UNTIL; 26 import static android.app.AlarmManager.FLAG_PRIORITIZE; 27 import static android.app.AlarmManager.FLAG_STANDALONE; 28 import static android.app.AlarmManager.FLAG_WAKE_FROM_IDLE; 29 import static android.app.AlarmManager.RTC; 30 import static android.app.AlarmManager.RTC_WAKEUP; 31 import static android.app.AlarmManager.WINDOW_EXACT; 32 import static android.app.AlarmManager.WINDOW_HEURISTIC; 33 import static android.app.AppOpsManager.MODE_ALLOWED; 34 import static android.app.AppOpsManager.MODE_DEFAULT; 35 import static android.app.AppOpsManager.MODE_ERRORED; 36 import static android.app.AppOpsManager.MODE_IGNORED; 37 import static android.app.AppOpsManager.OP_SCHEDULE_EXACT_ALARM; 38 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE; 39 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT; 40 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE; 41 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RESTRICTED; 42 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET; 43 import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED; 44 import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED; 45 46 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; 47 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod; 48 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 49 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow; 50 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; 51 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 52 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; 53 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; 54 import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH; 55 import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST; 56 import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT; 57 import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_LISTENER; 58 import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE; 59 import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION; 60 import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION; 61 import static com.android.server.alarm.AlarmManagerService.ACTIVE_INDEX; 62 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED; 63 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED; 64 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE; 65 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_ADDED; 66 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED; 67 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES; 68 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REMOVE_EXACT_ALARMS; 69 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED; 70 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REMOVE_FOR_CANCELED; 71 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.TARE_AFFORDABILITY_CHANGED; 72 import static com.android.server.alarm.AlarmManagerService.AlarmHandler.TEMPORARY_QUOTA_CHANGED; 73 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA; 74 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_COMPAT_WINDOW; 75 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_QUOTA; 76 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION; 77 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WINDOW; 78 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_EXACT_ALARM_DENY_LIST; 79 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LISTENER_TIMEOUT; 80 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MAX_DEVICE_IDLE_FUZZ; 81 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MAX_INTERVAL; 82 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_DEVICE_IDLE_FUZZ; 83 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_FUTURITY; 84 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_INTERVAL; 85 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_WINDOW; 86 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_PRIORITY_ALARM_DELAY; 87 import static com.android.server.alarm.AlarmManagerService.Constants.KEY_TEMPORARY_QUOTA_BUMP; 88 import static com.android.server.alarm.AlarmManagerService.Constants.MAX_EXACT_ALARM_DENY_LIST_SIZE; 89 import static com.android.server.alarm.AlarmManagerService.FREQUENT_INDEX; 90 import static com.android.server.alarm.AlarmManagerService.INDEFINITE_DELAY; 91 import static com.android.server.alarm.AlarmManagerService.IS_WAKEUP_MASK; 92 import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_UNDEFINED; 93 import static com.android.server.alarm.AlarmManagerService.TIME_CHANGED_MASK; 94 import static com.android.server.alarm.AlarmManagerService.WORKING_INDEX; 95 import static com.android.server.alarm.Constants.TEST_CALLING_PACKAGE; 96 import static com.android.server.alarm.Constants.TEST_CALLING_UID; 97 98 import static org.junit.Assert.assertEquals; 99 import static org.junit.Assert.assertFalse; 100 import static org.junit.Assert.assertNotNull; 101 import static org.junit.Assert.assertNull; 102 import static org.junit.Assert.assertTrue; 103 import static org.junit.Assert.fail; 104 import static org.mockito.ArgumentMatchers.any; 105 import static org.mockito.ArgumentMatchers.anyBoolean; 106 import static org.mockito.ArgumentMatchers.anyInt; 107 import static org.mockito.ArgumentMatchers.anyLong; 108 import static org.mockito.ArgumentMatchers.anyString; 109 import static org.mockito.ArgumentMatchers.argThat; 110 import static org.mockito.ArgumentMatchers.eq; 111 import static org.mockito.ArgumentMatchers.isNull; 112 import static org.mockito.Mockito.atLeastOnce; 113 import static org.mockito.Mockito.never; 114 import static org.mockito.Mockito.times; 115 import static org.mockito.Mockito.verifyZeroInteractions; 116 117 import android.Manifest; 118 import android.app.ActivityManager; 119 import android.app.ActivityManagerInternal; 120 import android.app.ActivityOptions; 121 import android.app.AlarmManager; 122 import android.app.AppOpsManager; 123 import android.app.BroadcastOptions; 124 import android.app.IActivityManager; 125 import android.app.IAlarmCompleteListener; 126 import android.app.IAlarmListener; 127 import android.app.IAlarmManager; 128 import android.app.PendingIntent; 129 import android.app.compat.CompatChanges; 130 import android.app.tare.EconomyManager; 131 import android.app.usage.UsageStatsManagerInternal; 132 import android.content.ContentResolver; 133 import android.content.Context; 134 import android.content.Intent; 135 import android.content.PermissionChecker; 136 import android.content.pm.PackageManagerInternal; 137 import android.net.Uri; 138 import android.os.BatteryManager; 139 import android.os.Bundle; 140 import android.os.Handler; 141 import android.os.IBinder; 142 import android.os.Looper; 143 import android.os.Message; 144 import android.os.PowerExemptionManager; 145 import android.os.PowerManager; 146 import android.os.RemoteException; 147 import android.os.ServiceManager; 148 import android.os.SystemProperties; 149 import android.os.UserHandle; 150 import android.platform.test.annotations.Presubmit; 151 import android.provider.DeviceConfig; 152 import android.provider.Settings; 153 import android.text.format.DateFormat; 154 import android.util.ArraySet; 155 import android.util.Log; 156 import android.util.SparseArray; 157 158 import androidx.test.runner.AndroidJUnit4; 159 160 import com.android.dx.mockito.inline.extended.MockedVoidMethod; 161 import com.android.internal.annotations.GuardedBy; 162 import com.android.internal.app.IAppOpsCallback; 163 import com.android.internal.app.IAppOpsService; 164 import com.android.internal.util.ArrayUtils; 165 import com.android.server.AlarmManagerInternal; 166 import com.android.server.AppStateTracker; 167 import com.android.server.AppStateTrackerImpl; 168 import com.android.server.DeviceIdleInternal; 169 import com.android.server.ExtendedMockitoRule; 170 import com.android.server.LocalServices; 171 import com.android.server.SystemClockTime.TimeConfidence; 172 import com.android.server.SystemService; 173 import com.android.server.pm.permission.PermissionManagerService; 174 import com.android.server.pm.permission.PermissionManagerServiceInternal; 175 import com.android.server.pm.pkg.AndroidPackage; 176 import com.android.server.tare.AlarmManagerEconomicPolicy; 177 import com.android.server.tare.EconomyManagerInternal; 178 import com.android.server.usage.AppStandbyInternal; 179 180 import libcore.util.EmptyArray; 181 182 import org.junit.Before; 183 import org.junit.Rule; 184 import org.junit.Test; 185 import org.junit.runner.RunWith; 186 import org.mockito.Answers; 187 import org.mockito.ArgumentCaptor; 188 import org.mockito.ArgumentMatchers; 189 import org.mockito.Mock; 190 import org.mockito.quality.Strictness; 191 import org.mockito.stubbing.Answer; 192 193 import java.util.ArrayList; 194 import java.util.Collections; 195 import java.util.HashSet; 196 import java.util.List; 197 import java.util.Random; 198 import java.util.concurrent.Executor; 199 import java.util.concurrent.atomic.AtomicInteger; 200 import java.util.function.LongConsumer; 201 202 @Presubmit 203 @SuppressWarnings("GuardedBy") // This test enforces synchronous behavior. 204 @RunWith(AndroidJUnit4.class) 205 public final class AlarmManagerServiceTest { 206 private static final String TAG = AlarmManagerServiceTest.class.getSimpleName(); 207 private static final int SYSTEM_UI_UID = 12345; 208 private static final int TEST_CALLING_USER = UserHandle.getUserId(TEST_CALLING_UID); 209 private static final int TEST_CALLING_UID_2 = TEST_CALLING_UID + 1; 210 private static final int[] ALARM_TYPES = 211 {RTC_WAKEUP, RTC, ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME}; 212 213 private long mAppStandbyWindow; 214 private long mAllowWhileIdleWindow; 215 private AlarmManagerService mService; 216 private AppStandbyInternal.AppIdleStateChangeListener mAppStandbyListener; 217 private AppStateTrackerImpl.Listener mListener; 218 private AlarmManagerService.UninstallReceiver mPackageChangesReceiver; 219 private AlarmManagerService.ChargingReceiver mChargingReceiver; 220 private IAppOpsCallback mIAppOpsCallback; 221 private IAlarmManager mBinder; 222 @Mock 223 private Context mMockContext; 224 @Mock 225 private ContentResolver mContentResolver; 226 @Mock 227 private IActivityManager mIActivityManager; 228 @Mock 229 private IAppOpsService mIAppOpsService; 230 @Mock 231 private AppOpsManager mAppOpsManager; 232 @Mock 233 private BatteryManager mBatteryManager; 234 @Mock 235 private DeviceIdleInternal mDeviceIdleInternal; 236 @Mock 237 private PermissionManagerServiceInternal mPermissionManagerInternal; 238 @Mock 239 private UsageStatsManagerInternal mUsageStatsManagerInternal; 240 @Mock 241 private AppStandbyInternal mAppStandbyInternal; 242 @Mock 243 private ActivityManagerInternal mActivityManagerInternal; 244 @Mock 245 private PackageManagerInternal mPackageManagerInternal; 246 @Mock 247 private AppStateTrackerImpl mAppStateTracker; 248 @Mock 249 private AlarmManagerService.ClockReceiver mClockReceiver; 250 @Mock 251 private PowerManager.WakeLock mWakeLock; 252 @Mock 253 private EconomyManagerInternal mEconomyManagerInternal; 254 @Mock 255 DeviceConfig.Properties mDeviceConfigProperties; 256 HashSet<String> mDeviceConfigKeys = new HashSet<>(); 257 258 private Injector mInjector; 259 private volatile long mNowElapsedTest; 260 private volatile long mNowRtcTest; 261 private volatile int mTestCallingUid = TEST_CALLING_UID; 262 @GuardedBy("mTestTimer") 263 private TestTimer mTestTimer = new TestTimer(); 264 265 static class TestTimer { 266 private long mElapsed; 267 boolean mExpired; 268 private int mType; 269 private int mFlags; // Flags used to decide what needs to be evaluated. 270 getElapsed()271 synchronized long getElapsed() { 272 return mElapsed; 273 } 274 set(int type, long millisElapsed)275 synchronized void set(int type, long millisElapsed) { 276 mType = type; 277 mElapsed = millisElapsed; 278 } 279 getType()280 synchronized int getType() { 281 return mType; 282 } 283 getFlags()284 synchronized int getFlags() { 285 return mFlags; 286 } 287 expire()288 synchronized void expire() throws InterruptedException { 289 expire(IS_WAKEUP_MASK); // Default: evaluate eligibility of all alarms 290 } 291 expire(int flags)292 synchronized void expire(int flags) throws InterruptedException { 293 mFlags = flags; 294 mExpired = true; 295 notifyAll(); 296 // Now wait for the alarm thread to finish execution. 297 wait(); 298 } 299 } 300 301 public class Injector extends AlarmManagerService.Injector { 302 Injector(Context context)303 Injector(Context context) { 304 super(context); 305 } 306 307 @Override init()308 void init() { 309 // Do nothing. 310 } 311 312 @Override waitForAlarm()313 int waitForAlarm() { 314 synchronized (mTestTimer) { 315 mTestTimer.notifyAll(); 316 if (!mTestTimer.mExpired) { 317 try { 318 mTestTimer.wait(); 319 } catch (InterruptedException ie) { 320 Log.e(TAG, "Wait interrupted!", ie); 321 return 0; 322 } 323 } 324 mTestTimer.mExpired = false; 325 } 326 return mTestTimer.getFlags(); 327 } 328 329 @Override setKernelTimeZoneOffset(int utcOffsetMillis)330 void setKernelTimeZoneOffset(int utcOffsetMillis) { 331 // Do nothing. 332 } 333 334 @Override syncKernelTimeZoneOffset()335 void syncKernelTimeZoneOffset() { 336 // Do nothing. 337 } 338 339 @Override getCallingUid()340 int getCallingUid() { 341 return mTestCallingUid; 342 } 343 344 @Override setAlarm(int type, long millis)345 void setAlarm(int type, long millis) { 346 mTestTimer.set(type, millis); 347 } 348 349 @Override getSystemUiUid(PackageManagerInternal unused)350 int getSystemUiUid(PackageManagerInternal unused) { 351 return SYSTEM_UI_UID; 352 } 353 354 @Override isAlarmDriverPresent()355 boolean isAlarmDriverPresent() { 356 // Pretend the driver is present, so code does not fall back to handler 357 return true; 358 } 359 360 @Override initializeTimeIfRequired()361 void initializeTimeIfRequired() { 362 // No-op 363 } 364 365 @Override setCurrentTimeMillis(long unixEpochMillis, @TimeConfidence int confidence, String logMsg)366 void setCurrentTimeMillis(long unixEpochMillis, 367 @TimeConfidence int confidence, String logMsg) { 368 mNowRtcTest = unixEpochMillis; 369 } 370 371 @Override getElapsedRealtimeMillis()372 long getElapsedRealtimeMillis() { 373 return mNowElapsedTest; 374 } 375 376 @Override getCurrentTimeMillis()377 long getCurrentTimeMillis() { 378 return mNowRtcTest; 379 } 380 381 @Override getClockReceiver(AlarmManagerService service)382 AlarmManagerService.ClockReceiver getClockReceiver(AlarmManagerService service) { 383 return mClockReceiver; 384 } 385 386 @Override getAlarmWakeLock()387 PowerManager.WakeLock getAlarmWakeLock() { 388 return mWakeLock; 389 } 390 391 @Override registerDeviceConfigListener(DeviceConfig.OnPropertiesChangedListener listener)392 void registerDeviceConfigListener(DeviceConfig.OnPropertiesChangedListener listener) { 393 // Do nothing. 394 // The tests become flaky with an error message of 395 // "IllegalStateException: Querying activity state off main thread is not allowed." 396 // when AlarmManager calls DeviceConfig.addOnPropertiesChangedListener(). 397 } 398 399 @Override getAppOpsService()400 IAppOpsService getAppOpsService() { 401 return mIAppOpsService; 402 } 403 } 404 405 @Rule 406 public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) 407 .setStrictness(Strictness.WARN) 408 .spyStatic(ActivityManager.class) 409 .mockStatic(CompatChanges.class) 410 .spyStatic(DateFormat.class) 411 .spyStatic(DeviceConfig.class) 412 .mockStatic(LocalServices.class) 413 .spyStatic(Looper.class) 414 .mockStatic(MetricsHelper.class) 415 .mockStatic(PermissionChecker.class) 416 .mockStatic(PermissionManagerService.class) 417 .mockStatic(ServiceManager.class) 418 .mockStatic(Settings.Global.class) 419 .mockStatic(SystemProperties.class) 420 .spyStatic(UserHandle.class) 421 .afterSessionFinished( 422 () -> LocalServices.removeServiceForTest(AlarmManagerInternal.class)) 423 .build(); 424 425 @Before setUp()426 public final void setUp() { 427 doReturn(mIActivityManager).when(ActivityManager::getService); 428 doReturn(mDeviceIdleInternal).when( 429 () -> LocalServices.getService(DeviceIdleInternal.class)); 430 doReturn(mEconomyManagerInternal).when( 431 () -> LocalServices.getService(EconomyManagerInternal.class)); 432 doReturn(mPermissionManagerInternal).when( 433 () -> LocalServices.getService(PermissionManagerServiceInternal.class)); 434 doReturn(mActivityManagerInternal).when( 435 () -> LocalServices.getService(ActivityManagerInternal.class)); 436 doReturn(mPackageManagerInternal).when( 437 () -> LocalServices.getService(PackageManagerInternal.class)); 438 doReturn(mAppStateTracker).when(() -> LocalServices.getService(AppStateTracker.class)); 439 doReturn(mAppStandbyInternal).when( 440 () -> LocalServices.getService(AppStandbyInternal.class)); 441 doReturn(mUsageStatsManagerInternal).when( 442 () -> LocalServices.getService(UsageStatsManagerInternal.class)); 443 doCallRealMethod().when((MockedVoidMethod) () -> 444 LocalServices.addService(eq(AlarmManagerInternal.class), any())); 445 doCallRealMethod().when(() -> LocalServices.getService(AlarmManagerInternal.class)); 446 doReturn(false).when(() -> UserHandle.isCore(anyInt())); 447 when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), 448 eq(TEST_CALLING_USER), anyLong())).thenReturn(STANDBY_BUCKET_ACTIVE); 449 doReturn(Looper.getMainLooper()).when(Looper::myLooper); 450 451 when(mMockContext.getContentResolver()).thenReturn(mContentResolver); 452 453 doReturn(mDeviceConfigKeys).when(mDeviceConfigProperties).getKeyset(); 454 when(mDeviceConfigProperties.getLong(anyString(), anyLong())) 455 .thenAnswer((Answer<Long>) invocationOnMock -> { 456 Object[] args = invocationOnMock.getArguments(); 457 return (Long) args[1]; 458 }); 459 when(mDeviceConfigProperties.getInt(anyString(), anyInt())) 460 .thenAnswer((Answer<Integer>) invocationOnMock -> { 461 Object[] args = invocationOnMock.getArguments(); 462 return (Integer) args[1]; 463 }); 464 doAnswer((Answer<Void>) invocationOnMock -> null) 465 .when(() -> DeviceConfig.addOnPropertiesChangedListener( 466 anyString(), any(Executor.class), 467 any(DeviceConfig.OnPropertiesChangedListener.class))); 468 doReturn(mDeviceConfigProperties).when( 469 () -> DeviceConfig.getProperties( 470 eq(DeviceConfig.NAMESPACE_ALARM_MANAGER), ArgumentMatchers.<String>any())); 471 // Needed to ensure logging doesn't cause tests to fail. 472 doReturn(true) 473 .when(() -> DateFormat.is24HourFormat(eq(mMockContext), anyInt())); 474 475 doReturn(PermissionChecker.PERMISSION_HARD_DENIED).when( 476 () -> PermissionChecker.checkPermissionForPreflight(any(), 477 eq(Manifest.permission.USE_EXACT_ALARM), anyInt(), anyInt(), anyString())); 478 doReturn(PermissionChecker.PERMISSION_HARD_DENIED).when( 479 () -> PermissionChecker.checkPermissionForPreflight(any(), eq(SCHEDULE_EXACT_ALARM), 480 anyInt(), anyInt(), anyString())); 481 482 when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager); 483 when(mMockContext.getSystemService(BatteryManager.class)).thenReturn(mBatteryManager); 484 485 registerAppIds(new String[]{TEST_CALLING_PACKAGE}, 486 new Integer[]{UserHandle.getAppId(TEST_CALLING_UID)}); 487 when(mPermissionManagerInternal.getAppOpPermissionPackages( 488 SCHEDULE_EXACT_ALARM)).thenReturn(EmptyArray.STRING); 489 490 mInjector = new Injector(mMockContext); 491 mService = new AlarmManagerService(mMockContext, mInjector); 492 spyOn(mService); 493 494 mService.onStart(); 495 // Unable to mock mMockContext to return a mock stats manager. 496 // So just mocking the whole MetricsHelper instance. 497 mService.mMetricsHelper = mock(MetricsHelper.class); 498 spyOn(mService.mHandler); 499 // Stubbing the handler. Test should simulate any handling of messages synchronously. 500 doReturn(true).when(mService.mHandler).sendMessageAtTime(any(Message.class), anyLong()); 501 502 assertEquals(mService.mSystemUiUid, SYSTEM_UI_UID); 503 assertEquals(mService.mClockReceiver, mClockReceiver); 504 assertEquals(mService.mWakeLock, mWakeLock); 505 506 // Other boot phases don't matter 507 mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); 508 509 verify(mBatteryManager).isCharging(); 510 setTareEnabled(EconomyManager.ENABLED_MODE_OFF); 511 mAppStandbyWindow = mService.mConstants.APP_STANDBY_WINDOW; 512 mAllowWhileIdleWindow = mService.mConstants.ALLOW_WHILE_IDLE_WINDOW; 513 514 ArgumentCaptor<AppStandbyInternal.AppIdleStateChangeListener> idleListenerCaptor = 515 ArgumentCaptor.forClass(AppStandbyInternal.AppIdleStateChangeListener.class); 516 verify(mAppStandbyInternal).addListener(idleListenerCaptor.capture()); 517 mAppStandbyListener = idleListenerCaptor.getValue(); 518 519 final ArgumentCaptor<AppStateTrackerImpl.Listener> trackerListenerCaptor = 520 ArgumentCaptor.forClass(AppStateTrackerImpl.Listener.class); 521 verify(mAppStateTracker).addListener(trackerListenerCaptor.capture()); 522 mListener = trackerListenerCaptor.getValue(); 523 524 final ArgumentCaptor<AlarmManagerService.ChargingReceiver> chargingReceiverCaptor = 525 ArgumentCaptor.forClass(AlarmManagerService.ChargingReceiver.class); 526 verify(mMockContext).registerReceiver(chargingReceiverCaptor.capture(), 527 argThat((filter) -> filter.hasAction(BatteryManager.ACTION_CHARGING) 528 && filter.hasAction(BatteryManager.ACTION_DISCHARGING))); 529 mChargingReceiver = chargingReceiverCaptor.getValue(); 530 531 final ArgumentCaptor<AlarmManagerService.UninstallReceiver> packageReceiverCaptor = 532 ArgumentCaptor.forClass(AlarmManagerService.UninstallReceiver.class); 533 verify(mMockContext).registerReceiverForAllUsers(packageReceiverCaptor.capture(), 534 argThat((filter) -> filter.hasAction(Intent.ACTION_PACKAGE_ADDED) 535 && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)), isNull(), isNull()); 536 mPackageChangesReceiver = packageReceiverCaptor.getValue(); 537 538 assertEquals(mService.mExactAlarmCandidates, Collections.emptySet()); 539 540 ArgumentCaptor<IBinder> binderCaptor = ArgumentCaptor.forClass(IBinder.class); 541 verify(() -> ServiceManager.addService(eq(Context.ALARM_SERVICE), binderCaptor.capture(), 542 anyBoolean(), anyInt())); 543 mBinder = IAlarmManager.Stub.asInterface(binderCaptor.getValue()); 544 545 ArgumentCaptor<IAppOpsCallback> appOpsCallbackCaptor = ArgumentCaptor.forClass( 546 IAppOpsCallback.class); 547 try { 548 verify(mIAppOpsService).startWatchingMode(eq(OP_SCHEDULE_EXACT_ALARM), 549 isNull(), appOpsCallbackCaptor.capture()); 550 } catch (RemoteException e) { 551 // Not expected on a mock. 552 } 553 mIAppOpsCallback = appOpsCallbackCaptor.getValue(); 554 setTestableQuotas(); 555 } 556 setTestAlarm(int type, long triggerTime, PendingIntent operation)557 private void setTestAlarm(int type, long triggerTime, PendingIntent operation) { 558 setTestAlarm(type, triggerTime, operation, 0, FLAG_STANDALONE, TEST_CALLING_UID); 559 } 560 setRepeatingTestAlarm(int type, long firstTrigger, long interval, PendingIntent pi)561 private void setRepeatingTestAlarm(int type, long firstTrigger, long interval, 562 PendingIntent pi) { 563 setTestAlarm(type, firstTrigger, pi, interval, FLAG_STANDALONE, TEST_CALLING_UID); 564 } 565 setIdleUntilAlarm(int type, long triggerTime, PendingIntent pi)566 private void setIdleUntilAlarm(int type, long triggerTime, PendingIntent pi) { 567 setTestAlarm(type, triggerTime, pi, 0, FLAG_IDLE_UNTIL | FLAG_STANDALONE, TEST_CALLING_UID); 568 } 569 setWakeFromIdle(int type, long triggerTime, PendingIntent pi)570 private void setWakeFromIdle(int type, long triggerTime, PendingIntent pi) { 571 // Note: Only alarm clock alarms are allowed to include this flag in the actual service. 572 // But this is a unit test so we'll only test the flag for granularity and convenience. 573 setTestAlarm(type, triggerTime, pi, 0, FLAG_WAKE_FROM_IDLE | FLAG_STANDALONE, 574 TEST_CALLING_UID); 575 } 576 setPrioritizedAlarm(int type, long triggerTime, long windowLength, IAlarmListener listener)577 private void setPrioritizedAlarm(int type, long triggerTime, long windowLength, 578 IAlarmListener listener) { 579 mService.setImpl(type, triggerTime, windowLength, 0, null, listener, "test", 580 FLAG_STANDALONE | FLAG_PRIORITIZE, null, null, TEST_CALLING_UID, 581 TEST_CALLING_PACKAGE, null, 0); 582 } 583 setAllowWhileIdleAlarm(int type, long triggerTime, PendingIntent pi, boolean unrestricted, boolean compat)584 private void setAllowWhileIdleAlarm(int type, long triggerTime, PendingIntent pi, 585 boolean unrestricted, boolean compat) { 586 assertFalse("Alarm cannot be compat and unrestricted", unrestricted && compat); 587 final int flags; 588 if (unrestricted) { 589 flags = FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; 590 } else if (compat) { 591 flags = FLAG_ALLOW_WHILE_IDLE_COMPAT; 592 } else { 593 flags = FLAG_ALLOW_WHILE_IDLE; 594 } 595 setTestAlarm(type, triggerTime, pi, 0, flags, TEST_CALLING_UID); 596 } 597 setTestAlarm(int type, long triggerTime, PendingIntent operation, long interval, int flags, int callingUid)598 private void setTestAlarm(int type, long triggerTime, PendingIntent operation, long interval, 599 int flags, int callingUid) { 600 setTestAlarm(type, triggerTime, 0, operation, interval, flags, callingUid, null); 601 } 602 setTestAlarm(int type, long triggerTime, long windowLength, PendingIntent operation, long interval, int flags, int callingUid, Bundle idleOptions)603 private void setTestAlarm(int type, long triggerTime, long windowLength, 604 PendingIntent operation, long interval, int flags, int callingUid, Bundle idleOptions) { 605 setTestAlarm(type, triggerTime, windowLength, operation, interval, flags, callingUid, 606 TEST_CALLING_PACKAGE, idleOptions); 607 } 608 setTestAlarm(int type, long triggerTime, long windowLength, PendingIntent operation, long interval, int flags, int callingUid, String callingPackage, Bundle idleOptions)609 private void setTestAlarm(int type, long triggerTime, long windowLength, 610 PendingIntent operation, long interval, int flags, int callingUid, 611 String callingPackage, Bundle idleOptions) { 612 mService.setImpl(type, triggerTime, windowLength, interval, operation, null, "test", flags, 613 null, null, callingUid, callingPackage, idleOptions, 0); 614 } 615 setTestAlarmWithListener(int type, long triggerTime, IAlarmListener listener)616 private void setTestAlarmWithListener(int type, long triggerTime, IAlarmListener listener) { 617 setTestAlarmWithListener(type, triggerTime, listener, WINDOW_EXACT, TEST_CALLING_UID); 618 } 619 setTestAlarmWithListener(int type, long triggerTime, IAlarmListener listener, long windowLength, int callingUid)620 private void setTestAlarmWithListener(int type, long triggerTime, IAlarmListener listener, 621 long windowLength, int callingUid) { 622 mService.setImpl(type, triggerTime, windowLength, 0, null, listener, "test", 623 FLAG_STANDALONE, null, null, callingUid, TEST_CALLING_PACKAGE, null, 0); 624 } 625 getNewMockPendingIntent()626 private PendingIntent getNewMockPendingIntent() { 627 return getNewMockPendingIntent(false); 628 } 629 getNewMockPendingIntent(boolean isActivity)630 private PendingIntent getNewMockPendingIntent(boolean isActivity) { 631 return getNewMockPendingIntent(TEST_CALLING_UID, TEST_CALLING_PACKAGE, isActivity); 632 } 633 getNewMockPendingIntent(int creatorUid, String creatorPackage)634 private PendingIntent getNewMockPendingIntent(int creatorUid, String creatorPackage) { 635 return getNewMockPendingIntent(creatorUid, creatorPackage, false); 636 } 637 getNewMockPendingIntent(int creatorUid, String creatorPackage, boolean isActivity)638 private PendingIntent getNewMockPendingIntent(int creatorUid, String creatorPackage, 639 boolean isActivity) { 640 final PendingIntent mockPi = mock(PendingIntent.class, Answers.RETURNS_DEEP_STUBS); 641 when(mockPi.getCreatorUid()).thenReturn(creatorUid); 642 when(mockPi.getCreatorPackage()).thenReturn(creatorPackage); 643 when(mockPi.isActivity()).thenReturn(isActivity); 644 return mockPi; 645 } 646 getNewListener(Runnable onAlarm)647 private IAlarmListener getNewListener(Runnable onAlarm) { 648 return new IAlarmListener.Stub() { 649 @Override 650 public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { 651 onAlarm.run(); 652 } 653 }; 654 } 655 656 private void setDeviceConfigInt(String key, int val) { 657 mDeviceConfigKeys.add(key); 658 doReturn(val).when(mDeviceConfigProperties).getInt(eq(key), anyInt()); 659 mService.mConstants.onPropertiesChanged(mDeviceConfigProperties); 660 } 661 662 private void setDeviceConfigLong(String key, long val) { 663 mDeviceConfigKeys.add(key); 664 doReturn(val).when(mDeviceConfigProperties).getLong(eq(key), anyLong()); 665 mService.mConstants.onPropertiesChanged(mDeviceConfigProperties); 666 } 667 668 private void setDeviceConfigBoolean(String key, boolean val) { 669 mDeviceConfigKeys.add(key); 670 doReturn(val).when(mDeviceConfigProperties).getBoolean(eq(key), anyBoolean()); 671 mService.mConstants.onPropertiesChanged(mDeviceConfigProperties); 672 } 673 674 private void setDeviceConfigString(String key, String val) { 675 mDeviceConfigKeys.add(key); 676 doReturn(val).when(mDeviceConfigProperties).getString(eq(key), anyString()); 677 mService.mConstants.onPropertiesChanged(mDeviceConfigProperties); 678 } 679 680 private void setTareEnabled(int enabledMode) { 681 when(mEconomyManagerInternal.getEnabledMode(eq(AlarmManagerEconomicPolicy.POLICY_ALARM))) 682 .thenReturn(enabledMode); 683 mService.mConstants.onTareEnabledModeChanged(enabledMode); 684 } 685 686 /** 687 * Lowers quotas to make testing feasible. Careful while calling as this will replace any 688 * existing settings for the calling test. 689 */ 690 private void setTestableQuotas() { 691 setDeviceConfigLong(KEY_MIN_FUTURITY, 0); 692 setDeviceConfigLong(KEY_MIN_INTERVAL, 0); 693 mDeviceConfigKeys.add(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX]); 694 mDeviceConfigKeys.add(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_INDEX]); 695 mDeviceConfigKeys.add(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[FREQUENT_INDEX]); 696 doReturn(50).when(mDeviceConfigProperties) 697 .getInt(eq(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX]), anyInt()); 698 doReturn(35).when(mDeviceConfigProperties) 699 .getInt(eq(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_INDEX]), anyInt()); 700 doReturn(20).when(mDeviceConfigProperties) 701 .getInt(eq(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[FREQUENT_INDEX]), anyInt()); 702 703 mService.mConstants.onPropertiesChanged(mDeviceConfigProperties); 704 } 705 706 @Test 707 public void singleElapsedAlarmSet() { 708 final long triggerTime = mNowElapsedTest + 5000; 709 final PendingIntent alarmPi = getNewMockPendingIntent(); 710 setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, alarmPi); 711 assertEquals(triggerTime, mTestTimer.getElapsed()); 712 } 713 714 @Test 715 public void singleRtcAlarmSet() { 716 mNowElapsedTest = 54; 717 mNowRtcTest = 1243; // arbitrary values of time 718 final long triggerRtc = mNowRtcTest + 5000; 719 final PendingIntent alarmPi = getNewMockPendingIntent(); 720 setTestAlarm(RTC_WAKEUP, triggerRtc, alarmPi); 721 final long triggerElapsed = triggerRtc - (mNowRtcTest - mNowElapsedTest); 722 assertEquals(triggerElapsed, mTestTimer.getElapsed()); 723 } 724 725 @Test 726 public void timeChangeMovesRtcAlarm() throws Exception { 727 mNowElapsedTest = 42; 728 mNowRtcTest = 4123; // arbitrary values of time 729 final long triggerRtc = mNowRtcTest + 5000; 730 final PendingIntent alarmPi = getNewMockPendingIntent(); 731 setTestAlarm(RTC_WAKEUP, triggerRtc, alarmPi); 732 final long triggerElapsed1 = mTestTimer.getElapsed(); 733 final long timeDelta = -123; 734 mNowRtcTest += timeDelta; 735 mTestTimer.expire(TIME_CHANGED_MASK); 736 final long triggerElapsed2 = mTestTimer.getElapsed(); 737 assertEquals("Invalid movement of triggerElapsed following time change", triggerElapsed2, 738 triggerElapsed1 - timeDelta); 739 } 740 741 @Test 742 public void testSingleAlarmExpiration() throws Exception { 743 final long triggerTime = mNowElapsedTest + 5000; 744 final PendingIntent alarmPi = getNewMockPendingIntent(); 745 setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, alarmPi); 746 747 mNowElapsedTest = mTestTimer.getElapsed(); 748 mTestTimer.expire(); 749 750 final ArgumentCaptor<PendingIntent.OnFinished> onFinishedCaptor = 751 ArgumentCaptor.forClass(PendingIntent.OnFinished.class); 752 verify(alarmPi).send(eq(mMockContext), eq(0), any(Intent.class), 753 onFinishedCaptor.capture(), any(Handler.class), isNull(), any()); 754 verify(mWakeLock).acquire(); 755 onFinishedCaptor.getValue().onSendFinished(alarmPi, null, 0, null, null); 756 verify(mWakeLock).release(); 757 } 758 759 @Test 760 public void testAlarmBroadcastOption() throws Exception { 761 final long triggerTime = mNowElapsedTest + 5000; 762 final PendingIntent alarmPi = getNewMockPendingIntent(); 763 setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, alarmPi); 764 765 mNowElapsedTest = mTestTimer.getElapsed(); 766 mTestTimer.expire(); 767 768 final ArgumentCaptor<PendingIntent.OnFinished> onFinishedCaptor = 769 ArgumentCaptor.forClass(PendingIntent.OnFinished.class); 770 final ArgumentCaptor<Bundle> optionsCaptor = ArgumentCaptor.forClass(Bundle.class); 771 verify(alarmPi).send(eq(mMockContext), eq(0), any(Intent.class), 772 onFinishedCaptor.capture(), any(Handler.class), isNull(), 773 optionsCaptor.capture()); 774 final BroadcastOptions options = new BroadcastOptions(optionsCaptor.getValue()); 775 assertTrue(options.isAlarmBroadcast()); 776 } 777 778 @Test 779 public void testUpdateConstants() { 780 setDeviceConfigLong(KEY_MIN_FUTURITY, 5); 781 setDeviceConfigLong(KEY_MIN_INTERVAL, 10); 782 setDeviceConfigLong(KEY_MAX_INTERVAL, 15); 783 setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_QUOTA, 20); 784 setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA, 25); 785 setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_WINDOW, 30); 786 setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_COMPAT_WINDOW, 35); 787 setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION, 40); 788 setDeviceConfigLong(KEY_LISTENER_TIMEOUT, 45); 789 setDeviceConfigLong(KEY_MIN_WINDOW, 50); 790 setDeviceConfigLong(KEY_PRIORITY_ALARM_DELAY, 55); 791 setDeviceConfigLong(KEY_MIN_DEVICE_IDLE_FUZZ, 60); 792 setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 65); 793 setDeviceConfigInt(KEY_TEMPORARY_QUOTA_BUMP, 70); 794 assertEquals(5, mService.mConstants.MIN_FUTURITY); 795 assertEquals(10, mService.mConstants.MIN_INTERVAL); 796 assertEquals(15, mService.mConstants.MAX_INTERVAL); 797 assertEquals(20, mService.mConstants.ALLOW_WHILE_IDLE_QUOTA); 798 assertEquals(25, mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA); 799 assertEquals(30, mService.mConstants.ALLOW_WHILE_IDLE_WINDOW); 800 assertEquals(35, mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW); 801 assertEquals(40, mService.mConstants.ALLOW_WHILE_IDLE_WHITELIST_DURATION); 802 assertEquals(45, mService.mConstants.LISTENER_TIMEOUT); 803 assertEquals(50, mService.mConstants.MIN_WINDOW); 804 assertEquals(55, mService.mConstants.PRIORITY_ALARM_DELAY); 805 assertEquals(60, mService.mConstants.MIN_DEVICE_IDLE_FUZZ); 806 assertEquals(65, mService.mConstants.MAX_DEVICE_IDLE_FUZZ); 807 assertEquals(70, mService.mConstants.TEMPORARY_QUOTA_BUMP); 808 } 809 810 @Test 811 public void updatingExactAlarmDenyList() { 812 ArraySet<String> denyListed = new ArraySet<>(new String[]{ 813 "com.example.package1", 814 "com.example.package2", 815 "com.example.package3", 816 }); 817 setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, 818 "com.example.package1,com.example.package2,com.example.package3"); 819 assertEquals(denyListed, mService.mConstants.EXACT_ALARM_DENY_LIST); 820 821 822 denyListed = new ArraySet<>(new String[]{ 823 "com.example.package1", 824 "com.example.package4", 825 }); 826 setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, 827 "com.example.package1,com.example.package4"); 828 assertEquals(denyListed, mService.mConstants.EXACT_ALARM_DENY_LIST); 829 830 setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, ""); 831 assertEquals(0, mService.mConstants.EXACT_ALARM_DENY_LIST.size()); 832 } 833 834 @Test 835 public void exactAlarmDenyListMaxSize() { 836 final ArraySet<String> expectedSet = new ArraySet<>(); 837 final StringBuilder sb = new StringBuilder("package1"); 838 expectedSet.add("package1"); 839 for (int i = 2; i <= 2 * MAX_EXACT_ALARM_DENY_LIST_SIZE; i++) { 840 sb.append(",package"); 841 sb.append(i); 842 if (i <= MAX_EXACT_ALARM_DENY_LIST_SIZE) { 843 expectedSet.add("package" + i); 844 } 845 } 846 assertEquals(MAX_EXACT_ALARM_DENY_LIST_SIZE, expectedSet.size()); 847 setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, sb.toString()); 848 assertEquals(expectedSet, mService.mConstants.EXACT_ALARM_DENY_LIST); 849 } 850 851 @Test 852 public void positiveWhileIdleQuotas() { 853 setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_QUOTA, -3); 854 assertEquals(1, mService.mConstants.ALLOW_WHILE_IDLE_QUOTA); 855 setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_QUOTA, 0); 856 assertEquals(1, mService.mConstants.ALLOW_WHILE_IDLE_QUOTA); 857 858 setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA, -8); 859 assertEquals(1, mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA); 860 setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA, 0); 861 assertEquals(1, mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA); 862 } 863 864 @Test 865 public void whileIdleWindowsDontExceedAnHour() { 866 setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_WINDOW, AlarmManager.INTERVAL_DAY); 867 assertEquals(AlarmManager.INTERVAL_HOUR, mService.mConstants.ALLOW_WHILE_IDLE_WINDOW); 868 setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_WINDOW, AlarmManager.INTERVAL_HOUR + 1); 869 assertEquals(AlarmManager.INTERVAL_HOUR, mService.mConstants.ALLOW_WHILE_IDLE_WINDOW); 870 871 setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_COMPAT_WINDOW, AlarmManager.INTERVAL_DAY); 872 assertEquals(AlarmManager.INTERVAL_HOUR, 873 mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW); 874 setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_COMPAT_WINDOW, AlarmManager.INTERVAL_HOUR + 1); 875 assertEquals(AlarmManager.INTERVAL_HOUR, 876 mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW); 877 } 878 879 @Test 880 public void deviceIdleFuzzRangeNonNegative() { 881 final long newMinFuzz = mService.mConstants.MAX_DEVICE_IDLE_FUZZ + 1542; 882 final long newMaxFuzz = mService.mConstants.MIN_DEVICE_IDLE_FUZZ - 131; 883 884 setDeviceConfigLong(KEY_MIN_DEVICE_IDLE_FUZZ, newMinFuzz); 885 assertTrue("Negative device-idle fuzz range", mService.mConstants.MAX_DEVICE_IDLE_FUZZ 886 >= mService.mConstants.MIN_DEVICE_IDLE_FUZZ); 887 888 setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, newMaxFuzz); 889 assertTrue("Negative device-idle fuzz range", mService.mConstants.MAX_DEVICE_IDLE_FUZZ 890 >= mService.mConstants.MIN_DEVICE_IDLE_FUZZ); 891 } 892 893 @Test 894 public void testMinFuturity() { 895 setDeviceConfigLong(KEY_MIN_FUTURITY, 10L); 896 assertEquals(10, mService.mConstants.MIN_FUTURITY); 897 final long triggerTime = mNowElapsedTest + 1; 898 final long expectedTriggerTime = mNowElapsedTest + mService.mConstants.MIN_FUTURITY; 899 setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, getNewMockPendingIntent()); 900 assertEquals(expectedTriggerTime, mTestTimer.getElapsed()); 901 } 902 903 @Test 904 public void testMinFuturityCoreUid() { 905 setDeviceConfigLong(KEY_MIN_FUTURITY, 10L); 906 assertEquals(10, mService.mConstants.MIN_FUTURITY); 907 final long triggerTime = mNowElapsedTest + 1; 908 doReturn(true).when(() -> UserHandle.isCore(TEST_CALLING_UID)); 909 final long expectedTriggerTime = triggerTime; 910 setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, getNewMockPendingIntent()); 911 assertEquals(expectedTriggerTime, mTestTimer.getElapsed()); 912 } 913 914 @Test 915 public void testEarliestAlarmSet() { 916 final PendingIntent pi6 = getNewMockPendingIntent(); 917 final PendingIntent pi8 = getNewMockPendingIntent(); 918 final PendingIntent pi9 = getNewMockPendingIntent(); 919 920 setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 8, pi8); 921 assertEquals(mNowElapsedTest + 8, mTestTimer.getElapsed()); 922 923 setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 9, pi9); 924 assertEquals(mNowElapsedTest + 8, mTestTimer.getElapsed()); 925 926 setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, pi6); 927 assertEquals(mNowElapsedTest + 6, mTestTimer.getElapsed()); 928 929 mService.removeLocked(pi6, null, REMOVE_REASON_UNDEFINED); 930 assertEquals(mNowElapsedTest + 8, mTestTimer.getElapsed()); 931 932 mService.removeLocked(pi8, null, REMOVE_REASON_UNDEFINED); 933 assertEquals(mNowElapsedTest + 9, mTestTimer.getElapsed()); 934 } 935 936 private void testQuotasDeferralOnSet(LongConsumer alarmSetter, int quota, long window) 937 throws Exception { 938 final long firstTrigger = mNowElapsedTest + 10; 939 for (int i = 0; i < quota; i++) { 940 alarmSetter.accept(firstTrigger + i); 941 mNowElapsedTest = mTestTimer.getElapsed(); 942 assertEquals("Incorrect trigger time at i=" + i, firstTrigger + i, mNowElapsedTest); 943 mTestTimer.expire(); 944 } 945 // This one should get deferred on set 946 alarmSetter.accept(firstTrigger + quota); 947 final long expectedNextTrigger = firstTrigger + window; 948 assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed()); 949 } 950 951 private void testQuotasDeferralOnExpiration(LongConsumer alarmSetter, int quota, long window) 952 throws Exception { 953 final long firstTrigger = mNowElapsedTest + 10; 954 for (int i = 0; i < quota; i++) { 955 alarmSetter.accept(firstTrigger + i); 956 } 957 // This one should get deferred after the latest alarm expires. 958 alarmSetter.accept(firstTrigger + quota); 959 for (int i = 0; i < quota; i++) { 960 mNowElapsedTest = mTestTimer.getElapsed(); 961 assertEquals("Incorrect trigger time at i=" + i, firstTrigger + i, mNowElapsedTest); 962 mTestTimer.expire(); 963 } 964 final long expectedNextTrigger = firstTrigger + window; 965 assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed()); 966 } 967 968 private void testQuotasNoDeferral(LongConsumer alarmSetter, int quota, long window) 969 throws Exception { 970 final long firstTrigger = mNowElapsedTest + 10; 971 for (int i = 0; i < quota; i++) { 972 alarmSetter.accept(firstTrigger + i); 973 } 974 // This delivery time maintains the quota invariant. Should not be deferred. 975 final long expectedNextTrigger = firstTrigger + window + 5; 976 alarmSetter.accept(expectedNextTrigger); 977 for (int i = 0; i < quota; i++) { 978 mNowElapsedTest = mTestTimer.getElapsed(); 979 assertEquals("Incorrect trigger time at i=" + i, firstTrigger + i, mNowElapsedTest); 980 mTestTimer.expire(); 981 } 982 assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed()); 983 } 984 985 private void testStandbyQuotasDeferralOnSet(int standbyBucket) throws Exception { 986 final int quota = mService.getQuotaForBucketLocked(standbyBucket); 987 when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), 988 anyLong())).thenReturn(standbyBucket); 989 testQuotasDeferralOnSet(trigger -> setTestAlarm(ELAPSED_REALTIME_WAKEUP, trigger, 990 getNewMockPendingIntent()), quota, mAppStandbyWindow); 991 } 992 993 private void testStandbyQuotasDeferralOnExpiration(int standbyBucket) throws Exception { 994 final int quota = mService.getQuotaForBucketLocked(standbyBucket); 995 when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), 996 anyLong())).thenReturn(standbyBucket); 997 testQuotasDeferralOnExpiration(trigger -> setTestAlarm(ELAPSED_REALTIME_WAKEUP, trigger, 998 getNewMockPendingIntent()), quota, mAppStandbyWindow); 999 } 1000 1001 private void testStandbyQuotasNoDeferral(int standbyBucket) throws Exception { 1002 final int quota = mService.getQuotaForBucketLocked(standbyBucket); 1003 when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), 1004 anyLong())).thenReturn(standbyBucket); 1005 testQuotasNoDeferral(trigger -> setTestAlarm(ELAPSED_REALTIME_WAKEUP, trigger, 1006 getNewMockPendingIntent()), quota, mAppStandbyWindow); 1007 } 1008 1009 @Test 1010 public void testActiveQuota_deferredOnSet() throws Exception { 1011 testStandbyQuotasDeferralOnSet(STANDBY_BUCKET_ACTIVE); 1012 } 1013 1014 @Test 1015 public void testActiveQuota_deferredOnExpiration() throws Exception { 1016 testStandbyQuotasDeferralOnExpiration(STANDBY_BUCKET_ACTIVE); 1017 } 1018 1019 @Test 1020 public void testActiveQuota_notDeferred() throws Exception { 1021 testStandbyQuotasNoDeferral(STANDBY_BUCKET_ACTIVE); 1022 } 1023 1024 @Test 1025 public void testWorkingQuota_deferredOnSet() throws Exception { 1026 testStandbyQuotasDeferralOnSet(STANDBY_BUCKET_WORKING_SET); 1027 } 1028 1029 @Test 1030 public void testWorkingQuota_deferredOnExpiration() throws Exception { 1031 testStandbyQuotasDeferralOnExpiration(STANDBY_BUCKET_WORKING_SET); 1032 } 1033 1034 @Test 1035 public void testWorkingQuota_notDeferred() throws Exception { 1036 testStandbyQuotasNoDeferral(STANDBY_BUCKET_WORKING_SET); 1037 } 1038 1039 @Test 1040 public void testFrequentQuota_deferredOnSet() throws Exception { 1041 testStandbyQuotasDeferralOnSet(STANDBY_BUCKET_FREQUENT); 1042 } 1043 1044 @Test 1045 public void testFrequentQuota_deferredOnExpiration() throws Exception { 1046 testStandbyQuotasDeferralOnExpiration(STANDBY_BUCKET_FREQUENT); 1047 } 1048 1049 @Test 1050 public void testFrequentQuota_notDeferred() throws Exception { 1051 testStandbyQuotasNoDeferral(STANDBY_BUCKET_FREQUENT); 1052 } 1053 1054 @Test 1055 public void testRareQuota_deferredOnSet() throws Exception { 1056 testStandbyQuotasDeferralOnSet(STANDBY_BUCKET_RARE); 1057 } 1058 1059 @Test 1060 public void testRareQuota_deferredOnExpiration() throws Exception { 1061 testStandbyQuotasDeferralOnExpiration(STANDBY_BUCKET_RARE); 1062 } 1063 1064 @Test 1065 public void testRareQuota_notDeferred() throws Exception { 1066 testStandbyQuotasNoDeferral(STANDBY_BUCKET_RARE); 1067 } 1068 1069 @Test 1070 public void testRestrictedBucketAlarmsDeferredOnSet() throws Exception { 1071 when(mUsageStatsManagerInternal 1072 .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())) 1073 .thenReturn(STANDBY_BUCKET_RESTRICTED); 1074 // This one should go off 1075 final long firstTrigger = mNowElapsedTest + 10; 1076 setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger, getNewMockPendingIntent()); 1077 mNowElapsedTest = mTestTimer.getElapsed(); 1078 mTestTimer.expire(); 1079 1080 // This one should get deferred on set 1081 setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + 1, getNewMockPendingIntent()); 1082 final long expectedNextTrigger = 1083 firstTrigger + mService.mConstants.APP_STANDBY_RESTRICTED_WINDOW; 1084 assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed()); 1085 } 1086 1087 @Test 1088 public void testRestrictedBucketAlarmsDeferredOnExpiration() throws Exception { 1089 when(mUsageStatsManagerInternal 1090 .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), anyLong())) 1091 .thenReturn(STANDBY_BUCKET_RESTRICTED); 1092 // This one should go off 1093 final long firstTrigger = mNowElapsedTest + 10; 1094 setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger, getNewMockPendingIntent()); 1095 1096 // This one should get deferred after the latest alarm expires 1097 setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + 1, getNewMockPendingIntent()); 1098 1099 mNowElapsedTest = mTestTimer.getElapsed(); 1100 mTestTimer.expire(); 1101 final long expectedNextTrigger = 1102 firstTrigger + mService.mConstants.APP_STANDBY_RESTRICTED_WINDOW; 1103 assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed()); 1104 } 1105 1106 private void assertAndHandleBucketChanged(int bucket) { 1107 when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), 1108 anyLong())).thenReturn(bucket); 1109 mAppStandbyListener.onAppIdleStateChanged(TEST_CALLING_PACKAGE, 1110 UserHandle.getUserId(TEST_CALLING_UID), false, bucket, 0); 1111 assertAndHandleMessageSync(APP_STANDBY_BUCKET_CHANGED); 1112 } 1113 1114 private void assertAndHandleMessageSync(int what) { 1115 final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); 1116 verify(mService.mHandler, atLeastOnce()).sendMessageAtTime(messageCaptor.capture(), 1117 anyLong()); 1118 1119 Message expectedMessage = null; 1120 final ArrayList<Integer> sentMessages = new ArrayList<>(); 1121 for (Message sentMessage : messageCaptor.getAllValues()) { 1122 if (sentMessage.what == what) { 1123 expectedMessage = sentMessage; 1124 } 1125 sentMessages.add(sentMessage.what); 1126 } 1127 1128 assertNotNull("Unexpected messages sent to handler. Expected: " + what + ", sent: " 1129 + sentMessages, expectedMessage); 1130 mService.mHandler.handleMessage(expectedMessage); 1131 } 1132 1133 @Test 1134 public void testStandbyQuotaDowngrade() throws Exception { 1135 final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET); 1136 when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), 1137 anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET); 1138 1139 final long firstTrigger = mNowElapsedTest + 10; 1140 for (int i = 0; i < workingQuota; i++) { 1141 setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent()); 1142 } 1143 // No deferrals now. 1144 for (int i = 0; i < workingQuota - 1; i++) { 1145 mNowElapsedTest = mTestTimer.getElapsed(); 1146 assertEquals(firstTrigger + i, mNowElapsedTest); 1147 mTestTimer.expire(); 1148 } 1149 // The next upcoming alarm in queue should also be set as expected. 1150 assertEquals(firstTrigger + workingQuota - 1, mTestTimer.getElapsed()); 1151 // Downgrading the bucket now 1152 assertAndHandleBucketChanged(STANDBY_BUCKET_RARE); 1153 final int rareQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_RARE); 1154 // The last alarm should now be deferred. 1155 final long expectedNextTrigger = (firstTrigger + workingQuota - 1 - rareQuota) 1156 + mAppStandbyWindow; 1157 assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed()); 1158 } 1159 1160 @Test 1161 public void testStandbyQuotaUpgrade() throws Exception { 1162 final int frequentQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_FREQUENT); 1163 when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), 1164 anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT); 1165 1166 final long firstTrigger = mNowElapsedTest + 10; 1167 for (int i = 0; i < frequentQuota + 1; i++) { 1168 setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent()); 1169 if (i < frequentQuota) { 1170 mNowElapsedTest = mTestTimer.getElapsed(); 1171 mTestTimer.expire(); 1172 } 1173 } 1174 // The last alarm should be deferred due to exceeding the quota 1175 final long deferredTrigger = firstTrigger + mAppStandbyWindow; 1176 assertEquals(deferredTrigger, mTestTimer.getElapsed()); 1177 1178 // Upgrading the bucket now 1179 assertAndHandleBucketChanged(STANDBY_BUCKET_ACTIVE); 1180 // The last alarm should now be rescheduled to go as per original expectations 1181 final long originalTrigger = firstTrigger + frequentQuota; 1182 assertEquals("Incorrect next alarm trigger", originalTrigger, mTestTimer.getElapsed()); 1183 } 1184 1185 private void assertAndHandleParoleChanged(boolean parole) { 1186 mChargingReceiver.onReceive(mMockContext, 1187 new Intent(parole ? BatteryManager.ACTION_CHARGING 1188 : BatteryManager.ACTION_DISCHARGING)); 1189 assertAndHandleMessageSync(CHARGING_STATUS_CHANGED); 1190 assertEquals(parole, mService.mAppStandbyParole); 1191 } 1192 1193 @Test 1194 public void testCharging() throws Exception { 1195 final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET); 1196 when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), 1197 anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET); 1198 1199 final long firstTrigger = mNowElapsedTest + 10; 1200 final int totalAlarms = workingQuota + 10; 1201 for (int i = 0; i < totalAlarms; i++) { 1202 setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent()); 1203 } 1204 // Use up the quota, no deferrals expected. 1205 for (int i = 0; i < workingQuota; i++) { 1206 mNowElapsedTest = mTestTimer.getElapsed(); 1207 assertEquals(firstTrigger + i, mNowElapsedTest); 1208 mTestTimer.expire(); 1209 } 1210 // Any subsequent alarms in queue should all be deferred 1211 assertEquals(firstTrigger + mAppStandbyWindow, mTestTimer.getElapsed()); 1212 // Paroling now 1213 assertAndHandleParoleChanged(true); 1214 1215 // Subsequent alarms should now go off as per original expectations. 1216 for (int i = 0; i < 5; i++) { 1217 mNowElapsedTest = mTestTimer.getElapsed(); 1218 assertEquals(firstTrigger + workingQuota + i, mNowElapsedTest); 1219 mTestTimer.expire(); 1220 } 1221 // Come out of parole 1222 assertAndHandleParoleChanged(false); 1223 1224 // Subsequent alarms should again get deferred 1225 final long expectedNextTrigger = (firstTrigger + 5) + mAppStandbyWindow; 1226 assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed()); 1227 } 1228 1229 @Test 1230 public void testAlarmRestrictedByFAS() throws Exception { 1231 final PendingIntent alarmPi = getNewMockPendingIntent(); 1232 when(mAppStateTracker.areAlarmsRestricted(TEST_CALLING_UID, 1233 TEST_CALLING_PACKAGE)).thenReturn(true); 1234 setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2, alarmPi); 1235 assertEquals(mNowElapsedTest + 2, mTestTimer.getElapsed()); 1236 1237 final SparseArray<ArrayList<Alarm>> restrictedAlarms = 1238 mService.mPendingBackgroundAlarms; 1239 assertNull(restrictedAlarms.get(TEST_CALLING_UID)); 1240 1241 mNowElapsedTest = mTestTimer.getElapsed(); 1242 mTestTimer.expire(); 1243 assertNotNull(restrictedAlarms.get(TEST_CALLING_UID)); 1244 1245 mListener.unblockAlarmsForUid(TEST_CALLING_UID); 1246 verify(alarmPi).send(eq(mMockContext), eq(0), any(Intent.class), any(), 1247 any(Handler.class), isNull(), any()); 1248 assertNull(restrictedAlarms.get(TEST_CALLING_UID)); 1249 } 1250 1251 @Test 1252 public void alarmsRemovedOnAppStartModeDisabled() { 1253 final PendingIntent alarmPi1 = getNewMockPendingIntent(); 1254 final PendingIntent alarmPi2 = getNewMockPendingIntent(); 1255 1256 setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2, alarmPi1); 1257 setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 4, alarmPi2); 1258 1259 assertEquals(2, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1260 1261 when(mActivityManagerInternal.isAppStartModeDisabled(TEST_CALLING_UID, 1262 TEST_CALLING_PACKAGE)).thenReturn(true); 1263 mListener.removeAlarmsForUid(TEST_CALLING_UID); 1264 assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1265 } 1266 1267 @Test 1268 public void sendsTimeTickOnInteractive() { 1269 final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); 1270 // Stubbing so the handler doesn't actually run the runnable. 1271 doReturn(true).when(mService.mHandler).post(runnableCaptor.capture()); 1272 // change interactive state: false -> true 1273 mService.interactiveStateChangedLocked(false); 1274 mService.interactiveStateChangedLocked(true); 1275 runnableCaptor.getValue().run(); 1276 final ArgumentCaptor<Bundle> optionsCaptor = ArgumentCaptor.forClass(Bundle.class); 1277 verify(mMockContext).sendBroadcastAsUser(eq(mService.mTimeTickIntent), eq(UserHandle.ALL), 1278 isNull(), optionsCaptor.capture()); 1279 verifyTimeTickBroadcastOptions(optionsCaptor.getValue()); 1280 } 1281 1282 @Test 1283 public void sendsTimeTickOnAlarmTrigger() throws Exception { 1284 final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); 1285 // Stubbing so the handler doesn't actually run the runnable. 1286 doReturn(true).when(mService.mHandler).post(runnableCaptor.capture()); 1287 mService.mTimeTickTrigger.doAlarm(mock(IAlarmCompleteListener.class)); 1288 runnableCaptor.getValue().run(); 1289 final ArgumentCaptor<Bundle> optionsCaptor = ArgumentCaptor.forClass(Bundle.class); 1290 verify(mMockContext).sendBroadcastAsUser(eq(mService.mTimeTickIntent), eq(UserHandle.ALL), 1291 isNull(), optionsCaptor.capture()); 1292 verifyTimeTickBroadcastOptions(optionsCaptor.getValue()); 1293 } 1294 1295 private void verifyTimeTickBroadcastOptions(Bundle actualOptionsBundle) { 1296 final BroadcastOptions actualOptions = new BroadcastOptions(actualOptionsBundle); 1297 assertEquals(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT, 1298 actualOptions.getDeliveryGroupPolicy()); 1299 assertEquals(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE, 1300 actualOptions.getDeferralPolicy()); 1301 } 1302 1303 @Test 1304 public void alarmCountKeyedOnCallingUid() { 1305 final int mockCreatorUid = 431412; 1306 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 5, 1307 getNewMockPendingIntent(mockCreatorUid, TEST_CALLING_PACKAGE)); 1308 assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1309 assertEquals(-1, mService.mAlarmsPerUid.get(mockCreatorUid, -1)); 1310 } 1311 1312 @Test 1313 public void alarmCountOnSetPi() { 1314 final int numAlarms = 103; 1315 for (int i = 1; i <= numAlarms; i++) { 1316 setTestAlarm(ALARM_TYPES[i % 4], mNowElapsedTest + i, getNewMockPendingIntent()); 1317 assertEquals(i, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1318 } 1319 } 1320 1321 @Test 1322 public void alarmCountOnSetListener() { 1323 final int numAlarms = 103; 1324 for (int i = 1; i <= numAlarms; i++) { 1325 setTestAlarmWithListener(ALARM_TYPES[i % 4], mNowElapsedTest + i, 1326 getNewListener(() -> {})); 1327 assertEquals(i, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1328 } 1329 } 1330 1331 @Test 1332 public void alarmCountOnExpirationPi() throws InterruptedException { 1333 final int numAlarms = 8; // This test is slow 1334 for (int i = 0; i < numAlarms; i++) { 1335 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, getNewMockPendingIntent()); 1336 } 1337 int expired = 0; 1338 while (expired < numAlarms) { 1339 mNowElapsedTest = mTestTimer.getElapsed(); 1340 mTestTimer.expire(); 1341 expired++; 1342 assertEquals(numAlarms - expired, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0)); 1343 } 1344 } 1345 1346 @Test 1347 public void alarmCountOnExpirationListener() throws InterruptedException { 1348 final int numAlarms = 8; // This test is slow 1349 for (int i = 0; i < numAlarms; i++) { 1350 setTestAlarmWithListener(ELAPSED_REALTIME, mNowElapsedTest + i + 10, 1351 getNewListener(() -> {})); 1352 } 1353 int expired = 0; 1354 while (expired < numAlarms) { 1355 mNowElapsedTest = mTestTimer.getElapsed(); 1356 mTestTimer.expire(); 1357 expired++; 1358 assertEquals(numAlarms - expired, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0)); 1359 } 1360 } 1361 1362 @Test 1363 public void alarmCountOnExceptionWhileSendingPi() throws Exception { 1364 final int numAlarms = 5; // This test is slow 1365 for (int i = 0; i < numAlarms; i++) { 1366 final PendingIntent pi = getNewMockPendingIntent(); 1367 doThrow(PendingIntent.CanceledException.class).when(pi).send(eq(mMockContext), eq(0), 1368 any(), any(), any(), any(), any()); 1369 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, pi); 1370 } 1371 int expired = 0; 1372 while (expired < numAlarms) { 1373 mNowElapsedTest = mTestTimer.getElapsed(); 1374 mTestTimer.expire(); 1375 expired++; 1376 assertEquals(numAlarms - expired, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0)); 1377 } 1378 } 1379 1380 @Test 1381 public void alarmCountOnExceptionWhileCallingListener() throws Exception { 1382 final int numAlarms = 5; // This test is slow 1383 for (int i = 0; i < numAlarms; i++) { 1384 final IAlarmListener listener = getNewListener(() -> { 1385 throw new RuntimeException("For testing behavior on exception"); 1386 }); 1387 setTestAlarmWithListener(ELAPSED_REALTIME, mNowElapsedTest + i + 10, listener); 1388 } 1389 int expired = 0; 1390 while (expired < numAlarms) { 1391 mNowElapsedTest = mTestTimer.getElapsed(); 1392 mTestTimer.expire(); 1393 expired++; 1394 assertEquals(numAlarms - expired, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0)); 1395 } 1396 } 1397 1398 @Test 1399 public void alarmCountForRepeatingAlarms() throws Exception { 1400 final long interval = 1231; 1401 final long firstTrigger = mNowElapsedTest + 321; 1402 final PendingIntent pi = getNewMockPendingIntent(); 1403 setRepeatingTestAlarm(ELAPSED_REALTIME, firstTrigger, interval, pi); 1404 assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1405 1406 for (int i = 0; i < 5; i++) { 1407 mNowElapsedTest = mTestTimer.getElapsed(); 1408 mTestTimer.expire(); 1409 assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1410 } 1411 doThrow(PendingIntent.CanceledException.class).when(pi).send(eq(mMockContext), eq(0), 1412 any(), any(), any(), any(), any()); 1413 mNowElapsedTest = mTestTimer.getElapsed(); 1414 mTestTimer.expire(); 1415 assertEquals(-1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, -1)); 1416 } 1417 1418 @Test 1419 public void alarmCountOnUidRemoved() { 1420 final int numAlarms = 10; 1421 for (int i = 0; i < numAlarms; i++) { 1422 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, getNewMockPendingIntent()); 1423 } 1424 assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1425 mService.removeLocked(TEST_CALLING_UID, 1426 REMOVE_REASON_UNDEFINED); 1427 assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0)); 1428 } 1429 1430 @Test 1431 public void alarmCountOnPackageRemoved() { 1432 final int numAlarms = 10; 1433 for (int i = 0; i < numAlarms; i++) { 1434 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, getNewMockPendingIntent()); 1435 } 1436 assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1437 mService.removeLocked(TEST_CALLING_PACKAGE, REMOVE_REASON_UNDEFINED); 1438 assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0)); 1439 } 1440 1441 @Test 1442 public void alarmCountOnUserRemoved() { 1443 final int mockUserId = 15; 1444 final int numAlarms = 10; 1445 for (int i = 0; i < numAlarms; i++) { 1446 int mockUid = UserHandle.getUid(mockUserId, 1234 + i); 1447 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, 1448 getNewMockPendingIntent(mockUid, TEST_CALLING_PACKAGE), 0, FLAG_STANDALONE, 1449 mockUid); 1450 } 1451 assertEquals(numAlarms, mService.mAlarmsPerUid.size()); 1452 mService.removeUserLocked(mockUserId); 1453 assertEquals(0, mService.mAlarmsPerUid.size()); 1454 } 1455 1456 @Test 1457 public void alarmCountOnAlarmRemoved() { 1458 final int numAlarms = 10; 1459 final PendingIntent[] pis = new PendingIntent[numAlarms]; 1460 for (int i = 0; i < numAlarms; i++) { 1461 pis[i] = getNewMockPendingIntent(); 1462 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 5, pis[i]); 1463 } 1464 assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1465 for (int i = 0; i < numAlarms; i++) { 1466 mService.removeLocked(pis[i], null, REMOVE_REASON_UNDEFINED); 1467 assertEquals(numAlarms - i - 1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0)); 1468 } 1469 } 1470 1471 @Test 1472 public void alarmTypes() throws Exception { 1473 final int[] typesToSet = ALARM_TYPES; 1474 final int[] typesExpected = {ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME, 1475 ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME}; 1476 assertAlarmTypeConversion(typesToSet, typesExpected); 1477 } 1478 1479 private void assertAlarmTypeConversion(int[] typesToSet, int[] typesExpected) throws Exception { 1480 for (int i = 0; i < typesToSet.length; i++) { 1481 setTestAlarm(typesToSet[i], 1234, getNewMockPendingIntent()); 1482 final int typeSet = mTestTimer.getType(); 1483 assertEquals("Alarm of type " + typesToSet[i] + " was set to type " + typeSet, 1484 typesExpected[i], typeSet); 1485 mNowElapsedTest = mTestTimer.getElapsed(); 1486 mTestTimer.expire(); 1487 } 1488 } 1489 1490 @Test 1491 public void alarmCountOnInvalidSet() { 1492 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 12345, null); 1493 assertEquals(-1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, -1)); 1494 } 1495 1496 @Test 1497 public void alarmCountOnRemoveForCanceled() { 1498 final AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class); 1499 final PendingIntent pi = getNewMockPendingIntent(); 1500 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 12345, pi); 1501 assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1502 ami.remove(pi); 1503 assertAndHandleMessageSync(REMOVE_FOR_CANCELED); 1504 assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1505 } 1506 1507 @Test 1508 public void alarmCountOnListenerBinderDied() { 1509 final int numAlarms = 10; 1510 final IAlarmListener[] listeners = new IAlarmListener[numAlarms]; 1511 for (int i = 0; i < numAlarms; i++) { 1512 listeners[i] = getNewListener(() -> {}); 1513 setTestAlarmWithListener(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + i, listeners[i]); 1514 } 1515 assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1516 for (int i = 0; i < numAlarms; i++) { 1517 mService.mListenerDeathRecipient.binderDied(listeners[i].asBinder()); 1518 assertEquals(numAlarms - i - 1, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 1519 } 1520 } 1521 1522 @Test 1523 public void nonWakeupAlarmsDeferred() throws Exception { 1524 final int numAlarms = 10; 1525 final PendingIntent[] pis = new PendingIntent[numAlarms]; 1526 for (int i = 0; i < numAlarms; i++) { 1527 pis[i] = getNewMockPendingIntent(); 1528 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 5, pis[i]); 1529 } 1530 doReturn(true).when(mService).checkAllowNonWakeupDelayLocked(anyLong()); 1531 // Advance time past all expirations. 1532 mNowElapsedTest += numAlarms + 5; 1533 mTestTimer.expire(); 1534 assertEquals(numAlarms, mService.mPendingNonWakeupAlarms.size()); 1535 1536 // These alarms should be sent on interactive state change to true 1537 mService.interactiveStateChangedLocked(false); 1538 mService.interactiveStateChangedLocked(true); 1539 1540 for (int i = 0; i < numAlarms; i++) { 1541 verify(pis[i]).send(eq(mMockContext), eq(0), any(Intent.class), any(), 1542 any(Handler.class), isNull(), any()); 1543 } 1544 } 1545 1546 /** 1547 * This tests that all non wakeup alarms are sent even when the mPendingNonWakeupAlarms gets 1548 * modified before the send is complete. This avoids bugs like b/175701084. 1549 */ 1550 @Test 1551 public void allNonWakeupAlarmsSentAtomically() throws Exception { 1552 final int numAlarms = 5; 1553 final AtomicInteger alarmsFired = new AtomicInteger(0); 1554 for (int i = 0; i < numAlarms; i++) { 1555 final IAlarmListener listener = getNewListener(() -> { 1556 alarmsFired.incrementAndGet(); 1557 mService.mPendingNonWakeupAlarms.clear(); 1558 }); 1559 setTestAlarmWithListener(ELAPSED_REALTIME, mNowElapsedTest + i + 5, listener); 1560 } 1561 doReturn(true).when(mService).checkAllowNonWakeupDelayLocked(anyLong()); 1562 // Advance time past all expirations. 1563 mNowElapsedTest += numAlarms + 5; 1564 mTestTimer.expire(); 1565 assertEquals(numAlarms, mService.mPendingNonWakeupAlarms.size()); 1566 1567 // All of these alarms should be sent on interactive state change to true 1568 mService.interactiveStateChangedLocked(false); 1569 mService.interactiveStateChangedLocked(true); 1570 1571 assertEquals(numAlarms, alarmsFired.get()); 1572 assertEquals(0, mService.mPendingNonWakeupAlarms.size()); 1573 } 1574 1575 @Test 1576 public void alarmCountOnPendingNonWakeupAlarmsRemoved() throws Exception { 1577 final int numAlarms = 10; 1578 final PendingIntent[] pis = new PendingIntent[numAlarms]; 1579 for (int i = 0; i < numAlarms; i++) { 1580 pis[i] = getNewMockPendingIntent(); 1581 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 5, pis[i]); 1582 } 1583 doReturn(true).when(mService).checkAllowNonWakeupDelayLocked(anyLong()); 1584 // Advance time past all expirations. 1585 mNowElapsedTest += numAlarms + 5; 1586 mTestTimer.expire(); 1587 assertEquals(numAlarms, mService.mPendingNonWakeupAlarms.size()); 1588 for (int i = 0; i < numAlarms; i++) { 1589 mService.removeLocked(pis[i], null, REMOVE_REASON_UNDEFINED); 1590 assertEquals(numAlarms - i - 1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0)); 1591 } 1592 } 1593 1594 @Test 1595 public void singleIdleUntil() { 1596 setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); 1597 1598 final PendingIntent idleUntilPi6 = getNewMockPendingIntent(); 1599 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, idleUntilPi6); 1600 1601 assertTrue(mService.mPendingIdleUntil.matches(idleUntilPi6, null)); 1602 assertEquals(mNowElapsedTest + 6, mTestTimer.getElapsed()); 1603 assertEquals(mNowElapsedTest + 6, mService.mPendingIdleUntil.getWhenElapsed()); 1604 1605 final PendingIntent idleUntilPi2 = getNewMockPendingIntent(); 1606 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2, idleUntilPi2); 1607 1608 // The same mPendingIdleUntil should get updated, even with a different PendingIntent. 1609 assertTrue(mService.mPendingIdleUntil.matches(idleUntilPi2, null)); 1610 assertEquals(mNowElapsedTest + 2, mTestTimer.getElapsed()); 1611 assertEquals(1, mService.mAlarmStore.size()); 1612 1613 final PendingIntent idleUntilPi10 = getNewMockPendingIntent(); 1614 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 10, idleUntilPi10); 1615 1616 // The same thing should happen even when the new alarm is in farther in the future. 1617 assertTrue(mService.mPendingIdleUntil.matches(idleUntilPi10, null)); 1618 assertEquals(mNowElapsedTest + 10, mTestTimer.getElapsed()); 1619 assertEquals(1, mService.mAlarmStore.size()); 1620 } 1621 1622 @Test 1623 public void nextWakeFromIdle() throws Exception { 1624 assertNull(mService.mNextWakeFromIdle); 1625 1626 final PendingIntent wakeFromIdle6 = getNewMockPendingIntent(); 1627 final long trigger6 = mNowElapsedTest + 6; 1628 setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, trigger6, wakeFromIdle6); 1629 1630 assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle6, null)); 1631 assertEquals(trigger6, mService.mNextWakeFromIdle.getWhenElapsed()); 1632 assertEquals(trigger6, mTestTimer.getElapsed()); 1633 1634 final PendingIntent wakeFromIdle10 = getNewMockPendingIntent(); 1635 final long trigger10 = mNowElapsedTest + 10; 1636 setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, trigger10, wakeFromIdle10); 1637 1638 // mNextWakeFromIdle should not get updated. 1639 assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle6, null)); 1640 assertEquals(trigger6, mTestTimer.getElapsed()); 1641 assertEquals(trigger6, mService.mNextWakeFromIdle.getWhenElapsed()); 1642 1643 final PendingIntent wakeFromIdle3 = getNewMockPendingIntent(); 1644 final long trigger3 = mNowElapsedTest + 3; 1645 setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, trigger3, wakeFromIdle3); 1646 1647 // mNextWakeFromIdle should always reflect the next earliest wake_from_idle alarm. 1648 assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle3, null)); 1649 assertEquals(trigger3, mTestTimer.getElapsed()); 1650 assertEquals(trigger3, mService.mNextWakeFromIdle.getWhenElapsed()); 1651 1652 mNowElapsedTest = trigger3; 1653 mTestTimer.expire(); 1654 1655 assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle6, null)); 1656 assertEquals(trigger6, mTestTimer.getElapsed()); 1657 assertEquals(trigger6, mService.mNextWakeFromIdle.getWhenElapsed()); 1658 1659 mService.removeLocked(wakeFromIdle6, null, REMOVE_REASON_UNDEFINED); 1660 1661 assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle10, null)); 1662 assertEquals(trigger10, mTestTimer.getElapsed()); 1663 assertEquals(trigger10, mService.mNextWakeFromIdle.getWhenElapsed()); 1664 1665 mService.removeLocked(wakeFromIdle10, null, REMOVE_REASON_UNDEFINED); 1666 assertNull(mService.mNextWakeFromIdle); 1667 } 1668 1669 private static void assertInRange(String message, long minIncl, long maxIncl, long val) { 1670 assertTrue(message, val >= minIncl && val <= maxIncl); 1671 } 1672 1673 @Test 1674 public void idleUntilFuzzedBeforeWakeFromIdle() { 1675 final long minFuzz = 6; 1676 final long maxFuzz = 17; 1677 setDeviceConfigLong(KEY_MIN_DEVICE_IDLE_FUZZ, minFuzz); 1678 setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, maxFuzz); 1679 1680 mNowElapsedTest = 119; // Arbitrary, just to ensure we are not testing on 0. 1681 1682 final PendingIntent idleUntilPi = getNewMockPendingIntent(); 1683 final long requestedIdleUntil = mNowElapsedTest + 12; 1684 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, requestedIdleUntil, idleUntilPi); 1685 1686 assertEquals(requestedIdleUntil, mService.mPendingIdleUntil.getWhenElapsed()); 1687 1688 final PendingIntent wakeFromIdle5 = getNewMockPendingIntent(); 1689 setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, wakeFromIdle5); 1690 // Anything before now, gets snapped to now. It is not necessary for it to fire 1691 // immediately, just how it is implemented today for simplicity. 1692 assertEquals(mNowElapsedTest, mService.mPendingIdleUntil.getWhenElapsed()); 1693 1694 final PendingIntent wakeFromIdle8 = getNewMockPendingIntent(); 1695 setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 8, wakeFromIdle8); 1696 // Next wake from idle is still the same. 1697 assertEquals(mNowElapsedTest, mService.mPendingIdleUntil.getWhenElapsed()); 1698 1699 final PendingIntent wakeFromIdle19 = getNewMockPendingIntent(); 1700 setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 19, wakeFromIdle19); 1701 // Next wake from idle is still the same. 1702 assertEquals(mNowElapsedTest, mService.mPendingIdleUntil.getWhenElapsed()); 1703 1704 mService.removeLocked(wakeFromIdle5, null, REMOVE_REASON_UNDEFINED); 1705 // Next wake from idle is at now + 8. 1706 long min = mNowElapsedTest; 1707 long max = mNowElapsedTest + 8 - minFuzz; 1708 assertInRange("Idle until alarm time not in expected range [" + min + ", " + max + "]", 1709 min, max, mService.mPendingIdleUntil.getWhenElapsed()); 1710 1711 mService.removeLocked(wakeFromIdle8, null, REMOVE_REASON_UNDEFINED); 1712 // Next wake from idle is at now + 19, which is > minFuzz distance from 1713 // the requested idle until time: now + 12. 1714 assertEquals(requestedIdleUntil, mService.mPendingIdleUntil.getWhenElapsed()); 1715 1716 mService.removeLocked(idleUntilPi, null, REMOVE_REASON_UNDEFINED); 1717 assertNull(mService.mPendingIdleUntil); 1718 1719 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 21, idleUntilPi); 1720 // Next wake from idle is at now + 19, which means this alarm should get pulled back. 1721 min = mNowElapsedTest + 19 - maxFuzz; 1722 max = mNowElapsedTest + 19 - minFuzz; 1723 assertInRange("Idle until alarm time not in expected range [" + min + ", " + max + "]", 1724 min, max, mService.mPendingIdleUntil.getWhenElapsed()); 1725 } 1726 1727 @Test 1728 public void allowWhileIdleAlarmsWhileDeviceIdle() throws Exception { 1729 setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); 1730 1731 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + mAllowWhileIdleWindow + 1000, 1732 getNewMockPendingIntent()); 1733 assertNotNull(mService.mPendingIdleUntil); 1734 1735 final int quota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA; 1736 final long firstTrigger = mNowElapsedTest + 10; 1737 for (int i = 0; i < quota; i++) { 1738 setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, 1739 getNewMockPendingIntent(), false, false); 1740 mNowElapsedTest = mTestTimer.getElapsed(); 1741 mTestTimer.expire(); 1742 } 1743 // This one should get deferred on set. 1744 setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota, 1745 getNewMockPendingIntent(), false, false); 1746 final long expectedNextTrigger = firstTrigger + mAllowWhileIdleWindow; 1747 assertEquals("Incorrect trigger when no quota left", expectedNextTrigger, 1748 mTestTimer.getElapsed()); 1749 1750 // Bring the idle until alarm back. 1751 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, expectedNextTrigger - 50, 1752 getNewMockPendingIntent()); 1753 assertEquals(expectedNextTrigger - 50, mService.mPendingIdleUntil.getWhenElapsed()); 1754 assertEquals(expectedNextTrigger - 50, mTestTimer.getElapsed()); 1755 } 1756 1757 @Test 1758 public void allowWhileIdleCompatAlarmsWhileDeviceIdle() throws Exception { 1759 setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); 1760 1761 final long window = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; 1762 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + window + 1000, 1763 getNewMockPendingIntent()); 1764 assertNotNull(mService.mPendingIdleUntil); 1765 1766 final int quota = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; 1767 final long firstTrigger = mNowElapsedTest + 10; 1768 for (int i = 0; i < quota; i++) { 1769 setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, 1770 getNewMockPendingIntent(), false, true); 1771 mNowElapsedTest = mTestTimer.getElapsed(); 1772 mTestTimer.expire(); 1773 } 1774 // This one should get deferred on set. 1775 setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota, 1776 getNewMockPendingIntent(), false, true); 1777 final long expectedNextTrigger = firstTrigger + window; 1778 assertEquals("Incorrect trigger when no quota left", expectedNextTrigger, 1779 mTestTimer.getElapsed()); 1780 1781 // Bring the idle until alarm back. 1782 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, expectedNextTrigger - 50, 1783 getNewMockPendingIntent()); 1784 assertEquals(expectedNextTrigger - 50, mService.mPendingIdleUntil.getWhenElapsed()); 1785 assertEquals(expectedNextTrigger - 50, mTestTimer.getElapsed()); 1786 } 1787 1788 @Test 1789 public void allowWhileIdleCompatHistorySeparate() throws Exception { 1790 when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, 1791 TEST_CALLING_PACKAGE)).thenReturn(true); 1792 when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true); 1793 1794 final int fullQuota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA; 1795 final int compatQuota = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; 1796 1797 final long fullWindow = mAllowWhileIdleWindow; 1798 final long compatWindow = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; 1799 1800 final long firstFullTrigger = mNowElapsedTest + 10; 1801 for (int i = 0; i < fullQuota; i++) { 1802 setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstFullTrigger + i, 1803 getNewMockPendingIntent(), false, false); 1804 mNowElapsedTest = mTestTimer.getElapsed(); 1805 mTestTimer.expire(); 1806 } 1807 // This one should get deferred on set, as full quota is not available. 1808 setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstFullTrigger + fullQuota, 1809 getNewMockPendingIntent(), false, false); 1810 final long expectedNextFullTrigger = firstFullTrigger + fullWindow; 1811 assertEquals("Incorrect trigger when no quota left", expectedNextFullTrigger, 1812 mTestTimer.getElapsed()); 1813 mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); 1814 1815 // The following should be allowed, as compat quota should be free. 1816 for (int i = 0; i < compatQuota; i++) { 1817 final long trigger = mNowElapsedTest + 1; 1818 setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), 1819 false, true); 1820 assertEquals(trigger, mTestTimer.getElapsed()); 1821 mNowElapsedTest = mTestTimer.getElapsed(); 1822 mTestTimer.expire(); 1823 } 1824 1825 // Refresh the state 1826 mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); 1827 mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); 1828 mService.mAllowWhileIdleCompatHistory.removeForPackage(TEST_CALLING_PACKAGE, 1829 TEST_CALLING_USER); 1830 1831 // Now test with flipped order 1832 1833 final long firstCompatTrigger = mNowElapsedTest + 10; 1834 for (int i = 0; i < compatQuota; i++) { 1835 setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstCompatTrigger + i, 1836 getNewMockPendingIntent(), false, true); 1837 mNowElapsedTest = mTestTimer.getElapsed(); 1838 mTestTimer.expire(); 1839 } 1840 // This one should get deferred on set, as full quota is not available. 1841 setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstCompatTrigger + compatQuota, 1842 getNewMockPendingIntent(), false, true); 1843 final long expectedNextCompatTrigger = firstCompatTrigger + compatWindow; 1844 assertEquals("Incorrect trigger when no quota left", expectedNextCompatTrigger, 1845 mTestTimer.getElapsed()); 1846 mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); 1847 1848 // The following should be allowed, as full quota should be free. 1849 for (int i = 0; i < fullQuota; i++) { 1850 final long trigger = mNowElapsedTest + 1; 1851 setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, getNewMockPendingIntent(), 1852 false, false); 1853 assertEquals(trigger, mTestTimer.getElapsed()); 1854 mNowElapsedTest = mTestTimer.getElapsed(); 1855 mTestTimer.expire(); 1856 } 1857 } 1858 1859 @Test 1860 public void allowWhileIdleUnrestricted() throws Exception { 1861 setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); 1862 1863 // Both battery saver and doze are on. 1864 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1000, 1865 getNewMockPendingIntent()); 1866 assertNotNull(mService.mPendingIdleUntil); 1867 1868 when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, 1869 TEST_CALLING_PACKAGE)).thenReturn(true); 1870 1871 final int numAlarms = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA + 100; 1872 final long firstTrigger = mNowElapsedTest + 10; 1873 for (int i = 0; i < numAlarms; i++) { 1874 setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, 1875 getNewMockPendingIntent(), true, false); 1876 } 1877 // All of them should fire as expected. 1878 for (int i = 0; i < numAlarms; i++) { 1879 mNowElapsedTest = mTestTimer.getElapsed(); 1880 assertEquals("Incorrect trigger at i=" + i, firstTrigger + i, mNowElapsedTest); 1881 mTestTimer.expire(); 1882 } 1883 } 1884 1885 @Test 1886 public void deviceIdleDeferralOnSet() throws Exception { 1887 setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); 1888 1889 final long deviceIdleUntil = mNowElapsedTest + 1234; 1890 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, deviceIdleUntil, getNewMockPendingIntent()); 1891 1892 assertEquals(deviceIdleUntil, mTestTimer.getElapsed()); 1893 1894 final int numAlarms = 10; 1895 final PendingIntent[] pis = new PendingIntent[numAlarms]; 1896 for (int i = 0; i < numAlarms; i++) { 1897 setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + i + 1, 1898 pis[i] = getNewMockPendingIntent()); 1899 assertEquals(deviceIdleUntil, mTestTimer.getElapsed()); 1900 } 1901 1902 mNowElapsedTest = mTestTimer.getElapsed(); 1903 mTestTimer.expire(); 1904 for (int i = 0; i < numAlarms; i++) { 1905 verify(pis[i]).send(eq(mMockContext), eq(0), any(Intent.class), any(), 1906 any(Handler.class), isNull(), any()); 1907 } 1908 } 1909 1910 @Test 1911 public void deviceIdleStateChanges() throws Exception { 1912 setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); 1913 1914 final int numAlarms = 10; 1915 final PendingIntent[] pis = new PendingIntent[numAlarms]; 1916 for (int i = 0; i < numAlarms; i++) { 1917 setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + i + 1, 1918 pis[i] = getNewMockPendingIntent()); 1919 assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed()); 1920 } 1921 1922 final PendingIntent idleUntil = getNewMockPendingIntent(); 1923 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1234, idleUntil); 1924 1925 assertEquals(mNowElapsedTest + 1234, mTestTimer.getElapsed()); 1926 1927 mNowElapsedTest += 5; 1928 mTestTimer.expire(); 1929 // Nothing should happen. 1930 verify(pis[0], never()).send(eq(mMockContext), eq(0), any(Intent.class), any(), 1931 any(Handler.class), isNull(), any()); 1932 1933 mService.removeLocked(idleUntil, null, REMOVE_REASON_UNDEFINED); 1934 mTestTimer.expire(); 1935 // Now, the first 5 alarms (upto i = 4) should expire. 1936 for (int i = 0; i < 5; i++) { 1937 verify(pis[i]).send(eq(mMockContext), eq(0), any(Intent.class), any(), 1938 any(Handler.class), isNull(), any()); 1939 } 1940 // Rest should be restored, so the timer should reflect the next alarm. 1941 assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed()); 1942 } 1943 1944 @Test 1945 public void batterySaverThrottling() { 1946 when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, 1947 TEST_CALLING_PACKAGE)).thenReturn(true); 1948 1949 final PendingIntent alarmPi = getNewMockPendingIntent(); 1950 setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 7, alarmPi); 1951 assertEquals(mNowElapsedTest + INDEFINITE_DELAY, mTestTimer.getElapsed()); 1952 1953 when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, 1954 TEST_CALLING_PACKAGE)).thenReturn(false); 1955 mListener.updateAllAlarms(); 1956 assertEquals(mNowElapsedTest + 7, mTestTimer.getElapsed()); 1957 1958 when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, 1959 TEST_CALLING_PACKAGE)).thenReturn(true); 1960 mListener.updateAlarmsForUid(TEST_CALLING_UID); 1961 assertEquals(mNowElapsedTest + INDEFINITE_DELAY, mTestTimer.getElapsed()); 1962 } 1963 1964 @Test 1965 public void allowWhileIdleAlarmsInBatterySaver() throws Exception { 1966 when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, 1967 TEST_CALLING_PACKAGE)).thenReturn(true); 1968 when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true); 1969 final int quota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA; 1970 1971 testQuotasDeferralOnSet(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, 1972 getNewMockPendingIntent(), false, false), quota, mAllowWhileIdleWindow); 1973 1974 // Refresh the state 1975 mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); 1976 mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); 1977 1978 testQuotasDeferralOnExpiration(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, 1979 trigger, getNewMockPendingIntent(), false, false), quota, mAllowWhileIdleWindow); 1980 1981 // Refresh the state 1982 mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); 1983 mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); 1984 1985 testQuotasNoDeferral(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, 1986 getNewMockPendingIntent(), false, false), quota, mAllowWhileIdleWindow); 1987 } 1988 1989 @Test 1990 public void allowWhileIdleCompatAlarmsInBatterySaver() throws Exception { 1991 when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, 1992 TEST_CALLING_PACKAGE)).thenReturn(true); 1993 when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true); 1994 1995 final int quota = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA; 1996 final long window = mService.mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW; 1997 1998 testQuotasDeferralOnSet(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, 1999 getNewMockPendingIntent(), false, true), quota, window); 2000 2001 // Refresh the state 2002 mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); 2003 mService.mAllowWhileIdleCompatHistory.removeForPackage(TEST_CALLING_PACKAGE, 2004 TEST_CALLING_USER); 2005 2006 testQuotasDeferralOnExpiration(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, 2007 trigger, getNewMockPendingIntent(), false, true), quota, window); 2008 2009 // Refresh the state 2010 mService.removeLocked(TEST_CALLING_UID, REMOVE_REASON_UNDEFINED); 2011 mService.mAllowWhileIdleCompatHistory.removeForPackage(TEST_CALLING_PACKAGE, 2012 TEST_CALLING_USER); 2013 2014 testQuotasNoDeferral(trigger -> setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, trigger, 2015 getNewMockPendingIntent(), false, true), quota, window); 2016 } 2017 2018 @Test 2019 public void prioritizedAlarmsInBatterySaver() throws Exception { 2020 when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, 2021 TEST_CALLING_PACKAGE)).thenReturn(true); 2022 when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true); 2023 final long minDelay = 5; 2024 setDeviceConfigLong(KEY_PRIORITY_ALARM_DELAY, minDelay); 2025 2026 final long firstTrigger = mNowElapsedTest + 4; 2027 final AtomicInteger alarmsFired = new AtomicInteger(0); 2028 final int numAlarms = 10; 2029 for (int i = 0; i < numAlarms; i++) { 2030 setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, 2031 0, new IAlarmListener.Stub() { 2032 @Override 2033 public void doAlarm(IAlarmCompleteListener callback) 2034 throws RemoteException { 2035 alarmsFired.incrementAndGet(); 2036 } 2037 }); 2038 } 2039 assertEquals(firstTrigger, mTestTimer.getElapsed()); 2040 mNowElapsedTest = firstTrigger; 2041 mTestTimer.expire(); 2042 while (alarmsFired.get() < numAlarms) { 2043 assertEquals(mNowElapsedTest + minDelay, mTestTimer.getElapsed()); 2044 mNowElapsedTest = mTestTimer.getElapsed(); 2045 mTestTimer.expire(); 2046 } 2047 assertEquals(numAlarms, alarmsFired.get()); 2048 } 2049 2050 @Test 2051 public void prioritizedAlarmsInDeviceIdle() throws Exception { 2052 setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); 2053 2054 final long minDelay = 5; 2055 setDeviceConfigLong(KEY_PRIORITY_ALARM_DELAY, minDelay); 2056 2057 final long idleUntil = mNowElapsedTest + 1000; 2058 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil, getNewMockPendingIntent()); 2059 assertNotNull(mService.mPendingIdleUntil); 2060 2061 final long firstTrigger = mNowElapsedTest + 4; 2062 final AtomicInteger alarmsFired = new AtomicInteger(0); 2063 final int numAlarms = 10; 2064 for (int i = 0; i < numAlarms; i++) { 2065 setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, 2066 0, new IAlarmListener.Stub() { 2067 @Override 2068 public void doAlarm(IAlarmCompleteListener callback) 2069 throws RemoteException { 2070 alarmsFired.incrementAndGet(); 2071 } 2072 }); 2073 } 2074 assertEquals(firstTrigger, mTestTimer.getElapsed()); 2075 mNowElapsedTest = firstTrigger; 2076 mTestTimer.expire(); 2077 while (alarmsFired.get() < numAlarms) { 2078 assertEquals(mNowElapsedTest + minDelay, mTestTimer.getElapsed()); 2079 mNowElapsedTest = mTestTimer.getElapsed(); 2080 mTestTimer.expire(); 2081 } 2082 assertEquals(numAlarms, alarmsFired.get()); 2083 2084 setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 3, 0, new IAlarmListener.Stub() { 2085 @Override 2086 public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { 2087 } 2088 }); 2089 setPrioritizedAlarm(ELAPSED_REALTIME_WAKEUP, idleUntil - 2, 0, new IAlarmListener.Stub() { 2090 @Override 2091 public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { 2092 } 2093 }); 2094 assertEquals(idleUntil - 3, mTestTimer.getElapsed()); 2095 mNowElapsedTest = mTestTimer.getElapsed(); 2096 mTestTimer.expire(); 2097 2098 assertEquals(idleUntil, mTestTimer.getElapsed()); 2099 } 2100 2101 @Test 2102 public void tareThrottling() { 2103 setTareEnabled(EconomyManager.ENABLED_MODE_ON); 2104 final ArgumentCaptor<EconomyManagerInternal.AffordabilityChangeListener> listenerCaptor = 2105 ArgumentCaptor.forClass(EconomyManagerInternal.AffordabilityChangeListener.class); 2106 final ArgumentCaptor<EconomyManagerInternal.ActionBill> billCaptor = 2107 ArgumentCaptor.forClass(EconomyManagerInternal.ActionBill.class); 2108 2109 when(mEconomyManagerInternal 2110 .canPayFor(eq(TEST_CALLING_USER), eq(TEST_CALLING_PACKAGE), billCaptor.capture())) 2111 .thenReturn(false); 2112 2113 final PendingIntent alarmPi = getNewMockPendingIntent(); 2114 setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 15, alarmPi); 2115 assertEquals(mNowElapsedTest + INDEFINITE_DELAY, mTestTimer.getElapsed()); 2116 2117 final EconomyManagerInternal.ActionBill bill = billCaptor.getValue(); 2118 verify(mEconomyManagerInternal).registerAffordabilityChangeListener( 2119 eq(TEST_CALLING_USER), eq(TEST_CALLING_PACKAGE), 2120 listenerCaptor.capture(), eq(bill)); 2121 final EconomyManagerInternal.AffordabilityChangeListener listener = 2122 listenerCaptor.getValue(); 2123 2124 when(mEconomyManagerInternal 2125 .canPayFor(eq(TEST_CALLING_USER), eq(TEST_CALLING_PACKAGE), eq(bill))) 2126 .thenReturn(true); 2127 listener.onAffordabilityChanged(TEST_CALLING_USER, TEST_CALLING_PACKAGE, bill, true); 2128 assertAndHandleMessageSync(TARE_AFFORDABILITY_CHANGED); 2129 assertEquals(mNowElapsedTest + 15, mTestTimer.getElapsed()); 2130 2131 when(mEconomyManagerInternal 2132 .canPayFor(eq(TEST_CALLING_USER), eq(TEST_CALLING_PACKAGE), eq(bill))) 2133 .thenReturn(false); 2134 listener.onAffordabilityChanged(TEST_CALLING_USER, TEST_CALLING_PACKAGE, bill, false); 2135 assertAndHandleMessageSync(TARE_AFFORDABILITY_CHANGED); 2136 assertEquals(mNowElapsedTest + INDEFINITE_DELAY, mTestTimer.getElapsed()); 2137 } 2138 2139 @Test 2140 public void dispatchOrder() throws Exception { 2141 setDeviceConfigLong(KEY_MAX_DEVICE_IDLE_FUZZ, 0); 2142 2143 final long deviceIdleUntil = mNowElapsedTest + 1234; 2144 final PendingIntent idleUntilPi = getNewMockPendingIntent(); 2145 setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, deviceIdleUntil, idleUntilPi); 2146 2147 assertEquals(deviceIdleUntil, mTestTimer.getElapsed()); 2148 2149 final PendingIntent pi5wakeup = getNewMockPendingIntent(); 2150 final PendingIntent pi4wakeupPackage = getNewMockPendingIntent(); 2151 final PendingIntent pi2nonWakeup = getNewMockPendingIntent(57, "test.different.package"); 2152 2153 setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, pi5wakeup); 2154 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 4, pi4wakeupPackage); 2155 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 2, pi2nonWakeup); 2156 2157 mNowElapsedTest = deviceIdleUntil; 2158 mTestTimer.expire(); 2159 2160 // The order of the alarms in delivery list should be: 2161 // IdleUntil, all alarms of a package with any wakeup alarms, then the rest. 2162 // Within a package, alarms should be ordered by requested delivery time. 2163 final PendingIntent[] expectedOrder = new PendingIntent[]{ 2164 idleUntilPi, pi4wakeupPackage, pi5wakeup, pi2nonWakeup}; 2165 2166 ArgumentCaptor<ArrayList<Alarm>> listCaptor = ArgumentCaptor.forClass(ArrayList.class); 2167 verify(mService).deliverAlarmsLocked(listCaptor.capture(), anyLong()); 2168 final ArrayList<Alarm> deliveryList = listCaptor.getValue(); 2169 2170 assertEquals(expectedOrder.length, deliveryList.size()); 2171 for (int i = 0; i < expectedOrder.length; i++) { 2172 assertTrue("Unexpected alarm: " + deliveryList.get(i) + " at pos: " + i, 2173 deliveryList.get(i).matches(expectedOrder[i], null)); 2174 } 2175 } 2176 2177 private void mockChangeEnabled(long changeId, boolean enabled) { 2178 doReturn(enabled).when(() -> CompatChanges.isChangeEnabled(eq(changeId), anyString(), 2179 any(UserHandle.class))); 2180 doReturn(enabled).when(() -> CompatChanges.isChangeEnabled(eq(changeId), anyInt())); 2181 } 2182 2183 @Test 2184 public void hasScheduleExactAlarmBinderCall() throws RemoteException { 2185 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2186 mockChangeEnabled(AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, true); 2187 2188 mockScheduleExactAlarmState(true); 2189 assertTrue(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2190 2191 mockScheduleExactAlarmState(false); 2192 assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2193 } 2194 2195 @Test 2196 public void hasScheduleExactAlarmBinderCallNotDenyListedPreT() throws RemoteException { 2197 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2198 2199 mockScheduleExactAlarmStatePreT(true, false, MODE_DEFAULT); 2200 assertTrue(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2201 2202 mockScheduleExactAlarmStatePreT(true, false, MODE_ALLOWED); 2203 assertTrue(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2204 2205 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 2206 assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2207 2208 mockScheduleExactAlarmStatePreT(true, false, MODE_IGNORED); 2209 assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2210 } 2211 2212 @Test 2213 public void hasScheduleExactAlarmBinderCallDenyListedPreT() throws RemoteException { 2214 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2215 2216 mockScheduleExactAlarmStatePreT(true, true, MODE_ERRORED); 2217 assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2218 2219 mockScheduleExactAlarmStatePreT(true, true, MODE_DEFAULT); 2220 assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2221 2222 mockScheduleExactAlarmStatePreT(true, true, MODE_IGNORED); 2223 assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2224 2225 mockScheduleExactAlarmStatePreT(true, true, MODE_ALLOWED); 2226 assertTrue(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2227 } 2228 2229 @Test 2230 public void hasScheduleExactAlarmBinderCallNotDeclaredPreT() throws RemoteException { 2231 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2232 2233 mockScheduleExactAlarmStatePreT(false, false, MODE_DEFAULT); 2234 assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2235 2236 mockScheduleExactAlarmStatePreT(false, false, MODE_ALLOWED); 2237 assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2238 2239 mockScheduleExactAlarmStatePreT(false, true, MODE_ALLOWED); 2240 assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER)); 2241 } 2242 2243 @Test 2244 public void canScheduleExactAlarmsBinderCallChangeDisabled() throws RemoteException { 2245 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false); 2246 2247 // canScheduleExactAlarms should be true regardless of any permission state. 2248 // Both SEA and UEA are denied in setUp. 2249 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2250 2251 mockUseExactAlarmState(false); 2252 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2253 2254 mockScheduleExactAlarmState(false); 2255 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2256 } 2257 2258 @Test 2259 public void canScheduleExactAlarmsBinderCallPreT() throws RemoteException { 2260 // Policy permission is denied in setUp(). 2261 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2262 mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); 2263 2264 // No permission, no exemption. 2265 mockScheduleExactAlarmStatePreT(true, true, MODE_DEFAULT); 2266 assertFalse(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2267 2268 // No permission, no exemption. 2269 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 2270 assertFalse(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2271 2272 // Policy permission only, no exemption. 2273 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 2274 mockUseExactAlarmState(true); 2275 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2276 2277 mockUseExactAlarmState(false); 2278 2279 // User permission only, no exemption. 2280 mockScheduleExactAlarmStatePreT(true, false, MODE_DEFAULT); 2281 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2282 2283 // User permission only, no exemption. 2284 mockScheduleExactAlarmStatePreT(true, true, MODE_ALLOWED); 2285 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2286 2287 // No permission, exemption. 2288 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 2289 when(mDeviceIdleInternal.isAppOnWhitelist(TEST_CALLING_UID)).thenReturn(true); 2290 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2291 2292 // No permission, exemption. 2293 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 2294 when(mDeviceIdleInternal.isAppOnWhitelist(TEST_CALLING_UID)).thenReturn(false); 2295 doReturn(true).when(() -> UserHandle.isCore(TEST_CALLING_UID)); 2296 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2297 2298 // Both permissions and exemption. 2299 mockScheduleExactAlarmStatePreT(true, false, MODE_ALLOWED); 2300 mockUseExactAlarmState(true); 2301 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2302 } 2303 2304 @Test 2305 public void canScheduleExactAlarmsBinderCall() throws RemoteException { 2306 // Both permissions are denied in setUp(). 2307 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2308 mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); 2309 mockChangeEnabled(AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, true); 2310 2311 // No permission, no exemption. 2312 assertFalse(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2313 2314 // Policy permission only, no exemption. 2315 mockUseExactAlarmState(true); 2316 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2317 2318 mockUseExactAlarmState(false); 2319 2320 // User permission only, no exemption. 2321 mockScheduleExactAlarmState(true); 2322 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2323 2324 // No permission, exemption. 2325 mockScheduleExactAlarmState(false); 2326 when(mDeviceIdleInternal.isAppOnWhitelist(TEST_CALLING_UID)).thenReturn(true); 2327 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2328 2329 // No permission, core uid exemption. 2330 when(mDeviceIdleInternal.isAppOnWhitelist(TEST_CALLING_UID)).thenReturn(false); 2331 doReturn(true).when(() -> UserHandle.isCore(TEST_CALLING_UID)); 2332 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2333 2334 // Both permissions and core uid exemption. 2335 mockScheduleExactAlarmState(true); 2336 mockUseExactAlarmState(true); 2337 assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE)); 2338 } 2339 2340 @Test 2341 public void noPermissionCheckWhenChangeDisabled() throws RemoteException { 2342 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false); 2343 2344 // alarm clock 2345 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 0, 2346 getNewMockPendingIntent(), null, null, null, 2347 mock(AlarmManager.AlarmClockInfo.class)); 2348 2349 // exact 2350 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2351 0, getNewMockPendingIntent(), null, null, null, null); 2352 2353 // exact, allow-while-idle 2354 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2355 FLAG_ALLOW_WHILE_IDLE, getNewMockPendingIntent(), null, null, null, null); 2356 2357 // inexact, allow-while-idle 2358 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_HEURISTIC, 0, 2359 FLAG_ALLOW_WHILE_IDLE, getNewMockPendingIntent(), null, null, null, null); 2360 2361 verify(mService, never()).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, 2362 TEST_CALLING_UID); 2363 verify(mService, never()).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, 2364 TEST_CALLING_UID); 2365 verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); 2366 } 2367 2368 @Test 2369 public void exactBinderCallWhenChangeDisabled() throws Exception { 2370 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false); 2371 2372 final PendingIntent alarmPi = getNewMockPendingIntent(); 2373 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2374 0, alarmPi, null, null, null, null); 2375 2376 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2377 eq(alarmPi), isNull(), isNull(), 2378 eq(FLAG_STANDALONE), isNull(), isNull(), 2379 eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), isNull(), 2380 eq(EXACT_ALLOW_REASON_COMPAT)); 2381 } 2382 2383 @Test 2384 public void exactAllowWhileIdleBinderCallWhenChangeDisabled() throws Exception { 2385 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false); 2386 2387 final PendingIntent alarmPi = getNewMockPendingIntent(); 2388 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2389 FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null); 2390 2391 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2392 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2393 eq(alarmPi), isNull(), isNull(), 2394 eq(FLAG_ALLOW_WHILE_IDLE_COMPAT | FLAG_STANDALONE), isNull(), isNull(), 2395 eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), 2396 eq(EXACT_ALLOW_REASON_COMPAT)); 2397 2398 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2399 final int type = idleOptions.getTemporaryAppAllowlistType(); 2400 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); 2401 } 2402 2403 @Test 2404 public void inexactAllowWhileIdleBinderCallWhenChangeDisabled() throws Exception { 2405 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false); 2406 2407 final PendingIntent alarmPi = getNewMockPendingIntent(); 2408 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_HEURISTIC, 0, 2409 FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null); 2410 2411 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2412 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), anyLong(), eq(0L), 2413 eq(alarmPi), isNull(), isNull(), eq(FLAG_ALLOW_WHILE_IDLE_COMPAT), isNull(), 2414 isNull(), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), 2415 eq(EXACT_ALLOW_REASON_NOT_APPLICABLE)); 2416 2417 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2418 final int type = idleOptions.getTemporaryAppAllowlistType(); 2419 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); 2420 } 2421 2422 @Test 2423 public void alarmClockBinderCallWhenChangeDisabled() throws Exception { 2424 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false); 2425 2426 final PendingIntent alarmPi = getNewMockPendingIntent(); 2427 final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class); 2428 mBinder.set(TEST_CALLING_PACKAGE, RTC_WAKEUP, 1234, WINDOW_EXACT, 0, 0, 2429 alarmPi, null, null, null, alarmClock); 2430 2431 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2432 verify(mService).setImpl(eq(RTC_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2433 eq(alarmPi), isNull(), isNull(), eq(FLAG_STANDALONE | FLAG_WAKE_FROM_IDLE), 2434 isNull(), eq(alarmClock), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), 2435 bundleCaptor.capture(), eq(EXACT_ALLOW_REASON_COMPAT)); 2436 2437 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2438 final int type = idleOptions.getTemporaryAppAllowlistType(); 2439 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); 2440 } 2441 2442 @Test 2443 public void alarmClockBinderCallWithSEAPermission() throws RemoteException { 2444 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2445 mockChangeEnabled(AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, true); 2446 2447 mockScheduleExactAlarmState(true); 2448 2449 final PendingIntent alarmPi = getNewMockPendingIntent(); 2450 final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class); 2451 mBinder.set(TEST_CALLING_PACKAGE, RTC_WAKEUP, 1234, WINDOW_EXACT, 0, 0, 2452 alarmPi, null, null, null, alarmClock); 2453 2454 // Correct permission checks are invoked. 2455 verify(mService).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); 2456 verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); 2457 2458 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2459 verify(mService).setImpl(eq(RTC_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2460 eq(alarmPi), isNull(), isNull(), eq(FLAG_STANDALONE | FLAG_WAKE_FROM_IDLE), 2461 isNull(), eq(alarmClock), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), 2462 bundleCaptor.capture(), eq(EXACT_ALLOW_REASON_PERMISSION)); 2463 2464 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2465 final int type = idleOptions.getTemporaryAppAllowlistType(); 2466 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); 2467 } 2468 2469 @Test 2470 public void alarmClockBinderCallWithUEAPermission() throws RemoteException { 2471 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2472 mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); 2473 mockChangeEnabled(AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, true); 2474 2475 mockUseExactAlarmState(true); 2476 mockScheduleExactAlarmState(false); 2477 2478 final PendingIntent alarmPi = getNewMockPendingIntent(); 2479 final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class); 2480 mBinder.set(TEST_CALLING_PACKAGE, RTC_WAKEUP, 1234, WINDOW_EXACT, 0, 0, 2481 alarmPi, null, null, null, alarmClock); 2482 2483 // Correct permission checks are invoked. 2484 verify(mService).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); 2485 verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); 2486 2487 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2488 verify(mService).setImpl(eq(RTC_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2489 eq(alarmPi), isNull(), isNull(), eq(FLAG_STANDALONE | FLAG_WAKE_FROM_IDLE), 2490 isNull(), eq(alarmClock), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), 2491 bundleCaptor.capture(), eq(EXACT_ALLOW_REASON_POLICY_PERMISSION)); 2492 2493 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2494 final int type = idleOptions.getTemporaryAppAllowlistType(); 2495 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); 2496 } 2497 2498 private void mockScheduleExactAlarmStatePreT(boolean declared, boolean denyList, int mode) { 2499 String[] requesters = declared ? new String[]{TEST_CALLING_PACKAGE} : EmptyArray.STRING; 2500 when(mPermissionManagerInternal.getAppOpPermissionPackages(SCHEDULE_EXACT_ALARM)) 2501 .thenReturn(requesters); 2502 mService.refreshExactAlarmCandidates(); 2503 2504 if (denyList) { 2505 setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, TEST_CALLING_PACKAGE); 2506 } else { 2507 setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, ""); 2508 } 2509 when(mAppOpsManager.checkOpNoThrow(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, 2510 TEST_CALLING_PACKAGE)).thenReturn(mode); 2511 } 2512 2513 private void mockScheduleExactAlarmState(boolean granted) { 2514 String[] requesters = granted ? new String[]{TEST_CALLING_PACKAGE} : EmptyArray.STRING; 2515 when(mPermissionManagerInternal.getAppOpPermissionPackages(SCHEDULE_EXACT_ALARM)) 2516 .thenReturn(requesters); 2517 mService.refreshExactAlarmCandidates(); 2518 2519 final int result = granted ? PermissionChecker.PERMISSION_GRANTED 2520 : PermissionChecker.PERMISSION_HARD_DENIED; 2521 doReturn(result).when( 2522 () -> PermissionChecker.checkPermissionForPreflight(eq(mMockContext), 2523 eq(SCHEDULE_EXACT_ALARM), anyInt(), eq(TEST_CALLING_UID), 2524 eq(TEST_CALLING_PACKAGE))); 2525 } 2526 2527 private void mockUseExactAlarmState(boolean granted) { 2528 final int result = granted ? PermissionChecker.PERMISSION_GRANTED 2529 : PermissionChecker.PERMISSION_HARD_DENIED; 2530 doReturn(result).when( 2531 () -> PermissionChecker.checkPermissionForPreflight(eq(mMockContext), 2532 eq(Manifest.permission.USE_EXACT_ALARM), anyInt(), eq(TEST_CALLING_UID), 2533 eq(TEST_CALLING_PACKAGE))); 2534 } 2535 2536 @Test 2537 public void alarmClockBinderCallWithoutPermission() throws RemoteException { 2538 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2539 2540 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 2541 when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true); 2542 2543 final PendingIntent alarmPi = getNewMockPendingIntent(); 2544 final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class); 2545 mBinder.set(TEST_CALLING_PACKAGE, RTC_WAKEUP, 1234, WINDOW_EXACT, 0, 0, 2546 alarmPi, null, null, null, alarmClock); 2547 2548 // Correct permission checks are invoked. 2549 verify(mService).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); 2550 verify(mDeviceIdleInternal).isAppOnWhitelist(UserHandle.getAppId(TEST_CALLING_UID)); 2551 2552 verify(mService).setImpl(eq(RTC_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2553 eq(alarmPi), isNull(), isNull(), eq(FLAG_STANDALONE | FLAG_WAKE_FROM_IDLE), 2554 isNull(), eq(alarmClock), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), 2555 isNull(), eq(EXACT_ALLOW_REASON_ALLOW_LIST)); 2556 } 2557 2558 @Test 2559 public void exactBinderCallWithSEAPermission() throws RemoteException { 2560 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2561 mockChangeEnabled(AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, true); 2562 2563 mockScheduleExactAlarmState(true); 2564 final PendingIntent alarmPi = getNewMockPendingIntent(); 2565 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2566 0, alarmPi, null, null, null, null); 2567 2568 verify(mService).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); 2569 verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); 2570 2571 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2572 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2573 eq(alarmPi), isNull(), isNull(), 2574 eq(FLAG_STANDALONE), isNull(), isNull(), 2575 eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), 2576 eq(EXACT_ALLOW_REASON_PERMISSION)); 2577 2578 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2579 final int type = idleOptions.getTemporaryAppAllowlistType(); 2580 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); 2581 } 2582 2583 @Test 2584 public void exactBinderCallWithUEAPermission() throws RemoteException { 2585 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2586 mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); 2587 mockChangeEnabled(AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, true); 2588 2589 mockUseExactAlarmState(true); 2590 mockScheduleExactAlarmState(false); 2591 final PendingIntent alarmPi = getNewMockPendingIntent(); 2592 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2593 0, alarmPi, null, null, null, null); 2594 2595 verify(mService).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); 2596 verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); 2597 2598 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2599 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2600 eq(alarmPi), isNull(), isNull(), 2601 eq(FLAG_STANDALONE), isNull(), isNull(), 2602 eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), 2603 eq(EXACT_ALLOW_REASON_POLICY_PERMISSION)); 2604 2605 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2606 final int type = idleOptions.getTemporaryAppAllowlistType(); 2607 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); 2608 } 2609 2610 @Test 2611 public void exactBinderCallWithAllowlist() throws RemoteException { 2612 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2613 // If permission is denied, only then allowlist will be checked. 2614 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 2615 when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true); 2616 2617 final PendingIntent alarmPi = getNewMockPendingIntent(); 2618 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2619 0, alarmPi, null, null, null, null); 2620 2621 verify(mDeviceIdleInternal).isAppOnWhitelist(UserHandle.getAppId(TEST_CALLING_UID)); 2622 2623 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2624 eq(alarmPi), isNull(), isNull(), 2625 eq(FLAG_STANDALONE), isNull(), isNull(), 2626 eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), isNull(), 2627 eq(EXACT_ALLOW_REASON_ALLOW_LIST)); 2628 } 2629 2630 @Test 2631 public void exactAllowWhileIdleBinderCallWithSEAPermission() throws RemoteException { 2632 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2633 2634 mockScheduleExactAlarmStatePreT(true, false, MODE_ALLOWED); 2635 final PendingIntent alarmPi = getNewMockPendingIntent(); 2636 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2637 FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null); 2638 2639 verify(mService).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); 2640 verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); 2641 2642 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2643 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2644 eq(alarmPi), isNull(), isNull(), 2645 eq(FLAG_ALLOW_WHILE_IDLE | FLAG_STANDALONE), isNull(), isNull(), 2646 eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), 2647 eq(EXACT_ALLOW_REASON_PERMISSION)); 2648 2649 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2650 final int type = idleOptions.getTemporaryAppAllowlistType(); 2651 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); 2652 } 2653 2654 @Test 2655 public void exactAllowWhileIdleBinderCallWithUEAPermission() throws RemoteException { 2656 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2657 mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); 2658 2659 mockUseExactAlarmState(true); 2660 mockScheduleExactAlarmStatePreT(false, false, MODE_ERRORED); 2661 final PendingIntent alarmPi = getNewMockPendingIntent(); 2662 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2663 FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null); 2664 2665 verify(mService).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); 2666 verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); 2667 2668 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2669 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2670 eq(alarmPi), isNull(), isNull(), 2671 eq(FLAG_ALLOW_WHILE_IDLE | FLAG_STANDALONE), isNull(), isNull(), 2672 eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), 2673 eq(EXACT_ALLOW_REASON_POLICY_PERMISSION)); 2674 2675 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2676 final int type = idleOptions.getTemporaryAppAllowlistType(); 2677 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); 2678 } 2679 2680 @Test 2681 public void exactAllowWhileIdleBinderCallWithAllowlist() throws RemoteException { 2682 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2683 // If permission is denied, only then allowlist will be checked. 2684 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 2685 when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true); 2686 2687 final PendingIntent alarmPi = getNewMockPendingIntent(); 2688 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2689 FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null); 2690 2691 verify(mDeviceIdleInternal).isAppOnWhitelist(UserHandle.getAppId(TEST_CALLING_UID)); 2692 2693 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2694 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2695 eq(alarmPi), isNull(), isNull(), 2696 eq(FLAG_ALLOW_WHILE_IDLE_COMPAT | FLAG_STANDALONE), isNull(), isNull(), 2697 eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), 2698 eq(EXACT_ALLOW_REASON_ALLOW_LIST)); 2699 2700 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2701 final int type = idleOptions.getTemporaryAppAllowlistType(); 2702 // App is on power allowlist, doesn't need explicit FGS grant in broadcast options. 2703 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED, type); 2704 } 2705 2706 @Test 2707 public void exactBinderCallsWithoutPermissionWithoutAllowlist() throws RemoteException { 2708 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2709 2710 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 2711 when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(false); 2712 2713 final PendingIntent alarmPi = getNewMockPendingIntent(); 2714 try { 2715 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2716 0, alarmPi, null, null, null, null); 2717 fail("exact binder call succeeded without permission"); 2718 } catch (SecurityException se) { 2719 // Expected. 2720 } 2721 try { 2722 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2723 FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null); 2724 fail("exact, allow-while-idle binder call succeeded without permission"); 2725 } catch (SecurityException se) { 2726 // Expected. 2727 } 2728 verify(mDeviceIdleInternal, times(2)).isAppOnWhitelist(anyInt()); 2729 } 2730 2731 @Test 2732 public void exactListenerBinderCallWithoutPermissionWithoutAllowlist() throws RemoteException { 2733 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2734 mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); 2735 2736 mockScheduleExactAlarmState(false); 2737 mockUseExactAlarmState(false); 2738 when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(false); 2739 2740 final IAlarmListener listener = getNewListener(() -> {}); 2741 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2742 0, null, listener, "test-tag", null, null); 2743 2744 verify(mService, never()).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); 2745 verify(mService, never()).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, 2746 TEST_CALLING_UID); 2747 verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); 2748 2749 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2750 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2751 isNull(), eq(listener), eq("test-tag"), eq(FLAG_STANDALONE), isNull(), isNull(), 2752 eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), 2753 eq(EXACT_ALLOW_REASON_LISTENER)); 2754 2755 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2756 final int type = idleOptions.getTemporaryAppAllowlistType(); 2757 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); 2758 } 2759 2760 @Test 2761 public void exactAllowWhileIdleListenerBinderCallWithoutPermissionWithoutAllowlist() 2762 throws RemoteException { 2763 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2764 mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); 2765 2766 mockScheduleExactAlarmState(false); 2767 mockUseExactAlarmState(false); 2768 when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(false); 2769 2770 final IAlarmListener listener = getNewListener(() -> {}); 2771 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2772 FLAG_ALLOW_WHILE_IDLE, null, listener, "test-tag", null, null); 2773 2774 verify(mService, never()).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID); 2775 verify(mService, never()).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, 2776 TEST_CALLING_UID); 2777 verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); 2778 2779 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2780 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2781 isNull(), eq(listener), eq("test-tag"), 2782 eq(FLAG_STANDALONE | FLAG_ALLOW_WHILE_IDLE_COMPAT), isNull(), isNull(), 2783 eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), 2784 eq(EXACT_ALLOW_REASON_LISTENER)); 2785 2786 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2787 final int type = idleOptions.getTemporaryAppAllowlistType(); 2788 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type); 2789 } 2790 2791 @Test 2792 public void inexactAllowWhileIdleBinderCall() throws RemoteException { 2793 // Both permission and power exemption status don't matter for these alarms. 2794 // We only want to test that the flags and idleOptions are correct. 2795 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2796 2797 final PendingIntent alarmPi = getNewMockPendingIntent(); 2798 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 4321, WINDOW_HEURISTIC, 0, 2799 FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null); 2800 2801 verify(mService, never()).hasScheduleExactAlarmInternal(anyString(), anyInt()); 2802 verify(mService, never()).hasUseExactAlarmInternal(anyString(), anyInt()); 2803 verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt()); 2804 2805 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2806 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(4321L), anyLong(), eq(0L), 2807 eq(alarmPi), isNull(), isNull(), eq(FLAG_ALLOW_WHILE_IDLE_COMPAT), isNull(), 2808 isNull(), eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(), 2809 eq(EXACT_ALLOW_REASON_NOT_APPLICABLE)); 2810 2811 final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue()); 2812 final int type = idleOptions.getTemporaryAppAllowlistType(); 2813 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED, type); 2814 } 2815 2816 @Test 2817 public void binderCallWithUserAllowlist() throws RemoteException { 2818 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 2819 2820 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 2821 when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true); 2822 when(mAppStateTracker.isUidPowerSaveUserExempt(TEST_CALLING_UID)).thenReturn(true); 2823 2824 final PendingIntent alarmPi = getNewMockPendingIntent(); 2825 mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0, 2826 FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null); 2827 2828 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 2829 verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L), 2830 eq(alarmPi), isNull(), isNull(), 2831 eq(FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED | FLAG_STANDALONE), isNull(), isNull(), 2832 eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), isNull(), 2833 eq(EXACT_ALLOW_REASON_ALLOW_LIST)); 2834 } 2835 2836 @Test 2837 public void removeAllBinderCall() throws RemoteException { 2838 for (int i = 0; i < 10; i++) { 2839 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 1, getNewMockPendingIntent()); 2840 } 2841 2842 final String otherPackage1 = "other.package1"; 2843 final String otherPackage2 = "other.package2"; 2844 final int otherAppId = 1243; 2845 final int otherUser1 = 31; 2846 final int otherUser2 = 8; 2847 final int otherUid1 = UserHandle.getUid(otherUser1, otherAppId); 2848 final int otherUid2 = UserHandle.getUid(otherUser2, otherAppId); 2849 2850 registerAppIds( 2851 new String[]{TEST_CALLING_PACKAGE, otherPackage1, otherPackage2}, 2852 new Integer[]{UserHandle.getAppId(TEST_CALLING_UID), otherAppId, otherAppId} 2853 ); 2854 2855 for (int i = 0; i < 9; i++) { 2856 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 11, 0, 2857 getNewMockPendingIntent(otherUid1, otherPackage1), 0, 0, otherUid1, 2858 otherPackage1, null); 2859 } 2860 2861 for (int i = 0; i < 8; i++) { 2862 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 20, 0, 2863 getNewMockPendingIntent(otherUid1, otherPackage2), 0, 0, otherUid1, 2864 otherPackage2, null); 2865 } 2866 2867 for (int i = 0; i < 7; i++) { 2868 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 28, 0, 2869 getNewMockPendingIntent(otherUid2, otherPackage2), 0, 0, otherUid2, 2870 otherPackage2, null); 2871 } 2872 2873 assertEquals(34, mService.mAlarmStore.size()); 2874 2875 try { 2876 mBinder.removeAll(otherPackage1); 2877 fail("removeAll() for wrong package did not throw SecurityException"); 2878 } catch (SecurityException se) { 2879 // Expected 2880 } 2881 2882 try { 2883 mBinder.removeAll(otherPackage2); 2884 fail("removeAll() for wrong package did not throw SecurityException"); 2885 } catch (SecurityException se) { 2886 // Expected 2887 } 2888 2889 mBinder.removeAll(TEST_CALLING_PACKAGE); 2890 assertEquals(24, mService.mAlarmStore.size()); 2891 assertEquals(0, mService.mAlarmStore.getCount(a -> a.matches(TEST_CALLING_PACKAGE))); 2892 2893 mTestCallingUid = otherUid1; 2894 mBinder.removeAll(otherPackage1); 2895 assertEquals(15, mService.mAlarmStore.size()); 2896 assertEquals(15, mService.mAlarmStore.getCount(a -> a.matches(otherPackage2))); 2897 assertEquals(0, mService.mAlarmStore.getCount(a -> a.matches(otherPackage1))); 2898 2899 mBinder.removeAll(otherPackage2); 2900 assertEquals(7, mService.mAlarmStore.size()); 2901 assertEquals(7, mService.mAlarmStore.getCount(a -> a.matches(otherPackage2))); 2902 2903 mTestCallingUid = otherUid2; 2904 mBinder.removeAll(otherPackage2); 2905 assertEquals(0, mService.mAlarmStore.size()); 2906 } 2907 2908 @Test 2909 public void minWindowChangeEnabled() { 2910 mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, true); 2911 final int minWindow = 73; 2912 setDeviceConfigLong(KEY_MIN_WINDOW, minWindow); 2913 2914 final Random random = new Random(42); 2915 2916 // 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC. 2917 for (int window = 1; window <= minWindow; window++) { 2918 final PendingIntent pi = getNewMockPendingIntent(); 2919 final long futurity = random.nextInt(minWindow); 2920 2921 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + futurity, window, pi, 0, 0, 2922 TEST_CALLING_UID, null); 2923 2924 final long minAllowed = (long) (futurity * 0.75); // This will always be <= minWindow. 2925 2926 assertEquals(1, mService.mAlarmStore.size()); 2927 final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0); 2928 assertEquals(Math.max(minAllowed, window), a.windowLength); 2929 } 2930 2931 for (int window = 1; window <= minWindow; window++) { 2932 final PendingIntent pi = getNewMockPendingIntent(); 2933 final long futurity = 2 * minWindow + window; // implies (0.75 * futurity) > minWindow 2934 2935 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + futurity, window, pi, 0, 0, 2936 TEST_CALLING_UID, null); 2937 2938 assertEquals(1, mService.mAlarmStore.size()); 2939 final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0); 2940 assertEquals(minWindow, a.windowLength); 2941 } 2942 2943 for (int i = 0; i < 20; i++) { 2944 final long window = minWindow + random.nextInt(100); 2945 final PendingIntent pi = getNewMockPendingIntent(); 2946 setTestAlarm(ELAPSED_REALTIME, 0, window, pi, 0, 0, TEST_CALLING_UID, null); 2947 2948 assertEquals(1, mService.mAlarmStore.size()); 2949 final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0); 2950 assertEquals(window, a.windowLength); 2951 } 2952 } 2953 2954 @Test 2955 public void minWindowChangeDisabled() { 2956 mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, false); 2957 final long minWindow = 73; 2958 final long futurity = 10_000; 2959 setDeviceConfigLong(KEY_MIN_WINDOW, minWindow); 2960 2961 // 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC. 2962 for (int window = 1; window <= minWindow; window++) { 2963 final PendingIntent pi = getNewMockPendingIntent(); 2964 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + futurity, window, pi, 0, 0, 2965 TEST_CALLING_UID, null); 2966 2967 assertEquals(1, mService.mAlarmStore.size()); 2968 final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0); 2969 assertEquals(window, a.windowLength); 2970 } 2971 } 2972 2973 @Test 2974 public void minWindowExempted() { 2975 mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, true); 2976 final long minWindow = 73; 2977 final long futurity = 10_000; 2978 2979 setDeviceConfigLong(KEY_MIN_WINDOW, minWindow); 2980 2981 final int coreUid = 2312; 2982 doReturn(true).when(() -> UserHandle.isCore(coreUid)); 2983 2984 final int allowlisted = 54239; 2985 when(mDeviceIdleInternal.isAppOnWhitelist(UserHandle.getAppId(allowlisted))).thenReturn( 2986 true); 2987 2988 for (final int callingUid : new int[]{SYSTEM_UI_UID, coreUid, coreUid}) { 2989 // 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC. 2990 for (int window = 1; window <= minWindow; window++) { 2991 final PendingIntent pi = getNewMockPendingIntent(); 2992 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + futurity, window, pi, 0, 0, 2993 callingUid, null); 2994 2995 assertEquals(1, mService.mAlarmStore.size()); 2996 final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0); 2997 assertEquals(window, a.windowLength); 2998 } 2999 } 3000 3001 // 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC. 3002 for (int window = 1; window <= minWindow; window++) { 3003 final PendingIntent pi = getNewMockPendingIntent(); 3004 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + futurity, window, pi, 0, 0, 3005 TEST_CALLING_UID, null); 3006 3007 assertEquals(1, mService.mAlarmStore.size()); 3008 final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0); 3009 assertEquals(minWindow, a.windowLength); 3010 } 3011 } 3012 3013 @Test 3014 public void minWindowPriorityAlarm() { 3015 mockChangeEnabled(AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, true); 3016 final long minWindow = 73; 3017 final long futurity = 10_000; 3018 setDeviceConfigLong(KEY_MIN_WINDOW, minWindow); 3019 3020 // 0 is WINDOW_EXACT and < 0 is WINDOW_HEURISTIC. 3021 for (int window = 1; window <= minWindow; window++) { 3022 setPrioritizedAlarm(ELAPSED_REALTIME, mNowElapsedTest + futurity, window, 3023 new IAlarmListener.Stub() { 3024 @Override 3025 public void doAlarm(IAlarmCompleteListener callback) 3026 throws RemoteException { 3027 } 3028 }); 3029 assertEquals(1, mService.mAlarmStore.size()); 3030 final Alarm a = mService.mAlarmStore.remove(unused -> true).get(0); 3031 assertEquals(window, a.windowLength); 3032 } 3033 } 3034 3035 @Test 3036 public void denyListChanged() { 3037 mService.mConstants.EXACT_ALARM_DENY_LIST = new ArraySet<>(new String[]{"p1", "p2", "p3"}); 3038 when(mActivityManagerInternal.getStartedUserIds()).thenReturn(EmptyArray.INT); 3039 3040 setDeviceConfigString(KEY_EXACT_ALARM_DENY_LIST, "p2,p4,p5"); 3041 3042 final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); 3043 verify(mService.mHandler, times(2)).sendMessageAtTime(messageCaptor.capture(), 3044 anyLong()); 3045 3046 final List<Message> messages = messageCaptor.getAllValues(); 3047 for (final Message msg : messages) { 3048 assertTrue("Unwanted message sent to handler: " + msg.what, 3049 msg.what == EXACT_ALARM_DENY_LIST_PACKAGES_ADDED 3050 || msg.what == EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED); 3051 mService.mHandler.handleMessage(msg); 3052 } 3053 3054 ArraySet<String> added = new ArraySet<>(new String[]{"p4", "p5"}); 3055 verify(mService).handleChangesToExactAlarmDenyList(eq(added), eq(true)); 3056 3057 ArraySet<String> removed = new ArraySet<>(new String[]{"p1", "p3"}); 3058 verify(mService).handleChangesToExactAlarmDenyList(eq(removed), eq(false)); 3059 } 3060 3061 @Test 3062 public void permissionGrantedDueToDenyList() { 3063 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 3064 3065 final String[] packages = {"example.package.1", "example.package.2"}; 3066 3067 final int appId1 = 232; 3068 final int appId2 = 431; 3069 3070 final int userId1 = 42; 3071 final int userId2 = 53; 3072 3073 registerAppIds(packages, new Integer[]{appId1, appId2}); 3074 3075 when(mActivityManagerInternal.getStartedUserIds()).thenReturn(new int[]{userId1, userId2}); 3076 3077 when(mPermissionManagerInternal.getAppOpPermissionPackages( 3078 SCHEDULE_EXACT_ALARM)).thenReturn(packages); 3079 mService.refreshExactAlarmCandidates(); 3080 3081 final long allowListDuration = 53442; 3082 when(mActivityManagerInternal.getBootTimeTempAllowListDuration()).thenReturn( 3083 allowListDuration); 3084 3085 mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId1, appId1), MODE_ALLOWED); 3086 mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId2, appId1), MODE_DEFAULT); 3087 mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId1, appId2), MODE_IGNORED); 3088 mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId2, appId2), MODE_ERRORED); 3089 3090 mService.handleChangesToExactAlarmDenyList(new ArraySet<>(packages), false); 3091 3092 // No permission revoked. 3093 verify(mService, never()).removeExactAlarmsOnPermissionRevoked(anyInt(), anyString(), 3094 anyBoolean()); 3095 3096 // Permission got granted only for (appId1, userId2). 3097 final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 3098 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 3099 final ArgumentCaptor<UserHandle> userCaptor = ArgumentCaptor.forClass(UserHandle.class); 3100 3101 verify(mMockContext).sendBroadcastAsUser(intentCaptor.capture(), userCaptor.capture(), 3102 isNull(), bundleCaptor.capture()); 3103 3104 assertEquals(userId2, userCaptor.getValue().getIdentifier()); 3105 3106 // Validate the intent. 3107 assertEquals(AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED, 3108 intentCaptor.getValue().getAction()); 3109 assertEquals(packages[0], intentCaptor.getValue().getPackage()); 3110 3111 // Validate the options. 3112 final BroadcastOptions bOptions = new BroadcastOptions(bundleCaptor.getValue()); 3113 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, 3114 bOptions.getTemporaryAppAllowlistType()); 3115 assertEquals(allowListDuration, bOptions.getTemporaryAppAllowlistDuration()); 3116 assertEquals(PowerExemptionManager.REASON_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED, 3117 bOptions.getTemporaryAppAllowlistReasonCode()); 3118 } 3119 3120 @Test 3121 public void permissionRevokedDueToDenyList() { 3122 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 3123 3124 final String[] packages = {"example.package.1", "example.package.2"}; 3125 3126 final int appId1 = 232; 3127 final int appId2 = 431; 3128 3129 final int userId1 = 42; 3130 final int userId2 = 53; 3131 3132 registerAppIds(packages, new Integer[]{appId1, appId2}); 3133 3134 when(mActivityManagerInternal.getStartedUserIds()).thenReturn(new int[]{userId1, userId2}); 3135 3136 when(mPermissionManagerInternal.getAppOpPermissionPackages( 3137 SCHEDULE_EXACT_ALARM)).thenReturn(packages); 3138 mService.refreshExactAlarmCandidates(); 3139 3140 mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId1, appId1), MODE_ALLOWED); 3141 mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId2, appId1), MODE_DEFAULT); 3142 mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId1, appId2), MODE_IGNORED); 3143 mService.mLastOpScheduleExactAlarm.put(UserHandle.getUid(userId2, appId2), MODE_ERRORED); 3144 3145 mService.handleChangesToExactAlarmDenyList(new ArraySet<>(packages), true); 3146 3147 // Permission got revoked only for (appId1, userId2) 3148 verify(mService, never()).removeExactAlarmsOnPermissionRevoked( 3149 eq(UserHandle.getUid(userId1, appId1)), eq(packages[0]), eq(true)); 3150 verify(mService, never()).removeExactAlarmsOnPermissionRevoked( 3151 eq(UserHandle.getUid(userId1, appId2)), eq(packages[1]), eq(true)); 3152 verify(mService, never()).removeExactAlarmsOnPermissionRevoked( 3153 eq(UserHandle.getUid(userId2, appId2)), eq(packages[1]), eq(true)); 3154 3155 verify(mService).removeExactAlarmsOnPermissionRevoked( 3156 eq(UserHandle.getUid(userId2, appId1)), eq(packages[0]), eq(true)); 3157 } 3158 3159 @Test 3160 public void opChangedPermissionRevoked() throws Exception { 3161 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 3162 3163 mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ALLOWED); 3164 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 3165 3166 mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE); 3167 assertAndHandleMessageSync(REMOVE_EXACT_ALARMS); 3168 verify(mService).removeExactAlarmsOnPermissionRevoked(TEST_CALLING_UID, 3169 TEST_CALLING_PACKAGE, true); 3170 } 3171 3172 @Test 3173 public void opChangedChangeDisabled() throws Exception { 3174 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false); 3175 3176 mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ALLOWED); 3177 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 3178 3179 mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE); 3180 3181 verify(mService.mHandler, never()).sendMessageAtTime( 3182 argThat(m -> m.what == REMOVE_EXACT_ALARMS), anyLong()); 3183 } 3184 3185 @Test 3186 public void opChangedNoPermissionChangeDueToDenyList() throws Exception { 3187 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false); 3188 3189 mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ERRORED); 3190 mockScheduleExactAlarmStatePreT(true, true, MODE_DEFAULT); 3191 3192 mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE); 3193 3194 verify(mService.mHandler, never()).sendMessageAtTime( 3195 argThat(m -> m.what == REMOVE_EXACT_ALARMS), anyLong()); 3196 } 3197 3198 @Test 3199 public void opChangedPermissionGranted() throws Exception { 3200 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 3201 3202 final long durationMs = 20000L; 3203 when(mActivityManagerInternal.getBootTimeTempAllowListDuration()).thenReturn(durationMs); 3204 3205 mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ERRORED); 3206 mockScheduleExactAlarmStatePreT(true, false, MODE_ALLOWED); 3207 mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE); 3208 3209 final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 3210 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 3211 3212 verify(mMockContext).sendBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.SYSTEM), 3213 isNull(), bundleCaptor.capture()); 3214 3215 // Validate the intent. 3216 assertEquals(AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED, 3217 intentCaptor.getValue().getAction()); 3218 assertEquals(TEST_CALLING_PACKAGE, intentCaptor.getValue().getPackage()); 3219 3220 // Validate the options. 3221 final BroadcastOptions bOptions = new BroadcastOptions(bundleCaptor.getValue()); 3222 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, 3223 bOptions.getTemporaryAppAllowlistType()); 3224 assertEquals(durationMs, bOptions.getTemporaryAppAllowlistDuration()); 3225 assertEquals(PowerExemptionManager.REASON_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED, 3226 bOptions.getTemporaryAppAllowlistReasonCode()); 3227 } 3228 3229 @Test 3230 public void removeExactAlarmsOnPermissionRevoked() { 3231 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 3232 3233 // basic exact alarm 3234 setTestAlarm(ELAPSED_REALTIME, 0, 0, getNewMockPendingIntent(), 0, 0, TEST_CALLING_UID, 3235 null); 3236 // exact and allow-while-idle alarm 3237 setTestAlarm(ELAPSED_REALTIME, 0, 0, getNewMockPendingIntent(), 0, FLAG_ALLOW_WHILE_IDLE, 3238 TEST_CALLING_UID, null); 3239 // alarm clock 3240 setWakeFromIdle(RTC_WAKEUP, 0, getNewMockPendingIntent()); 3241 3242 final PendingIntent inexact = getNewMockPendingIntent(); 3243 setTestAlarm(ELAPSED_REALTIME, 0, 10, inexact, 0, 0, TEST_CALLING_UID, null); 3244 3245 final PendingIntent inexactAwi = getNewMockPendingIntent(); 3246 setTestAlarm(ELAPSED_REALTIME, 0, 10, inexactAwi, 0, FLAG_ALLOW_WHILE_IDLE, 3247 TEST_CALLING_UID, null); 3248 3249 final PendingIntent exactButDifferentUid = getNewMockPendingIntent(); 3250 setTestAlarm(ELAPSED_REALTIME, 0, 0, exactButDifferentUid, 0, 0, TEST_CALLING_UID + 5, 3251 null); 3252 assertEquals(6, mService.mAlarmStore.size()); 3253 3254 mService.removeExactAlarmsOnPermissionRevoked(TEST_CALLING_UID, TEST_CALLING_PACKAGE, 3255 true); 3256 3257 final ArrayList<Alarm> remaining = mService.mAlarmStore.asList(); 3258 assertEquals(3, remaining.size()); 3259 assertTrue("Basic inexact alarm removed", 3260 remaining.removeIf(a -> a.matches(inexact, null))); 3261 assertTrue("Inexact allow-while-idle alarm removed", 3262 remaining.removeIf(a -> a.matches(inexactAwi, null))); 3263 assertTrue("Alarm from different uid removed", 3264 remaining.removeIf(a -> a.matches(exactButDifferentUid, null))); 3265 3266 // Mock should return false by default. 3267 verify(mDeviceIdleInternal, atLeastOnce()).isAppOnWhitelist( 3268 UserHandle.getAppId(TEST_CALLING_UID)); 3269 3270 verify(() -> PermissionManagerService.killUid(eq(TEST_CALLING_UID), eq(TEST_CALLING_USER), 3271 anyString())); 3272 } 3273 3274 private void optionsSentOnExpiration(boolean isActivity, Bundle idleOptions) 3275 throws Exception { 3276 final long triggerTime = mNowElapsedTest + 5000; 3277 final PendingIntent alarmPi = getNewMockPendingIntent(isActivity); 3278 setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, 0, alarmPi, 0, 0, TEST_CALLING_UID, 3279 idleOptions); 3280 3281 mNowElapsedTest = mTestTimer.getElapsed(); 3282 mTestTimer.expire(); 3283 3284 ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 3285 verify(alarmPi).send(eq(mMockContext), eq(0), any(Intent.class), 3286 any(), any(Handler.class), isNull(), bundleCaptor.capture()); 3287 if (idleOptions != null) { 3288 assertEquals(idleOptions, bundleCaptor.getValue()); 3289 } else { 3290 assertFalse("BAL flag needs to be false in alarm manager", 3291 bundleCaptor.getValue().getBoolean( 3292 ActivityOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, 3293 true)); 3294 } 3295 } 3296 3297 @Test 3298 public void activityIdleOptionsSentOnExpiration() throws Exception { 3299 final Bundle idleOptions = new Bundle(); 3300 idleOptions.putChar("TEST_CHAR_KEY", 'x'); 3301 idleOptions.putInt("TEST_INT_KEY", 53); 3302 optionsSentOnExpiration(true, idleOptions); 3303 } 3304 3305 @Test 3306 public void broadcastIdleOptionsSentOnExpiration() throws Exception { 3307 final Bundle idleOptions = new Bundle(); 3308 idleOptions.putChar("TEST_CHAR_KEY", 'x'); 3309 idleOptions.putInt("TEST_INT_KEY", 53); 3310 optionsSentOnExpiration(false, idleOptions); 3311 } 3312 3313 @Test 3314 public void emptyActivityOptionsSentOnExpiration() throws Exception { 3315 optionsSentOnExpiration(true, null); 3316 } 3317 3318 @Test 3319 public void emptyBroadcastOptionsSentOnExpiration() throws Exception { 3320 optionsSentOnExpiration(false, null); 3321 } 3322 3323 private void registerAppIds(String[] packages, Integer[] ids) { 3324 assertEquals(packages.length, ids.length); 3325 3326 when(mPackageManagerInternal.getPackageUid(anyString(), anyLong(), anyInt())).thenAnswer( 3327 invocation -> { 3328 final String pkg = invocation.getArgument(0); 3329 final int index = ArrayUtils.indexOf(packages, pkg); 3330 if (index < 0) { 3331 return index; 3332 } 3333 final int userId = invocation.getArgument(2); 3334 return UserHandle.getUid(userId, ids[index]); 3335 }); 3336 } 3337 3338 @Test 3339 public void onLastOpScheduleExactAlarmOnUserStart() { 3340 final int userId = 54; 3341 SystemService.TargetUser mockTargetUser = mock(SystemService.TargetUser.class); 3342 when(mockTargetUser.getUserIdentifier()).thenReturn(userId); 3343 3344 final Integer[] appIds = new Integer[]{43, 254, 7731}; 3345 final int unknownAppId = 2347; 3346 final String[] packageNames = new String[]{"p43", "p254", "p7731"}; 3347 final int[] appOpModes = new int[]{MODE_ALLOWED, MODE_IGNORED, MODE_ERRORED}; 3348 mService.mExactAlarmCandidates = new ArraySet<>(appIds); 3349 mService.mExactAlarmCandidates.add(unknownAppId); 3350 3351 for (int i = 0; i < appIds.length; i++) { 3352 final int uid = UserHandle.getUid(userId, appIds[i]); 3353 final AndroidPackage pkg = mock(AndroidPackage.class); 3354 when(pkg.getPackageName()).thenReturn(packageNames[i]); 3355 3356 when(mPackageManagerInternal.getPackage(uid)).thenReturn(pkg); 3357 when(mAppOpsManager.checkOpNoThrow(OP_SCHEDULE_EXACT_ALARM, uid, 3358 packageNames[i])).thenReturn(appOpModes[i]); 3359 } 3360 3361 final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); 3362 doReturn(true).when(mService.mHandler).post(runnableCaptor.capture()); 3363 3364 mService.onUserStarting(mockTargetUser); 3365 runnableCaptor.getValue().run(); 3366 3367 assertEquals(appIds.length, mService.mLastOpScheduleExactAlarm.size()); 3368 for (int i = 0; i < appIds.length; i++) { 3369 final int uid = UserHandle.getUid(userId, appIds[i]); 3370 assertEquals(appOpModes[i], mService.mLastOpScheduleExactAlarm.get(uid, -1)); 3371 } 3372 assertTrue(mService.mLastOpScheduleExactAlarm.indexOfKey( 3373 UserHandle.getUid(userId, unknownAppId)) < 0); 3374 } 3375 3376 @Test 3377 public void refreshExactAlarmCandidatesOnPackageAdded() { 3378 final String[] exactAlarmRequesters = new String[]{"p11", "p2", "p9"}; 3379 final Integer[] appIds = new Integer[]{11, 2, 9}; 3380 registerAppIds(exactAlarmRequesters, appIds); 3381 3382 when(mPermissionManagerInternal.getAppOpPermissionPackages( 3383 SCHEDULE_EXACT_ALARM)).thenReturn(exactAlarmRequesters); 3384 3385 final Intent packageAdded = new Intent(Intent.ACTION_PACKAGE_ADDED) 3386 .setPackage(TEST_CALLING_PACKAGE); 3387 mPackageChangesReceiver.onReceive(mMockContext, packageAdded); 3388 3389 assertAndHandleMessageSync(REFRESH_EXACT_ALARM_CANDIDATES); 3390 assertEquals(new ArraySet<>(appIds), mService.mExactAlarmCandidates); 3391 } 3392 3393 @Test 3394 public void refreshExactAlarmCandidatesOnPackageReplaced() { 3395 final String[] exactAlarmRequesters = new String[]{"p15", "p21", "p3"}; 3396 final Integer[] appIds = new Integer[]{15, 21, 3}; 3397 registerAppIds(exactAlarmRequesters, appIds); 3398 3399 when(mPermissionManagerInternal.getAppOpPermissionPackages( 3400 SCHEDULE_EXACT_ALARM)).thenReturn(exactAlarmRequesters); 3401 3402 final Intent packageAdded = new Intent(Intent.ACTION_PACKAGE_ADDED) 3403 .setData(Uri.fromParts("package", TEST_CALLING_PACKAGE, null)) 3404 .putExtra(Intent.EXTRA_REPLACING, true); 3405 mPackageChangesReceiver.onReceive(mMockContext, packageAdded); 3406 3407 assertAndHandleMessageSync(REFRESH_EXACT_ALARM_CANDIDATES); 3408 assertEquals(new ArraySet<>(appIds), mService.mExactAlarmCandidates); 3409 } 3410 3411 @Test 3412 public void refreshExactAlarmCandidatesOnPackageRemoved() { 3413 final String[] exactAlarmRequesters = new String[]{"p99", "p1", "p19"}; 3414 final Integer[] appIds = new Integer[]{99, 1, 19}; 3415 registerAppIds(exactAlarmRequesters, appIds); 3416 3417 when(mPermissionManagerInternal.getAppOpPermissionPackages( 3418 SCHEDULE_EXACT_ALARM)).thenReturn(exactAlarmRequesters); 3419 3420 final Intent packageRemoved = new Intent(Intent.ACTION_PACKAGE_REMOVED) 3421 .setPackage(TEST_CALLING_PACKAGE); 3422 mPackageChangesReceiver.onReceive(mMockContext, packageRemoved); 3423 3424 assertAndHandleMessageSync(REFRESH_EXACT_ALARM_CANDIDATES); 3425 assertEquals(new ArraySet<>(appIds), mService.mExactAlarmCandidates); 3426 } 3427 3428 @Test 3429 public void exactAlarmsRemovedIfNeededOnPackageReplaced() { 3430 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 3431 mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); 3432 3433 final int otherUid = 2313; 3434 final String otherPackage = "p1"; 3435 3436 final PendingIntent exactAlarm1 = getNewMockPendingIntent(); 3437 setTestAlarm(ELAPSED_REALTIME, 1, 0, exactAlarm1, 0, 0, TEST_CALLING_UID, 3438 TEST_CALLING_PACKAGE, null); 3439 3440 final PendingIntent exactAlarm2 = getNewMockPendingIntent(); 3441 setTestAlarm(ELAPSED_REALTIME, 2, 0, exactAlarm2, 0, 0, TEST_CALLING_UID, 3442 TEST_CALLING_PACKAGE, null); 3443 3444 final PendingIntent otherPackageExactAlarm = getNewMockPendingIntent(otherUid, 3445 otherPackage); 3446 setTestAlarm(ELAPSED_REALTIME, 0, 0, otherPackageExactAlarm, 0, 0, otherUid, otherPackage, 3447 null); 3448 3449 final PendingIntent inexactAlarm = getNewMockPendingIntent(); 3450 setTestAlarm(ELAPSED_REALTIME, 0, 23, inexactAlarm, 0, 0, TEST_CALLING_UID, 3451 TEST_CALLING_PACKAGE, null); 3452 3453 final PendingIntent otherPackageInexactAlarm = getNewMockPendingIntent(otherUid, 3454 otherPackage); 3455 setTestAlarm(ELAPSED_REALTIME, 0, 23, otherPackageInexactAlarm, 0, 0, otherUid, 3456 otherPackage, null); 3457 3458 assertEquals(5, mService.mAlarmStore.size()); 3459 3460 final Intent packageReplacedIntent = new Intent(Intent.ACTION_PACKAGE_ADDED) 3461 .setData(Uri.fromParts("package", TEST_CALLING_PACKAGE, null)) 3462 .putExtra(Intent.EXTRA_UID, TEST_CALLING_UID) 3463 .putExtra(Intent.EXTRA_REPLACING, true); 3464 3465 mockUseExactAlarmState(false); 3466 mockScheduleExactAlarmStatePreT(true, false, MODE_ALLOWED); 3467 mPackageChangesReceiver.onReceive(mMockContext, packageReplacedIntent); 3468 assertAndHandleMessageSync(CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE); 3469 3470 // user permission is granted, no alarms should be removed 3471 assertEquals(5, mService.mAlarmStore.size()); 3472 3473 mockUseExactAlarmState(true); 3474 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 3475 mPackageChangesReceiver.onReceive(mMockContext, packageReplacedIntent); 3476 assertAndHandleMessageSync(CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE); 3477 3478 // policy permission is granted, no alarms should be removed 3479 assertEquals(5, mService.mAlarmStore.size()); 3480 3481 mockUseExactAlarmState(false); 3482 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 3483 mPackageChangesReceiver.onReceive(mMockContext, packageReplacedIntent); 3484 assertAndHandleMessageSync(CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE); 3485 3486 // no permission is granted, exact alarms should be removed 3487 assertEquals(3, mService.mAlarmStore.size()); 3488 3489 List<Alarm> remaining = mService.mAlarmStore.asList(); 3490 assertTrue("Inexact alarm removed", remaining.removeIf(a -> a.matches(inexactAlarm, null))); 3491 3492 assertEquals(2, remaining.size()); 3493 assertTrue("Alarms from other package removed", 3494 remaining.removeIf(a -> a.matches(otherPackageExactAlarm, null) 3495 || a.matches(otherPackageInexactAlarm, null))); 3496 3497 assertEquals(0, remaining.size()); 3498 } 3499 3500 @Test 3501 public void alarmScheduledAtomPushed() { 3502 for (int i = 0; i < 10; i++) { 3503 final PendingIntent pi = getNewMockPendingIntent(); 3504 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i, pi); 3505 3506 verify(() -> MetricsHelper.pushAlarmScheduled(argThat(a -> a.matches(pi, null)), 3507 anyInt())); 3508 } 3509 } 3510 3511 @Test 3512 public void alarmBatchDeliveredAtomPushed() throws InterruptedException { 3513 for (int i = 0; i < 10; i++) { 3514 final int type = ((i & 1) == 0) ? ELAPSED_REALTIME : ELAPSED_REALTIME_WAKEUP; 3515 setTestAlarm(type, mNowElapsedTest + i, getNewMockPendingIntent()); 3516 } 3517 for (int i = 0; i < 4; i++) { 3518 final int type = ((i & 1) == 0) ? ELAPSED_REALTIME : ELAPSED_REALTIME_WAKEUP; 3519 setTestAlarm( 3520 type, 3521 mNowElapsedTest + i, 3522 getNewMockPendingIntent(), 3523 0, 3524 FLAG_STANDALONE, 3525 TEST_CALLING_UID_2); 3526 } 3527 mNowElapsedTest += 100; 3528 mTestTimer.expire(); 3529 3530 final ArgumentCaptor<int[]> uidsCaptor = ArgumentCaptor.forClass(int[].class); 3531 final ArgumentCaptor<int[]> alarmsPerUidCaptor = ArgumentCaptor.forClass(int[].class); 3532 final ArgumentCaptor<int[]> wakeupAlarmsPerUidCaptor = ArgumentCaptor.forClass(int[].class); 3533 3534 verify(() -> MetricsHelper.pushAlarmBatchDelivered( 3535 eq(14), 3536 eq(7), 3537 uidsCaptor.capture(), 3538 alarmsPerUidCaptor.capture(), 3539 wakeupAlarmsPerUidCaptor.capture())); 3540 assertEquals(2, uidsCaptor.getValue().length); 3541 assertEquals(2, alarmsPerUidCaptor.getValue().length); 3542 assertEquals(2, wakeupAlarmsPerUidCaptor.getValue().length); 3543 final int uid1Idx = uidsCaptor.getValue()[0] == TEST_CALLING_UID ? 0 : 1; 3544 final int uid2Idx = 1 - uid1Idx; 3545 assertEquals(TEST_CALLING_UID, uidsCaptor.getValue()[uid1Idx]); 3546 assertEquals(TEST_CALLING_UID_2, uidsCaptor.getValue()[uid2Idx]); 3547 assertEquals(10, alarmsPerUidCaptor.getValue()[uid1Idx]); 3548 assertEquals(5, wakeupAlarmsPerUidCaptor.getValue()[uid1Idx]); 3549 assertEquals(4, alarmsPerUidCaptor.getValue()[uid2Idx]); 3550 assertEquals(2, wakeupAlarmsPerUidCaptor.getValue()[uid2Idx]); 3551 } 3552 3553 @Test 3554 public void tareEventPushed_on() throws Exception { 3555 setTareEnabled(EconomyManager.ENABLED_MODE_ON); 3556 runTareEventPushed(); 3557 } 3558 3559 @Test 3560 public void tareEventPushed_shadow() throws Exception { 3561 setTareEnabled(EconomyManager.ENABLED_MODE_SHADOW); 3562 runTareEventPushed(); 3563 } 3564 3565 private void runTareEventPushed() throws Exception { 3566 for (int i = 0; i < 10; i++) { 3567 final int type = (i % 2 == 1) ? ELAPSED_REALTIME : ELAPSED_REALTIME_WAKEUP; 3568 setTestAlarm(type, mNowElapsedTest + i, getNewMockPendingIntent()); 3569 } 3570 3571 final ArrayList<Alarm> alarms = mService.mAlarmStore.remove((alarm) -> { 3572 return alarm.creatorUid == TEST_CALLING_UID; 3573 }); 3574 mService.deliverAlarmsLocked(alarms, mNowElapsedTest); 3575 verify(mEconomyManagerInternal, times(10)).noteInstantaneousEvent( 3576 eq(TEST_CALLING_USER), eq(TEST_CALLING_PACKAGE), anyInt(), any()); 3577 } 3578 3579 @Test 3580 public void setTimeZoneImpl() { 3581 final long durationMs = 20000L; 3582 when(mActivityManagerInternal.getBootTimeTempAllowListDuration()).thenReturn(durationMs); 3583 mService.setTimeZoneImpl("UTC", TIME_ZONE_CONFIDENCE_HIGH, "AlarmManagerServiceTest"); 3584 final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 3585 final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); 3586 verify(mMockContext).sendBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL), 3587 isNull(), bundleCaptor.capture()); 3588 assertEquals(Intent.ACTION_TIMEZONE_CHANGED, intentCaptor.getValue().getAction()); 3589 assertEquals("UTC", intentCaptor.getValue().getStringExtra(Intent.EXTRA_TIMEZONE)); 3590 final BroadcastOptions bOptions = new BroadcastOptions(bundleCaptor.getValue()); 3591 assertEquals(durationMs, bOptions.getTemporaryAppAllowlistDuration()); 3592 assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, 3593 bOptions.getTemporaryAppAllowlistType()); 3594 assertEquals(PowerExemptionManager.REASON_TIMEZONE_CHANGED, 3595 bOptions.getTemporaryAppAllowlistReasonCode()); 3596 } 3597 3598 @Test 3599 public void hasUseExactAlarmInternal() { 3600 mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true); 3601 3602 mockUseExactAlarmState(true); 3603 assertTrue(mService.hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3604 3605 mockUseExactAlarmState(false); 3606 assertFalse(mService.hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3607 } 3608 3609 @Test 3610 public void hasUseExactAlarmInternalChangeDisabled() { 3611 mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, false); 3612 3613 mockUseExactAlarmState(true); 3614 assertFalse(mService.hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3615 3616 mockUseExactAlarmState(false); 3617 assertFalse(mService.hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3618 } 3619 3620 @Test 3621 public void hasScheduleExactAlarmInternal() { 3622 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 3623 mockChangeEnabled(AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, true); 3624 3625 mockScheduleExactAlarmState(false); 3626 assertFalse(mService.hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3627 3628 mockScheduleExactAlarmState(true); 3629 assertTrue(mService.hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3630 } 3631 3632 @Test 3633 public void hasScheduleExactAlarmInternalPreT() { 3634 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true); 3635 mockChangeEnabled(AlarmManager.SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT, false); 3636 3637 mockScheduleExactAlarmStatePreT(true, true, MODE_DEFAULT); 3638 assertFalse(mService.hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3639 3640 mockScheduleExactAlarmStatePreT(false, false, MODE_ALLOWED); 3641 assertFalse(mService.hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3642 3643 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 3644 assertFalse(mService.hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3645 3646 mockScheduleExactAlarmStatePreT(true, false, MODE_ALLOWED); 3647 assertTrue(mService.hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3648 } 3649 3650 @Test 3651 public void hasScheduleExactAlarmInternalPreS() { 3652 mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false); 3653 3654 mockScheduleExactAlarmState(true); 3655 mockScheduleExactAlarmStatePreT(true, false, MODE_ALLOWED); 3656 assertFalse(mService.hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3657 3658 mockScheduleExactAlarmState(false); 3659 mockScheduleExactAlarmStatePreT(true, false, MODE_ERRORED); 3660 assertFalse(mService.hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3661 } 3662 3663 @Test 3664 public void temporaryQuotaReserve_hasQuota() { 3665 final int quotaToFill = 5; 3666 final String package1 = "package1"; 3667 final int user1 = 123; 3668 final long startTime = 54; 3669 final long quotaDuration = 17; 3670 3671 final AlarmManagerService.TemporaryQuotaReserve quotaReserve = 3672 new AlarmManagerService.TemporaryQuotaReserve(quotaDuration); 3673 quotaReserve.replenishQuota(package1, user1, quotaToFill, startTime); 3674 3675 for (long time = startTime; time <= startTime + quotaDuration; time++) { 3676 assertTrue(quotaReserve.hasQuota(package1, user1, time)); 3677 assertFalse(quotaReserve.hasQuota("some.other.package", 21, time)); 3678 assertFalse(quotaReserve.hasQuota(package1, 321, time)); 3679 } 3680 3681 assertFalse(quotaReserve.hasQuota(package1, user1, startTime + quotaDuration + 1)); 3682 assertFalse(quotaReserve.hasQuota(package1, user1, startTime + quotaDuration + 435421)); 3683 3684 for (int i = 0; i < quotaToFill - 1; i++) { 3685 assertTrue(i < quotaDuration); 3686 // Use record usage multiple times with the same timestamp. 3687 quotaReserve.recordUsage(package1, user1, startTime + i); 3688 quotaReserve.recordUsage(package1, user1, startTime + i); 3689 quotaReserve.recordUsage(package1, user1, startTime + i); 3690 quotaReserve.recordUsage(package1, user1, startTime + i); 3691 3692 // Quota should not run out in this loop. 3693 assertTrue(quotaReserve.hasQuota(package1, user1, startTime + i)); 3694 } 3695 quotaReserve.recordUsage(package1, user1, startTime + quotaDuration); 3696 3697 // Should be out of quota now. 3698 for (long time = startTime; time <= startTime + quotaDuration; time++) { 3699 assertFalse(quotaReserve.hasQuota(package1, user1, time)); 3700 } 3701 } 3702 3703 @Test 3704 public void temporaryQuotaReserve_removeForPackage() { 3705 final String[] packages = new String[]{"package1", "test.package2"}; 3706 final int userId = 472; 3707 final long startTime = 59; 3708 final long quotaDuration = 100; 3709 3710 final AlarmManagerService.TemporaryQuotaReserve quotaReserve = 3711 new AlarmManagerService.TemporaryQuotaReserve(quotaDuration); 3712 3713 quotaReserve.replenishQuota(packages[0], userId, 10, startTime); 3714 quotaReserve.replenishQuota(packages[1], userId, 10, startTime); 3715 3716 assertTrue(quotaReserve.hasQuota(packages[0], userId, startTime + 1)); 3717 assertTrue(quotaReserve.hasQuota(packages[1], userId, startTime + 1)); 3718 3719 quotaReserve.removeForPackage(packages[0], userId); 3720 3721 assertFalse(quotaReserve.hasQuota(packages[0], userId, startTime + 1)); 3722 assertTrue(quotaReserve.hasQuota(packages[1], userId, startTime + 1)); 3723 } 3724 3725 @Test 3726 public void temporaryQuotaReserve_removeForUser() { 3727 final String[] packagesUser1 = new String[]{"test1.package1", "test1.package2"}; 3728 final String[] packagesUser2 = new String[]{"test2.p1", "test2.p2", "test2.p3"}; 3729 final int user1 = 3201; 3730 final int user2 = 5409; 3731 final long startTime = 59; 3732 final long quotaDuration = 100; 3733 3734 final AlarmManagerService.TemporaryQuotaReserve quotaReserve = 3735 new AlarmManagerService.TemporaryQuotaReserve(quotaDuration); 3736 3737 for (String packageUser1 : packagesUser1) { 3738 quotaReserve.replenishQuota(packageUser1, user1, 10, startTime); 3739 } 3740 for (String packageUser2 : packagesUser2) { 3741 quotaReserve.replenishQuota(packageUser2, user2, 10, startTime); 3742 } 3743 3744 for (String packageUser1 : packagesUser1) { 3745 assertTrue(quotaReserve.hasQuota(packageUser1, user1, startTime)); 3746 } 3747 for (String packageUser2 : packagesUser2) { 3748 assertTrue(quotaReserve.hasQuota(packageUser2, user2, startTime)); 3749 } 3750 3751 quotaReserve.removeForUser(user2); 3752 3753 for (String packageUser1 : packagesUser1) { 3754 assertTrue(quotaReserve.hasQuota(packageUser1, user1, startTime)); 3755 } 3756 for (String packageUser2 : packagesUser2) { 3757 assertFalse(quotaReserve.hasQuota(packageUser2, user2, startTime)); 3758 } 3759 } 3760 3761 @Test 3762 public void triggerTemporaryQuotaBump_zeroQuota() { 3763 setDeviceConfigInt(KEY_TEMPORARY_QUOTA_BUMP, 0); 3764 3765 mAppStandbyListener.triggerTemporaryQuotaBump(TEST_CALLING_PACKAGE, TEST_CALLING_USER); 3766 verifyZeroInteractions(mPackageManagerInternal); 3767 verifyZeroInteractions(mService.mHandler); 3768 } 3769 3770 private void testTemporaryQuota_bumpedAfterDeferral(int standbyBucket) throws Exception { 3771 final int temporaryQuota = 31; 3772 setDeviceConfigInt(KEY_TEMPORARY_QUOTA_BUMP, temporaryQuota); 3773 3774 final int standbyQuota = mService.getQuotaForBucketLocked(standbyBucket); 3775 when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), 3776 anyLong())).thenReturn(standbyBucket); 3777 3778 final long firstTrigger = mNowElapsedTest + 10; 3779 for (int i = 0; i < standbyQuota + 1; i++) { 3780 setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent()); 3781 } 3782 3783 for (int i = 0; i < standbyQuota; i++) { 3784 mNowElapsedTest = mTestTimer.getElapsed(); 3785 assertEquals("Incorrect trigger time at i=" + i, firstTrigger + i, mNowElapsedTest); 3786 mTestTimer.expire(); 3787 } 3788 3789 // The last alarm should be deferred due to exceeding the quota 3790 final long deferredTrigger = firstTrigger + mAppStandbyWindow; 3791 assertEquals(deferredTrigger, mTestTimer.getElapsed()); 3792 3793 // Triggering temporary quota now. 3794 mAppStandbyListener.triggerTemporaryQuotaBump(TEST_CALLING_PACKAGE, TEST_CALLING_USER); 3795 assertAndHandleMessageSync(TEMPORARY_QUOTA_CHANGED); 3796 // The last alarm should now be rescheduled to go as per original expectations 3797 final long originalTrigger = firstTrigger + standbyQuota; 3798 assertEquals("Incorrect next alarm trigger", originalTrigger, mTestTimer.getElapsed()); 3799 } 3800 3801 3802 @Test 3803 public void temporaryQuota_bumpedAfterDeferral_active() throws Exception { 3804 testTemporaryQuota_bumpedAfterDeferral(STANDBY_BUCKET_ACTIVE); 3805 } 3806 3807 @Test 3808 public void temporaryQuota_bumpedAfterDeferral_working() throws Exception { 3809 testTemporaryQuota_bumpedAfterDeferral(STANDBY_BUCKET_WORKING_SET); 3810 } 3811 3812 @Test 3813 public void temporaryQuota_bumpedAfterDeferral_frequent() throws Exception { 3814 testTemporaryQuota_bumpedAfterDeferral(STANDBY_BUCKET_FREQUENT); 3815 } 3816 3817 @Test 3818 public void temporaryQuota_bumpedAfterDeferral_rare() throws Exception { 3819 testTemporaryQuota_bumpedAfterDeferral(STANDBY_BUCKET_RARE); 3820 } 3821 3822 private void testTemporaryQuota_bumpedBeforeDeferral(int standbyBucket) throws Exception { 3823 final int temporaryQuota = 7; 3824 setDeviceConfigInt(KEY_TEMPORARY_QUOTA_BUMP, temporaryQuota); 3825 3826 final int standbyQuota = mService.getQuotaForBucketLocked(standbyBucket); 3827 when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(), 3828 anyLong())).thenReturn(standbyBucket); 3829 3830 mAppStandbyListener.triggerTemporaryQuotaBump(TEST_CALLING_PACKAGE, TEST_CALLING_USER); 3831 // No need to handle message TEMPORARY_QUOTA_CHANGED, as the quota change doesn't need to 3832 // trigger a re-evaluation in this test. 3833 testQuotasDeferralOnExpiration(trigger -> setTestAlarm(ELAPSED_REALTIME_WAKEUP, trigger, 3834 getNewMockPendingIntent()), standbyQuota + temporaryQuota, mAppStandbyWindow); 3835 3836 // refresh the state. 3837 mService.removeLocked(TEST_CALLING_PACKAGE, REMOVE_REASON_UNDEFINED); 3838 mService.mAppWakeupHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); 3839 mService.mTemporaryQuotaReserve.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); 3840 3841 mAppStandbyListener.triggerTemporaryQuotaBump(TEST_CALLING_PACKAGE, TEST_CALLING_USER); 3842 testQuotasDeferralOnSet(trigger -> setTestAlarm(ELAPSED_REALTIME_WAKEUP, trigger, 3843 getNewMockPendingIntent()), standbyQuota + temporaryQuota, mAppStandbyWindow); 3844 3845 // refresh the state. 3846 mService.removeLocked(TEST_CALLING_PACKAGE, REMOVE_REASON_UNDEFINED); 3847 mService.mAppWakeupHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); 3848 mService.mTemporaryQuotaReserve.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER); 3849 3850 mAppStandbyListener.triggerTemporaryQuotaBump(TEST_CALLING_PACKAGE, TEST_CALLING_USER); 3851 testQuotasNoDeferral(trigger -> setTestAlarm(ELAPSED_REALTIME_WAKEUP, trigger, 3852 getNewMockPendingIntent()), standbyQuota + temporaryQuota, mAppStandbyWindow); 3853 } 3854 3855 @Test 3856 public void temporaryQuota_bumpedBeforeDeferral_active() throws Exception { 3857 testTemporaryQuota_bumpedBeforeDeferral(STANDBY_BUCKET_ACTIVE); 3858 } 3859 3860 @Test 3861 public void temporaryQuota_bumpedBeforeDeferral_working() throws Exception { 3862 testTemporaryQuota_bumpedBeforeDeferral(STANDBY_BUCKET_WORKING_SET); 3863 } 3864 3865 @Test 3866 public void temporaryQuota_bumpedBeforeDeferral_frequent() throws Exception { 3867 testTemporaryQuota_bumpedBeforeDeferral(STANDBY_BUCKET_FREQUENT); 3868 } 3869 3870 @Test 3871 public void temporaryQuota_bumpedBeforeDeferral_rare() throws Exception { 3872 testTemporaryQuota_bumpedBeforeDeferral(STANDBY_BUCKET_RARE); 3873 } 3874 3875 @Test 3876 public void exactListenerAlarmsRemovedOnCached() { 3877 mockChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, true); 3878 3879 setTestAlarmWithListener(ELAPSED_REALTIME, 31, getNewListener(() -> {}), WINDOW_EXACT, 3880 TEST_CALLING_UID); 3881 setTestAlarmWithListener(RTC, 42, getNewListener(() -> {}), 56, TEST_CALLING_UID); 3882 setTestAlarm(ELAPSED_REALTIME, 54, WINDOW_EXACT, getNewMockPendingIntent(), 0, 0, 3883 TEST_CALLING_UID, null); 3884 setTestAlarm(RTC, 49, 154, getNewMockPendingIntent(), 0, 0, TEST_CALLING_UID, null); 3885 3886 setTestAlarmWithListener(ELAPSED_REALTIME, 21, getNewListener(() -> {}), WINDOW_EXACT, 3887 TEST_CALLING_UID_2); 3888 setTestAlarmWithListener(RTC, 412, getNewListener(() -> {}), 561, TEST_CALLING_UID_2); 3889 setTestAlarm(ELAPSED_REALTIME, 26, WINDOW_EXACT, getNewMockPendingIntent(), 0, 0, 3890 TEST_CALLING_UID_2, null); 3891 setTestAlarm(RTC, 549, 234, getNewMockPendingIntent(), 0, 0, TEST_CALLING_UID_2, null); 3892 3893 assertEquals(8, mService.mAlarmStore.size()); 3894 3895 mListener.handleUidCachedChanged(TEST_CALLING_UID, true); 3896 assertAndHandleMessageSync(REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED); 3897 assertEquals(7, mService.mAlarmStore.size()); 3898 3899 mListener.handleUidCachedChanged(TEST_CALLING_UID_2, true); 3900 assertAndHandleMessageSync(REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED); 3901 assertEquals(6, mService.mAlarmStore.size()); 3902 } 3903 3904 @Test 3905 public void alarmCountOnListenerCached() { 3906 mockChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, true); 3907 3908 // Set some alarms for TEST_CALLING_UID. 3909 final int numExactListenerUid1 = 14; 3910 for (int i = 0; i < numExactListenerUid1; i++) { 3911 setTestAlarmWithListener(ALARM_TYPES[i % 4], mNowElapsedTest + i, 3912 getNewListener(() -> {})); 3913 } 3914 setTestAlarmWithListener(RTC, 42, getNewListener(() -> {}), 56, TEST_CALLING_UID); 3915 setTestAlarm(ELAPSED_REALTIME, 54, getNewMockPendingIntent()); 3916 setTestAlarm(RTC, 49, 154, getNewMockPendingIntent(), 0, 0, TEST_CALLING_UID, null); 3917 3918 // Set some alarms for TEST_CALLING_UID_2. 3919 final int numExactListenerUid2 = 9; 3920 for (int i = 0; i < numExactListenerUid2; i++) { 3921 setTestAlarmWithListener(ALARM_TYPES[i % 4], mNowElapsedTest + i, 3922 getNewListener(() -> {}), WINDOW_EXACT, TEST_CALLING_UID_2); 3923 } 3924 setTestAlarmWithListener(RTC, 412, getNewListener(() -> {}), 561, TEST_CALLING_UID_2); 3925 setTestAlarm(RTC_WAKEUP, 26, WINDOW_EXACT, getNewMockPendingIntent(), 0, 0, 3926 TEST_CALLING_UID_2, null); 3927 3928 assertEquals(numExactListenerUid1 + 3, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 3929 assertEquals(numExactListenerUid2 + 2, mService.mAlarmsPerUid.get(TEST_CALLING_UID_2)); 3930 3931 mListener.handleUidCachedChanged(TEST_CALLING_UID, true); 3932 assertAndHandleMessageSync(REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED); 3933 assertEquals(3, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); 3934 3935 mListener.handleUidCachedChanged(TEST_CALLING_UID_2, true); 3936 assertAndHandleMessageSync(REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED); 3937 assertEquals(2, mService.mAlarmsPerUid.get(TEST_CALLING_UID_2)); 3938 } 3939 3940 @Test 3941 public void lookForPackageLocked() throws Exception { 3942 final String package2 = "test.package.2"; 3943 final int uid2 = 359712; 3944 setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 10, getNewMockPendingIntent()); 3945 setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 15, 3946 getNewMockPendingIntent(uid2, package2)); 3947 3948 doReturn(true).when(mService).checkAllowNonWakeupDelayLocked(anyLong()); 3949 3950 assertTrue(mService.lookForPackageLocked(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3951 assertTrue(mService.lookForPackageLocked(package2, uid2)); 3952 3953 mNowElapsedTest += 10; // Advance time past the first alarm only. 3954 mTestTimer.expire(); 3955 3956 assertTrue(mService.lookForPackageLocked(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3957 assertTrue(mService.lookForPackageLocked(package2, uid2)); 3958 3959 // The non-wakeup alarm is sent on interactive state change: false -> true. 3960 mService.interactiveStateChangedLocked(false); 3961 mService.interactiveStateChangedLocked(true); 3962 3963 assertFalse(mService.lookForPackageLocked(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3964 assertTrue(mService.lookForPackageLocked(package2, uid2)); 3965 3966 mNowElapsedTest += 10; // Advance time past the second alarm. 3967 mTestTimer.expire(); 3968 3969 assertFalse(mService.lookForPackageLocked(TEST_CALLING_PACKAGE, TEST_CALLING_UID)); 3970 assertFalse(mService.lookForPackageLocked(package2, uid2)); 3971 } 3972 3973 @Test 3974 public void onQueryPackageRestart() { 3975 final String[] packages = {"p1", "p2", "p3"}; 3976 final int uid = 5421; 3977 final Intent packageAdded = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART) 3978 .setData(Uri.fromParts("package", packages[0], null)) 3979 .putExtra(Intent.EXTRA_PACKAGES, packages) 3980 .putExtra(Intent.EXTRA_UID, uid); 3981 mPackageChangesReceiver.onReceive(mMockContext, packageAdded); 3982 3983 for (String p : packages) { 3984 verify(mService).lookForPackageLocked(p, uid); 3985 } 3986 } 3987 } 3988