AppTimeLimitControllerTests.java revision c870309921dab30893f26409625058f0eddf5a18
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 17package com.android.server.usage; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertFalse; 21import static org.junit.Assert.assertTrue; 22import static org.junit.Assert.fail; 23 24import android.app.PendingIntent; 25import android.os.HandlerThread; 26import android.os.Looper; 27import android.support.test.filters.MediumTest; 28import android.support.test.runner.AndroidJUnit4; 29 30import org.junit.After; 31import org.junit.Before; 32import org.junit.Test; 33import org.junit.runner.RunWith; 34 35import java.util.concurrent.CountDownLatch; 36import java.util.concurrent.TimeUnit; 37 38@RunWith(AndroidJUnit4.class) 39@MediumTest 40public class AppTimeLimitControllerTests { 41 42 private static final String PKG_SOC1 = "package.soc1"; 43 private static final String PKG_SOC2 = "package.soc2"; 44 private static final String PKG_GAME1 = "package.game1"; 45 private static final String PKG_GAME2 = "package.game2"; 46 private static final String PKG_PROD = "package.prod"; 47 48 private static final int UID = 10100; 49 private static final int USER_ID = 10; 50 private static final int OBS_ID1 = 1; 51 private static final int OBS_ID2 = 2; 52 private static final int OBS_ID3 = 3; 53 private static final int OBS_ID4 = 4; 54 private static final int OBS_ID5 = 5; 55 private static final int OBS_ID6 = 6; 56 private static final int OBS_ID7 = 7; 57 private static final int OBS_ID8 = 8; 58 private static final int OBS_ID9 = 9; 59 private static final int OBS_ID10 = 10; 60 private static final int OBS_ID11 = 11; 61 62 private static final long TIME_30_MIN = 30 * 60_000L; 63 private static final long TIME_10_MIN = 10 * 60_000L; 64 65 private static final long MAX_OBSERVER_PER_UID = 10; 66 private static final long MIN_TIME_LIMIT = 4_000L; 67 68 private static final String[] GROUP1 = { 69 PKG_SOC1, PKG_GAME1, PKG_PROD 70 }; 71 72 private static final String[] GROUP_SOC = { 73 PKG_SOC1, PKG_SOC2 74 }; 75 76 private static final String[] GROUP_GAME = { 77 PKG_GAME1, PKG_GAME2 78 }; 79 80 private final CountDownLatch mCountDownLatch = new CountDownLatch(1); 81 82 private AppTimeLimitController mController; 83 84 private HandlerThread mThread; 85 86 private long mUptimeMillis; 87 88 AppTimeLimitController.OnLimitReachedListener mListener 89 = new AppTimeLimitController.OnLimitReachedListener() { 90 91 @Override 92 public void onLimitReached(int observerId, int userId, long timeLimit, long timeElapsed, 93 PendingIntent callbackIntent) { 94 mCountDownLatch.countDown(); 95 } 96 }; 97 98 class MyAppTimeLimitController extends AppTimeLimitController { 99 MyAppTimeLimitController(AppTimeLimitController.OnLimitReachedListener listener, 100 Looper looper) { 101 super(listener, looper); 102 } 103 104 @Override 105 protected long getUptimeMillis() { 106 return mUptimeMillis; 107 } 108 109 @Override 110 protected long getObserverPerUidLimit() { 111 return MAX_OBSERVER_PER_UID; 112 } 113 114 @Override 115 protected long getMinTimeLimit() { 116 return MIN_TIME_LIMIT; 117 } 118 } 119 120 @Before 121 public void setUp() { 122 mThread = new HandlerThread("Test"); 123 mThread.start(); 124 mController = new MyAppTimeLimitController(mListener, mThread.getLooper()); 125 } 126 127 @After 128 public void tearDown() { 129 mThread.quit(); 130 } 131 132 /** Verify observer is added */ 133 @Test 134 public void testAddObserver() { 135 addObserver(OBS_ID1, GROUP1, TIME_30_MIN); 136 assertTrue("Observer wasn't added", hasObserver(OBS_ID1)); 137 addObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN); 138 assertTrue("Observer wasn't added", hasObserver(OBS_ID2)); 139 assertTrue("Observer wasn't added", hasObserver(OBS_ID1)); 140 } 141 142 /** Verify observer is removed */ 143 @Test 144 public void testRemoveObserver() { 145 addObserver(OBS_ID1, GROUP1, TIME_30_MIN); 146 assertTrue("Observer wasn't added", hasObserver(OBS_ID1)); 147 mController.removeObserver(UID, OBS_ID1, USER_ID); 148 assertFalse("Observer wasn't removed", hasObserver(OBS_ID1)); 149 } 150 151 /** Re-adding an observer should result in only one copy */ 152 @Test 153 public void testObserverReAdd() { 154 addObserver(OBS_ID1, GROUP1, TIME_30_MIN); 155 assertTrue("Observer wasn't added", hasObserver(OBS_ID1)); 156 addObserver(OBS_ID1, GROUP1, TIME_10_MIN); 157 assertTrue("Observer wasn't added", 158 mController.getObserverGroup(OBS_ID1, USER_ID).timeLimit == TIME_10_MIN); 159 mController.removeObserver(UID, OBS_ID1, USER_ID); 160 assertFalse("Observer wasn't removed", hasObserver(OBS_ID1)); 161 } 162 163 /** Verify that usage across different apps within a group are added up */ 164 @Test 165 public void testAccumulation() throws Exception { 166 setTime(0L); 167 addObserver(OBS_ID1, GROUP1, TIME_30_MIN); 168 moveToForeground(PKG_SOC1); 169 // Add 10 mins 170 setTime(TIME_10_MIN); 171 moveToBackground(PKG_SOC1); 172 173 long timeRemaining = mController.getObserverGroup(OBS_ID1, USER_ID).timeRemaining; 174 assertEquals(TIME_10_MIN * 2, timeRemaining); 175 176 moveToForeground(PKG_SOC1); 177 setTime(TIME_10_MIN * 2); 178 moveToBackground(PKG_SOC1); 179 180 timeRemaining = mController.getObserverGroup(OBS_ID1, USER_ID).timeRemaining; 181 assertEquals(TIME_10_MIN, timeRemaining); 182 183 setTime(TIME_30_MIN); 184 185 assertFalse(mCountDownLatch.await(100L, TimeUnit.MILLISECONDS)); 186 187 // Add a different package in the group 188 moveToForeground(PKG_GAME1); 189 setTime(TIME_30_MIN + TIME_10_MIN); 190 moveToBackground(PKG_GAME1); 191 192 assertEquals(0, mController.getObserverGroup(OBS_ID1, USER_ID).timeRemaining); 193 assertTrue(mCountDownLatch.await(100L, TimeUnit.MILLISECONDS)); 194 } 195 196 /** Verify that time limit does not get triggered due to a different app */ 197 @Test 198 public void testTimeoutOtherApp() throws Exception { 199 setTime(0L); 200 addObserver(OBS_ID1, GROUP1, 4_000L); 201 moveToForeground(PKG_SOC2); 202 assertFalse(mCountDownLatch.await(6_000L, TimeUnit.MILLISECONDS)); 203 setTime(6_000L); 204 moveToBackground(PKG_SOC2); 205 assertFalse(mCountDownLatch.await(100L, TimeUnit.MILLISECONDS)); 206 } 207 208 /** Verify the timeout message is delivered at the right time */ 209 @Test 210 public void testTimeout() throws Exception { 211 setTime(0L); 212 addObserver(OBS_ID1, GROUP1, 4_000L); 213 moveToForeground(PKG_SOC1); 214 setTime(6_000L); 215 assertTrue(mCountDownLatch.await(6_000L, TimeUnit.MILLISECONDS)); 216 moveToBackground(PKG_SOC1); 217 // Verify that the observer was removed 218 assertFalse(hasObserver(OBS_ID1)); 219 } 220 221 /** If an app was already running, make sure it is partially counted towards the time limit */ 222 @Test 223 public void testAlreadyRunning() throws Exception { 224 setTime(TIME_10_MIN); 225 moveToForeground(PKG_GAME1); 226 setTime(TIME_30_MIN); 227 addObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN); 228 setTime(TIME_30_MIN + TIME_10_MIN); 229 moveToBackground(PKG_GAME1); 230 assertFalse(mCountDownLatch.await(1000L, TimeUnit.MILLISECONDS)); 231 232 moveToForeground(PKG_GAME2); 233 setTime(TIME_30_MIN + TIME_30_MIN); 234 moveToBackground(PKG_GAME2); 235 assertTrue(mCountDownLatch.await(1000L, TimeUnit.MILLISECONDS)); 236 // Verify that the observer was removed 237 assertFalse(hasObserver(OBS_ID2)); 238 } 239 240 /** If watched app is already running, verify the timeout callback happens at the right time */ 241 @Test 242 public void testAlreadyRunningTimeout() throws Exception { 243 setTime(0); 244 moveToForeground(PKG_SOC1); 245 setTime(TIME_10_MIN); 246 // 10 second time limit 247 addObserver(OBS_ID1, GROUP_SOC, 10_000L); 248 setTime(TIME_10_MIN + 5_000L); 249 // Shouldn't call back in 6 seconds 250 assertFalse(mCountDownLatch.await(6_000L, TimeUnit.MILLISECONDS)); 251 setTime(TIME_10_MIN + 10_000L); 252 // Should call back by 11 seconds (6 earlier + 5 now) 253 assertTrue(mCountDownLatch.await(5_000L, TimeUnit.MILLISECONDS)); 254 // Verify that the observer was removed 255 assertFalse(hasObserver(OBS_ID1)); 256 } 257 258 /** Verify that App Time Limit Controller will limit the number of observerIds */ 259 @Test 260 public void testMaxObserverLimit() throws Exception { 261 boolean receivedException = false; 262 int ANOTHER_UID = UID + 1; 263 addObserver(OBS_ID1, GROUP1, TIME_30_MIN); 264 addObserver(OBS_ID2, GROUP1, TIME_30_MIN); 265 addObserver(OBS_ID3, GROUP1, TIME_30_MIN); 266 addObserver(OBS_ID4, GROUP1, TIME_30_MIN); 267 addObserver(OBS_ID5, GROUP1, TIME_30_MIN); 268 addObserver(OBS_ID6, GROUP1, TIME_30_MIN); 269 addObserver(OBS_ID7, GROUP1, TIME_30_MIN); 270 addObserver(OBS_ID8, GROUP1, TIME_30_MIN); 271 addObserver(OBS_ID9, GROUP1, TIME_30_MIN); 272 addObserver(OBS_ID10, GROUP1, TIME_30_MIN); 273 // Readding an observer should not cause an IllegalStateException 274 addObserver(OBS_ID5, GROUP1, TIME_30_MIN); 275 // Adding an observer for a different uid shouldn't cause an IllegalStateException 276 mController.addObserver(ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, null, USER_ID); 277 try { 278 addObserver(OBS_ID11, GROUP1, TIME_30_MIN); 279 } catch (IllegalStateException ise) { 280 receivedException = true; 281 } 282 assertTrue("Should have caused an IllegalStateException", receivedException); 283 } 284 285 /** Verify that addObserver minimum time limit is one minute */ 286 @Test 287 public void testMinimumTimeLimit() throws Exception { 288 boolean receivedException = false; 289 // adding an observer with a one minute time limit should not cause an exception 290 addObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT); 291 try { 292 addObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT - 1); 293 } catch (IllegalArgumentException iae) { 294 receivedException = true; 295 } 296 assertTrue("Should have caused an IllegalArgumentException", receivedException); 297 } 298 299 private void moveToForeground(String packageName) { 300 mController.moveToForeground(packageName, "class", USER_ID); 301 } 302 303 private void moveToBackground(String packageName) { 304 mController.moveToBackground(packageName, "class", USER_ID); 305 } 306 307 private void addObserver(int observerId, String[] packages, long timeLimit) { 308 mController.addObserver(UID, observerId, packages, timeLimit, null, USER_ID); 309 } 310 311 /** Is there still an observer by that id */ 312 private boolean hasObserver(int observerId) { 313 return mController.getObserverGroup(observerId, USER_ID) != null; 314 } 315 316 private void setTime(long time) { 317 mUptimeMillis = time; 318 } 319} 320