blob: cbbdca6b394ff0eb7d50f4f52093b422ea73ff30 [file] [log] [blame]
Amith Yamasani17fffee2017-09-29 13:17:43 -07001/*
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
17package com.android.server.usage;
18
Amith Yamasani803eab692017-11-09 17:47:04 -080019import static android.app.usage.UsageEvents.Event.NOTIFICATION_SEEN;
20import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
Amith Yamasani93885192017-12-13 11:52:10 -080021import static android.app.usage.UsageStatsManager.REASON_DEFAULT;
22import static android.app.usage.UsageStatsManager.REASON_FORCED;
Amith Yamasanibd7b3022017-12-06 17:40:25 -080023import static android.app.usage.UsageStatsManager.REASON_PREDICTED;
Amith Yamasani93885192017-12-13 11:52:10 -080024import static android.app.usage.UsageStatsManager.REASON_TIMEOUT;
25import static android.app.usage.UsageStatsManager.REASON_USAGE;
Amith Yamasaniafbccb72017-11-27 10:44:24 -080026import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
Amith Yamasani777b1532018-01-28 23:20:07 +000027import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
Amith Yamasaniafbccb72017-11-27 10:44:24 -080028import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
Amith Yamasani93885192017-12-13 11:52:10 -080029import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
Amith Yamasaniafbccb72017-11-27 10:44:24 -080030import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
31import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
Amith Yamasani803eab692017-11-09 17:47:04 -080032
Amith Yamasani17fffee2017-09-29 13:17:43 -070033import static org.junit.Assert.assertEquals;
34import static org.junit.Assert.assertFalse;
35import static org.junit.Assert.assertNotEquals;
36import static org.junit.Assert.assertTrue;
37
Sudheer Shanka101c3532018-01-08 16:28:42 -080038import static org.junit.Assert.fail;
Amith Yamasani777b1532018-01-28 23:20:07 +000039import static org.mockito.ArgumentMatchers.eq;
Amith Yamasani17fffee2017-09-29 13:17:43 -070040import static org.mockito.Matchers.anyInt;
41import static org.mockito.Matchers.anyString;
42import static org.mockito.Mockito.doReturn;
43import static org.mockito.Mockito.mock;
44
Amith Yamasani17fffee2017-09-29 13:17:43 -070045import android.app.usage.UsageEvents;
46import android.appwidget.AppWidgetManager;
47import android.content.Context;
48import android.content.ContextWrapper;
49import android.content.pm.ApplicationInfo;
50import android.content.pm.PackageInfo;
51import android.content.pm.PackageManager;
52import android.hardware.display.DisplayManager;
53import android.os.Handler;
54import android.os.Looper;
55import android.os.RemoteException;
Amith Yamasani53f06ea2018-01-05 17:53:46 -080056import android.platform.test.annotations.Presubmit;
57import android.support.test.filters.SmallTest;
Amith Yamasani17fffee2017-09-29 13:17:43 -070058import android.support.test.InstrumentationRegistry;
59import android.support.test.runner.AndroidJUnit4;
Sudheer Shanka101c3532018-01-08 16:28:42 -080060import android.util.ArraySet;
Amith Yamasani17fffee2017-09-29 13:17:43 -070061import android.view.Display;
62
63import com.android.server.SystemService;
64
65import org.junit.Before;
66import org.junit.Test;
67import org.junit.runner.RunWith;
68
69import java.io.File;
70import java.util.ArrayList;
Sudheer Shanka101c3532018-01-08 16:28:42 -080071import java.util.Arrays;
Amith Yamasani17fffee2017-09-29 13:17:43 -070072import java.util.List;
Sudheer Shanka101c3532018-01-08 16:28:42 -080073import java.util.Set;
Amith Yamasani17fffee2017-09-29 13:17:43 -070074
75/**
76 * Unit test for AppStandbyController.
77 */
78@RunWith(AndroidJUnit4.class)
Amith Yamasani53f06ea2018-01-05 17:53:46 -080079@Presubmit
80@SmallTest
Amith Yamasani17fffee2017-09-29 13:17:43 -070081public class AppStandbyControllerTests {
82
83 private static final String PACKAGE_1 = "com.example.foo";
84 private static final int UID_1 = 10000;
Amith Yamasani777b1532018-01-28 23:20:07 +000085 private static final String PACKAGE_EXEMPTED_1 = "com.android.exempted";
86 private static final int UID_EXEMPTED_1 = 10001;
Amith Yamasani17fffee2017-09-29 13:17:43 -070087 private static final int USER_ID = 0;
Sudheer Shanka101c3532018-01-08 16:28:42 -080088 private static final int USER_ID2 = 10;
89
90 private static final String ADMIN_PKG = "com.android.admin";
91 private static final String ADMIN_PKG2 = "com.android.admin2";
92 private static final String ADMIN_PKG3 = "com.android.admin3";
Amith Yamasani17fffee2017-09-29 13:17:43 -070093
94 private static final long MINUTE_MS = 60 * 1000;
95 private static final long HOUR_MS = 60 * MINUTE_MS;
96 private static final long DAY_MS = 24 * HOUR_MS;
97
Amith Yamasani301e94a2017-11-17 16:35:44 -080098 private static final long WORKING_SET_THRESHOLD = 12 * HOUR_MS;
99 private static final long FREQUENT_THRESHOLD = 24 * HOUR_MS;
100 private static final long RARE_THRESHOLD = 48 * HOUR_MS;
101
Amith Yamasani17fffee2017-09-29 13:17:43 -0700102 private MyInjector mInjector;
Amith Yamasani93885192017-12-13 11:52:10 -0800103 private AppStandbyController mController;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700104
105 static class MyContextWrapper extends ContextWrapper {
106 PackageManager mockPm = mock(PackageManager.class);
107
108 public MyContextWrapper(Context base) {
109 super(base);
110 }
111
112 public PackageManager getPackageManager() {
113 return mockPm;
114 }
115 }
116
117 static class MyInjector extends AppStandbyController.Injector {
118 long mElapsedRealtime;
119 boolean mIsCharging;
120 List<String> mPowerSaveWhitelistExceptIdle = new ArrayList<>();
121 boolean mDisplayOn;
122 DisplayManager.DisplayListener mDisplayListener;
Amith Yamasani777b1532018-01-28 23:20:07 +0000123 String mBoundWidgetPackage = PACKAGE_EXEMPTED_1;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700124
125 MyInjector(Context context, Looper looper) {
126 super(context, looper);
127 }
128
129 @Override
130 void onBootPhase(int phase) {
131 }
132
133 @Override
134 int getBootPhase() {
135 return SystemService.PHASE_BOOT_COMPLETED;
136 }
137
138 @Override
139 long elapsedRealtime() {
140 return mElapsedRealtime;
141 }
142
143 @Override
144 long currentTimeMillis() {
145 return mElapsedRealtime;
146 }
147
148 @Override
149 boolean isAppIdleEnabled() {
150 return true;
151 }
152
153 @Override
154 boolean isCharging() {
155 return mIsCharging;
156 }
157
158 @Override
159 boolean isPowerSaveWhitelistExceptIdleApp(String packageName) throws RemoteException {
160 return mPowerSaveWhitelistExceptIdle.contains(packageName);
161 }
162
163 @Override
164 File getDataSystemDirectory() {
165 return new File(getContext().getFilesDir(), Long.toString(Math.randomLongInternal()));
166 }
167
168 @Override
169 void noteEvent(int event, String packageName, int uid) throws RemoteException {
170 }
171
172 @Override
173 boolean isPackageEphemeral(int userId, String packageName) {
174 // TODO: update when testing ephemeral apps scenario
175 return false;
176 }
177
178 @Override
179 int[] getRunningUserIds() {
180 return new int[] {USER_ID};
181 }
182
183 @Override
184 boolean isDefaultDisplayOn() {
185 return mDisplayOn;
186 }
187
188 @Override
189 void registerDisplayListener(DisplayManager.DisplayListener listener, Handler handler) {
190 mDisplayListener = listener;
191 }
192
193 @Override
194 String getActiveNetworkScorer() {
195 return null;
196 }
197
198 @Override
199 public boolean isBoundWidgetPackage(AppWidgetManager appWidgetManager, String packageName,
200 int userId) {
201 return packageName != null && packageName.equals(mBoundWidgetPackage);
202 }
203
Amith Yamasani301e94a2017-11-17 16:35:44 -0800204 @Override
205 String getAppIdleSettings() {
206 return "screen_thresholds=0/0/0/" + HOUR_MS + ",elapsed_thresholds=0/"
207 + WORKING_SET_THRESHOLD + "/"
208 + FREQUENT_THRESHOLD + "/"
209 + RARE_THRESHOLD;
210 }
211
Amith Yamasani17fffee2017-09-29 13:17:43 -0700212 // Internal methods
213
214 void setDisplayOn(boolean on) {
215 mDisplayOn = on;
216 if (mDisplayListener != null) {
217 mDisplayListener.onDisplayChanged(Display.DEFAULT_DISPLAY);
218 }
219 }
220 }
221
222 private void setupPm(PackageManager mockPm) throws PackageManager.NameNotFoundException {
223 List<PackageInfo> packages = new ArrayList<>();
224 PackageInfo pi = new PackageInfo();
225 pi.applicationInfo = new ApplicationInfo();
226 pi.applicationInfo.uid = UID_1;
227 pi.packageName = PACKAGE_1;
228 packages.add(pi);
229
Amith Yamasani777b1532018-01-28 23:20:07 +0000230 PackageInfo pie = new PackageInfo();
231 pie.applicationInfo = new ApplicationInfo();
232 pie.applicationInfo.uid = UID_EXEMPTED_1;
233 pie.packageName = PACKAGE_EXEMPTED_1;
234 packages.add(pie);
235
Amith Yamasani17fffee2017-09-29 13:17:43 -0700236 doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(), anyInt());
237 try {
Amith Yamasani777b1532018-01-28 23:20:07 +0000238 doReturn(UID_1).when(mockPm).getPackageUidAsUser(eq(PACKAGE_1), anyInt(), anyInt());
239 doReturn(UID_EXEMPTED_1).when(mockPm).getPackageUidAsUser(eq(PACKAGE_EXEMPTED_1),
240 anyInt(), anyInt());
241 doReturn(pi.applicationInfo).when(mockPm).getApplicationInfo(eq(pi.packageName),
242 anyInt());
243 doReturn(pie.applicationInfo).when(mockPm).getApplicationInfo(eq(pie.packageName),
244 anyInt());
Amith Yamasani17fffee2017-09-29 13:17:43 -0700245 } catch (PackageManager.NameNotFoundException nnfe) {}
246 }
247
248 private void setChargingState(AppStandbyController controller, boolean charging) {
249 mInjector.mIsCharging = charging;
250 if (controller != null) {
251 controller.setChargingState(charging);
252 }
253 }
254
255 private AppStandbyController setupController() throws Exception {
256 mInjector.mElapsedRealtime = 0;
Amith Yamasani777b1532018-01-28 23:20:07 +0000257 setupPm(mInjector.getContext().getPackageManager());
Amith Yamasani17fffee2017-09-29 13:17:43 -0700258 AppStandbyController controller = new AppStandbyController(mInjector);
Amith Yamasani777b1532018-01-28 23:20:07 +0000259 controller.initializeDefaultsForSystemApps(USER_ID);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700260 controller.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
261 controller.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
262 mInjector.setDisplayOn(false);
263 mInjector.setDisplayOn(true);
264 setChargingState(controller, false);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700265 controller.checkIdleStates(USER_ID);
Amith Yamasani777b1532018-01-28 23:20:07 +0000266 assertEquals(STANDBY_BUCKET_EXEMPTED,
267 controller.getAppStandbyBucket(PACKAGE_EXEMPTED_1, USER_ID,
268 mInjector.mElapsedRealtime, false));
269 assertNotEquals(STANDBY_BUCKET_EXEMPTED,
270 controller.getAppStandbyBucket(PACKAGE_1, USER_ID,
271 mInjector.mElapsedRealtime, false));
Amith Yamasani17fffee2017-09-29 13:17:43 -0700272
273 return controller;
274 }
275
276 @Before
277 public void setUp() throws Exception {
278 MyContextWrapper myContext = new MyContextWrapper(InstrumentationRegistry.getContext());
279 mInjector = new MyInjector(myContext, Looper.getMainLooper());
Amith Yamasani93885192017-12-13 11:52:10 -0800280 mController = setupController();
Amith Yamasani17fffee2017-09-29 13:17:43 -0700281 }
282
283 @Test
284 public void testCharging() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800285 setChargingState(mController, true);
Amith Yamasani301e94a2017-11-17 16:35:44 -0800286 mInjector.mElapsedRealtime = RARE_THRESHOLD + 1;
Amith Yamasani93885192017-12-13 11:52:10 -0800287 assertFalse(mController.isAppIdleFilteredOrParoled(PACKAGE_1, USER_ID,
Amith Yamasani17fffee2017-09-29 13:17:43 -0700288 mInjector.mElapsedRealtime, false));
289
Amith Yamasani93885192017-12-13 11:52:10 -0800290 setChargingState(mController, false);
Amith Yamasani301e94a2017-11-17 16:35:44 -0800291 mInjector.mElapsedRealtime = 2 * RARE_THRESHOLD + 2;
Amith Yamasani93885192017-12-13 11:52:10 -0800292 mController.checkIdleStates(USER_ID);
293 assertTrue(mController.isAppIdleFilteredOrParoled(PACKAGE_1, USER_ID,
Amith Yamasani17fffee2017-09-29 13:17:43 -0700294 mInjector.mElapsedRealtime, false));
Amith Yamasani93885192017-12-13 11:52:10 -0800295 setChargingState(mController, true);
296 assertFalse(mController.isAppIdleFilteredOrParoled(PACKAGE_1,USER_ID,
Amith Yamasani17fffee2017-09-29 13:17:43 -0700297 mInjector.mElapsedRealtime, false));
298 }
299
300 private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket) {
301 mInjector.mElapsedRealtime = elapsedTime;
302 controller.checkIdleStates(USER_ID);
303 assertEquals(bucket,
304 controller.getAppStandbyBucket(PACKAGE_1, USER_ID, mInjector.mElapsedRealtime,
305 false));
306 }
307
Amith Yamasani803eab692017-11-09 17:47:04 -0800308 private void reportEvent(AppStandbyController controller, int eventType,
309 long elapsedTime) {
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800310 // Back to ACTIVE on event
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800311 mInjector.mElapsedRealtime = elapsedTime;
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800312 UsageEvents.Event ev = new UsageEvents.Event();
313 ev.mPackage = PACKAGE_1;
Amith Yamasani803eab692017-11-09 17:47:04 -0800314 ev.mEventType = eventType;
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800315 controller.reportEvent(ev, elapsedTime, USER_ID);
316 }
317
Amith Yamasani803eab692017-11-09 17:47:04 -0800318 private int getStandbyBucket(AppStandbyController controller) {
319 return controller.getAppStandbyBucket(PACKAGE_1, USER_ID, mInjector.mElapsedRealtime,
320 true);
321 }
322
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800323 private void assertBucket(int bucket) {
324 assertEquals(bucket, getStandbyBucket(mController));
325 }
326
Amith Yamasani17fffee2017-09-29 13:17:43 -0700327 @Test
328 public void testBuckets() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800329 assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700330
Amith Yamasani93885192017-12-13 11:52:10 -0800331 reportEvent(mController, USER_INTERACTION, 0);
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800332
Amith Yamasani17fffee2017-09-29 13:17:43 -0700333 // ACTIVE bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800334 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700335
336 // WORKING_SET bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800337 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700338
339 // WORKING_SET bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800340 assertTimeout(mController, FREQUENT_THRESHOLD - 1, STANDBY_BUCKET_WORKING_SET);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700341
342 // FREQUENT bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800343 assertTimeout(mController, FREQUENT_THRESHOLD + 1, STANDBY_BUCKET_FREQUENT);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700344
345 // RARE bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800346 assertTimeout(mController, RARE_THRESHOLD + 1, STANDBY_BUCKET_RARE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700347
Amith Yamasani93885192017-12-13 11:52:10 -0800348 reportEvent(mController, USER_INTERACTION, RARE_THRESHOLD + 1);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700349
Amith Yamasani93885192017-12-13 11:52:10 -0800350 assertTimeout(mController, RARE_THRESHOLD + 1, STANDBY_BUCKET_ACTIVE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700351
352 // RARE bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800353 assertTimeout(mController, RARE_THRESHOLD * 2 + 2, STANDBY_BUCKET_RARE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700354 }
355
356 @Test
357 public void testScreenTimeAndBuckets() throws Exception {
Amith Yamasani17fffee2017-09-29 13:17:43 -0700358 mInjector.setDisplayOn(false);
359
Amith Yamasani93885192017-12-13 11:52:10 -0800360 assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800361
Amith Yamasani93885192017-12-13 11:52:10 -0800362 reportEvent(mController, USER_INTERACTION, 0);
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800363
Amith Yamasani17fffee2017-09-29 13:17:43 -0700364 // ACTIVE bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800365 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700366
367 // WORKING_SET bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800368 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700369
370 // RARE bucket, should fail because the screen wasn't ON.
Amith Yamasani301e94a2017-11-17 16:35:44 -0800371 mInjector.mElapsedRealtime = RARE_THRESHOLD + 1;
Amith Yamasani93885192017-12-13 11:52:10 -0800372 mController.checkIdleStates(USER_ID);
373 assertNotEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController));
Amith Yamasani17fffee2017-09-29 13:17:43 -0700374
375 mInjector.setDisplayOn(true);
Amith Yamasani93885192017-12-13 11:52:10 -0800376 assertTimeout(mController, RARE_THRESHOLD * 2 + 2, STANDBY_BUCKET_RARE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700377 }
378
379 @Test
380 public void testForcedIdle() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800381 setChargingState(mController, false);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700382
Amith Yamasani93885192017-12-13 11:52:10 -0800383 mController.forceIdleState(PACKAGE_1, USER_ID, true);
384 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController));
385 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
Amith Yamasani17fffee2017-09-29 13:17:43 -0700386
Amith Yamasani93885192017-12-13 11:52:10 -0800387 mController.forceIdleState(PACKAGE_1, USER_ID, false);
388 assertEquals(STANDBY_BUCKET_ACTIVE, mController.getAppStandbyBucket(PACKAGE_1, USER_ID, 0,
Amith Yamasani17fffee2017-09-29 13:17:43 -0700389 true));
Amith Yamasani93885192017-12-13 11:52:10 -0800390 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
Amith Yamasani17fffee2017-09-29 13:17:43 -0700391 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800392
393 @Test
394 public void testNotificationEvent() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800395 setChargingState(mController, false);
Amith Yamasani803eab692017-11-09 17:47:04 -0800396
Amith Yamasani93885192017-12-13 11:52:10 -0800397 reportEvent(mController, USER_INTERACTION, 0);
398 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
Amith Yamasani803eab692017-11-09 17:47:04 -0800399 mInjector.mElapsedRealtime = 1;
Amith Yamasani93885192017-12-13 11:52:10 -0800400 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
401 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
Amith Yamasani803eab692017-11-09 17:47:04 -0800402
Amith Yamasani93885192017-12-13 11:52:10 -0800403 mController.forceIdleState(PACKAGE_1, USER_ID, true);
404 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
405 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController));
Amith Yamasani803eab692017-11-09 17:47:04 -0800406 }
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800407
408 @Test
409 public void testPredictionTimedout() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800410 setChargingState(mController, false);
411 // Set it to timeout or usage, so that prediction can override it
412 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
413 REASON_TIMEOUT, 1 * HOUR_MS);
414 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController));
415
416 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
417 REASON_PREDICTED + ":CTS", 1 * HOUR_MS);
418 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800419
420 // Fast forward 12 hours
421 mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD;
Amith Yamasani93885192017-12-13 11:52:10 -0800422 mController.checkIdleStates(USER_ID);
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800423 // Should still be in predicted bucket, since prediction timeout is 1 day since prediction
Amith Yamasani93885192017-12-13 11:52:10 -0800424 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800425 // Fast forward two more hours
426 mInjector.mElapsedRealtime += 2 * HOUR_MS;
Amith Yamasani93885192017-12-13 11:52:10 -0800427 mController.checkIdleStates(USER_ID);
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800428 // Should have now applied prediction timeout
Amith Yamasani93885192017-12-13 11:52:10 -0800429 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController));
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800430
431 // Fast forward RARE bucket
432 mInjector.mElapsedRealtime += RARE_THRESHOLD;
Amith Yamasani93885192017-12-13 11:52:10 -0800433 mController.checkIdleStates(USER_ID);
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800434 // Should continue to apply prediction timeout
Amith Yamasani93885192017-12-13 11:52:10 -0800435 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController));
436 }
437
438 @Test
439 public void testOverrides() throws Exception {
440 setChargingState(mController, false);
441 // Can force to NEVER
442 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
443 REASON_FORCED, 1 * HOUR_MS);
444 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController));
445
446 // Prediction can't override FORCED reason
447 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
448 REASON_FORCED, 1 * HOUR_MS);
449 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
450 REASON_PREDICTED, 1 * HOUR_MS);
451 assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController));
452
453 // Prediction can't override NEVER
454 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
455 REASON_DEFAULT, 2 * HOUR_MS);
456 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
457 REASON_PREDICTED, 2 * HOUR_MS);
458 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController));
459
460 // Prediction can't set to NEVER
461 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
462 REASON_USAGE, 2 * HOUR_MS);
463 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
464 REASON_PREDICTED, 2 * HOUR_MS);
465 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800466 }
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800467
468 @Test
469 public void testTimeout() throws Exception {
470 setChargingState(mController, false);
471
472 reportEvent(mController, USER_INTERACTION, 0);
473 assertBucket(STANDBY_BUCKET_ACTIVE);
474
475 mInjector.mElapsedRealtime = 2000;
476 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
477 REASON_PREDICTED, mInjector.mElapsedRealtime);
478 assertBucket(STANDBY_BUCKET_ACTIVE);
479
480 // bucketing works after timeout
481 mInjector.mElapsedRealtime = FREQUENT_THRESHOLD - 100;
482 mController.checkIdleStates(USER_ID);
483 assertBucket(STANDBY_BUCKET_WORKING_SET);
484
485 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
486 REASON_PREDICTED, mInjector.mElapsedRealtime);
487 assertBucket(STANDBY_BUCKET_FREQUENT);
Sudheer Shanka101c3532018-01-08 16:28:42 -0800488 }
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800489
Sudheer Shanka101c3532018-01-08 16:28:42 -0800490 @Test
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800491 public void testCascadingTimeouts() throws Exception {
492 setChargingState(mController, false);
493
494 reportEvent(mController, USER_INTERACTION, 0);
495 assertBucket(STANDBY_BUCKET_ACTIVE);
496
497 reportEvent(mController, NOTIFICATION_SEEN, 1000);
498 assertBucket(STANDBY_BUCKET_ACTIVE);
499
500 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
501 REASON_PREDICTED, 1000);
502 assertBucket(STANDBY_BUCKET_ACTIVE);
503
504 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
505 REASON_PREDICTED, 2000 + mController.mStrongUsageTimeoutMillis);
506 assertBucket(STANDBY_BUCKET_WORKING_SET);
507
508 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
509 REASON_PREDICTED, 2000 + mController.mNotificationSeenTimeoutMillis);
510 assertBucket(STANDBY_BUCKET_FREQUENT);
511 }
512
513 @Test
514 public void testOverlappingTimeouts() throws Exception {
515 setChargingState(mController, false);
516
517 reportEvent(mController, USER_INTERACTION, 0);
518 assertBucket(STANDBY_BUCKET_ACTIVE);
519
520 reportEvent(mController, NOTIFICATION_SEEN, 1000);
521 assertBucket(STANDBY_BUCKET_ACTIVE);
522
523 // Overlapping USER_INTERACTION before previous one times out
524 reportEvent(mController, USER_INTERACTION, mController.mStrongUsageTimeoutMillis - 1000);
525 assertBucket(STANDBY_BUCKET_ACTIVE);
526
527 // Still in ACTIVE after first USER_INTERACTION times out
528 mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis + 1000;
529 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
530 REASON_PREDICTED, mInjector.mElapsedRealtime);
531 assertBucket(STANDBY_BUCKET_ACTIVE);
532
533 // Both timed out, so NOTIFICATION_SEEN timeout should be effective
534 mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis * 2 + 2000;
535 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
536 REASON_PREDICTED, mInjector.mElapsedRealtime);
537 assertBucket(STANDBY_BUCKET_WORKING_SET);
538
539 mInjector.mElapsedRealtime = mController.mNotificationSeenTimeoutMillis + 2000;
540 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
541 REASON_PREDICTED, mInjector.mElapsedRealtime);
542 assertBucket(STANDBY_BUCKET_RARE);
543 }
544
545 @Test
546 public void testPredictionNotOverridden() throws Exception {
547 setChargingState(mController, false);
548
549 reportEvent(mController, USER_INTERACTION, 0);
550 assertBucket(STANDBY_BUCKET_ACTIVE);
551
552 mInjector.mElapsedRealtime = WORKING_SET_THRESHOLD - 1000;
553 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
554 assertBucket(STANDBY_BUCKET_ACTIVE);
555
556 // Falls back to WORKING_SET
557 mInjector.mElapsedRealtime += 5000;
558 mController.checkIdleStates(USER_ID);
559 assertBucket(STANDBY_BUCKET_WORKING_SET);
560
561 // Predict to ACTIVE
562 mInjector.mElapsedRealtime += 1000;
563 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
564 REASON_PREDICTED, mInjector.mElapsedRealtime);
565 assertBucket(STANDBY_BUCKET_ACTIVE);
566
567 // CheckIdleStates should not change the prediction
568 mInjector.mElapsedRealtime += 1000;
569 mController.checkIdleStates(USER_ID);
570 assertBucket(STANDBY_BUCKET_ACTIVE);
571 }
572
573 @Test
Sudheer Shanka101c3532018-01-08 16:28:42 -0800574 public void testAddActiveDeviceAdmin() {
575 assertActiveAdmins(USER_ID, (String[]) null);
576 assertActiveAdmins(USER_ID2, (String[]) null);
577
578 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID);
579 assertActiveAdmins(USER_ID, ADMIN_PKG);
580 assertActiveAdmins(USER_ID2, (String[]) null);
581
582 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID);
583 assertActiveAdmins(USER_ID, ADMIN_PKG);
584 assertActiveAdmins(USER_ID2, (String[]) null);
585
586 mController.addActiveDeviceAdmin(ADMIN_PKG2, USER_ID2);
587 assertActiveAdmins(USER_ID, ADMIN_PKG);
588 assertActiveAdmins(USER_ID2, ADMIN_PKG2);
589 }
590
591 @Test
592 public void testSetActiveAdminApps() {
593 assertActiveAdmins(USER_ID, (String[]) null);
594 assertActiveAdmins(USER_ID2, (String[]) null);
595
596 setActiveAdmins(USER_ID, ADMIN_PKG, ADMIN_PKG2);
597 assertActiveAdmins(USER_ID, ADMIN_PKG, ADMIN_PKG2);
598 assertActiveAdmins(USER_ID2, (String[]) null);
599
600 mController.addActiveDeviceAdmin(ADMIN_PKG2, USER_ID2);
601 setActiveAdmins(USER_ID2, ADMIN_PKG);
602 assertActiveAdmins(USER_ID, ADMIN_PKG, ADMIN_PKG2);
603 assertActiveAdmins(USER_ID2, ADMIN_PKG);
604
605 mController.setActiveAdminApps(null, USER_ID);
606 assertActiveAdmins(USER_ID, (String[]) null);
607 }
608
609 @Test
610 public void isActiveDeviceAdmin() {
611 assertActiveAdmins(USER_ID, (String[]) null);
612 assertActiveAdmins(USER_ID2, (String[]) null);
613
614 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID);
615 assertIsActiveAdmin(ADMIN_PKG, USER_ID);
616 assertIsNotActiveAdmin(ADMIN_PKG, USER_ID2);
617
618 mController.addActiveDeviceAdmin(ADMIN_PKG2, USER_ID2);
619 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID2);
620 assertIsActiveAdmin(ADMIN_PKG, USER_ID);
621 assertIsNotActiveAdmin(ADMIN_PKG2, USER_ID);
622 assertIsActiveAdmin(ADMIN_PKG, USER_ID2);
623 assertIsActiveAdmin(ADMIN_PKG2, USER_ID2);
624
625 setActiveAdmins(USER_ID2, ADMIN_PKG2);
626 assertIsActiveAdmin(ADMIN_PKG2, USER_ID2);
627 assertIsNotActiveAdmin(ADMIN_PKG, USER_ID2);
628 assertIsActiveAdmin(ADMIN_PKG, USER_ID);
629 assertIsNotActiveAdmin(ADMIN_PKG2, USER_ID);
630 }
631
632 private String getAdminAppsStr(int userId) {
633 return getAdminAppsStr(userId, mController.getActiveAdminAppsForTest(userId));
634 }
635
636 private String getAdminAppsStr(int userId, Set<String> adminApps) {
637 return "admin apps for u" + userId + ": "
638 + (adminApps == null ? "null" : Arrays.toString(adminApps.toArray()));
639 }
640
641 private void assertIsActiveAdmin(String adminApp, int userId) {
642 assertTrue(adminApp + " should be an active admin; " + getAdminAppsStr(userId),
643 mController.isActiveDeviceAdmin(adminApp, userId));
644 }
645
646 private void assertIsNotActiveAdmin(String adminApp, int userId) {
647 assertFalse(adminApp + " shouldn't be an active admin; " + getAdminAppsStr(userId),
648 mController.isActiveDeviceAdmin(adminApp, userId));
649 }
650
651 private void assertActiveAdmins(int userId, String... admins) {
652 final Set<String> actualAdminApps = mController.getActiveAdminAppsForTest(userId);
653 if (admins == null) {
654 if (actualAdminApps != null && !actualAdminApps.isEmpty()) {
655 fail("Admin apps should be null; " + getAdminAppsStr(userId, actualAdminApps));
656 }
657 return;
658 }
659 assertEquals("No. of admin apps not equal; " + getAdminAppsStr(userId, actualAdminApps)
660 + "; expected=" + Arrays.toString(admins), admins.length, actualAdminApps.size());
661 final Set<String> adminAppsCopy = new ArraySet<>(actualAdminApps);
662 for (String admin : admins) {
663 adminAppsCopy.remove(admin);
664 }
665 assertTrue("Unexpected admin apps; " + getAdminAppsStr(userId, actualAdminApps)
666 + "; expected=" + Arrays.toString(admins), adminAppsCopy.isEmpty());
667 }
668
669 private void setActiveAdmins(int userId, String... admins) {
670 mController.setActiveAdminApps(new ArraySet<>(Arrays.asList(admins)), userId);
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800671 }
Amith Yamasani17fffee2017-09-29 13:17:43 -0700672}