blob: eb4eb606341a308f7d853fd71f8dac9663cf6f44 [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
Michael Wachenschwanz6ced0ee2019-04-15 16:43:28 -070019import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
Amith Yamasani803eab692017-11-09 17:47:04 -080020import static android.app.usage.UsageEvents.Event.NOTIFICATION_SEEN;
Jason Monk1918ef72018-03-14 09:20:39 -040021import static android.app.usage.UsageEvents.Event.SLICE_PINNED;
22import static android.app.usage.UsageEvents.Event.SLICE_PINNED_PRIV;
Amith Yamasani7f53c7b2018-03-25 21:55:50 -070023import static android.app.usage.UsageEvents.Event.SYSTEM_INTERACTION;
Amith Yamasani803eab692017-11-09 17:47:04 -080024import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
Amith Yamasani119be9a2018-02-18 22:23:00 -080025import static android.app.usage.UsageStatsManager.REASON_MAIN_DEFAULT;
Kweku Adamsc182d5e2020-01-08 18:37:26 -080026import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_SYSTEM;
27import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER;
Amith Yamasani119be9a2018-02-18 22:23:00 -080028import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED;
29import static android.app.usage.UsageStatsManager.REASON_MAIN_TIMEOUT;
30import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
Kweku Adamsaa461942020-03-16 11:59:05 -070031import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE;
32import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE;
33import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY;
34import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED;
Kweku Adamsc6a9b342020-01-08 18:37:26 -080035import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE;
36import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
37import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYNC_ADAPTER;
38import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYSTEM_INTERACTION;
39import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACTION;
Amith Yamasaniafbccb72017-11-27 10:44:24 -080040import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
Amith Yamasani777b1532018-01-28 23:20:07 +000041import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
Amith Yamasaniafbccb72017-11-27 10:44:24 -080042import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
Amith Yamasani93885192017-12-13 11:52:10 -080043import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
Amith Yamasaniafbccb72017-11-27 10:44:24 -080044import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
Kweku Adamsc6a9b342020-01-08 18:37:26 -080045import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RESTRICTED;
Amith Yamasaniafbccb72017-11-27 10:44:24 -080046import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
Amith Yamasani803eab692017-11-09 17:47:04 -080047
Amith Yamasani17fffee2017-09-29 13:17:43 -070048import static org.junit.Assert.assertEquals;
49import static org.junit.Assert.assertFalse;
50import static org.junit.Assert.assertNotEquals;
51import static org.junit.Assert.assertTrue;
Sudheer Shanka101c3532018-01-08 16:28:42 -080052import static org.junit.Assert.fail;
Yan Zhudf47a142019-07-30 10:31:04 -070053import static org.junit.Assume.assumeTrue;
Amith Yamasani777b1532018-01-28 23:20:07 +000054import static org.mockito.ArgumentMatchers.eq;
Amith Yamasani17fffee2017-09-29 13:17:43 -070055import static org.mockito.Matchers.anyInt;
Amith Yamasani17fffee2017-09-29 13:17:43 -070056import static org.mockito.Mockito.doReturn;
57import static org.mockito.Mockito.mock;
58
Kweku Adamsc6a9b342020-01-08 18:37:26 -080059import android.annotation.NonNull;
60import android.app.ActivityManager;
Varun Shah7609b752018-10-15 15:07:47 -070061import android.app.usage.AppStandbyInfo;
Amith Yamasani17fffee2017-09-29 13:17:43 -070062import android.app.usage.UsageEvents;
63import android.appwidget.AppWidgetManager;
64import android.content.Context;
65import android.content.ContextWrapper;
66import android.content.pm.ApplicationInfo;
67import android.content.pm.PackageInfo;
68import android.content.pm.PackageManager;
69import android.hardware.display.DisplayManager;
70import android.os.Handler;
71import android.os.Looper;
72import android.os.RemoteException;
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -080073import android.os.UserHandle;
Amith Yamasani53f06ea2018-01-05 17:53:46 -080074import android.platform.test.annotations.Presubmit;
Sudheer Shanka101c3532018-01-08 16:28:42 -080075import android.util.ArraySet;
Amith Yamasani17fffee2017-09-29 13:17:43 -070076import android.view.Display;
77
Brett Chabota26eda92018-07-23 13:08:30 -070078import androidx.test.InstrumentationRegistry;
79import androidx.test.filters.SmallTest;
80import androidx.test.runner.AndroidJUnit4;
81
Amith Yamasani17fffee2017-09-29 13:17:43 -070082import com.android.server.SystemService;
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -080083import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
Amith Yamasani17fffee2017-09-29 13:17:43 -070084
85import org.junit.Before;
86import org.junit.Test;
87import org.junit.runner.RunWith;
88
89import java.io.File;
90import java.util.ArrayList;
Sudheer Shanka101c3532018-01-08 16:28:42 -080091import java.util.Arrays;
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -080092import java.util.Collections;
Amith Yamasani17fffee2017-09-29 13:17:43 -070093import java.util.List;
Sudheer Shanka101c3532018-01-08 16:28:42 -080094import java.util.Set;
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -080095import java.util.concurrent.CountDownLatch;
Michael Wachenschwanz5ca5cb62018-04-25 16:12:59 -070096import java.util.concurrent.TimeUnit;
Amith Yamasani17fffee2017-09-29 13:17:43 -070097
98/**
99 * Unit test for AppStandbyController.
100 */
101@RunWith(AndroidJUnit4.class)
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800102@Presubmit
103@SmallTest
Amith Yamasani17fffee2017-09-29 13:17:43 -0700104public class AppStandbyControllerTests {
105
106 private static final String PACKAGE_1 = "com.example.foo";
107 private static final int UID_1 = 10000;
Amith Yamasani777b1532018-01-28 23:20:07 +0000108 private static final String PACKAGE_EXEMPTED_1 = "com.android.exempted";
109 private static final int UID_EXEMPTED_1 = 10001;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700110 private static final int USER_ID = 0;
Sudheer Shanka101c3532018-01-08 16:28:42 -0800111 private static final int USER_ID2 = 10;
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800112 private static final UserHandle USER_HANDLE_USER2 = new UserHandle(USER_ID2);
113 private static final int USER_ID3 = 11;
Sudheer Shanka101c3532018-01-08 16:28:42 -0800114
Varun Shah7609b752018-10-15 15:07:47 -0700115 private static final String PACKAGE_UNKNOWN = "com.example.unknown";
116
Sudheer Shanka101c3532018-01-08 16:28:42 -0800117 private static final String ADMIN_PKG = "com.android.admin";
118 private static final String ADMIN_PKG2 = "com.android.admin2";
119 private static final String ADMIN_PKG3 = "com.android.admin3";
Amith Yamasani17fffee2017-09-29 13:17:43 -0700120
121 private static final long MINUTE_MS = 60 * 1000;
122 private static final long HOUR_MS = 60 * MINUTE_MS;
123 private static final long DAY_MS = 24 * HOUR_MS;
124
Amith Yamasani301e94a2017-11-17 16:35:44 -0800125 private static final long WORKING_SET_THRESHOLD = 12 * HOUR_MS;
126 private static final long FREQUENT_THRESHOLD = 24 * HOUR_MS;
127 private static final long RARE_THRESHOLD = 48 * HOUR_MS;
Kweku Adams4297b5d2020-02-06 15:56:12 -0800128 private static final long RESTRICTED_THRESHOLD = 96 * HOUR_MS;
Amith Yamasani301e94a2017-11-17 16:35:44 -0800129
Varun Shah7609b752018-10-15 15:07:47 -0700130 /** Mock variable used in {@link MyInjector#isPackageInstalled(String, int, int)} */
131 private static boolean isPackageInstalled = true;
132
Amith Yamasani17fffee2017-09-29 13:17:43 -0700133 private MyInjector mInjector;
Amith Yamasani93885192017-12-13 11:52:10 -0800134 private AppStandbyController mController;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700135
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -0800136 private CountDownLatch mStateChangedLatch = new CountDownLatch(1);
137 private AppIdleStateChangeListener mListener = new AppIdleStateChangeListener() {
138 @Override
139 public void onAppIdleStateChanged(String packageName, int userId,
140 boolean idle, int bucket, int reason) {
141 mStateChangedLatch.countDown();
142 }
143 };
144
Amith Yamasani17fffee2017-09-29 13:17:43 -0700145 static class MyContextWrapper extends ContextWrapper {
146 PackageManager mockPm = mock(PackageManager.class);
147
148 public MyContextWrapper(Context base) {
149 super(base);
150 }
151
152 public PackageManager getPackageManager() {
153 return mockPm;
154 }
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800155
156 public Object getSystemService(@NonNull String name) {
157 if (Context.ACTIVITY_SERVICE.equals(name)) {
158 return mock(ActivityManager.class);
159 }
160 return super.getSystemService(name);
161 }
Amith Yamasani17fffee2017-09-29 13:17:43 -0700162 }
163
164 static class MyInjector extends AppStandbyController.Injector {
165 long mElapsedRealtime;
Kweku Adams1e8947c2018-11-05 18:06:13 -0800166 boolean mIsAppIdleEnabled = true;
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800167 boolean mIsCharging;
Kweku Adamsede42f92020-02-27 15:38:44 -0800168 List<String> mNonIdleWhitelistApps = new ArrayList<>();
Amith Yamasani17fffee2017-09-29 13:17:43 -0700169 boolean mDisplayOn;
170 DisplayManager.DisplayListener mDisplayListener;
Amith Yamasani777b1532018-01-28 23:20:07 +0000171 String mBoundWidgetPackage = PACKAGE_EXEMPTED_1;
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800172 int[] mRunningUsers = new int[] {USER_ID};
173 List<UserHandle> mCrossProfileTargets = Collections.emptyList();
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -0800174 boolean mDeviceIdleMode = false;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700175
176 MyInjector(Context context, Looper looper) {
177 super(context, looper);
178 }
179
180 @Override
181 void onBootPhase(int phase) {
182 }
183
184 @Override
185 int getBootPhase() {
186 return SystemService.PHASE_BOOT_COMPLETED;
187 }
188
189 @Override
190 long elapsedRealtime() {
191 return mElapsedRealtime;
192 }
193
194 @Override
195 long currentTimeMillis() {
196 return mElapsedRealtime;
197 }
198
199 @Override
200 boolean isAppIdleEnabled() {
Kweku Adams1e8947c2018-11-05 18:06:13 -0800201 return mIsAppIdleEnabled;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700202 }
203
204 @Override
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800205 boolean isCharging() {
206 return mIsCharging;
207 }
208
209 @Override
Kweku Adamsede42f92020-02-27 15:38:44 -0800210 boolean isNonIdleWhitelisted(String packageName) throws RemoteException {
211 return mNonIdleWhitelistApps.contains(packageName);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700212 }
213
214 @Override
215 File getDataSystemDirectory() {
216 return new File(getContext().getFilesDir(), Long.toString(Math.randomLongInternal()));
217 }
218
219 @Override
220 void noteEvent(int event, String packageName, int uid) throws RemoteException {
221 }
222
223 @Override
224 boolean isPackageEphemeral(int userId, String packageName) {
225 // TODO: update when testing ephemeral apps scenario
226 return false;
227 }
228
229 @Override
Varun Shah7609b752018-10-15 15:07:47 -0700230 boolean isPackageInstalled(String packageName, int flags, int userId) {
231 // Should always return true (default value) unless testing for an uninstalled app
232 return isPackageInstalled;
233 }
234
235 @Override
Amith Yamasani17fffee2017-09-29 13:17:43 -0700236 int[] getRunningUserIds() {
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800237 return mRunningUsers;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700238 }
239
240 @Override
241 boolean isDefaultDisplayOn() {
242 return mDisplayOn;
243 }
244
245 @Override
246 void registerDisplayListener(DisplayManager.DisplayListener listener, Handler handler) {
247 mDisplayListener = listener;
248 }
249
250 @Override
251 String getActiveNetworkScorer() {
252 return null;
253 }
254
255 @Override
256 public boolean isBoundWidgetPackage(AppWidgetManager appWidgetManager, String packageName,
257 int userId) {
258 return packageName != null && packageName.equals(mBoundWidgetPackage);
259 }
260
Amith Yamasani301e94a2017-11-17 16:35:44 -0800261 @Override
262 String getAppIdleSettings() {
263 return "screen_thresholds=0/0/0/" + HOUR_MS + ",elapsed_thresholds=0/"
Kweku Adams4297b5d2020-02-06 15:56:12 -0800264 + WORKING_SET_THRESHOLD + "/" + FREQUENT_THRESHOLD + "/" + RARE_THRESHOLD
265 + "/" + RESTRICTED_THRESHOLD;
Amith Yamasani301e94a2017-11-17 16:35:44 -0800266 }
267
Makoto Onukid5f25d22018-05-22 16:02:17 -0700268 @Override
269 public boolean isDeviceIdleMode() {
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -0800270 return mDeviceIdleMode;
Makoto Onukid5f25d22018-05-22 16:02:17 -0700271 }
272
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800273 @Override
274 public List<UserHandle> getValidCrossProfileTargets(String pkg, int userId) {
275 return mCrossProfileTargets;
276 }
277
Amith Yamasani17fffee2017-09-29 13:17:43 -0700278 // Internal methods
279
280 void setDisplayOn(boolean on) {
281 mDisplayOn = on;
282 if (mDisplayListener != null) {
283 mDisplayListener.onDisplayChanged(Display.DEFAULT_DISPLAY);
284 }
285 }
286 }
287
288 private void setupPm(PackageManager mockPm) throws PackageManager.NameNotFoundException {
289 List<PackageInfo> packages = new ArrayList<>();
290 PackageInfo pi = new PackageInfo();
291 pi.applicationInfo = new ApplicationInfo();
292 pi.applicationInfo.uid = UID_1;
293 pi.packageName = PACKAGE_1;
294 packages.add(pi);
295
Amith Yamasani777b1532018-01-28 23:20:07 +0000296 PackageInfo pie = new PackageInfo();
297 pie.applicationInfo = new ApplicationInfo();
298 pie.applicationInfo.uid = UID_EXEMPTED_1;
299 pie.packageName = PACKAGE_EXEMPTED_1;
300 packages.add(pie);
301
Amith Yamasani17fffee2017-09-29 13:17:43 -0700302 doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(), anyInt());
303 try {
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800304 doReturn(UID_1).when(mockPm).getPackageUidAsUser(eq(PACKAGE_1), anyInt());
Amith Yamasani777b1532018-01-28 23:20:07 +0000305 doReturn(UID_1).when(mockPm).getPackageUidAsUser(eq(PACKAGE_1), anyInt(), anyInt());
306 doReturn(UID_EXEMPTED_1).when(mockPm).getPackageUidAsUser(eq(PACKAGE_EXEMPTED_1),
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800307 anyInt());
308 doReturn(UID_EXEMPTED_1).when(mockPm).getPackageUidAsUser(eq(PACKAGE_EXEMPTED_1),
Amith Yamasani777b1532018-01-28 23:20:07 +0000309 anyInt(), anyInt());
310 doReturn(pi.applicationInfo).when(mockPm).getApplicationInfo(eq(pi.packageName),
311 anyInt());
312 doReturn(pie.applicationInfo).when(mockPm).getApplicationInfo(eq(pie.packageName),
313 anyInt());
Amith Yamasani17fffee2017-09-29 13:17:43 -0700314 } catch (PackageManager.NameNotFoundException nnfe) {}
315 }
316
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800317 private void setChargingState(AppStandbyController controller, boolean charging) {
318 mInjector.mIsCharging = charging;
319 if (controller != null) {
320 controller.setChargingState(charging);
321 }
322 }
323
Kweku Adams1e8947c2018-11-05 18:06:13 -0800324 private void setAppIdleEnabled(AppStandbyController controller, boolean enabled) {
325 mInjector.mIsAppIdleEnabled = enabled;
326 if (controller != null) {
327 controller.setAppIdleEnabled(enabled);
328 }
329 }
330
Amith Yamasani17fffee2017-09-29 13:17:43 -0700331 private AppStandbyController setupController() throws Exception {
332 mInjector.mElapsedRealtime = 0;
Amith Yamasani777b1532018-01-28 23:20:07 +0000333 setupPm(mInjector.getContext().getPackageManager());
Amith Yamasani17fffee2017-09-29 13:17:43 -0700334 AppStandbyController controller = new AppStandbyController(mInjector);
Amith Yamasani777b1532018-01-28 23:20:07 +0000335 controller.initializeDefaultsForSystemApps(USER_ID);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700336 controller.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
337 controller.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
338 mInjector.setDisplayOn(false);
339 mInjector.setDisplayOn(true);
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800340 setChargingState(controller, false);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700341 controller.checkIdleStates(USER_ID);
Amith Yamasani777b1532018-01-28 23:20:07 +0000342 assertNotEquals(STANDBY_BUCKET_EXEMPTED,
343 controller.getAppStandbyBucket(PACKAGE_1, USER_ID,
344 mInjector.mElapsedRealtime, false));
Amith Yamasani17fffee2017-09-29 13:17:43 -0700345
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -0800346 controller.addListener(mListener);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700347 return controller;
348 }
349
Michael Wachenschwanz5ca5cb62018-04-25 16:12:59 -0700350 private long getCurrentTime() {
351 return TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
352 }
353
Amith Yamasani17fffee2017-09-29 13:17:43 -0700354 @Before
355 public void setUp() throws Exception {
356 MyContextWrapper myContext = new MyContextWrapper(InstrumentationRegistry.getContext());
357 mInjector = new MyInjector(myContext, Looper.getMainLooper());
Amith Yamasani93885192017-12-13 11:52:10 -0800358 mController = setupController();
Michael Wachenschwanz5ca5cb62018-04-25 16:12:59 -0700359 }
360
Amith Yamasani17fffee2017-09-29 13:17:43 -0700361 @Test
Yan Zhudf47a142019-07-30 10:31:04 -0700362 public void testBoundWidgetPackageExempt() throws Exception {
363 assumeTrue(mInjector.getContext().getSystemService(AppWidgetManager.class) != null);
364 assertEquals(STANDBY_BUCKET_EXEMPTED,
365 mController.getAppStandbyBucket(PACKAGE_EXEMPTED_1, USER_ID,
366 mInjector.mElapsedRealtime, false));
367 }
368
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800369 @Test
370 public void testIsAppIdle_Charging() throws Exception {
371 setChargingState(mController, false);
372 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
373 REASON_MAIN_FORCED_BY_SYSTEM);
374 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
375 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
376 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
377
378 setChargingState(mController, true);
379 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
380 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
381 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
382
383 setChargingState(mController, false);
384 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
385 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
386 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
387 }
388
389 @Test
390 public void testIsAppIdle_Enabled() throws Exception {
391 setChargingState(mController, false);
392 setAppIdleEnabled(mController, true);
393 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
394 REASON_MAIN_FORCED_BY_SYSTEM);
395 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
396 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
397 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
398
399 setAppIdleEnabled(mController, false);
400 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
401 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
402
403 setAppIdleEnabled(mController, true);
404 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
405 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
406 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
407 }
408
Amith Yamasani17fffee2017-09-29 13:17:43 -0700409 private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket) {
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800410 assertTimeout(controller, elapsedTime, bucket, USER_ID);
411 }
412
413 private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket,
414 int userId) {
Amith Yamasani17fffee2017-09-29 13:17:43 -0700415 mInjector.mElapsedRealtime = elapsedTime;
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800416 controller.checkIdleStates(userId);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700417 assertEquals(bucket,
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800418 controller.getAppStandbyBucket(PACKAGE_1, userId, mInjector.mElapsedRealtime,
Amith Yamasani17fffee2017-09-29 13:17:43 -0700419 false));
420 }
421
Varun Shah7609b752018-10-15 15:07:47 -0700422 private void reportEvent(AppStandbyController controller, int eventType, long elapsedTime,
423 String packageName) {
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800424 // Back to ACTIVE on event
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800425 mInjector.mElapsedRealtime = elapsedTime;
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800426 UsageEvents.Event ev = new UsageEvents.Event();
Varun Shah7609b752018-10-15 15:07:47 -0700427 ev.mPackage = packageName;
Amith Yamasani803eab692017-11-09 17:47:04 -0800428 ev.mEventType = eventType;
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800429 controller.reportEvent(ev, elapsedTime, USER_ID);
430 }
431
Varun Shah7609b752018-10-15 15:07:47 -0700432 private int getStandbyBucket(AppStandbyController controller, String packageName) {
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800433 return getStandbyBucket(USER_ID, controller, packageName);
434 }
435
436 private int getStandbyBucket(int userId, AppStandbyController controller, String packageName) {
437 return controller.getAppStandbyBucket(packageName, userId, mInjector.mElapsedRealtime,
Amith Yamasani803eab692017-11-09 17:47:04 -0800438 true);
439 }
440
Kweku Adamsaa461942020-03-16 11:59:05 -0700441 private int getStandbyBucketReason(String packageName) {
442 return mController.getAppStandbyBucketReason(packageName, USER_ID,
443 mInjector.mElapsedRealtime);
444 }
445
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800446 private void assertBucket(int bucket) {
Varun Shah7609b752018-10-15 15:07:47 -0700447 assertEquals(bucket, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800448 }
449
Amith Yamasani17fffee2017-09-29 13:17:43 -0700450 @Test
451 public void testBuckets() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800452 assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700453
Varun Shah7609b752018-10-15 15:07:47 -0700454 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800455
Amith Yamasani17fffee2017-09-29 13:17:43 -0700456 // ACTIVE bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800457 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700458
459 // WORKING_SET bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800460 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700461
462 // WORKING_SET bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800463 assertTimeout(mController, FREQUENT_THRESHOLD - 1, STANDBY_BUCKET_WORKING_SET);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700464
465 // FREQUENT bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800466 assertTimeout(mController, FREQUENT_THRESHOLD + 1, STANDBY_BUCKET_FREQUENT);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700467
468 // RARE bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800469 assertTimeout(mController, RARE_THRESHOLD + 1, STANDBY_BUCKET_RARE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700470
Kweku Adams4297b5d2020-02-06 15:56:12 -0800471 // RESTRICTED bucket
472 assertTimeout(mController, RESTRICTED_THRESHOLD + 1, STANDBY_BUCKET_RESTRICTED);
473
Varun Shah7609b752018-10-15 15:07:47 -0700474 reportEvent(mController, USER_INTERACTION, RARE_THRESHOLD + 1, PACKAGE_1);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700475
Amith Yamasani93885192017-12-13 11:52:10 -0800476 assertTimeout(mController, RARE_THRESHOLD + 1, STANDBY_BUCKET_ACTIVE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700477
Kweku Adams4297b5d2020-02-06 15:56:12 -0800478 // RESTRICTED bucket
479 assertTimeout(mController, RESTRICTED_THRESHOLD * 2 + 2, STANDBY_BUCKET_RESTRICTED);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700480 }
481
482 @Test
Varun Shah7609b752018-10-15 15:07:47 -0700483 public void testSetAppStandbyBucket() throws Exception {
484 // For a known package, standby bucket should be set properly
485 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800486 mInjector.mElapsedRealtime = HOUR_MS;
Varun Shah7609b752018-10-15 15:07:47 -0700487 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800488 REASON_MAIN_TIMEOUT);
Varun Shah7609b752018-10-15 15:07:47 -0700489 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
490
491 // For an unknown package, standby bucket should not be set, hence NEVER is returned
492 // Ensure the unknown package is not already in history by removing it
493 mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID);
494 isPackageInstalled = false; // Mock package is not installed
495 mController.setAppStandbyBucket(PACKAGE_UNKNOWN, USER_ID, STANDBY_BUCKET_ACTIVE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800496 REASON_MAIN_TIMEOUT);
Varun Shah7609b752018-10-15 15:07:47 -0700497 isPackageInstalled = true; // Reset mocked variable for other tests
498 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN));
499 }
500
501 @Test
502 public void testAppStandbyBucketOnInstallAndUninstall() throws Exception {
503 // On package install, standby bucket should be ACTIVE
504 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_UNKNOWN);
505 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_UNKNOWN));
506
507 // On uninstall, package should not exist in history and should return a NEVER bucket
508 mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID);
509 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN));
510 // Ensure uninstalled app is not in history
511 List<AppStandbyInfo> buckets = mController.getAppStandbyBuckets(USER_ID);
512 for(AppStandbyInfo bucket : buckets) {
513 if (bucket.mPackageName.equals(PACKAGE_UNKNOWN)) {
514 fail("packageName found in app idle history after uninstall.");
515 }
516 }
517 }
518
519 @Test
Amith Yamasani17fffee2017-09-29 13:17:43 -0700520 public void testScreenTimeAndBuckets() throws Exception {
Amith Yamasani17fffee2017-09-29 13:17:43 -0700521 mInjector.setDisplayOn(false);
522
Amith Yamasani93885192017-12-13 11:52:10 -0800523 assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800524
Varun Shah7609b752018-10-15 15:07:47 -0700525 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800526
Amith Yamasani17fffee2017-09-29 13:17:43 -0700527 // ACTIVE bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800528 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700529
530 // WORKING_SET bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800531 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700532
533 // RARE bucket, should fail because the screen wasn't ON.
Amith Yamasani301e94a2017-11-17 16:35:44 -0800534 mInjector.mElapsedRealtime = RARE_THRESHOLD + 1;
Amith Yamasani93885192017-12-13 11:52:10 -0800535 mController.checkIdleStates(USER_ID);
Varun Shah7609b752018-10-15 15:07:47 -0700536 assertNotEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani17fffee2017-09-29 13:17:43 -0700537
538 mInjector.setDisplayOn(true);
Kweku Adams4297b5d2020-02-06 15:56:12 -0800539 assertTimeout(mController, RARE_THRESHOLD + 2 * HOUR_MS + 1, STANDBY_BUCKET_RARE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700540 }
541
542 @Test
543 public void testForcedIdle() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800544 mController.forceIdleState(PACKAGE_1, USER_ID, true);
Varun Shah7609b752018-10-15 15:07:47 -0700545 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani93885192017-12-13 11:52:10 -0800546 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
Amith Yamasani17fffee2017-09-29 13:17:43 -0700547
Amith Yamasani93885192017-12-13 11:52:10 -0800548 mController.forceIdleState(PACKAGE_1, USER_ID, false);
549 assertEquals(STANDBY_BUCKET_ACTIVE, mController.getAppStandbyBucket(PACKAGE_1, USER_ID, 0,
Amith Yamasani17fffee2017-09-29 13:17:43 -0700550 true));
Amith Yamasani93885192017-12-13 11:52:10 -0800551 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
Amith Yamasani17fffee2017-09-29 13:17:43 -0700552 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800553
554 @Test
555 public void testNotificationEvent() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -0700556 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
557 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani803eab692017-11-09 17:47:04 -0800558 mInjector.mElapsedRealtime = 1;
Varun Shah7609b752018-10-15 15:07:47 -0700559 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1);
560 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani803eab692017-11-09 17:47:04 -0800561
Amith Yamasani93885192017-12-13 11:52:10 -0800562 mController.forceIdleState(PACKAGE_1, USER_ID, true);
Varun Shah7609b752018-10-15 15:07:47 -0700563 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1);
564 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani803eab692017-11-09 17:47:04 -0800565 }
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800566
567 @Test
Jason Monk1918ef72018-03-14 09:20:39 -0400568 public void testSlicePinnedEvent() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -0700569 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
570 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Jason Monk1918ef72018-03-14 09:20:39 -0400571 mInjector.mElapsedRealtime = 1;
Varun Shah7609b752018-10-15 15:07:47 -0700572 reportEvent(mController, SLICE_PINNED, mInjector.mElapsedRealtime, PACKAGE_1);
573 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Jason Monk1918ef72018-03-14 09:20:39 -0400574
575 mController.forceIdleState(PACKAGE_1, USER_ID, true);
Varun Shah7609b752018-10-15 15:07:47 -0700576 reportEvent(mController, SLICE_PINNED, mInjector.mElapsedRealtime, PACKAGE_1);
577 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
Jason Monk1918ef72018-03-14 09:20:39 -0400578 }
579
580 @Test
581 public void testSlicePinnedPrivEvent() throws Exception {
Jason Monk1918ef72018-03-14 09:20:39 -0400582 mController.forceIdleState(PACKAGE_1, USER_ID, true);
Varun Shah7609b752018-10-15 15:07:47 -0700583 reportEvent(mController, SLICE_PINNED_PRIV, mInjector.mElapsedRealtime, PACKAGE_1);
584 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Jason Monk1918ef72018-03-14 09:20:39 -0400585 }
586
587 @Test
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800588 public void testPredictionTimedOut() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800589 // Set it to timeout or usage, so that prediction can override it
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800590 mInjector.mElapsedRealtime = HOUR_MS;
Amith Yamasani93885192017-12-13 11:52:10 -0800591 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800592 REASON_MAIN_TIMEOUT);
Varun Shah7609b752018-10-15 15:07:47 -0700593 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani93885192017-12-13 11:52:10 -0800594
595 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800596 REASON_MAIN_PREDICTED);
Varun Shah7609b752018-10-15 15:07:47 -0700597 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800598
599 // Fast forward 12 hours
600 mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD;
Amith Yamasani93885192017-12-13 11:52:10 -0800601 mController.checkIdleStates(USER_ID);
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800602 // Should still be in predicted bucket, since prediction timeout is 1 day since prediction
Varun Shah7609b752018-10-15 15:07:47 -0700603 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800604 // Fast forward two more hours
605 mInjector.mElapsedRealtime += 2 * HOUR_MS;
Amith Yamasani93885192017-12-13 11:52:10 -0800606 mController.checkIdleStates(USER_ID);
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800607 // Should have now applied prediction timeout
Varun Shah7609b752018-10-15 15:07:47 -0700608 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800609
610 // Fast forward RARE bucket
611 mInjector.mElapsedRealtime += RARE_THRESHOLD;
Amith Yamasani93885192017-12-13 11:52:10 -0800612 mController.checkIdleStates(USER_ID);
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800613 // Should continue to apply prediction timeout
Varun Shah7609b752018-10-15 15:07:47 -0700614 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani93885192017-12-13 11:52:10 -0800615 }
616
617 @Test
618 public void testOverrides() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800619 // Can force to NEVER
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800620 mInjector.mElapsedRealtime = HOUR_MS;
Amith Yamasani93885192017-12-13 11:52:10 -0800621 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
Kweku Adamsc182d5e2020-01-08 18:37:26 -0800622 REASON_MAIN_FORCED_BY_USER);
Varun Shah7609b752018-10-15 15:07:47 -0700623 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani93885192017-12-13 11:52:10 -0800624
Kweku Adamsc182d5e2020-01-08 18:37:26 -0800625 // Prediction can't override FORCED reasons
626 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
627 REASON_MAIN_FORCED_BY_SYSTEM);
628 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
629 REASON_MAIN_PREDICTED);
630 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
631
Amith Yamasani93885192017-12-13 11:52:10 -0800632 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc182d5e2020-01-08 18:37:26 -0800633 REASON_MAIN_FORCED_BY_USER);
Amith Yamasani93885192017-12-13 11:52:10 -0800634 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800635 REASON_MAIN_PREDICTED);
Varun Shah7609b752018-10-15 15:07:47 -0700636 assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani93885192017-12-13 11:52:10 -0800637
638 // Prediction can't override NEVER
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800639 mInjector.mElapsedRealtime = 2 * HOUR_MS;
Amith Yamasani93885192017-12-13 11:52:10 -0800640 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800641 REASON_MAIN_DEFAULT);
Amith Yamasani93885192017-12-13 11:52:10 -0800642 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800643 REASON_MAIN_PREDICTED);
Varun Shah7609b752018-10-15 15:07:47 -0700644 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani93885192017-12-13 11:52:10 -0800645
646 // Prediction can't set to NEVER
647 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800648 REASON_MAIN_USAGE);
Amith Yamasani93885192017-12-13 11:52:10 -0800649 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800650 REASON_MAIN_PREDICTED);
Varun Shah7609b752018-10-15 15:07:47 -0700651 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800652
653 // Prediction can't remove from RESTRICTED
654 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
655 REASON_MAIN_FORCED_BY_USER);
656 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
657 REASON_MAIN_PREDICTED);
658 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
659
660 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
661 REASON_MAIN_FORCED_BY_SYSTEM);
662 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
663 REASON_MAIN_PREDICTED);
664 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
665
666 // Force from user can remove from RESTRICTED
667 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
668 REASON_MAIN_FORCED_BY_USER);
669 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
670 REASON_MAIN_FORCED_BY_USER);
671 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
672
673 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
674 REASON_MAIN_FORCED_BY_SYSTEM);
675 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
676 REASON_MAIN_FORCED_BY_USER);
677 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
678
679 // Force from system can remove from RESTRICTED if it was put it in due to system
680 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
681 REASON_MAIN_FORCED_BY_SYSTEM);
682 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
683 REASON_MAIN_FORCED_BY_SYSTEM);
684 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
685
686 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
687 REASON_MAIN_FORCED_BY_USER);
688 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
689 REASON_MAIN_FORCED_BY_SYSTEM);
690 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
691
692 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
693 REASON_MAIN_PREDICTED);
694 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
695 REASON_MAIN_FORCED_BY_SYSTEM);
696 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
697
698 // Non-user usage can't remove from RESTRICTED
699 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
700 REASON_MAIN_FORCED_BY_SYSTEM);
701 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
702 REASON_MAIN_USAGE);
703 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
704 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
705 REASON_MAIN_USAGE | REASON_SUB_USAGE_SYSTEM_INTERACTION);
706 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
707 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
708 REASON_MAIN_USAGE | REASON_SUB_USAGE_SYNC_ADAPTER);
709 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
710 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
711 REASON_MAIN_USAGE | REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE);
712 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
713
714 // Explicit user usage can remove from RESTRICTED
715 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
716 REASON_MAIN_FORCED_BY_USER);
717 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
718 REASON_MAIN_USAGE | REASON_SUB_USAGE_USER_INTERACTION);
719 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
720 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
721 REASON_MAIN_FORCED_BY_SYSTEM);
722 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
723 REASON_MAIN_USAGE | REASON_SUB_USAGE_MOVE_TO_FOREGROUND);
724 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800725 }
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800726
727 @Test
728 public void testTimeout() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -0700729 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800730 assertBucket(STANDBY_BUCKET_ACTIVE);
731
732 mInjector.mElapsedRealtime = 2000;
733 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800734 REASON_MAIN_PREDICTED);
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800735 assertBucket(STANDBY_BUCKET_ACTIVE);
736
737 // bucketing works after timeout
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700738 mInjector.mElapsedRealtime = mController.mPredictionTimeoutMillis - 100;
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800739 mController.checkIdleStates(USER_ID);
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700740 // Use recent prediction
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800741 assertBucket(STANDBY_BUCKET_FREQUENT);
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700742
743 // Way past prediction timeout, use system thresholds
Kweku Adams4297b5d2020-02-06 15:56:12 -0800744 mInjector.mElapsedRealtime = RARE_THRESHOLD;
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700745 mController.checkIdleStates(USER_ID);
746 assertBucket(STANDBY_BUCKET_RARE);
Sudheer Shanka101c3532018-01-08 16:28:42 -0800747 }
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800748
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800749 /**
750 * Test that setAppStandbyBucket to RESTRICTED doesn't change the bucket until the usage
751 * timeout has passed.
752 */
753 @Test
754 public void testTimeoutBeforeRestricted() throws Exception {
755 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
756 assertBucket(STANDBY_BUCKET_ACTIVE);
757
758 mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD;
759 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
760 REASON_MAIN_FORCED_BY_SYSTEM);
761 // Bucket shouldn't change
762 assertBucket(STANDBY_BUCKET_ACTIVE);
763
764 // bucketing works after timeout
765 mInjector.mElapsedRealtime += DAY_MS;
766 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
767 REASON_MAIN_FORCED_BY_SYSTEM);
768 assertBucket(STANDBY_BUCKET_RESTRICTED);
769
770 // Way past all timeouts. Make sure timeout processing doesn't raise bucket.
Kweku Adams4297b5d2020-02-06 15:56:12 -0800771 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800772 mController.checkIdleStates(USER_ID);
773 assertBucket(STANDBY_BUCKET_RESTRICTED);
774 }
775
776 /**
777 * Test that an app is put into the RESTRICTED bucket after enough time has passed.
778 */
779 @Test
780 public void testRestrictedDelay() throws Exception {
781 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
782 assertBucket(STANDBY_BUCKET_ACTIVE);
783
Kweku Adams109cd9c2020-02-11 11:10:52 -0800784 mInjector.mElapsedRealtime += mInjector.getAutoRestrictedBucketDelayMs() - 5000;
785 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
786 REASON_MAIN_FORCED_BY_SYSTEM);
787 // Bucket shouldn't change
788 assertBucket(STANDBY_BUCKET_ACTIVE);
789
790 // bucketing works after timeout
791 mInjector.mElapsedRealtime += 6000;
792
793 Thread.sleep(6000);
794 // Enough time has passed. The app should automatically be put into the RESTRICTED bucket.
795 assertBucket(STANDBY_BUCKET_RESTRICTED);
796 }
797
798 /**
799 * Test that an app is put into the RESTRICTED bucket after enough time has passed.
800 */
801 @Test
802 public void testRestrictedDelay_DelayChange() throws Exception {
803 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
804 assertBucket(STANDBY_BUCKET_ACTIVE);
805
806 mInjector.mAutoRestrictedBucketDelayMs = 2 * HOUR_MS;
807 mInjector.mElapsedRealtime += 2 * HOUR_MS - 5000;
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800808 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
809 REASON_MAIN_FORCED_BY_SYSTEM);
810 // Bucket shouldn't change
811 assertBucket(STANDBY_BUCKET_ACTIVE);
812
813 // bucketing works after timeout
814 mInjector.mElapsedRealtime += 6000;
815
816 Thread.sleep(6000);
817 // Enough time has passed. The app should automatically be put into the RESTRICTED bucket.
818 assertBucket(STANDBY_BUCKET_RESTRICTED);
819 }
820
Sudheer Shanka101c3532018-01-08 16:28:42 -0800821 @Test
Kweku Adams4297b5d2020-02-06 15:56:12 -0800822 public void testPredictionRaiseFromRestrictedTimeout() {
823 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
824
825 // Way past all timeouts. App times out into RESTRICTED bucket.
826 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
827 mController.checkIdleStates(USER_ID);
828 assertBucket(STANDBY_BUCKET_RESTRICTED);
829
830 // Since the app timed out into RESTRICTED, prediction should be able to remove from the
831 // bucket.
832 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD;
833 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
834 REASON_MAIN_PREDICTED);
835 }
836
837 @Test
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800838 public void testCascadingTimeouts() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -0700839 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800840 assertBucket(STANDBY_BUCKET_ACTIVE);
841
Varun Shah7609b752018-10-15 15:07:47 -0700842 reportEvent(mController, NOTIFICATION_SEEN, 1000, PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800843 assertBucket(STANDBY_BUCKET_ACTIVE);
844
845 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800846 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800847 assertBucket(STANDBY_BUCKET_ACTIVE);
848
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800849 mInjector.mElapsedRealtime = 2000 + mController.mStrongUsageTimeoutMillis;
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800850 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800851 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800852 assertBucket(STANDBY_BUCKET_WORKING_SET);
853
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800854 mInjector.mElapsedRealtime = 2000 + mController.mNotificationSeenTimeoutMillis;
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800855 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800856 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800857 assertBucket(STANDBY_BUCKET_FREQUENT);
858 }
859
860 @Test
861 public void testOverlappingTimeouts() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -0700862 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800863 assertBucket(STANDBY_BUCKET_ACTIVE);
864
Varun Shah7609b752018-10-15 15:07:47 -0700865 reportEvent(mController, NOTIFICATION_SEEN, 1000, PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800866 assertBucket(STANDBY_BUCKET_ACTIVE);
867
868 // Overlapping USER_INTERACTION before previous one times out
Varun Shah7609b752018-10-15 15:07:47 -0700869 reportEvent(mController, USER_INTERACTION, mController.mStrongUsageTimeoutMillis - 1000,
870 PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800871 assertBucket(STANDBY_BUCKET_ACTIVE);
872
873 // Still in ACTIVE after first USER_INTERACTION times out
874 mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis + 1000;
875 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800876 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800877 assertBucket(STANDBY_BUCKET_ACTIVE);
878
879 // Both timed out, so NOTIFICATION_SEEN timeout should be effective
880 mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis * 2 + 2000;
881 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800882 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800883 assertBucket(STANDBY_BUCKET_WORKING_SET);
884
885 mInjector.mElapsedRealtime = mController.mNotificationSeenTimeoutMillis + 2000;
886 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800887 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800888 assertBucket(STANDBY_BUCKET_RARE);
889 }
890
891 @Test
Amith Yamasani7f53c7b2018-03-25 21:55:50 -0700892 public void testSystemInteractionTimeout() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -0700893 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasani7f53c7b2018-03-25 21:55:50 -0700894 // Fast forward to RARE
895 mInjector.mElapsedRealtime = RARE_THRESHOLD + 100;
896 mController.checkIdleStates(USER_ID);
897 assertBucket(STANDBY_BUCKET_RARE);
898
899 // Trigger a SYSTEM_INTERACTION and verify bucket
Varun Shah7609b752018-10-15 15:07:47 -0700900 reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
Amith Yamasani7f53c7b2018-03-25 21:55:50 -0700901 assertBucket(STANDBY_BUCKET_ACTIVE);
902
903 // Verify it's still in ACTIVE close to end of timeout
904 mInjector.mElapsedRealtime += mController.mSystemInteractionTimeoutMillis - 100;
905 mController.checkIdleStates(USER_ID);
906 assertBucket(STANDBY_BUCKET_ACTIVE);
907
908 // Verify bucket moves to RARE after timeout
909 mInjector.mElapsedRealtime += 200;
910 mController.checkIdleStates(USER_ID);
911 assertBucket(STANDBY_BUCKET_RARE);
912 }
913
914 @Test
Michael Wachenschwanz6ced0ee2019-04-15 16:43:28 -0700915 public void testInitialForegroundServiceTimeout() throws Exception {
Michael Wachenschwanz6ced0ee2019-04-15 16:43:28 -0700916 mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100;
917 // Make sure app is in NEVER bucket
918 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
Kweku Adamsc182d5e2020-01-08 18:37:26 -0800919 REASON_MAIN_FORCED_BY_USER);
Michael Wachenschwanz6ced0ee2019-04-15 16:43:28 -0700920 mController.checkIdleStates(USER_ID);
921 assertBucket(STANDBY_BUCKET_NEVER);
922
923 mInjector.mElapsedRealtime += 100;
924
925 // Trigger a FOREGROUND_SERVICE_START and verify bucket
926 reportEvent(mController, FOREGROUND_SERVICE_START, mInjector.mElapsedRealtime, PACKAGE_1);
927 mController.checkIdleStates(USER_ID);
928 assertBucket(STANDBY_BUCKET_ACTIVE);
929
930 // Verify it's still in ACTIVE close to end of timeout
931 mInjector.mElapsedRealtime += mController.mInitialForegroundServiceStartTimeoutMillis - 100;
932 mController.checkIdleStates(USER_ID);
933 assertBucket(STANDBY_BUCKET_ACTIVE);
934
935 // Verify bucket moves to RARE after timeout
936 mInjector.mElapsedRealtime += 200;
937 mController.checkIdleStates(USER_ID);
938 assertBucket(STANDBY_BUCKET_RARE);
939
940 // Trigger a FOREGROUND_SERVICE_START again
941 reportEvent(mController, FOREGROUND_SERVICE_START, mInjector.mElapsedRealtime, PACKAGE_1);
942 mController.checkIdleStates(USER_ID);
943 // Bucket should not be immediately elevated on subsequent service starts
944 assertBucket(STANDBY_BUCKET_RARE);
945 }
946
947 @Test
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800948 public void testPredictionNotOverridden() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -0700949 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800950 assertBucket(STANDBY_BUCKET_ACTIVE);
951
952 mInjector.mElapsedRealtime = WORKING_SET_THRESHOLD - 1000;
Varun Shah7609b752018-10-15 15:07:47 -0700953 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800954 assertBucket(STANDBY_BUCKET_ACTIVE);
955
956 // Falls back to WORKING_SET
957 mInjector.mElapsedRealtime += 5000;
958 mController.checkIdleStates(USER_ID);
959 assertBucket(STANDBY_BUCKET_WORKING_SET);
960
961 // Predict to ACTIVE
962 mInjector.mElapsedRealtime += 1000;
963 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800964 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800965 assertBucket(STANDBY_BUCKET_ACTIVE);
966
967 // CheckIdleStates should not change the prediction
968 mInjector.mElapsedRealtime += 1000;
969 mController.checkIdleStates(USER_ID);
970 assertBucket(STANDBY_BUCKET_ACTIVE);
971 }
972
973 @Test
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700974 public void testPredictionStrikesBack() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -0700975 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700976 assertBucket(STANDBY_BUCKET_ACTIVE);
977
978 // Predict to FREQUENT
979 mInjector.mElapsedRealtime = RARE_THRESHOLD;
980 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800981 REASON_MAIN_PREDICTED);
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700982 assertBucket(STANDBY_BUCKET_FREQUENT);
983
984 // Add a short timeout event
985 mInjector.mElapsedRealtime += 1000;
Varun Shah7609b752018-10-15 15:07:47 -0700986 reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700987 assertBucket(STANDBY_BUCKET_ACTIVE);
988 mInjector.mElapsedRealtime += 1000;
989 mController.checkIdleStates(USER_ID);
990 assertBucket(STANDBY_BUCKET_ACTIVE);
991
992 // Verify it reverted to predicted
993 mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD / 2;
994 mController.checkIdleStates(USER_ID);
995 assertBucket(STANDBY_BUCKET_FREQUENT);
996 }
997
998 @Test
Kweku Adamsaa461942020-03-16 11:59:05 -0700999 public void testSystemForcedFlags_NotAddedForUserForce() throws Exception {
1000 final int expectedReason = REASON_MAIN_FORCED_BY_USER;
1001 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1002 REASON_MAIN_FORCED_BY_USER);
1003 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
1004 assertEquals(expectedReason, getStandbyBucketReason(PACKAGE_1));
1005
1006 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1007 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE);
1008 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
1009 assertEquals(expectedReason, getStandbyBucketReason(PACKAGE_1));
1010 }
1011
1012 @Test
1013 public void testSystemForcedFlags_AddedForSystemForce() throws Exception {
1014 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
1015 REASON_MAIN_DEFAULT);
1016 mInjector.mElapsedRealtime += 4 * RESTRICTED_THRESHOLD;
1017
1018 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1019 REASON_MAIN_FORCED_BY_SYSTEM
1020 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE);
1021 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
1022 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM
1023 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE,
1024 getStandbyBucketReason(PACKAGE_1));
1025
1026 mController.restrictApp(PACKAGE_1, USER_ID, REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE);
1027 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
1028 // Flags should be combined
1029 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM
1030 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE
1031 | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE, getStandbyBucketReason(PACKAGE_1));
1032 }
1033
1034 @Test
1035 public void testSystemForcedFlags_SystemForceChangesBuckets() throws Exception {
1036 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
1037 REASON_MAIN_DEFAULT);
1038 mInjector.mElapsedRealtime += 4 * RESTRICTED_THRESHOLD;
1039
1040 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
1041 REASON_MAIN_FORCED_BY_SYSTEM
1042 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE);
1043 assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1));
1044 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM
1045 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE,
1046 getStandbyBucketReason(PACKAGE_1));
1047
1048 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
1049 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE);
1050 assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1));
1051 // Flags should be combined
1052 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM
1053 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE
1054 | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE,
1055 getStandbyBucketReason(PACKAGE_1));
1056
1057 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
1058 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);
1059 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
1060 // Flags should be combined
1061 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY,
1062 getStandbyBucketReason(PACKAGE_1));
1063
1064 mController.restrictApp(PACKAGE_1, USER_ID, REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED);
1065 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
1066 // Flags should not be combined since the bucket changed.
1067 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED,
1068 getStandbyBucketReason(PACKAGE_1));
1069 }
1070
1071 @Test
Sudheer Shanka101c3532018-01-08 16:28:42 -08001072 public void testAddActiveDeviceAdmin() {
1073 assertActiveAdmins(USER_ID, (String[]) null);
1074 assertActiveAdmins(USER_ID2, (String[]) null);
1075
1076 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID);
1077 assertActiveAdmins(USER_ID, ADMIN_PKG);
1078 assertActiveAdmins(USER_ID2, (String[]) null);
1079
1080 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID);
1081 assertActiveAdmins(USER_ID, ADMIN_PKG);
1082 assertActiveAdmins(USER_ID2, (String[]) null);
1083
1084 mController.addActiveDeviceAdmin(ADMIN_PKG2, USER_ID2);
1085 assertActiveAdmins(USER_ID, ADMIN_PKG);
1086 assertActiveAdmins(USER_ID2, ADMIN_PKG2);
1087 }
1088
1089 @Test
1090 public void testSetActiveAdminApps() {
1091 assertActiveAdmins(USER_ID, (String[]) null);
1092 assertActiveAdmins(USER_ID2, (String[]) null);
1093
1094 setActiveAdmins(USER_ID, ADMIN_PKG, ADMIN_PKG2);
1095 assertActiveAdmins(USER_ID, ADMIN_PKG, ADMIN_PKG2);
1096 assertActiveAdmins(USER_ID2, (String[]) null);
1097
1098 mController.addActiveDeviceAdmin(ADMIN_PKG2, USER_ID2);
1099 setActiveAdmins(USER_ID2, ADMIN_PKG);
1100 assertActiveAdmins(USER_ID, ADMIN_PKG, ADMIN_PKG2);
1101 assertActiveAdmins(USER_ID2, ADMIN_PKG);
1102
1103 mController.setActiveAdminApps(null, USER_ID);
1104 assertActiveAdmins(USER_ID, (String[]) null);
1105 }
1106
1107 @Test
1108 public void isActiveDeviceAdmin() {
1109 assertActiveAdmins(USER_ID, (String[]) null);
1110 assertActiveAdmins(USER_ID2, (String[]) null);
1111
1112 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID);
1113 assertIsActiveAdmin(ADMIN_PKG, USER_ID);
1114 assertIsNotActiveAdmin(ADMIN_PKG, USER_ID2);
1115
1116 mController.addActiveDeviceAdmin(ADMIN_PKG2, USER_ID2);
1117 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID2);
1118 assertIsActiveAdmin(ADMIN_PKG, USER_ID);
1119 assertIsNotActiveAdmin(ADMIN_PKG2, USER_ID);
1120 assertIsActiveAdmin(ADMIN_PKG, USER_ID2);
1121 assertIsActiveAdmin(ADMIN_PKG2, USER_ID2);
1122
1123 setActiveAdmins(USER_ID2, ADMIN_PKG2);
1124 assertIsActiveAdmin(ADMIN_PKG2, USER_ID2);
1125 assertIsNotActiveAdmin(ADMIN_PKG, USER_ID2);
1126 assertIsActiveAdmin(ADMIN_PKG, USER_ID);
1127 assertIsNotActiveAdmin(ADMIN_PKG2, USER_ID);
1128 }
1129
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -08001130 @Test
1131 public void testUserInteraction_CrossProfile() throws Exception {
1132 mInjector.mRunningUsers = new int[] {USER_ID, USER_ID2, USER_ID3};
1133 mInjector.mCrossProfileTargets = Arrays.asList(USER_HANDLE_USER2);
1134 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
1135 assertEquals("Cross profile connected package bucket should be elevated on usage",
1136 STANDBY_BUCKET_ACTIVE, getStandbyBucket(USER_ID2, mController, PACKAGE_1));
1137 assertEquals("Not Cross profile connected package bucket should not be elevated on usage",
1138 STANDBY_BUCKET_NEVER, getStandbyBucket(USER_ID3, mController, PACKAGE_1));
1139
1140 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE, USER_ID);
1141 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE, USER_ID2);
1142
1143 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET, USER_ID);
1144 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET, USER_ID2);
1145
1146 mInjector.mCrossProfileTargets = Collections.emptyList();
1147 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
1148 assertEquals("No longer cross profile connected package bucket should not be "
1149 + "elevated on usage",
1150 STANDBY_BUCKET_WORKING_SET, getStandbyBucket(USER_ID2, mController, PACKAGE_1));
1151 }
1152
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -08001153 @Test
1154 public void testUnexemptedSyncScheduled() throws Exception {
1155 mStateChangedLatch = new CountDownLatch(1);
1156 mController.addListener(mListener);
1157 assertEquals("Test package did not start in the Never bucket", STANDBY_BUCKET_NEVER,
1158 getStandbyBucket(mController, PACKAGE_1));
1159
1160 mController.postReportSyncScheduled(PACKAGE_1, USER_ID, false);
1161 mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
1162 assertEquals("Unexempted sync scheduled should bring the package out of the Never bucket",
1163 STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
1164
1165 setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
1166
1167 mStateChangedLatch = new CountDownLatch(1);
1168 mController.postReportSyncScheduled(PACKAGE_1, USER_ID, false);
1169 mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
1170 assertEquals("Unexempted sync scheduled should not elevate a non Never bucket",
1171 STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
1172 }
1173
1174 @Test
1175 public void testExemptedSyncScheduled() throws Exception {
1176 setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
1177 mInjector.mDeviceIdleMode = true;
1178 mStateChangedLatch = new CountDownLatch(1);
1179 mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true);
1180 mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
1181 assertEquals("Exempted sync scheduled in doze should set bucket to working set",
1182 STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
1183
1184 setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
1185 mInjector.mDeviceIdleMode = false;
1186 mStateChangedLatch = new CountDownLatch(1);
1187 mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true);
1188 mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
1189 assertEquals("Exempted sync scheduled while not in doze should set bucket to active",
1190 STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
1191 }
1192
Sudheer Shanka101c3532018-01-08 16:28:42 -08001193 private String getAdminAppsStr(int userId) {
1194 return getAdminAppsStr(userId, mController.getActiveAdminAppsForTest(userId));
1195 }
1196
1197 private String getAdminAppsStr(int userId, Set<String> adminApps) {
1198 return "admin apps for u" + userId + ": "
1199 + (adminApps == null ? "null" : Arrays.toString(adminApps.toArray()));
1200 }
1201
1202 private void assertIsActiveAdmin(String adminApp, int userId) {
1203 assertTrue(adminApp + " should be an active admin; " + getAdminAppsStr(userId),
1204 mController.isActiveDeviceAdmin(adminApp, userId));
1205 }
1206
1207 private void assertIsNotActiveAdmin(String adminApp, int userId) {
1208 assertFalse(adminApp + " shouldn't be an active admin; " + getAdminAppsStr(userId),
1209 mController.isActiveDeviceAdmin(adminApp, userId));
1210 }
1211
1212 private void assertActiveAdmins(int userId, String... admins) {
1213 final Set<String> actualAdminApps = mController.getActiveAdminAppsForTest(userId);
1214 if (admins == null) {
1215 if (actualAdminApps != null && !actualAdminApps.isEmpty()) {
1216 fail("Admin apps should be null; " + getAdminAppsStr(userId, actualAdminApps));
1217 }
1218 return;
1219 }
1220 assertEquals("No. of admin apps not equal; " + getAdminAppsStr(userId, actualAdminApps)
1221 + "; expected=" + Arrays.toString(admins), admins.length, actualAdminApps.size());
1222 final Set<String> adminAppsCopy = new ArraySet<>(actualAdminApps);
1223 for (String admin : admins) {
1224 adminAppsCopy.remove(admin);
1225 }
1226 assertTrue("Unexpected admin apps; " + getAdminAppsStr(userId, actualAdminApps)
1227 + "; expected=" + Arrays.toString(admins), adminAppsCopy.isEmpty());
1228 }
1229
1230 private void setActiveAdmins(int userId, String... admins) {
1231 mController.setActiveAdminApps(new ArraySet<>(Arrays.asList(admins)), userId);
Amith Yamasani53f06ea2018-01-05 17:53:46 -08001232 }
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -08001233
1234 private void setAndAssertBucket(String pkg, int user, int bucket, int reason) throws Exception {
1235 mStateChangedLatch = new CountDownLatch(1);
1236 mController.setAppStandbyBucket(pkg, user, bucket, reason);
1237 mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
1238 assertEquals("Failed to set package bucket", bucket,
1239 getStandbyBucket(mController, PACKAGE_1));
1240 }
Amith Yamasani17fffee2017-09-29 13:17:43 -07001241}