• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
17 
18 import static android.app.AlarmManager.ELAPSED_REALTIME;
19 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
20 import static android.app.AlarmManager.RTC;
21 import static android.app.AlarmManager.RTC_WAKEUP;
22 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
23 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
24 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
25 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
26 
27 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
28 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
29 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
30 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
31 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
32 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
33 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
34 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
35 import static com.android.server.AlarmManagerService.ACTIVE_INDEX;
36 import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
37 import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_PAROLE_CHANGED;
38 import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME;
39 import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME;
40 import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
41 import static com.android.server.AlarmManagerService.Constants.KEY_APP_STANDBY_QUOTAS_ENABLED;
42 import static com.android.server.AlarmManagerService.Constants.KEY_LISTENER_TIMEOUT;
43 import static com.android.server.AlarmManagerService.Constants.KEY_MAX_INTERVAL;
44 import static com.android.server.AlarmManagerService.Constants.KEY_MIN_FUTURITY;
45 import static com.android.server.AlarmManagerService.Constants.KEY_MIN_INTERVAL;
46 import static com.android.server.AlarmManagerService.IS_WAKEUP_MASK;
47 import static com.android.server.AlarmManagerService.TIME_CHANGED_MASK;
48 import static com.android.server.AlarmManagerService.WORKING_INDEX;
49 
50 import static org.junit.Assert.assertEquals;
51 import static org.junit.Assert.assertNotNull;
52 import static org.junit.Assert.assertNull;
53 import static org.mockito.ArgumentMatchers.any;
54 import static org.mockito.ArgumentMatchers.anyInt;
55 import static org.mockito.ArgumentMatchers.anyLong;
56 import static org.mockito.ArgumentMatchers.eq;
57 import static org.mockito.ArgumentMatchers.isNull;
58 import static org.mockito.Mockito.atLeastOnce;
59 
60 import android.app.ActivityManager;
61 import android.app.AlarmManager;
62 import android.app.IActivityManager;
63 import android.app.IAlarmCompleteListener;
64 import android.app.IAlarmListener;
65 import android.app.IUidObserver;
66 import android.app.PendingIntent;
67 import android.app.usage.UsageStatsManagerInternal;
68 import android.content.ContentResolver;
69 import android.content.Context;
70 import android.content.Intent;
71 import android.os.Handler;
72 import android.os.Looper;
73 import android.os.Message;
74 import android.os.PowerManager;
75 import android.os.RemoteException;
76 import android.os.UserHandle;
77 import android.platform.test.annotations.Presubmit;
78 import android.provider.Settings;
79 import android.util.Log;
80 import android.util.SparseArray;
81 
82 import androidx.test.filters.FlakyTest;
83 import androidx.test.runner.AndroidJUnit4;
84 
85 import com.android.internal.annotations.GuardedBy;
86 
87 import org.junit.After;
88 import org.junit.Before;
89 import org.junit.Test;
90 import org.junit.runner.RunWith;
91 import org.mockito.Answers;
92 import org.mockito.ArgumentCaptor;
93 import org.mockito.Mock;
94 import org.mockito.MockitoSession;
95 import org.mockito.quality.Strictness;
96 
97 import java.util.ArrayList;
98 
99 @Presubmit
100 @RunWith(AndroidJUnit4.class)
101 public class AlarmManagerServiceTest {
102     private static final String TAG = AlarmManagerServiceTest.class.getSimpleName();
103     private static final String TEST_CALLING_PACKAGE = "com.android.framework.test-package";
104     private static final int SYSTEM_UI_UID = 123456789;
105     private static final int TEST_CALLING_UID = 12345;
106 
107     private long mAppStandbyWindow;
108     private AlarmManagerService mService;
109     private UsageStatsManagerInternal.AppIdleStateChangeListener mAppStandbyListener;
110     @Mock
111     private ContentResolver mMockResolver;
112     @Mock
113     private Context mMockContext;
114     @Mock
115     private IActivityManager mIActivityManager;
116     @Mock
117     private UsageStatsManagerInternal mUsageStatsManagerInternal;
118     @Mock
119     private AppStateTracker mAppStateTracker;
120     @Mock
121     private AlarmManagerService.ClockReceiver mClockReceiver;
122     @Mock
123     private PowerManager.WakeLock mWakeLock;
124 
125     private MockitoSession mMockingSession;
126     private Injector mInjector;
127     private volatile long mNowElapsedTest;
128     private volatile long mNowRtcTest;
129     @GuardedBy("mTestTimer")
130     private TestTimer mTestTimer = new TestTimer();
131 
132     static class TestTimer {
133         private long mElapsed;
134         boolean mExpired;
135         private int mType;
136         private int mFlags; // Flags used to decide what needs to be evaluated.
137 
getElapsed()138         synchronized long getElapsed() {
139             return mElapsed;
140         }
141 
set(int type, long millisElapsed)142         synchronized void set(int type, long millisElapsed) {
143             mType = type;
144             mElapsed = millisElapsed;
145         }
146 
getType()147         synchronized int getType() {
148             return mType;
149         }
150 
getFlags()151         synchronized int getFlags() {
152             return mFlags;
153         }
154 
expire()155         synchronized void expire() throws InterruptedException {
156             expire(IS_WAKEUP_MASK); // Default: evaluate eligibility of all alarms
157         }
158 
expire(int flags)159         synchronized void expire(int flags) throws InterruptedException {
160             mFlags = flags;
161             mExpired = true;
162             notifyAll();
163             // Now wait for the alarm thread to finish execution.
164             wait();
165         }
166     }
167 
168     public class Injector extends AlarmManagerService.Injector {
169         boolean mIsAutomotiveOverride;
170 
Injector(Context context)171         Injector(Context context) {
172             super(context);
173         }
174 
175         @Override
init()176         void init() {
177             // Do nothing.
178         }
179 
180         @Override
waitForAlarm()181         int waitForAlarm() {
182             synchronized (mTestTimer) {
183                 mTestTimer.notifyAll();
184                 if (!mTestTimer.mExpired) {
185                     try {
186                         mTestTimer.wait();
187                     } catch (InterruptedException ie) {
188                         Log.e(TAG, "Wait interrupted!", ie);
189                         return 0;
190                     }
191                 }
192                 mTestTimer.mExpired = false;
193             }
194             return mTestTimer.getFlags();
195         }
196 
197         @Override
setKernelTimezone(int minutesWest)198         void setKernelTimezone(int minutesWest) {
199             // Do nothing.
200         }
201 
202         @Override
setAlarm(int type, long millis)203         void setAlarm(int type, long millis) {
204             mTestTimer.set(type, millis);
205         }
206 
207         @Override
setKernelTime(long millis)208         void setKernelTime(long millis) {
209         }
210 
211         @Override
getSystemUiUid()212         int getSystemUiUid() {
213             return SYSTEM_UI_UID;
214         }
215 
216         @Override
isAlarmDriverPresent()217         boolean isAlarmDriverPresent() {
218             // Pretend the driver is present, so code does not fall back to handler
219             return true;
220         }
221 
222         @Override
getElapsedRealtime()223         long getElapsedRealtime() {
224             return mNowElapsedTest;
225         }
226 
227         @Override
getCurrentTimeMillis()228         long getCurrentTimeMillis() {
229             return mNowRtcTest;
230         }
231 
232         @Override
getClockReceiver(AlarmManagerService service)233         AlarmManagerService.ClockReceiver getClockReceiver(AlarmManagerService service) {
234             return mClockReceiver;
235         }
236 
237         @Override
getAlarmWakeLock()238         PowerManager.WakeLock getAlarmWakeLock() {
239             return mWakeLock;
240         }
241     }
242 
243     @Before
setUp()244     public final void setUp() throws Exception {
245         mMockingSession = mockitoSession()
246                 .initMocks(this)
247                 .spyStatic(ActivityManager.class)
248                 .mockStatic(LocalServices.class)
249                 .spyStatic(Looper.class)
250                 .spyStatic(Settings.Global.class)
251                 .strictness(Strictness.WARN)
252                 .startMocking();
253         doReturn(mIActivityManager).when(ActivityManager::getService);
254         doReturn(mAppStateTracker).when(() -> LocalServices.getService(AppStateTracker.class));
255         doReturn(null)
256                 .when(() -> LocalServices.getService(DeviceIdleController.LocalService.class));
257         doReturn(mUsageStatsManagerInternal).when(
258                 () -> LocalServices.getService(UsageStatsManagerInternal.class));
259         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
260                 eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()))
261                 .thenReturn(STANDBY_BUCKET_ACTIVE);
262         doReturn(Looper.getMainLooper()).when(Looper::myLooper);
263 
264         when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
265         doReturn("min_futurity=0,min_interval=0").when(() ->
266                 Settings.Global.getString(mMockResolver, Settings.Global.ALARM_MANAGER_CONSTANTS));
267 
268         mInjector = new Injector(mMockContext);
269         mService = new AlarmManagerService(mMockContext, mInjector);
270         spyOn(mService);
271         doNothing().when(mService).publishBinderService(any(), any());
272 
273         mService.onStart();
274         spyOn(mService.mHandler);
275         // Stubbing the handler. Test should simulate any handling of messages synchronously.
276         doReturn(true).when(mService.mHandler).sendMessageAtTime(any(Message.class), anyLong());
277 
278         assertEquals(mService.mSystemUiUid, SYSTEM_UI_UID);
279         assertEquals(mService.mClockReceiver, mClockReceiver);
280         assertEquals(mService.mWakeLock, mWakeLock);
281         verify(mIActivityManager).registerUidObserver(any(IUidObserver.class), anyInt(), anyInt(),
282                 isNull());
283 
284         // Other boot phases don't matter
285         mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
286         assertEquals(0, mService.mConstants.MIN_FUTURITY);
287         assertEquals(0, mService.mConstants.MIN_INTERVAL);
288         mAppStandbyWindow = mService.mConstants.APP_STANDBY_WINDOW;
289         ArgumentCaptor<UsageStatsManagerInternal.AppIdleStateChangeListener> captor =
290                 ArgumentCaptor.forClass(UsageStatsManagerInternal.AppIdleStateChangeListener.class);
291         verify(mUsageStatsManagerInternal).addAppIdleStateChangeListener(captor.capture());
292         mAppStandbyListener = captor.getValue();
293     }
294 
setTestAlarm(int type, long triggerTime, PendingIntent operation)295     private void setTestAlarm(int type, long triggerTime, PendingIntent operation) {
296         setTestAlarm(type, triggerTime, operation, 0, TEST_CALLING_UID);
297     }
298 
setRepeatingTestAlarm(int type, long firstTrigger, long interval, PendingIntent pi)299     private void setRepeatingTestAlarm(int type, long firstTrigger, long interval,
300             PendingIntent pi) {
301         setTestAlarm(type, firstTrigger, pi, interval, TEST_CALLING_UID);
302     }
303 
setTestAlarm(int type, long triggerTime, PendingIntent operation, long interval, int callingUid)304     private void setTestAlarm(int type, long triggerTime, PendingIntent operation, long interval,
305             int callingUid) {
306         mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, interval,
307                 operation, null, "test", AlarmManager.FLAG_STANDALONE, null, null,
308                 callingUid, TEST_CALLING_PACKAGE);
309     }
310 
setTestAlarmWithListener(int type, long triggerTime, IAlarmListener listener)311     private void setTestAlarmWithListener(int type, long triggerTime, IAlarmListener listener) {
312         mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, 0,
313                 null, listener, "test", AlarmManager.FLAG_STANDALONE, null, null,
314                 TEST_CALLING_UID, TEST_CALLING_PACKAGE);
315     }
316 
317 
getNewMockPendingIntent()318     private PendingIntent getNewMockPendingIntent() {
319         return getNewMockPendingIntent(TEST_CALLING_UID);
320     }
321 
getNewMockPendingIntent(int mockUid)322     private PendingIntent getNewMockPendingIntent(int mockUid) {
323         final PendingIntent mockPi = mock(PendingIntent.class, Answers.RETURNS_DEEP_STUBS);
324         when(mockPi.getCreatorUid()).thenReturn(mockUid);
325         when(mockPi.getCreatorPackage()).thenReturn(TEST_CALLING_PACKAGE);
326         return mockPi;
327     }
328 
329     /**
330      * Careful while calling as this will replace any existing settings for the calling test.
331      */
setQuotasEnabled(boolean enabled)332     private void setQuotasEnabled(boolean enabled) {
333         final StringBuilder constantsBuilder = new StringBuilder();
334         constantsBuilder.append(KEY_MIN_FUTURITY);
335         constantsBuilder.append("=0,");
336         // Capping active and working quotas to make testing feasible.
337         constantsBuilder.append(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX]);
338         constantsBuilder.append("=8,");
339         constantsBuilder.append(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_INDEX]);
340         constantsBuilder.append("=5,");
341         if (!enabled) {
342             constantsBuilder.append(KEY_APP_STANDBY_QUOTAS_ENABLED);
343             constantsBuilder.append("=false,");
344         }
345         doReturn(constantsBuilder.toString()).when(() -> Settings.Global.getString(mMockResolver,
346                 Settings.Global.ALARM_MANAGER_CONSTANTS));
347         mService.mConstants.onChange(false, null);
348         assertEquals(mService.mConstants.APP_STANDBY_QUOTAS_ENABLED, enabled);
349     }
350 
351     @Test
singleElapsedAlarmSet()352     public void singleElapsedAlarmSet() {
353         final long triggerTime = mNowElapsedTest + 5000;
354         final PendingIntent alarmPi = getNewMockPendingIntent();
355         setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, alarmPi);
356         assertEquals(triggerTime, mTestTimer.getElapsed());
357     }
358 
359     @Test
singleRtcAlarmSet()360     public void singleRtcAlarmSet() {
361         mNowElapsedTest = 54;
362         mNowRtcTest = 1243;     // arbitrary values of time
363         final long triggerRtc = mNowRtcTest + 5000;
364         final PendingIntent alarmPi = getNewMockPendingIntent();
365         setTestAlarm(RTC_WAKEUP, triggerRtc, alarmPi);
366         final long triggerElapsed = triggerRtc - (mNowRtcTest - mNowElapsedTest);
367         assertEquals(triggerElapsed, mTestTimer.getElapsed());
368     }
369 
370     @Test
timeChangeMovesRtcAlarm()371     public void timeChangeMovesRtcAlarm() throws Exception {
372         mNowElapsedTest = 42;
373         mNowRtcTest = 4123;     // arbitrary values of time
374         final long triggerRtc = mNowRtcTest + 5000;
375         final PendingIntent alarmPi = getNewMockPendingIntent();
376         setTestAlarm(RTC_WAKEUP, triggerRtc, alarmPi);
377         final long triggerElapsed1 = mTestTimer.getElapsed();
378         final long timeDelta = -123;
379         mNowRtcTest += timeDelta;
380         mTestTimer.expire(TIME_CHANGED_MASK);
381         final long triggerElapsed2 = mTestTimer.getElapsed();
382         assertEquals("Invalid movement of triggerElapsed following time change", triggerElapsed2,
383                 triggerElapsed1 - timeDelta);
384     }
385 
386     @Test
testSingleAlarmExpiration()387     public void testSingleAlarmExpiration() throws Exception {
388         final long triggerTime = mNowElapsedTest + 5000;
389         final PendingIntent alarmPi = getNewMockPendingIntent();
390         setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, alarmPi);
391 
392         mNowElapsedTest = mTestTimer.getElapsed();
393         mTestTimer.expire();
394 
395         final ArgumentCaptor<PendingIntent.OnFinished> onFinishedCaptor =
396                 ArgumentCaptor.forClass(PendingIntent.OnFinished.class);
397         verify(alarmPi).send(eq(mMockContext), eq(0), any(Intent.class),
398                 onFinishedCaptor.capture(), any(Handler.class), isNull(), any());
399         verify(mWakeLock).acquire();
400         onFinishedCaptor.getValue().onSendFinished(alarmPi, null, 0, null, null);
401         verify(mWakeLock).release();
402     }
403 
404     @Test
testUpdateConstants()405     public void testUpdateConstants() {
406         final StringBuilder constantsBuilder = new StringBuilder();
407         constantsBuilder.append(KEY_MIN_FUTURITY);
408         constantsBuilder.append("=5,");
409         constantsBuilder.append(KEY_MIN_INTERVAL);
410         constantsBuilder.append("=10,");
411         constantsBuilder.append(KEY_MAX_INTERVAL);
412         constantsBuilder.append("=15,");
413         constantsBuilder.append(KEY_ALLOW_WHILE_IDLE_SHORT_TIME);
414         constantsBuilder.append("=20,");
415         constantsBuilder.append(KEY_ALLOW_WHILE_IDLE_LONG_TIME);
416         constantsBuilder.append("=25,");
417         constantsBuilder.append(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
418         constantsBuilder.append("=30,");
419         constantsBuilder.append(KEY_LISTENER_TIMEOUT);
420         constantsBuilder.append("=35,");
421 
422         doReturn(constantsBuilder.toString()).when(() -> Settings.Global.getString(mMockResolver,
423                 Settings.Global.ALARM_MANAGER_CONSTANTS));
424         mService.mConstants.onChange(false, null);
425         assertEquals(5, mService.mConstants.MIN_FUTURITY);
426         assertEquals(10, mService.mConstants.MIN_INTERVAL);
427         assertEquals(15, mService.mConstants.MAX_INTERVAL);
428         assertEquals(20, mService.mConstants.ALLOW_WHILE_IDLE_SHORT_TIME);
429         assertEquals(25, mService.mConstants.ALLOW_WHILE_IDLE_LONG_TIME);
430         assertEquals(30, mService.mConstants.ALLOW_WHILE_IDLE_WHITELIST_DURATION);
431         assertEquals(35, mService.mConstants.LISTENER_TIMEOUT);
432     }
433 
434     @Test
testMinFuturity()435     public void testMinFuturity() {
436         doReturn("min_futurity=10").when(() ->
437                 Settings.Global.getString(mMockResolver, Settings.Global.ALARM_MANAGER_CONSTANTS));
438         mService.mConstants.onChange(false, null);
439         assertEquals(10, mService.mConstants.MIN_FUTURITY);
440         final long triggerTime = mNowElapsedTest + 1;
441         final long expectedTriggerTime = mNowElapsedTest + mService.mConstants.MIN_FUTURITY;
442         setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, getNewMockPendingIntent());
443         assertEquals(expectedTriggerTime, mTestTimer.getElapsed());
444     }
445 
446     @FlakyTest(bugId = 130313408)
447     @Test
testEarliestAlarmSet()448     public void testEarliestAlarmSet() {
449         final PendingIntent pi6 = getNewMockPendingIntent();
450         final PendingIntent pi8 = getNewMockPendingIntent();
451         final PendingIntent pi9 = getNewMockPendingIntent();
452 
453         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 8, pi8);
454         assertEquals(mNowElapsedTest + 8, mTestTimer.getElapsed());
455 
456         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 9, pi9);
457         assertEquals(mNowElapsedTest + 8, mTestTimer.getElapsed());
458 
459         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, pi6);
460         assertEquals(mNowElapsedTest + 6, mTestTimer.getElapsed());
461 
462         mService.removeLocked(pi6, null);
463         assertEquals(mNowElapsedTest + 8, mTestTimer.getElapsed());
464 
465         mService.removeLocked(pi8, null);
466         assertEquals(mNowElapsedTest + 9, mTestTimer.getElapsed());
467     }
468 
469     @Test
testStandbyBucketDelay_workingSet()470     public void testStandbyBucketDelay_workingSet() throws Exception {
471         setQuotasEnabled(false);
472         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent());
473         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent());
474         assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed());
475 
476         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
477                 anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET);
478 
479         mNowElapsedTest = mTestTimer.getElapsed();
480         mTestTimer.expire();
481 
482         verify(mUsageStatsManagerInternal, atLeastOnce())
483                 .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
484                         eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong());
485         final long expectedNextTrigger = mNowElapsedTest
486                 + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_WORKING_SET);
487         assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed());
488     }
489 
490     @Test
testStandbyBucketDelay_frequent()491     public void testStandbyBucketDelay_frequent() throws Exception {
492         setQuotasEnabled(false);
493         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent());
494         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent());
495         assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed());
496 
497         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
498                 anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT);
499         mNowElapsedTest = mTestTimer.getElapsed();
500         mTestTimer.expire();
501 
502         verify(mUsageStatsManagerInternal, atLeastOnce())
503                 .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
504                         eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong());
505         final long expectedNextTrigger = mNowElapsedTest
506                 + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_FREQUENT);
507         assertEquals("Incorrect next alarm trigger.", expectedNextTrigger, mTestTimer.getElapsed());
508     }
509 
510     @Test
testStandbyBucketDelay_rare()511     public void testStandbyBucketDelay_rare() throws Exception {
512         setQuotasEnabled(false);
513         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent());
514         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent());
515         assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed());
516 
517         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
518                 anyLong())).thenReturn(STANDBY_BUCKET_RARE);
519         mNowElapsedTest = mTestTimer.getElapsed();
520         mTestTimer.expire();
521 
522         verify(mUsageStatsManagerInternal, atLeastOnce())
523                 .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
524                         eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong());
525         final long expectedNextTrigger = mNowElapsedTest
526                 + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_RARE);
527         assertEquals("Incorrect next alarm trigger.", expectedNextTrigger, mTestTimer.getElapsed());
528     }
529 
testQuotasDeferralOnSet(int standbyBucket)530     private void testQuotasDeferralOnSet(int standbyBucket) throws Exception {
531         final int quota = mService.getQuotaForBucketLocked(standbyBucket);
532         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
533                 anyLong())).thenReturn(standbyBucket);
534         final long firstTrigger = mNowElapsedTest + 10;
535         for (int i = 0; i < quota; i++) {
536             setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 10 + i,
537                     getNewMockPendingIntent());
538             mNowElapsedTest = mTestTimer.getElapsed();
539             mTestTimer.expire();
540         }
541         // This one should get deferred on set
542         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + quota + 10,
543                 getNewMockPendingIntent());
544         final long expectedNextTrigger = firstTrigger + 1 + mAppStandbyWindow;
545         assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed());
546     }
547 
testQuotasDeferralOnExpiration(int standbyBucket)548     private void testQuotasDeferralOnExpiration(int standbyBucket) throws Exception {
549         final int quota = mService.getQuotaForBucketLocked(standbyBucket);
550         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
551                 anyLong())).thenReturn(standbyBucket);
552         final long firstTrigger = mNowElapsedTest + 10;
553         for (int i = 0; i < quota; i++) {
554             setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 10 + i,
555                     getNewMockPendingIntent());
556         }
557         // This one should get deferred after the latest alarm expires
558         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + quota + 10,
559                 getNewMockPendingIntent());
560         for (int i = 0; i < quota; i++) {
561             mNowElapsedTest = mTestTimer.getElapsed();
562             mTestTimer.expire();
563         }
564         final long expectedNextTrigger = firstTrigger + 1 + mAppStandbyWindow;
565         assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed());
566     }
567 
testQuotasNoDeferral(int standbyBucket)568     private void testQuotasNoDeferral(int standbyBucket) throws Exception {
569         final int quota = mService.getQuotaForBucketLocked(standbyBucket);
570         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
571                 anyLong())).thenReturn(standbyBucket);
572         final long firstTrigger = mNowElapsedTest + 10;
573         for (int i = 0; i < quota; i++) {
574             setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 10 + i,
575                     getNewMockPendingIntent());
576         }
577         // This delivery time maintains the quota invariant. Should not be deferred.
578         final long expectedNextTrigger = firstTrigger + mAppStandbyWindow + 5;
579         setTestAlarm(ELAPSED_REALTIME_WAKEUP, expectedNextTrigger, getNewMockPendingIntent());
580         for (int i = 0; i < quota; i++) {
581             mNowElapsedTest = mTestTimer.getElapsed();
582             mTestTimer.expire();
583         }
584         assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed());
585     }
586 
587     @Test
testActiveQuota_deferredOnSet()588     public void testActiveQuota_deferredOnSet() throws Exception {
589         setQuotasEnabled(true);
590         testQuotasDeferralOnSet(STANDBY_BUCKET_ACTIVE);
591     }
592 
593     @Test
testActiveQuota_deferredOnExpiration()594     public void testActiveQuota_deferredOnExpiration() throws Exception {
595         setQuotasEnabled(true);
596         testQuotasDeferralOnExpiration(STANDBY_BUCKET_ACTIVE);
597     }
598 
599     @Test
testActiveQuota_notDeferred()600     public void testActiveQuota_notDeferred() throws Exception {
601         setQuotasEnabled(true);
602         testQuotasNoDeferral(STANDBY_BUCKET_ACTIVE);
603     }
604 
605     @Test
testWorkingQuota_deferredOnSet()606     public void testWorkingQuota_deferredOnSet() throws Exception {
607         setQuotasEnabled(true);
608         testQuotasDeferralOnSet(STANDBY_BUCKET_WORKING_SET);
609     }
610 
611     @Test
testWorkingQuota_deferredOnExpiration()612     public void testWorkingQuota_deferredOnExpiration() throws Exception {
613         setQuotasEnabled(true);
614         testQuotasDeferralOnExpiration(STANDBY_BUCKET_WORKING_SET);
615     }
616 
617     @Test
testWorkingQuota_notDeferred()618     public void testWorkingQuota_notDeferred() throws Exception {
619         setQuotasEnabled(true);
620         testQuotasNoDeferral(STANDBY_BUCKET_WORKING_SET);
621     }
622 
623     @Test
testFrequentQuota_deferredOnSet()624     public void testFrequentQuota_deferredOnSet() throws Exception {
625         setQuotasEnabled(true);
626         testQuotasDeferralOnSet(STANDBY_BUCKET_FREQUENT);
627     }
628 
629     @Test
testFrequentQuota_deferredOnExpiration()630     public void testFrequentQuota_deferredOnExpiration() throws Exception {
631         setQuotasEnabled(true);
632         testQuotasDeferralOnExpiration(STANDBY_BUCKET_FREQUENT);
633     }
634 
635     @Test
testFrequentQuota_notDeferred()636     public void testFrequentQuota_notDeferred() throws Exception {
637         setQuotasEnabled(true);
638         testQuotasNoDeferral(STANDBY_BUCKET_FREQUENT);
639     }
640 
641     @Test
testRareQuota_deferredOnSet()642     public void testRareQuota_deferredOnSet() throws Exception {
643         setQuotasEnabled(true);
644         testQuotasDeferralOnSet(STANDBY_BUCKET_RARE);
645     }
646 
647     @Test
testRareQuota_deferredOnExpiration()648     public void testRareQuota_deferredOnExpiration() throws Exception {
649         setQuotasEnabled(true);
650         testQuotasDeferralOnExpiration(STANDBY_BUCKET_RARE);
651     }
652 
653     @Test
testRareQuota_notDeferred()654     public void testRareQuota_notDeferred() throws Exception {
655         setQuotasEnabled(true);
656         testQuotasNoDeferral(STANDBY_BUCKET_RARE);
657     }
658 
assertAndHandleBucketChanged(int bucket)659     private void assertAndHandleBucketChanged(int bucket) {
660         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
661                 anyLong())).thenReturn(bucket);
662         mAppStandbyListener.onAppIdleStateChanged(TEST_CALLING_PACKAGE,
663                 UserHandle.getUserId(TEST_CALLING_UID), false, bucket, 0);
664         final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
665         verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture());
666         final Message lastMessage = messageCaptor.getValue();
667         assertEquals("Unexpected message send to handler", lastMessage.what,
668                 APP_STANDBY_BUCKET_CHANGED);
669         mService.mHandler.handleMessage(lastMessage);
670     }
671 
672     @Test
testQuotaDowngrade()673     public void testQuotaDowngrade() throws Exception {
674         setQuotasEnabled(true);
675         final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET);
676         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
677                 anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET);
678 
679         final long firstTrigger = mNowElapsedTest + 10;
680         for (int i = 0; i < workingQuota; i++) {
681             setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent());
682         }
683         // No deferrals now.
684         for (int i = 0; i < workingQuota - 1; i++) {
685             mNowElapsedTest = mTestTimer.getElapsed();
686             assertEquals(firstTrigger + i, mNowElapsedTest);
687             mTestTimer.expire();
688         }
689         // The next upcoming alarm in queue should also be set as expected.
690         assertEquals(firstTrigger + workingQuota - 1, mTestTimer.getElapsed());
691         // Downgrading the bucket now
692         assertAndHandleBucketChanged(STANDBY_BUCKET_RARE);
693         final int rareQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_RARE);
694         // The last alarm should now be deferred.
695         final long expectedNextTrigger = (firstTrigger + workingQuota - 1 - rareQuota)
696                 + mAppStandbyWindow + 1;
697         assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed());
698     }
699 
700     @Test
testQuotaUpgrade()701     public void testQuotaUpgrade() throws Exception {
702         setQuotasEnabled(true);
703         final int frequentQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_FREQUENT);
704         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
705                 anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT);
706 
707         final long firstTrigger = mNowElapsedTest + 10;
708         for (int i = 0; i < frequentQuota + 1; i++) {
709             setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent());
710             if (i < frequentQuota) {
711                 mNowElapsedTest = mTestTimer.getElapsed();
712                 mTestTimer.expire();
713             }
714         }
715         // The last alarm should be deferred due to exceeding the quota
716         final long deferredTrigger = firstTrigger + 1 + mAppStandbyWindow;
717         assertEquals(deferredTrigger, mTestTimer.getElapsed());
718 
719         // Upgrading the bucket now
720         assertAndHandleBucketChanged(STANDBY_BUCKET_ACTIVE);
721         // The last alarm should now be rescheduled to go as per original expectations
722         final long originalTrigger = firstTrigger + frequentQuota;
723         assertEquals("Incorrect next alarm trigger", originalTrigger, mTestTimer.getElapsed());
724     }
725 
assertAndHandleParoleChanged(boolean parole)726     private void assertAndHandleParoleChanged(boolean parole) {
727         mAppStandbyListener.onParoleStateChanged(parole);
728         final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
729         verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture());
730         final Message lastMessage = messageCaptor.getValue();
731         assertEquals("Unexpected message send to handler", lastMessage.what,
732                 APP_STANDBY_PAROLE_CHANGED);
733         mService.mHandler.handleMessage(lastMessage);
734     }
735 
736     @Test
testParole()737     public void testParole() throws Exception {
738         setQuotasEnabled(true);
739         final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET);
740         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
741                 anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET);
742 
743         final long firstTrigger = mNowElapsedTest + 10;
744         final int totalAlarms = workingQuota + 10;
745         for (int i = 0; i < totalAlarms; i++) {
746             setTestAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i, getNewMockPendingIntent());
747         }
748         // Use up the quota, no deferrals expected.
749         for (int i = 0; i < workingQuota; i++) {
750             mNowElapsedTest = mTestTimer.getElapsed();
751             assertEquals(firstTrigger + i, mNowElapsedTest);
752             mTestTimer.expire();
753         }
754         // Any subsequent alarms in queue should all be deferred
755         assertEquals(firstTrigger + mAppStandbyWindow + 1, mTestTimer.getElapsed());
756         // Paroling now
757         assertAndHandleParoleChanged(true);
758 
759         // Subsequent alarms should now go off as per original expectations.
760         for (int i = 0; i < 5; i++) {
761             mNowElapsedTest = mTestTimer.getElapsed();
762             assertEquals(firstTrigger + workingQuota + i, mNowElapsedTest);
763             mTestTimer.expire();
764         }
765         // Come out of parole
766         assertAndHandleParoleChanged(false);
767 
768         // Subsequent alarms should again get deferred
769         final long expectedNextTrigger = (firstTrigger + 5) + 1 + mAppStandbyWindow;
770         assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed());
771     }
772 
773     @Test
testAlarmRestrictedInBatterSaver()774     public void testAlarmRestrictedInBatterSaver() throws Exception {
775         final ArgumentCaptor<AppStateTracker.Listener> listenerArgumentCaptor =
776                 ArgumentCaptor.forClass(AppStateTracker.Listener.class);
777         verify(mAppStateTracker).addListener(listenerArgumentCaptor.capture());
778 
779         final PendingIntent alarmPi = getNewMockPendingIntent();
780         when(mAppStateTracker.areAlarmsRestricted(TEST_CALLING_UID, TEST_CALLING_PACKAGE,
781                 false)).thenReturn(true);
782         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2, alarmPi);
783         assertEquals(mNowElapsedTest + 2, mTestTimer.getElapsed());
784 
785         final SparseArray<ArrayList<AlarmManagerService.Alarm>> restrictedAlarms =
786                 mService.mPendingBackgroundAlarms;
787         assertNull(restrictedAlarms.get(TEST_CALLING_UID));
788 
789         mNowElapsedTest = mTestTimer.getElapsed();
790         mTestTimer.expire();
791         assertNotNull(restrictedAlarms.get(TEST_CALLING_UID));
792 
793         listenerArgumentCaptor.getValue().unblockAlarmsForUid(TEST_CALLING_UID);
794         verify(alarmPi).send(eq(mMockContext), eq(0), any(Intent.class), any(),
795                 any(Handler.class), isNull(), any());
796         assertNull(restrictedAlarms.get(TEST_CALLING_UID));
797     }
798 
799     @Test
sendsTimeTickOnInteractive()800     public void sendsTimeTickOnInteractive() {
801         final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
802         // Stubbing so the handler doesn't actually run the runnable.
803         doReturn(true).when(mService.mHandler).post(runnableCaptor.capture());
804         // change interactive state: false -> true
805         mService.interactiveStateChangedLocked(false);
806         mService.interactiveStateChangedLocked(true);
807         runnableCaptor.getValue().run();
808         verify(mMockContext).sendBroadcastAsUser(mService.mTimeTickIntent, UserHandle.ALL);
809     }
810 
811     @Test
alarmCountKeyedOnCallingUid()812     public void alarmCountKeyedOnCallingUid() {
813         final int mockCreatorUid = 431412;
814         setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 5,
815                 getNewMockPendingIntent(mockCreatorUid));
816         assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
817         assertEquals(-1, mService.mAlarmsPerUid.get(mockCreatorUid, -1));
818     }
819 
820     @Test
alarmCountOnSetPi()821     public void alarmCountOnSetPi() {
822         final int numAlarms = 103;
823         final int[] types = {RTC_WAKEUP, RTC, ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME};
824         for (int i = 1; i <= numAlarms; i++) {
825             setTestAlarm(types[i % 4], mNowElapsedTest + i, getNewMockPendingIntent());
826             assertEquals(i, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
827         }
828     }
829 
830     @Test
alarmCountOnSetListener()831     public void alarmCountOnSetListener() {
832         final int numAlarms = 103;
833         final int[] types = {RTC_WAKEUP, RTC, ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME};
834         for (int i = 1; i <= numAlarms; i++) {
835             setTestAlarmWithListener(types[i % 4], mNowElapsedTest + i, new IAlarmListener.Stub() {
836                 @Override
837                 public void doAlarm(IAlarmCompleteListener callback) throws RemoteException {
838                 }
839             });
840             assertEquals(i, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
841         }
842     }
843 
844     @Test
alarmCountOnExpirationPi()845     public void alarmCountOnExpirationPi() throws InterruptedException {
846         final int numAlarms = 8; // This test is slow
847         for (int i = 0; i < numAlarms; i++) {
848             setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, getNewMockPendingIntent());
849         }
850         int expired = 0;
851         while (expired < numAlarms) {
852             mNowElapsedTest = mTestTimer.getElapsed();
853             mTestTimer.expire();
854             expired++;
855             assertEquals(numAlarms - expired, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
856         }
857     }
858 
859     @Test
alarmCountOnExpirationListener()860     public void alarmCountOnExpirationListener() throws InterruptedException {
861         final int numAlarms = 8; // This test is slow
862         for (int i = 0; i < numAlarms; i++) {
863             setTestAlarmWithListener(ELAPSED_REALTIME, mNowElapsedTest + i + 10,
864                     new IAlarmListener.Stub() {
865                         @Override
866                         public void doAlarm(IAlarmCompleteListener callback)
867                                 throws RemoteException {
868                         }
869                     });
870         }
871         int expired = 0;
872         while (expired < numAlarms) {
873             mNowElapsedTest = mTestTimer.getElapsed();
874             mTestTimer.expire();
875             expired++;
876             assertEquals(numAlarms - expired, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
877         }
878     }
879 
880     @Test
alarmCountOnExceptionWhileSendingPi()881     public void alarmCountOnExceptionWhileSendingPi() throws Exception {
882         final int numAlarms = 5; // This test is slow
883         for (int i = 0; i < numAlarms; i++) {
884             final PendingIntent pi = getNewMockPendingIntent();
885             doThrow(PendingIntent.CanceledException.class).when(pi).send(eq(mMockContext), eq(0),
886                     any(), any(), any(), any(), any());
887             setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, pi);
888         }
889         int expired = 0;
890         while (expired < numAlarms) {
891             mNowElapsedTest = mTestTimer.getElapsed();
892             mTestTimer.expire();
893             expired++;
894             assertEquals(numAlarms - expired, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
895         }
896     }
897 
898     @Test
alarmCountOnExceptionWhileCallingListener()899     public void alarmCountOnExceptionWhileCallingListener() throws Exception {
900         final int numAlarms = 5; // This test is slow
901         for (int i = 0; i < numAlarms; i++) {
902             final IAlarmListener listener = new IAlarmListener.Stub() {
903                 @Override
904                 public void doAlarm(IAlarmCompleteListener callback) throws RemoteException {
905                     throw new RemoteException("For testing behavior on exception");
906                 }
907             };
908             setTestAlarmWithListener(ELAPSED_REALTIME, mNowElapsedTest + i + 10, listener);
909         }
910         int expired = 0;
911         while (expired < numAlarms) {
912             mNowElapsedTest = mTestTimer.getElapsed();
913             mTestTimer.expire();
914             expired++;
915             assertEquals(numAlarms - expired, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
916         }
917     }
918 
919     @Test
alarmCountForRepeatingAlarms()920     public void alarmCountForRepeatingAlarms() throws Exception {
921         final long interval = 1231;
922         final long firstTrigger = mNowElapsedTest + 321;
923         final PendingIntent pi = getNewMockPendingIntent();
924         setRepeatingTestAlarm(ELAPSED_REALTIME, firstTrigger, interval, pi);
925         assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
926 
927         for (int i = 0; i < 5; i++) {
928             mNowElapsedTest = mTestTimer.getElapsed();
929             mTestTimer.expire();
930             assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
931         }
932         doThrow(PendingIntent.CanceledException.class).when(pi).send(eq(mMockContext), eq(0),
933                 any(), any(), any(), any(), any());
934         mNowElapsedTest = mTestTimer.getElapsed();
935         mTestTimer.expire();
936         assertEquals(-1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, -1));
937     }
938 
939     @Test
alarmCountOnUidRemoved()940     public void alarmCountOnUidRemoved() {
941         final int numAlarms = 10;
942         for (int i = 0; i < numAlarms; i++) {
943             setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, getNewMockPendingIntent());
944         }
945         assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
946         mService.removeLocked(TEST_CALLING_UID);
947         assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
948     }
949 
950     @Test
alarmCountOnPackageRemoved()951     public void alarmCountOnPackageRemoved() {
952         final int numAlarms = 10;
953         for (int i = 0; i < numAlarms; i++) {
954             setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10, getNewMockPendingIntent());
955         }
956         assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
957         mService.removeLocked(TEST_CALLING_PACKAGE);
958         assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
959     }
960 
961     @Test
alarmCountOnUserRemoved()962     public void alarmCountOnUserRemoved() {
963         final int mockUserId = 15;
964         final int numAlarms = 10;
965         for (int i = 0; i < numAlarms; i++) {
966             int mockUid = UserHandle.getUid(mockUserId, 1234 + i);
967             setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10,
968                     getNewMockPendingIntent(mockUid), 0, mockUid);
969         }
970         assertEquals(numAlarms, mService.mAlarmsPerUid.size());
971         mService.removeUserLocked(mockUserId);
972         assertEquals(0, mService.mAlarmsPerUid.size());
973     }
974 
975     @Test
alarmCountOnRemoveFromPendingWhileIdle()976     public void alarmCountOnRemoveFromPendingWhileIdle() {
977         mService.mPendingIdleUntil = mock(AlarmManagerService.Alarm.class);
978         final int numAlarms = 15;
979         final PendingIntent[] pis = new PendingIntent[numAlarms];
980         for (int i = 0; i < numAlarms; i++) {
981             pis[i] = getNewMockPendingIntent();
982             setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 5, pis[i]);
983         }
984         assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
985         assertEquals(numAlarms, mService.mPendingWhileIdleAlarms.size());
986         final int toRemove = 8;
987         for (int i = 0; i < toRemove; i++) {
988             mService.removeLocked(pis[i], null);
989             assertEquals(numAlarms - i - 1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
990         }
991         mService.removeLocked(TEST_CALLING_UID);
992         assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
993     }
994 
995     @Test
alarmCountOnAlarmRemoved()996     public void alarmCountOnAlarmRemoved() {
997         final int numAlarms = 10;
998         final PendingIntent[] pis = new PendingIntent[numAlarms];
999         for (int i = 0; i < numAlarms; i++) {
1000             pis[i] = getNewMockPendingIntent();
1001             setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 5, pis[i]);
1002         }
1003         assertEquals(numAlarms, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
1004         for (int i = 0; i < numAlarms; i++) {
1005             mService.removeLocked(pis[i], null);
1006             assertEquals(numAlarms - i - 1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
1007         }
1008     }
1009 
1010     @Test
alarmTypes()1011     public void alarmTypes() throws Exception {
1012         final int[] typesToSet = {ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME, RTC_WAKEUP, RTC};
1013         final int[] typesExpected = {ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME,
1014                 ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME};
1015         assertAlarmTypeConversion(typesToSet, typesExpected);
1016     }
1017 
assertAlarmTypeConversion(int[] typesToSet, int[] typesExpected)1018     private void assertAlarmTypeConversion(int[] typesToSet, int[] typesExpected) throws Exception {
1019         for (int i = 0; i < typesToSet.length; i++) {
1020             setTestAlarm(typesToSet[i], 1234, getNewMockPendingIntent());
1021             final int typeSet = mTestTimer.getType();
1022             assertEquals("Alarm of type " + typesToSet[i] + " was set to type " + typeSet,
1023                     typesExpected[i], typeSet);
1024             mNowElapsedTest = mTestTimer.getElapsed();
1025             mTestTimer.expire();
1026         }
1027     }
1028 
1029     @Test
alarmCountOnInvalidSet()1030     public void alarmCountOnInvalidSet() {
1031         setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 12345, null);
1032         assertEquals(-1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, -1));
1033     }
1034 
1035     @Test
alarmCountOnPendingIntentCancel()1036     public void alarmCountOnPendingIntentCancel() {
1037         final PendingIntent pi = getNewMockPendingIntent();
1038         setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 123, pi);
1039         verify(pi).registerCancelListener(mService.mOperationCancelListener);
1040         assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
1041         mService.mOperationCancelListener.onCancelled(pi);
1042         assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
1043     }
1044 
1045     @After
tearDown()1046     public void tearDown() {
1047         if (mMockingSession != null) {
1048             mMockingSession.finishMocking();
1049         }
1050     }
1051 }
1052