1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.usage;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertTrue;
23 import static org.junit.Assert.fail;
24 import static org.mockito.ArgumentMatchers.any;
25 import static org.mockito.ArgumentMatchers.anyLong;
26 import static org.mockito.ArgumentMatchers.anyString;
27 import static org.mockito.ArgumentMatchers.eq;
28 import static org.mockito.Mockito.times;
29 import static org.mockito.Mockito.verify;
30 
31 import android.app.AlarmManager;
32 import android.app.PendingIntent;
33 import android.app.usage.UsageStatsManagerInternal;
34 import android.os.HandlerThread;
35 import android.os.Looper;
36 import android.os.UserHandle;
37 
38 import androidx.test.InstrumentationRegistry;
39 import androidx.test.filters.LargeTest;
40 import androidx.test.runner.AndroidJUnit4;
41 
42 import org.junit.After;
43 import org.junit.Before;
44 import org.junit.Test;
45 import org.junit.runner.RunWith;
46 import org.mockito.ArgumentCaptor;
47 import org.mockito.Mock;
48 import org.mockito.MockitoAnnotations;
49 
50 import java.io.PrintWriter;
51 import java.io.StringWriter;
52 import java.util.concurrent.CountDownLatch;
53 import java.util.concurrent.TimeUnit;
54 
55 @RunWith(AndroidJUnit4.class)
56 @LargeTest
57 public class AppTimeLimitControllerTests {
58 
59     private static final String PKG_SOC1 = "package.soc1";
60     private static final String PKG_SOC2 = "package.soc2";
61     private static final String PKG_GAME1 = "package.game1";
62     private static final String PKG_GAME2 = "package.game2";
63     private static final String PKG_PROD = "package.prod";
64 
65     private static final int UID = 10100;
66     private static final int USER_ID = 10;
67     private static final int OBS_ID1 = 1;
68     private static final int OBS_ID2 = 2;
69     private static final int OBS_ID3 = 3;
70     private static final int OBS_ID4 = 4;
71     private static final int OBS_ID5 = 5;
72     private static final int OBS_ID6 = 6;
73     private static final int OBS_ID7 = 7;
74     private static final int OBS_ID8 = 8;
75     private static final int OBS_ID9 = 9;
76     private static final int OBS_ID10 = 10;
77     private static final int OBS_ID11 = 11;
78 
79     private static final long TIME_30_MIN = 30 * 60_000L;
80     private static final long TIME_10_MIN = 10 * 60_000L;
81     private static final long TIME_1_MIN = 1 * 60_000L;
82 
83     private static final long MAX_OBSERVER_PER_UID = 10;
84     private static final long MIN_TIME_LIMIT = 4_000L;
85 
86     private static final String[] GROUP1 = {
87             PKG_SOC1, PKG_GAME1, PKG_PROD
88     };
89 
90     private static final String[] GROUP_SOC = {
91             PKG_SOC1, PKG_SOC2
92     };
93 
94     private static final String[] GROUP_GAME = {
95             PKG_GAME1, PKG_GAME2
96     };
97 
98     private CountDownLatch mLimitReachedLatch = new CountDownLatch(1);
99     private CountDownLatch mSessionEndLatch = new CountDownLatch(1);
100 
101     private AppTimeLimitController mController;
102 
103     @Mock private AlarmManager mMockAlarmManager;
104 
105     private HandlerThread mThread;
106 
107     private long mElapsedTime;
108 
109     AppTimeLimitController.TimeLimitCallbackListener mListener =
110             new AppTimeLimitController.TimeLimitCallbackListener() {
111                 @Override
112                 public void onLimitReached(int observerId, int userId, long timeLimit,
113                         long timeElapsed,
114                         PendingIntent callbackIntent) {
115                     mLimitReachedLatch.countDown();
116                 }
117 
118                 @Override
119                 public void onSessionEnd(int observerId, int userId, long timeElapsed,
120                         PendingIntent callbackIntent) {
121                     mSessionEndLatch.countDown();
122                 }
123             };
124 
125     class MyAppTimeLimitController extends AppTimeLimitController {
MyAppTimeLimitController(AppTimeLimitController.TimeLimitCallbackListener listener, Looper looper)126         MyAppTimeLimitController(AppTimeLimitController.TimeLimitCallbackListener listener,
127                 Looper looper) {
128             super(InstrumentationRegistry.getContext(), listener, looper);
129         }
130 
131         @Override
getAlarmManager()132         protected AlarmManager getAlarmManager() {
133             return mMockAlarmManager;
134         }
135 
136         @Override
getElapsedRealtime()137         protected long getElapsedRealtime() {
138             return mElapsedTime;
139         }
140 
141         @Override
getAppUsageObserverPerUidLimit()142         protected long getAppUsageObserverPerUidLimit() {
143             return MAX_OBSERVER_PER_UID;
144         }
145 
146         @Override
getUsageSessionObserverPerUidLimit()147         protected long getUsageSessionObserverPerUidLimit() {
148             return MAX_OBSERVER_PER_UID;
149         }
150 
151         @Override
getAppUsageLimitObserverPerUidLimit()152         protected long getAppUsageLimitObserverPerUidLimit() {
153             return MAX_OBSERVER_PER_UID;
154         }
155 
156         @Override
getMinTimeLimit()157         protected long getMinTimeLimit() {
158             return MIN_TIME_LIMIT;
159         }
160     }
161 
162     @Before
setUp()163     public void setUp() {
164         mThread = new HandlerThread("Test");
165         mThread.start();
166         mController = new MyAppTimeLimitController(mListener, mThread.getLooper());
167 
168         MockitoAnnotations.initMocks(this);
169     }
170 
171     @After
tearDown()172     public void tearDown() {
173         mThread.quit();
174     }
175 
176     /** Verify app usage observer is added */
177     @Test
testAppUsageObserver_AddObserver()178     public void testAppUsageObserver_AddObserver() {
179         addAppUsageObserver(OBS_ID1, GROUP1, TIME_30_MIN);
180         assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1));
181         addAppUsageObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN);
182         assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID2));
183         assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1));
184     }
185 
186     /** Verify usage session observer is added */
187     @Test
testUsageSessionObserver_AddObserver()188     public void testUsageSessionObserver_AddObserver() {
189         addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
190         assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
191         addUsageSessionObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, TIME_1_MIN);
192         assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID2));
193     }
194 
195     /** Verify app usage limit observer is added */
196     @Test
testAppUsageLimitObserver_AddObserver()197     public void testAppUsageLimitObserver_AddObserver() {
198         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
199         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
200         addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, 0);
201         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID2));
202         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
203     }
204 
205     /** Verify app usage observer is removed */
206     @Test
testAppUsageObserver_RemoveObserver()207     public void testAppUsageObserver_RemoveObserver() {
208         addAppUsageObserver(OBS_ID1, GROUP1, TIME_30_MIN);
209         assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1));
210         mController.removeAppUsageObserver(UID, OBS_ID1, USER_ID);
211         assertFalse("Observer wasn't removed", hasAppUsageObserver(UID, OBS_ID1));
212     }
213 
214     /** Verify usage session observer is removed */
215     @Test
testUsageSessionObserver_RemoveObserver()216     public void testUsageSessionObserver_RemoveObserver() {
217         addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
218         assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
219         mController.removeUsageSessionObserver(UID, OBS_ID1, USER_ID);
220         assertFalse("Observer wasn't removed", hasUsageSessionObserver(UID, OBS_ID1));
221     }
222 
223     /** Verify app usage limit observer is removed */
224     @Test
testAppUsageLimitObserver_RemoveObserver()225     public void testAppUsageLimitObserver_RemoveObserver() {
226         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
227         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
228         mController.removeAppUsageLimitObserver(UID, OBS_ID1, USER_ID);
229         assertFalse("Observer wasn't removed", hasAppUsageLimitObserver(UID, OBS_ID1));
230     }
231 
232     /** Verify nothing happens when a nonexistent app usage observer is removed */
233     @Test
testAppUsageObserver_RemoveMissingObserver()234     public void testAppUsageObserver_RemoveMissingObserver() {
235         assertFalse("Observer should not exist", hasAppUsageObserver(UID, OBS_ID1));
236         try {
237             mController.removeAppUsageObserver(UID, OBS_ID1, USER_ID);
238         } catch (Exception e) {
239             StringWriter sw = new StringWriter();
240             sw.write("Hit exception trying to remove nonexistent observer:\n");
241             sw.write(e.toString());
242             PrintWriter pw = new PrintWriter(sw);
243             e.printStackTrace(pw);
244             sw.write("\nTest Failed!");
245             fail(sw.toString());
246         }
247         assertFalse("Observer should not exist", hasAppUsageObserver(UID, OBS_ID1));
248     }
249 
250     /** Verify nothing happens when a nonexistent usage session observer is removed */
251     @Test
testUsageSessionObserver_RemoveMissingObserver()252     public void testUsageSessionObserver_RemoveMissingObserver() {
253         assertFalse("Observer should not exist", hasUsageSessionObserver(UID, OBS_ID1));
254         try {
255             mController.removeUsageSessionObserver(UID, OBS_ID1, USER_ID);
256         } catch (Exception e) {
257             StringWriter sw = new StringWriter();
258             sw.write("Hit exception trying to remove nonexistent observer:");
259             sw.write(e.toString());
260             PrintWriter pw = new PrintWriter(sw);
261             e.printStackTrace(pw);
262             sw.write("\nTest Failed!");
263             fail(sw.toString());
264         }
265         assertFalse("Observer should not exist", hasUsageSessionObserver(UID, OBS_ID1));
266     }
267 
268     /** Verify nothing happens when a nonexistent app usage limit observer is removed */
269     @Test
testAppUsageLimitObserver_RemoveMissingObserver()270     public void testAppUsageLimitObserver_RemoveMissingObserver() {
271         assertFalse("Observer should not exist", hasAppUsageLimitObserver(UID, OBS_ID1));
272         try {
273             mController.removeAppUsageLimitObserver(UID, OBS_ID1, USER_ID);
274         } catch (Exception e) {
275             StringWriter sw = new StringWriter();
276             sw.write("Hit exception trying to remove nonexistent observer:\n");
277             sw.write(e.toString());
278             PrintWriter pw = new PrintWriter(sw);
279             e.printStackTrace(pw);
280             sw.write("\nTest Failed!");
281             fail(sw.toString());
282         }
283         assertFalse("Observer should not exist", hasAppUsageLimitObserver(UID, OBS_ID1));
284     }
285 
286     /** Re-adding an observer should result in only one copy */
287     @Test
testAppUsageObserver_ObserverReAdd()288     public void testAppUsageObserver_ObserverReAdd() {
289         addAppUsageObserver(OBS_ID1, GROUP1, TIME_30_MIN);
290         assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1));
291         addAppUsageObserver(OBS_ID1, GROUP1, TIME_10_MIN);
292         assertTrue("Observer wasn't added",
293                 mController.getAppUsageGroup(UID, OBS_ID1).getTimeLimitMs() == TIME_10_MIN);
294         mController.removeAppUsageObserver(UID, OBS_ID1, USER_ID);
295         assertFalse("Observer wasn't removed", hasAppUsageObserver(UID, OBS_ID1));
296     }
297 
298     /** Re-adding an observer should result in only one copy */
299     @Test
testUsageSessionObserver_ObserverReAdd()300     public void testUsageSessionObserver_ObserverReAdd() {
301         addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
302         assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
303         addUsageSessionObserver(OBS_ID1, GROUP1, TIME_10_MIN, TIME_1_MIN);
304         assertTrue("Observer wasn't added",
305                 mController.getSessionUsageGroup(UID, OBS_ID1).getTimeLimitMs() == TIME_10_MIN);
306         mController.removeUsageSessionObserver(UID, OBS_ID1, USER_ID);
307         assertFalse("Observer wasn't removed", hasUsageSessionObserver(UID, OBS_ID1));
308     }
309 
310     /** Re-adding an observer should result in only one copy */
311     @Test
testAppUsageLimitObserver_ObserverReAdd()312     public void testAppUsageLimitObserver_ObserverReAdd() {
313         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
314         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
315         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN, 0);
316         assertTrue("Observer wasn't added",
317                 getAppUsageLimitObserver(UID, OBS_ID1).getTimeLimitMs() == TIME_10_MIN);
318         mController.removeAppUsageLimitObserver(UID, OBS_ID1, USER_ID);
319         assertFalse("Observer wasn't removed", hasAppUsageLimitObserver(UID, OBS_ID1));
320     }
321 
322     /** Different type observers can be registered to the same observerId value */
323     @Test
testAllObservers_ExclusiveObserverIds()324     public void testAllObservers_ExclusiveObserverIds() {
325         addAppUsageObserver(OBS_ID1, GROUP1, TIME_10_MIN);
326         addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
327         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN, 0);
328         assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1));
329         assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
330         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
331 
332         AppTimeLimitController.UsageGroup appUsageGroup = mController.getAppUsageGroup(UID,
333                 OBS_ID1);
334         AppTimeLimitController.UsageGroup sessionUsageGroup = mController.getSessionUsageGroup(UID,
335                 OBS_ID1);
336         AppTimeLimitController.UsageGroup appUsageLimitGroup = getAppUsageLimitObserver(
337                 UID, OBS_ID1);
338 
339         // Verify data still intact
340         assertEquals(TIME_10_MIN, appUsageGroup.getTimeLimitMs());
341         assertEquals(TIME_30_MIN, sessionUsageGroup.getTimeLimitMs());
342         assertEquals(TIME_10_MIN, appUsageLimitGroup.getTimeLimitMs());
343     }
344 
345     /** Verify that usage across different apps within a group are added up */
346     @Test
testAppUsageObserver_Accumulation()347     public void testAppUsageObserver_Accumulation() throws Exception {
348         setTime(0L);
349         addAppUsageObserver(OBS_ID1, GROUP1, TIME_30_MIN);
350         startUsage(PKG_SOC1);
351         // Add 10 mins
352         setTime(TIME_10_MIN);
353         stopUsage(PKG_SOC1);
354 
355         AppTimeLimitController.UsageGroup group = mController.getAppUsageGroup(UID, OBS_ID1);
356 
357         long timeRemaining = group.getTimeLimitMs() - group.getUsageTimeMs();
358         assertEquals(TIME_10_MIN * 2, timeRemaining);
359 
360         startUsage(PKG_SOC1);
361         setTime(TIME_10_MIN * 2);
362         stopUsage(PKG_SOC1);
363 
364         timeRemaining = group.getTimeLimitMs() - group.getUsageTimeMs();
365         assertEquals(TIME_10_MIN, timeRemaining);
366 
367         setTime(TIME_30_MIN);
368 
369         assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
370 
371         // Add a different package in the group
372         startUsage(PKG_GAME1);
373         setTime(TIME_30_MIN + TIME_10_MIN);
374         stopUsage(PKG_GAME1);
375 
376         assertEquals(0, group.getTimeLimitMs() - group.getUsageTimeMs());
377         assertTrue(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
378     }
379 
380     /** Verify that usage across different apps within a group are added up */
381     @Test
testUsageSessionObserver_Accumulation()382     public void testUsageSessionObserver_Accumulation() throws Exception {
383         setTime(0L);
384         addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_10_MIN);
385         startUsage(PKG_SOC1);
386         // Add 10 mins
387         setTime(TIME_10_MIN);
388         stopUsage(PKG_SOC1);
389 
390         AppTimeLimitController.UsageGroup group = mController.getSessionUsageGroup(UID, OBS_ID1);
391 
392         long timeRemaining = group.getTimeLimitMs() - group.getUsageTimeMs();
393         assertEquals(TIME_10_MIN * 2, timeRemaining);
394 
395         startUsage(PKG_SOC1);
396         setTime(TIME_10_MIN * 2);
397         stopUsage(PKG_SOC1);
398 
399         timeRemaining = group.getTimeLimitMs() - group.getUsageTimeMs();
400         assertEquals(TIME_10_MIN, timeRemaining);
401 
402         setTime(TIME_30_MIN);
403 
404         assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
405 
406         // Add a different package in the group
407         startUsage(PKG_GAME1);
408         setTime(TIME_30_MIN + TIME_10_MIN);
409         stopUsage(PKG_GAME1);
410 
411         assertEquals(0, group.getTimeLimitMs() - group.getUsageTimeMs());
412         assertTrue(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
413     }
414 
415     /** Verify that usage across different apps within a group are added up */
416     @Test
testAppUsageLimitObserver_Accumulation()417     public void testAppUsageLimitObserver_Accumulation() throws Exception {
418         setTime(0L);
419         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
420         startUsage(PKG_SOC1);
421         // Add 10 mins
422         setTime(TIME_10_MIN);
423         stopUsage(PKG_SOC1);
424 
425         AppTimeLimitController.UsageGroup group = getAppUsageLimitObserver(UID, OBS_ID1);
426 
427         long timeRemaining = group.getTimeLimitMs() - group.getUsageTimeMs();
428         assertEquals(TIME_10_MIN * 2, timeRemaining);
429 
430         startUsage(PKG_SOC1);
431         setTime(TIME_10_MIN * 2);
432         stopUsage(PKG_SOC1);
433 
434         timeRemaining = group.getTimeLimitMs() - group.getUsageTimeMs();
435         assertEquals(TIME_10_MIN, timeRemaining);
436 
437         setTime(TIME_30_MIN);
438 
439         assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
440 
441         // Add a different package in the group
442         startUsage(PKG_GAME1);
443         setTime(TIME_30_MIN + TIME_10_MIN);
444         stopUsage(PKG_GAME1);
445 
446         assertEquals(0, group.getTimeLimitMs() - group.getUsageTimeMs());
447         assertTrue(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
448     }
449 
450     /** Verify that time limit does not get triggered due to a different app */
451     @Test
testAppUsageObserver_TimeoutOtherApp()452     public void testAppUsageObserver_TimeoutOtherApp() throws Exception {
453         setTime(0L);
454         addAppUsageObserver(OBS_ID1, GROUP1, 4_000L);
455         startUsage(PKG_SOC2);
456         assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
457         setTime(6_000L);
458         stopUsage(PKG_SOC2);
459         assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
460     }
461 
462     /** Verify that time limit does not get triggered due to a different app */
463     @Test
testUsageSessionObserver_TimeoutOtherApp()464     public void testUsageSessionObserver_TimeoutOtherApp() throws Exception {
465         setTime(0L);
466         addUsageSessionObserver(OBS_ID1, GROUP1, 4_000L, 1_000L);
467         startUsage(PKG_SOC2);
468         assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
469         setTime(6_000L);
470         stopUsage(PKG_SOC2);
471         assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
472 
473     }
474 
475     /** Verify that time limit does not get triggered due to a different app */
476     @Test
testAppUsageLimitObserver_TimeoutOtherApp()477     public void testAppUsageLimitObserver_TimeoutOtherApp() throws Exception {
478         setTime(0L);
479         addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L, 0);
480         startUsage(PKG_SOC2);
481         assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
482         setTime(6_000L);
483         stopUsage(PKG_SOC2);
484         assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
485     }
486 
487     /** Verify the timeout message is delivered at the right time */
488     @Test
testAppUsageObserver_Timeout()489     public void testAppUsageObserver_Timeout() throws Exception {
490         setTime(0L);
491         addAppUsageObserver(OBS_ID1, GROUP1, 4_000L);
492         startUsage(PKG_SOC1);
493         setTime(6_000L);
494         assertTrue(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
495         stopUsage(PKG_SOC1);
496         // Verify that the observer was removed
497         assertFalse(hasAppUsageObserver(UID, OBS_ID1));
498     }
499 
500     /** Verify the timeout message is delivered at the right time */
501     @Test
testUsageSessionObserver_Timeout()502     public void testUsageSessionObserver_Timeout() throws Exception {
503         setTime(0L);
504         addUsageSessionObserver(OBS_ID1, GROUP1, 4_000L, 1_000L);
505         startUsage(PKG_SOC1);
506         setTime(6_000L);
507         assertTrue(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
508         stopUsage(PKG_SOC1);
509         final ArgumentCaptor<AlarmManager.OnAlarmListener> onAlarmListenerArgumentCaptor =
510                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
511         verify(mMockAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
512                 anyString(), onAlarmListenerArgumentCaptor.capture(), any());
513         // Usage has stopped, Session should end in a second. Verify session end occurs in a second
514         // (+/- 100ms, which is hopefully not too slim a margin)
515         assertFalse(mSessionEndLatch.await(900L, TimeUnit.MILLISECONDS));
516         onAlarmListenerArgumentCaptor.getValue().onAlarm();
517         assertTrue(mSessionEndLatch.await(200L, TimeUnit.MILLISECONDS));
518         // Verify that the observer was not removed
519         assertTrue(hasUsageSessionObserver(UID, OBS_ID1));
520     }
521 
522     /** Verify the timeout message is delivered at the right time */
523     @Test
testAppUsageLimitObserver_Timeout()524     public void testAppUsageLimitObserver_Timeout() throws Exception {
525         setTime(0L);
526         addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L, 0);
527         startUsage(PKG_SOC1);
528         setTime(6_000L);
529         assertTrue(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
530         stopUsage(PKG_SOC1);
531         // Verify that the observer was not removed
532         assertTrue(hasAppUsageLimitObserver(UID, OBS_ID1));
533     }
534 
535     /** If an app was already running, make sure it is partially counted towards the time limit */
536     @Test
testAppUsageObserver_AlreadyRunning()537     public void testAppUsageObserver_AlreadyRunning() throws Exception {
538         setTime(TIME_10_MIN);
539         startUsage(PKG_GAME1);
540         setTime(TIME_30_MIN);
541         addAppUsageObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN);
542         setTime(TIME_30_MIN + TIME_10_MIN);
543         stopUsage(PKG_GAME1);
544         assertFalse(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
545 
546         startUsage(PKG_GAME2);
547         setTime(TIME_30_MIN + TIME_30_MIN);
548         stopUsage(PKG_GAME2);
549         assertTrue(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
550         // Verify that the observer was removed
551         assertFalse(hasAppUsageObserver(UID, OBS_ID2));
552     }
553 
554     /** If an app was already running, make sure it is partially counted towards the time limit */
555     @Test
testUsageSessionObserver_AlreadyRunning()556     public void testUsageSessionObserver_AlreadyRunning() throws Exception {
557         setTime(TIME_10_MIN);
558         startUsage(PKG_GAME1);
559         setTime(TIME_30_MIN);
560         addUsageSessionObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, TIME_1_MIN);
561         setTime(TIME_30_MIN + TIME_10_MIN);
562         stopUsage(PKG_GAME1);
563         assertFalse(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
564 
565         startUsage(PKG_GAME2);
566         setTime(TIME_30_MIN + TIME_30_MIN);
567         stopUsage(PKG_GAME2);
568         assertTrue(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
569         // Verify that the observer was removed
570         assertTrue(hasUsageSessionObserver(UID, OBS_ID2));
571     }
572 
573     /** If an app was already running, make sure it is partially counted towards the time limit */
574     @Test
testAppUsageLimitObserver_AlreadyRunning()575     public void testAppUsageLimitObserver_AlreadyRunning() throws Exception {
576         setTime(TIME_10_MIN);
577         startUsage(PKG_GAME1);
578         setTime(TIME_30_MIN);
579         addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, 0);
580         setTime(TIME_30_MIN + TIME_10_MIN);
581         stopUsage(PKG_GAME1);
582         assertFalse(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
583 
584         startUsage(PKG_GAME2);
585         setTime(TIME_30_MIN + TIME_30_MIN);
586         stopUsage(PKG_GAME2);
587         assertTrue(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
588         // Verify that the observer was not removed
589         assertTrue(hasAppUsageLimitObserver(UID, OBS_ID2));
590     }
591 
592     /** If watched app is already running, verify the timeout callback happens at the right time */
593     @Test
testAppUsageObserver_AlreadyRunningTimeout()594     public void testAppUsageObserver_AlreadyRunningTimeout() throws Exception {
595         setTime(0);
596         startUsage(PKG_SOC1);
597         setTime(TIME_10_MIN);
598         // 10 second time limit
599         addAppUsageObserver(OBS_ID1, GROUP_SOC, 10_000L);
600         setTime(TIME_10_MIN + 5_000L);
601         // Shouldn't call back in 6 seconds
602         assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
603         setTime(TIME_10_MIN + 10_000L);
604         // Should call back by 11 seconds (6 earlier + 5 now)
605         assertTrue(mLimitReachedLatch.await(5_000L, TimeUnit.MILLISECONDS));
606         // Verify that the observer was removed
607         assertFalse(hasAppUsageObserver(UID, OBS_ID1));
608     }
609 
610     /** If watched app is already running, verify the timeout callback happens at the right time */
611     @Test
testUsageSessionObserver_AlreadyRunningTimeout()612     public void testUsageSessionObserver_AlreadyRunningTimeout() throws Exception {
613         setTime(0);
614         startUsage(PKG_SOC1);
615         setTime(TIME_10_MIN);
616         // 10 second time limit
617         addUsageSessionObserver(OBS_ID1, GROUP_SOC, 10_000L, 1_000L);
618         setTime(TIME_10_MIN + 5_000L);
619         // Shouldn't call back in 6 seconds
620         assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
621         setTime(TIME_10_MIN + 10_000L);
622         // Should call back by 11 seconds (6 earlier + 5 now)
623         assertTrue(mLimitReachedLatch.await(5_000L, TimeUnit.MILLISECONDS));
624         stopUsage(PKG_SOC1);
625         final ArgumentCaptor<AlarmManager.OnAlarmListener> onAlarmListenerArgumentCaptor =
626                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
627         verify(mMockAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
628                 anyString(), onAlarmListenerArgumentCaptor.capture(), any());
629         // Usage has stopped, Session should end in a second. Verify session end occurs in a second
630         // (+/- 100ms, which is hopefully not too slim a margin)
631         assertFalse(mSessionEndLatch.await(900L, TimeUnit.MILLISECONDS));
632         onAlarmListenerArgumentCaptor.getValue().onAlarm();
633         assertTrue(mSessionEndLatch.await(200L, TimeUnit.MILLISECONDS));
634         // Verify that the observer was removed
635         assertTrue(hasUsageSessionObserver(UID, OBS_ID1));
636     }
637 
638     /** If watched app is already running, verify the timeout callback happens at the right time */
639     @Test
testAppUsageLimitObserver_AlreadyRunningTimeout()640     public void testAppUsageLimitObserver_AlreadyRunningTimeout() throws Exception {
641         setTime(0);
642         startUsage(PKG_SOC1);
643         setTime(TIME_10_MIN);
644         // 10 second time limit
645         addAppUsageLimitObserver(OBS_ID1, GROUP_SOC, 10_000L, 0);
646         setTime(TIME_10_MIN + 5_000L);
647         // Shouldn't call back in 6 seconds
648         assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
649         setTime(TIME_10_MIN + 10_000L);
650         // Should call back by 11 seconds (6 earlier + 5 now)
651         assertTrue(mLimitReachedLatch.await(5_000L, TimeUnit.MILLISECONDS));
652         // Verify that the observer was not removed
653         assertTrue(hasAppUsageLimitObserver(UID, OBS_ID1));
654     }
655 
656     /**
657      * Verify that App Time Limit Controller will limit the number of observerIds for app usage
658      * observers
659      */
660     @Test
testAppUsageObserver_MaxObserverLimit()661     public void testAppUsageObserver_MaxObserverLimit() throws Exception {
662         boolean receivedException = false;
663         int ANOTHER_UID = UID + 1;
664         addAppUsageObserver(OBS_ID1, GROUP1, TIME_30_MIN);
665         addAppUsageObserver(OBS_ID2, GROUP1, TIME_30_MIN);
666         addAppUsageObserver(OBS_ID3, GROUP1, TIME_30_MIN);
667         addAppUsageObserver(OBS_ID4, GROUP1, TIME_30_MIN);
668         addAppUsageObserver(OBS_ID5, GROUP1, TIME_30_MIN);
669         addAppUsageObserver(OBS_ID6, GROUP1, TIME_30_MIN);
670         addAppUsageObserver(OBS_ID7, GROUP1, TIME_30_MIN);
671         addAppUsageObserver(OBS_ID8, GROUP1, TIME_30_MIN);
672         addAppUsageObserver(OBS_ID9, GROUP1, TIME_30_MIN);
673         addAppUsageObserver(OBS_ID10, GROUP1, TIME_30_MIN);
674         // Readding an observer should not cause an IllegalStateException
675         addAppUsageObserver(OBS_ID5, GROUP1, TIME_30_MIN);
676         // Adding an observer for a different uid shouldn't cause an IllegalStateException
677         mController.addAppUsageObserver(ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, null, USER_ID);
678         try {
679             addAppUsageObserver(OBS_ID11, GROUP1, TIME_30_MIN);
680         } catch (IllegalStateException ise) {
681             receivedException = true;
682         }
683         assertTrue("Should have caused an IllegalStateException", receivedException);
684     }
685 
686     /**
687      * Verify that App Time Limit Controller will limit the number of observerIds for usage session
688      * observers
689      */
690     @Test
testUsageSessionObserver_MaxObserverLimit()691     public void testUsageSessionObserver_MaxObserverLimit() throws Exception {
692         addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
693         boolean receivedException = false;
694         int ANOTHER_UID = UID + 1;
695         addUsageSessionObserver(OBS_ID2, GROUP1, TIME_30_MIN, TIME_1_MIN);
696         addUsageSessionObserver(OBS_ID3, GROUP1, TIME_30_MIN, TIME_1_MIN);
697         addUsageSessionObserver(OBS_ID4, GROUP1, TIME_30_MIN, TIME_1_MIN);
698         addUsageSessionObserver(OBS_ID5, GROUP1, TIME_30_MIN, TIME_1_MIN);
699         addUsageSessionObserver(OBS_ID6, GROUP1, TIME_30_MIN, TIME_1_MIN);
700         addUsageSessionObserver(OBS_ID7, GROUP1, TIME_30_MIN, TIME_1_MIN);
701         addUsageSessionObserver(OBS_ID8, GROUP1, TIME_30_MIN, TIME_1_MIN);
702         addUsageSessionObserver(OBS_ID9, GROUP1, TIME_30_MIN, TIME_1_MIN);
703         addUsageSessionObserver(OBS_ID10, GROUP1, TIME_30_MIN, TIME_1_MIN);
704         // Readding an observer should not cause an IllegalStateException
705         addUsageSessionObserver(OBS_ID5, GROUP1, TIME_30_MIN, TIME_1_MIN);
706         // Adding an observer for a different uid shouldn't cause an IllegalStateException
707         mController.addUsageSessionObserver(ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, TIME_1_MIN,
708                 null, null, USER_ID);
709         try {
710             addUsageSessionObserver(OBS_ID11, GROUP1, TIME_30_MIN, TIME_1_MIN);
711         } catch (IllegalStateException ise) {
712             receivedException = true;
713         }
714         assertTrue("Should have caused an IllegalStateException", receivedException);
715     }
716 
717     /**
718      * Verify that App Time Limit Controller will limit the number of observerIds for app usage
719      * limit observers
720      */
721     @Test
testAppUsageLimitObserver_MaxObserverLimit()722     public void testAppUsageLimitObserver_MaxObserverLimit() throws Exception {
723         boolean receivedException = false;
724         int ANOTHER_UID = UID + 1;
725         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
726         addAppUsageLimitObserver(OBS_ID2, GROUP1, TIME_30_MIN, 0);
727         addAppUsageLimitObserver(OBS_ID3, GROUP1, TIME_30_MIN, 0);
728         addAppUsageLimitObserver(OBS_ID4, GROUP1, TIME_30_MIN, 0);
729         addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN, 0);
730         addAppUsageLimitObserver(OBS_ID6, GROUP1, TIME_30_MIN, 0);
731         addAppUsageLimitObserver(OBS_ID7, GROUP1, TIME_30_MIN, 0);
732         addAppUsageLimitObserver(OBS_ID8, GROUP1, TIME_30_MIN, 0);
733         addAppUsageLimitObserver(OBS_ID9, GROUP1, TIME_30_MIN, 0);
734         addAppUsageLimitObserver(OBS_ID10, GROUP1, TIME_30_MIN, 0);
735         // Readding an observer should not cause an IllegalStateException
736         addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN, 0);
737         // Adding an observer for a different uid shouldn't cause an IllegalStateException
738         mController.addAppUsageLimitObserver(
739                 ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, 0, null, USER_ID);
740         try {
741             addAppUsageLimitObserver(OBS_ID11, GROUP1, TIME_30_MIN, 0);
742         } catch (IllegalStateException ise) {
743             receivedException = true;
744         }
745         assertTrue("Should have caused an IllegalStateException", receivedException);
746     }
747 
748     /** Verify that addAppUsageObserver minimum time limit is one minute */
749     @Test
testAppUsageObserver_MinimumTimeLimit()750     public void testAppUsageObserver_MinimumTimeLimit() throws Exception {
751         boolean receivedException = false;
752         // adding an observer with a one minute time limit should not cause an exception
753         addAppUsageObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT);
754         try {
755             addAppUsageObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT - 1);
756         } catch (IllegalArgumentException iae) {
757             receivedException = true;
758         }
759         assertTrue("Should have caused an IllegalArgumentException", receivedException);
760     }
761 
762     /** Verify that addUsageSessionObserver minimum time limit is one minute */
763     @Test
testUsageSessionObserver_MinimumTimeLimit()764     public void testUsageSessionObserver_MinimumTimeLimit() throws Exception {
765         boolean receivedException = false;
766         // test also for session observers
767         addUsageSessionObserver(OBS_ID10, GROUP1, MIN_TIME_LIMIT, TIME_1_MIN);
768         try {
769             addUsageSessionObserver(OBS_ID10, GROUP1, MIN_TIME_LIMIT - 1, TIME_1_MIN);
770         } catch (IllegalArgumentException iae) {
771             receivedException = true;
772         }
773         assertTrue("Should have caused an IllegalArgumentException", receivedException);
774     }
775 
776     /** Verify that addAppUsageLimitObserver minimum time limit is one minute */
777     @Test
testAppUsageLimitObserver_MinimumTimeLimit()778     public void testAppUsageLimitObserver_MinimumTimeLimit() throws Exception {
779         boolean receivedException = false;
780         // adding an observer with a one minute time limit should not cause an exception
781         addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT, 0);
782         try {
783             addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT - 1, 0);
784         } catch (IllegalArgumentException iae) {
785             receivedException = true;
786         }
787         assertTrue("Should have caused an IllegalArgumentException", receivedException);
788     }
789 
790     /** Verify that concurrent usage from multiple apps in the same group will counted correctly */
791     @Test
testAppUsageObserver_ConcurrentUsage()792     public void testAppUsageObserver_ConcurrentUsage() throws Exception {
793         setTime(0L);
794         addAppUsageObserver(OBS_ID1, GROUP1, TIME_30_MIN);
795         AppTimeLimitController.UsageGroup group = mController.getAppUsageGroup(UID, OBS_ID1);
796         startUsage(PKG_SOC1);
797         // Add 10 mins
798         setTime(TIME_10_MIN);
799 
800         // Add a different package in the group will first package is still in use
801         startUsage(PKG_GAME1);
802         setTime(TIME_10_MIN * 2);
803         // Stop first package usage
804         stopUsage(PKG_SOC1);
805 
806         setTime(TIME_30_MIN);
807         stopUsage(PKG_GAME1);
808 
809         assertEquals(TIME_30_MIN, group.getUsageTimeMs());
810         assertTrue(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
811     }
812 
813     /** Verify that concurrent usage from multiple apps in the same group will counted correctly */
814     @Test
testUsageSessionObserver_ConcurrentUsage()815     public void testUsageSessionObserver_ConcurrentUsage() throws Exception {
816         setTime(0L);
817         addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
818         AppTimeLimitController.UsageGroup group = mController.getSessionUsageGroup(UID, OBS_ID1);
819         startUsage(PKG_SOC1);
820         // Add 10 mins
821         setTime(TIME_10_MIN);
822 
823         // Add a different package in the group will first package is still in use
824         startUsage(PKG_GAME1);
825         setTime(TIME_10_MIN * 2);
826         // Stop first package usage
827         stopUsage(PKG_SOC1);
828 
829         setTime(TIME_30_MIN);
830         stopUsage(PKG_GAME1);
831 
832         assertEquals(TIME_30_MIN, group.getUsageTimeMs());
833         assertTrue(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
834     }
835 
836     /** Verify that concurrent usage from multiple apps in the same group will counted correctly */
837     @Test
testAppUsageLimitObserver_ConcurrentUsage()838     public void testAppUsageLimitObserver_ConcurrentUsage() throws Exception {
839         setTime(0L);
840         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
841         AppTimeLimitController.UsageGroup group = getAppUsageLimitObserver(UID, OBS_ID1);
842         startUsage(PKG_SOC1);
843         // Add 10 mins
844         setTime(TIME_10_MIN);
845 
846         // Add a different package in the group will first package is still in use
847         startUsage(PKG_GAME1);
848         setTime(TIME_10_MIN * 2);
849         // Stop first package usage
850         stopUsage(PKG_SOC1);
851 
852         setTime(TIME_30_MIN);
853         stopUsage(PKG_GAME1);
854 
855         assertEquals(TIME_30_MIN, group.getUsageTimeMs());
856         assertTrue(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
857     }
858 
859     /** Verify that a session will continue if usage starts again within the session threshold */
860     @Test
testUsageSessionObserver_ContinueSession()861     public void testUsageSessionObserver_ContinueSession() throws Exception {
862         setTime(0L);
863         addUsageSessionObserver(OBS_ID1, GROUP1, 10_000L, 2_000L);
864         startUsage(PKG_SOC1);
865         setTime(6_000L);
866         stopUsage(PKG_SOC1);
867         // Wait momentarily, Session should not end
868         assertFalse(mSessionEndLatch.await(1_000L, TimeUnit.MILLISECONDS));
869 
870         setTime(7_000L);
871         startUsage(PKG_SOC1);
872         setTime(10_500L);
873         stopUsage(PKG_SOC1);
874         // Total usage time has not reached the limit. Time limit callback should not fire yet
875         assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
876 
877         setTime(10_600L);
878         startUsage(PKG_SOC1);
879         setTime(12_000L);
880         assertTrue(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
881         stopUsage(PKG_SOC1);
882         final ArgumentCaptor<AlarmManager.OnAlarmListener> onAlarmListenerArgumentCaptor =
883                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
884         verify(mMockAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
885                 anyString(), onAlarmListenerArgumentCaptor.capture(), any());
886         // Usage has stopped, Session should end in 2 seconds. Verify session end occurs
887         // (+/- 100ms, which is hopefully not too slim a margin)
888         assertFalse(mSessionEndLatch.await(1_900L, TimeUnit.MILLISECONDS));
889         onAlarmListenerArgumentCaptor.getValue().onAlarm();
890         assertTrue(mSessionEndLatch.await(200L, TimeUnit.MILLISECONDS));
891         // Verify that the observer was not removed
892         assertTrue(hasUsageSessionObserver(UID, OBS_ID1));
893     }
894 
895     /** Verify that a new session will start if next usage starts after the session threshold */
896     @Test
testUsageSessionObserver_NewSession()897     public void testUsageSessionObserver_NewSession() throws Exception {
898         setTime(0L);
899         addUsageSessionObserver(OBS_ID1, GROUP1, 10_000L, 1_000L);
900         startUsage(PKG_SOC1);
901         setTime(6_000L);
902         stopUsage(PKG_SOC1);
903         // Wait for longer than the session threshold. Session end callback should not be triggered
904         // because the usage timelimit hasn't been triggered.
905         assertFalse(mSessionEndLatch.await(1_500L, TimeUnit.MILLISECONDS));
906 
907         setTime(7_500L);
908         // This should be the start of a new session
909         startUsage(PKG_SOC1);
910         setTime(16_000L);
911         stopUsage(PKG_SOC1);
912         // Total usage has exceed the timelimit, but current session time has not
913         assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
914 
915         setTime(16_100L);
916         startUsage(PKG_SOC1);
917         setTime(18_000L);
918         assertTrue(mLimitReachedLatch.await(2000L, TimeUnit.MILLISECONDS));
919         stopUsage(PKG_SOC1);
920         final ArgumentCaptor<AlarmManager.OnAlarmListener> onAlarmListenerArgumentCaptor =
921                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
922         verify(mMockAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
923                 anyString(), onAlarmListenerArgumentCaptor.capture(), any());
924         // Usage has stopped, Session should end in 2 seconds. Verify session end occurs
925         // (+/- 100ms, which is hopefully not too slim a margin)
926         assertFalse(mSessionEndLatch.await(900L, TimeUnit.MILLISECONDS));
927         onAlarmListenerArgumentCaptor.getValue().onAlarm();
928         assertTrue(mSessionEndLatch.await(200L, TimeUnit.MILLISECONDS));
929         // Verify that the observer was not removed
930         assertTrue(hasUsageSessionObserver(UID, OBS_ID1));
931     }
932 
933     /** Verify that the callbacks will be triggered for multiple sessions */
934     @Test
testUsageSessionObserver_RepeatSessions()935     public void testUsageSessionObserver_RepeatSessions() throws Exception {
936         setTime(0L);
937         addUsageSessionObserver(OBS_ID1, GROUP1, 10_000L, 1_000L);
938         startUsage(PKG_SOC1);
939         setTime(9_000L);
940         stopUsage(PKG_SOC1);
941         // Stutter usage here, to reduce real world time needed trigger limit reached callback
942         startUsage(PKG_SOC1);
943         setTime(11_000L);
944         assertTrue(mLimitReachedLatch.await(2_000L, TimeUnit.MILLISECONDS));
945         stopUsage(PKG_SOC1);
946         final ArgumentCaptor<AlarmManager.OnAlarmListener> onAlarmListenerArgumentCaptor =
947                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
948         verify(mMockAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
949                 anyString(), onAlarmListenerArgumentCaptor.capture(), any());
950         // Usage has stopped, Session should end in 1 seconds. Verify session end occurs
951         // (+/- 100ms, which is hopefully not too slim a margin)
952         assertFalse(mSessionEndLatch.await(900L, TimeUnit.MILLISECONDS));
953         onAlarmListenerArgumentCaptor.getValue().onAlarm();
954         assertTrue(mSessionEndLatch.await(200L, TimeUnit.MILLISECONDS));
955 
956         // Rearm the countdown latches
957         mLimitReachedLatch = new CountDownLatch(1);
958         mSessionEndLatch = new CountDownLatch(1);
959 
960         // New session start
961         setTime(20_000L);
962         startUsage(PKG_SOC1);
963         setTime(29_000L);
964         stopUsage(PKG_SOC1);
965         startUsage(PKG_SOC1);
966         setTime(31_000L);
967         assertTrue(mLimitReachedLatch.await(2_000L, TimeUnit.MILLISECONDS));
968         stopUsage(PKG_SOC1);
969         verify(mMockAlarmManager, times(2)).setExact(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
970                 anyString(), onAlarmListenerArgumentCaptor.capture(), any());
971         assertFalse(mSessionEndLatch.await(900L, TimeUnit.MILLISECONDS));
972         onAlarmListenerArgumentCaptor.getValue().onAlarm();
973         assertTrue(mSessionEndLatch.await(200L, TimeUnit.MILLISECONDS));
974         assertTrue(hasUsageSessionObserver(UID, OBS_ID1));
975     }
976 
977     /** Verify the timeout message is delivered at the right time after past usage was reported */
978     @Test
testAppUsageObserver_PastUsage()979     public void testAppUsageObserver_PastUsage() throws Exception {
980         setTime(10_000L);
981         addAppUsageObserver(OBS_ID1, GROUP1, 6_000L);
982         setTime(20_000L);
983         startPastUsage(PKG_SOC1, 5_000);
984         setTime(21_000L);
985         assertTrue(mLimitReachedLatch.await(2_000L, TimeUnit.MILLISECONDS));
986         stopUsage(PKG_SOC1);
987         // Verify that the observer was removed
988         assertFalse(hasAppUsageObserver(UID, OBS_ID1));
989     }
990 
991     /**
992      * Verify the timeout message is delivered at the right time after past usage was reported
993      * that overlaps with already known usage
994      */
995     @Test
testAppUsageObserver_PastUsageOverlap()996     public void testAppUsageObserver_PastUsageOverlap() throws Exception {
997         setTime(0L);
998         addAppUsageObserver(OBS_ID1, GROUP1, 20_000L);
999         setTime(10_000L);
1000         startUsage(PKG_SOC1);
1001         setTime(20_000L);
1002         stopUsage(PKG_SOC1);
1003         setTime(25_000L);
1004         startPastUsage(PKG_SOC1, 9_000);
1005         setTime(26_000L);
1006         // the 4 seconds of overlapped usage should not be counted
1007         assertFalse(mLimitReachedLatch.await(2_000L, TimeUnit.MILLISECONDS));
1008         setTime(30_000L);
1009         assertTrue(mLimitReachedLatch.await(4_000L, TimeUnit.MILLISECONDS));
1010         stopUsage(PKG_SOC1);
1011         // Verify that the observer was removed
1012         assertFalse(hasAppUsageObserver(UID, OBS_ID1));
1013     }
1014 
1015     /** Verify app usage limit observer added correctly reports its total usage limit */
1016     @Test
testAppUsageLimitObserver_GetTotalUsageLimit()1017     public void testAppUsageLimitObserver_GetTotalUsageLimit() {
1018         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
1019         AppTimeLimitController.AppUsageLimitGroup group = getAppUsageLimitObserver(UID, OBS_ID1);
1020         assertNotNull("Observer wasn't added", group);
1021         assertEquals("Observer didn't correctly report total usage limit",
1022                 TIME_30_MIN, group.getTotaUsageLimit());
1023     }
1024 
1025     /** Verify app usage limit observer added correctly reports its total usage limit */
1026     @Test
testAppUsageLimitObserver_GetUsageRemaining()1027     public void testAppUsageLimitObserver_GetUsageRemaining() {
1028         setTime(0L);
1029         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
1030         startUsage(PKG_SOC1);
1031         setTime(TIME_10_MIN);
1032         stopUsage(PKG_SOC1);
1033         AppTimeLimitController.AppUsageLimitGroup group = getAppUsageLimitObserver(UID, OBS_ID1);
1034         assertNotNull("Observer wasn't added", group);
1035         assertEquals("Observer didn't correctly report total usage limit",
1036                 TIME_10_MIN * 2, group.getUsageRemaining());
1037     }
1038 
1039     /** Verify the app usage limit observer with the smallest usage limit remaining is returned
1040      *  when querying the getAppUsageLimit API.
1041      */
1042     @Test
testAppUsageLimitObserver_GetAppUsageLimit()1043     public void testAppUsageLimitObserver_GetAppUsageLimit() {
1044         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
1045         addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, 0);
1046         UsageStatsManagerInternal.AppUsageLimitData group = getAppUsageLimit(PKG_SOC1);
1047         assertEquals("Observer with the smallest usage limit remaining wasn't returned",
1048                 TIME_10_MIN, group.getTotalUsageLimit());
1049     }
1050 
1051     /** Verify the app usage limit observer with the smallest usage limit remaining is returned
1052      *  when querying the getAppUsageLimit API.
1053      */
1054     @Test
testAppUsageLimitObserver_GetAppUsageLimitUsed()1055     public void testAppUsageLimitObserver_GetAppUsageLimitUsed() {
1056         setTime(0L);
1057         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
1058         addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, 0);
1059         startUsage(PKG_GAME1);
1060         setTime(TIME_10_MIN * 2 + TIME_1_MIN);
1061         stopUsage(PKG_GAME1);
1062         // PKG_GAME1 is only in GROUP1 but since we're querying for PCK_SOC1 which is
1063         // in both groups, GROUP1 should be returned since it has a smaller time remaining
1064         UsageStatsManagerInternal.AppUsageLimitData group = getAppUsageLimit(PKG_SOC1);
1065         assertEquals("Observer with the smallest usage limit remaining wasn't returned",
1066                 TIME_1_MIN * 9, group.getUsageRemaining());
1067     }
1068 
1069     /** Verify the app usage limit observer with the smallest usage limit remaining is returned
1070      *  when querying the getAppUsageLimit API.
1071      */
1072     @Test
testAppUsageLimitObserver_GetAppUsageLimitAllUsed()1073     public void testAppUsageLimitObserver_GetAppUsageLimitAllUsed() {
1074         setTime(0L);
1075         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, 0);
1076         addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, 0);
1077         startUsage(PKG_SOC1);
1078         setTime(TIME_10_MIN);
1079         stopUsage(PKG_SOC1);
1080         // GROUP_SOC should be returned since it should be completely used up (0ms remaining)
1081         UsageStatsManagerInternal.AppUsageLimitData group = getAppUsageLimit(PKG_SOC1);
1082         assertEquals("Observer with the smallest usage limit remaining wasn't returned",
1083                 0L, group.getUsageRemaining());
1084     }
1085 
1086     /** Verify that a limit of 0 is not allowed. */
1087     @Test
testAppUsageLimitObserver_ZeroTimeLimitIsNotAllowed()1088     public void testAppUsageLimitObserver_ZeroTimeLimitIsNotAllowed() {
1089         try {
1090             addAppUsageLimitObserver(OBS_ID1, GROUP1, 0, 0);
1091             fail("timeLimit of 0 should not be allowed.");
1092         } catch (IllegalArgumentException expected) {
1093             // Exception expected.
1094         }
1095     }
1096 
1097     /** Verify that timeUsed can be the same as timeLimit (for re-registering observers). */
1098     @Test
testAppUsageLimitObserver_ZeroTimeRemainingIsAllowed()1099     public void testAppUsageLimitObserver_ZeroTimeRemainingIsAllowed() {
1100         addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_1_MIN, TIME_1_MIN);
1101         AppTimeLimitController.AppUsageLimitGroup group = getAppUsageLimitObserver(UID, OBS_ID1);
1102         assertNotNull("Observer wasn't added", group);
1103         assertEquals("Usage remaining was not 0.", 0, group.getUsageRemaining());
1104     }
1105 
startUsage(String packageName)1106     private void startUsage(String packageName) {
1107         mController.noteUsageStart(packageName, USER_ID);
1108     }
1109 
startPastUsage(String packageName, int timeAgo)1110     private void startPastUsage(String packageName, int timeAgo) {
1111         mController.noteUsageStart(packageName, USER_ID, timeAgo);
1112     }
1113 
stopUsage(String packageName)1114     private void stopUsage(String packageName) {
1115         mController.noteUsageStop(packageName, USER_ID);
1116     }
1117 
addAppUsageObserver(int observerId, String[] packages, long timeLimit)1118     private void addAppUsageObserver(int observerId, String[] packages, long timeLimit) {
1119         mController.addAppUsageObserver(UID, observerId, packages, timeLimit, null, USER_ID);
1120     }
1121 
addUsageSessionObserver(int observerId, String[] packages, long timeLimit, long sessionThreshold)1122     private void addUsageSessionObserver(int observerId, String[] packages, long timeLimit,
1123             long sessionThreshold) {
1124         mController.addUsageSessionObserver(UID, observerId, packages, timeLimit, sessionThreshold,
1125                 null, null, USER_ID);
1126     }
1127 
addAppUsageLimitObserver(int observerId, String[] packages, long timeLimit, long timeUsed)1128     private void addAppUsageLimitObserver(int observerId, String[] packages, long timeLimit,
1129             long timeUsed) {
1130         mController.addAppUsageLimitObserver(UID, observerId, packages, timeLimit, timeUsed,
1131                 null, USER_ID);
1132     }
1133 
1134     /** Is there still an app usage observer by that id */
hasAppUsageObserver(int uid, int observerId)1135     private boolean hasAppUsageObserver(int uid, int observerId) {
1136         return mController.getAppUsageGroup(uid, observerId) != null;
1137     }
1138 
1139     /** Is there still an usage session observer by that id */
hasUsageSessionObserver(int uid, int observerId)1140     private boolean hasUsageSessionObserver(int uid, int observerId) {
1141         return mController.getSessionUsageGroup(uid, observerId) != null;
1142     }
1143 
1144     /** Is there still an app usage limit observer by that id */
hasAppUsageLimitObserver(int uid, int observerId)1145     private boolean hasAppUsageLimitObserver(int uid, int observerId) {
1146         return mController.getAppUsageLimitGroup(uid, observerId) != null;
1147     }
1148 
getAppUsageLimitObserver( int uid, int observerId)1149     private AppTimeLimitController.AppUsageLimitGroup getAppUsageLimitObserver(
1150             int uid, int observerId) {
1151         return mController.getAppUsageLimitGroup(uid, observerId);
1152     }
1153 
getAppUsageLimit(String packageName)1154     private UsageStatsManagerInternal.AppUsageLimitData getAppUsageLimit(String packageName) {
1155         return mController.getAppUsageLimit(packageName, UserHandle.of(USER_ID));
1156     }
1157 
setTime(long time)1158     private void setTime(long time) {
1159         mElapsedTime = time;
1160     }
1161 }
1162