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