blob: 1a04d2ff8c2909e8e90fff18f19bd10d52ec00b9 [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;
Kweku Adams95cd9522020-05-08 09:56:53 -070066import android.content.pm.ActivityInfo;
Amith Yamasani17fffee2017-09-29 13:17:43 -070067import android.content.pm.ApplicationInfo;
68import android.content.pm.PackageInfo;
69import android.content.pm.PackageManager;
70import android.hardware.display.DisplayManager;
71import android.os.Handler;
72import android.os.Looper;
73import android.os.RemoteException;
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -080074import android.os.UserHandle;
Amith Yamasani53f06ea2018-01-05 17:53:46 -080075import android.platform.test.annotations.Presubmit;
Sudheer Shanka101c3532018-01-08 16:28:42 -080076import android.util.ArraySet;
Amith Yamasani17fffee2017-09-29 13:17:43 -070077import android.view.Display;
78
Brett Chabota26eda92018-07-23 13:08:30 -070079import androidx.test.InstrumentationRegistry;
80import androidx.test.filters.SmallTest;
81import androidx.test.runner.AndroidJUnit4;
82
Amith Yamasani17fffee2017-09-29 13:17:43 -070083import com.android.server.SystemService;
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -080084import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
Amith Yamasani17fffee2017-09-29 13:17:43 -070085
86import org.junit.Before;
87import org.junit.Test;
88import org.junit.runner.RunWith;
89
90import java.io.File;
91import java.util.ArrayList;
Sudheer Shanka101c3532018-01-08 16:28:42 -080092import java.util.Arrays;
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -080093import java.util.Collections;
Amith Yamasani17fffee2017-09-29 13:17:43 -070094import java.util.List;
Sudheer Shanka101c3532018-01-08 16:28:42 -080095import java.util.Set;
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -080096import java.util.concurrent.CountDownLatch;
Michael Wachenschwanz5ca5cb62018-04-25 16:12:59 -070097import java.util.concurrent.TimeUnit;
Amith Yamasani17fffee2017-09-29 13:17:43 -070098
99/**
100 * Unit test for AppStandbyController.
101 */
102@RunWith(AndroidJUnit4.class)
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800103@Presubmit
104@SmallTest
Amith Yamasani17fffee2017-09-29 13:17:43 -0700105public class AppStandbyControllerTests {
106
107 private static final String PACKAGE_1 = "com.example.foo";
108 private static final int UID_1 = 10000;
Amith Yamasani777b1532018-01-28 23:20:07 +0000109 private static final String PACKAGE_EXEMPTED_1 = "com.android.exempted";
110 private static final int UID_EXEMPTED_1 = 10001;
Kweku Adams95cd9522020-05-08 09:56:53 -0700111 private static final String PACKAGE_SYSTEM_HEADFULL = "com.example.system.headfull";
112 private static final int UID_SYSTEM_HEADFULL = 10002;
113 private static final String PACKAGE_SYSTEM_HEADLESS = "com.example.system.headless";
114 private static final int UID_SYSTEM_HEADLESS = 10003;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700115 private static final int USER_ID = 0;
Sudheer Shanka101c3532018-01-08 16:28:42 -0800116 private static final int USER_ID2 = 10;
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800117 private static final UserHandle USER_HANDLE_USER2 = new UserHandle(USER_ID2);
118 private static final int USER_ID3 = 11;
Sudheer Shanka101c3532018-01-08 16:28:42 -0800119
Varun Shah7609b752018-10-15 15:07:47 -0700120 private static final String PACKAGE_UNKNOWN = "com.example.unknown";
121
Sudheer Shanka101c3532018-01-08 16:28:42 -0800122 private static final String ADMIN_PKG = "com.android.admin";
123 private static final String ADMIN_PKG2 = "com.android.admin2";
124 private static final String ADMIN_PKG3 = "com.android.admin3";
Amith Yamasani17fffee2017-09-29 13:17:43 -0700125
126 private static final long MINUTE_MS = 60 * 1000;
127 private static final long HOUR_MS = 60 * MINUTE_MS;
128 private static final long DAY_MS = 24 * HOUR_MS;
129
Amith Yamasani301e94a2017-11-17 16:35:44 -0800130 private static final long WORKING_SET_THRESHOLD = 12 * HOUR_MS;
131 private static final long FREQUENT_THRESHOLD = 24 * HOUR_MS;
132 private static final long RARE_THRESHOLD = 48 * HOUR_MS;
Kweku Adams4297b5d2020-02-06 15:56:12 -0800133 private static final long RESTRICTED_THRESHOLD = 96 * HOUR_MS;
Amith Yamasani301e94a2017-11-17 16:35:44 -0800134
Varun Shah7609b752018-10-15 15:07:47 -0700135 /** Mock variable used in {@link MyInjector#isPackageInstalled(String, int, int)} */
136 private static boolean isPackageInstalled = true;
137
Amith Yamasani17fffee2017-09-29 13:17:43 -0700138 private MyInjector mInjector;
Amith Yamasani93885192017-12-13 11:52:10 -0800139 private AppStandbyController mController;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700140
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -0800141 private CountDownLatch mStateChangedLatch = new CountDownLatch(1);
142 private AppIdleStateChangeListener mListener = new AppIdleStateChangeListener() {
143 @Override
144 public void onAppIdleStateChanged(String packageName, int userId,
145 boolean idle, int bucket, int reason) {
146 mStateChangedLatch.countDown();
147 }
148 };
149
Amith Yamasani17fffee2017-09-29 13:17:43 -0700150 static class MyContextWrapper extends ContextWrapper {
151 PackageManager mockPm = mock(PackageManager.class);
152
153 public MyContextWrapper(Context base) {
154 super(base);
155 }
156
157 public PackageManager getPackageManager() {
158 return mockPm;
159 }
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800160
161 public Object getSystemService(@NonNull String name) {
162 if (Context.ACTIVITY_SERVICE.equals(name)) {
163 return mock(ActivityManager.class);
164 }
165 return super.getSystemService(name);
166 }
Amith Yamasani17fffee2017-09-29 13:17:43 -0700167 }
168
169 static class MyInjector extends AppStandbyController.Injector {
170 long mElapsedRealtime;
Kweku Adams1e8947c2018-11-05 18:06:13 -0800171 boolean mIsAppIdleEnabled = true;
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800172 boolean mIsCharging;
Kweku Adams2d79ce52020-05-05 12:31:35 -0700173 boolean mIsRestrictedBucketEnabled = true;
Kweku Adamsede42f92020-02-27 15:38:44 -0800174 List<String> mNonIdleWhitelistApps = new ArrayList<>();
Amith Yamasani17fffee2017-09-29 13:17:43 -0700175 boolean mDisplayOn;
176 DisplayManager.DisplayListener mDisplayListener;
Amith Yamasani777b1532018-01-28 23:20:07 +0000177 String mBoundWidgetPackage = PACKAGE_EXEMPTED_1;
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800178 int[] mRunningUsers = new int[] {USER_ID};
179 List<UserHandle> mCrossProfileTargets = Collections.emptyList();
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -0800180 boolean mDeviceIdleMode = false;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700181
182 MyInjector(Context context, Looper looper) {
183 super(context, looper);
184 }
185
186 @Override
187 void onBootPhase(int phase) {
188 }
189
190 @Override
191 int getBootPhase() {
192 return SystemService.PHASE_BOOT_COMPLETED;
193 }
194
195 @Override
196 long elapsedRealtime() {
197 return mElapsedRealtime;
198 }
199
200 @Override
201 long currentTimeMillis() {
202 return mElapsedRealtime;
203 }
204
205 @Override
206 boolean isAppIdleEnabled() {
Kweku Adams1e8947c2018-11-05 18:06:13 -0800207 return mIsAppIdleEnabled;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700208 }
209
210 @Override
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800211 boolean isCharging() {
212 return mIsCharging;
213 }
214
215 @Override
Kweku Adamseffeb2a2020-06-16 10:11:56 -0700216 boolean isNonIdleWhitelisted(String packageName) {
Kweku Adamsede42f92020-02-27 15:38:44 -0800217 return mNonIdleWhitelistApps.contains(packageName);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700218 }
219
220 @Override
Kweku Adams2d79ce52020-05-05 12:31:35 -0700221 boolean isRestrictedBucketEnabled() {
222 return mIsRestrictedBucketEnabled;
223 }
224
225 @Override
Amith Yamasani17fffee2017-09-29 13:17:43 -0700226 File getDataSystemDirectory() {
227 return new File(getContext().getFilesDir(), Long.toString(Math.randomLongInternal()));
228 }
229
230 @Override
231 void noteEvent(int event, String packageName, int uid) throws RemoteException {
232 }
233
234 @Override
235 boolean isPackageEphemeral(int userId, String packageName) {
236 // TODO: update when testing ephemeral apps scenario
237 return false;
238 }
239
240 @Override
Varun Shah7609b752018-10-15 15:07:47 -0700241 boolean isPackageInstalled(String packageName, int flags, int userId) {
242 // Should always return true (default value) unless testing for an uninstalled app
243 return isPackageInstalled;
244 }
245
246 @Override
Amith Yamasani17fffee2017-09-29 13:17:43 -0700247 int[] getRunningUserIds() {
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800248 return mRunningUsers;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700249 }
250
251 @Override
252 boolean isDefaultDisplayOn() {
253 return mDisplayOn;
254 }
255
256 @Override
257 void registerDisplayListener(DisplayManager.DisplayListener listener, Handler handler) {
258 mDisplayListener = listener;
259 }
260
261 @Override
262 String getActiveNetworkScorer() {
263 return null;
264 }
265
266 @Override
267 public boolean isBoundWidgetPackage(AppWidgetManager appWidgetManager, String packageName,
268 int userId) {
269 return packageName != null && packageName.equals(mBoundWidgetPackage);
270 }
271
Amith Yamasani301e94a2017-11-17 16:35:44 -0800272 @Override
273 String getAppIdleSettings() {
274 return "screen_thresholds=0/0/0/" + HOUR_MS + ",elapsed_thresholds=0/"
Kweku Adams4297b5d2020-02-06 15:56:12 -0800275 + WORKING_SET_THRESHOLD + "/" + FREQUENT_THRESHOLD + "/" + RARE_THRESHOLD
276 + "/" + RESTRICTED_THRESHOLD;
Amith Yamasani301e94a2017-11-17 16:35:44 -0800277 }
278
Makoto Onukid5f25d22018-05-22 16:02:17 -0700279 @Override
280 public boolean isDeviceIdleMode() {
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -0800281 return mDeviceIdleMode;
Makoto Onukid5f25d22018-05-22 16:02:17 -0700282 }
283
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800284 @Override
285 public List<UserHandle> getValidCrossProfileTargets(String pkg, int userId) {
286 return mCrossProfileTargets;
287 }
288
Amith Yamasani17fffee2017-09-29 13:17:43 -0700289 // Internal methods
290
291 void setDisplayOn(boolean on) {
292 mDisplayOn = on;
293 if (mDisplayListener != null) {
294 mDisplayListener.onDisplayChanged(Display.DEFAULT_DISPLAY);
295 }
296 }
297 }
298
299 private void setupPm(PackageManager mockPm) throws PackageManager.NameNotFoundException {
300 List<PackageInfo> packages = new ArrayList<>();
301 PackageInfo pi = new PackageInfo();
302 pi.applicationInfo = new ApplicationInfo();
303 pi.applicationInfo.uid = UID_1;
304 pi.packageName = PACKAGE_1;
305 packages.add(pi);
306
Amith Yamasani777b1532018-01-28 23:20:07 +0000307 PackageInfo pie = new PackageInfo();
308 pie.applicationInfo = new ApplicationInfo();
309 pie.applicationInfo.uid = UID_EXEMPTED_1;
310 pie.packageName = PACKAGE_EXEMPTED_1;
311 packages.add(pie);
312
Kweku Adams95cd9522020-05-08 09:56:53 -0700313 PackageInfo pis = new PackageInfo();
314 pis.activities = new ActivityInfo[]{mock(ActivityInfo.class)};
315 pis.applicationInfo = new ApplicationInfo();
316 pis.applicationInfo.uid = UID_SYSTEM_HEADFULL;
317 pis.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
318 pis.packageName = PACKAGE_SYSTEM_HEADFULL;
319 packages.add(pis);
320
321 PackageInfo pish = new PackageInfo();
322 pish.applicationInfo = new ApplicationInfo();
323 pish.applicationInfo.uid = UID_SYSTEM_HEADLESS;
324 pish.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
325 pish.packageName = PACKAGE_SYSTEM_HEADLESS;
326 packages.add(pish);
327
Amith Yamasani17fffee2017-09-29 13:17:43 -0700328 doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(), anyInt());
329 try {
Kweku Adams95cd9522020-05-08 09:56:53 -0700330 for (int i = 0; i < packages.size(); ++i) {
331 PackageInfo pkg = packages.get(i);
332
333 doReturn(pkg.applicationInfo.uid).when(mockPm)
334 .getPackageUidAsUser(eq(pkg.packageName), anyInt());
335 doReturn(pkg.applicationInfo.uid).when(mockPm)
336 .getPackageUidAsUser(eq(pkg.packageName), anyInt(), anyInt());
337 doReturn(pkg.applicationInfo).when(mockPm)
338 .getApplicationInfo(eq(pkg.packageName), anyInt());
339 }
Amith Yamasani17fffee2017-09-29 13:17:43 -0700340 } catch (PackageManager.NameNotFoundException nnfe) {}
341 }
342
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800343 private void setChargingState(AppStandbyController controller, boolean charging) {
344 mInjector.mIsCharging = charging;
345 if (controller != null) {
346 controller.setChargingState(charging);
347 }
348 }
349
Kweku Adams1e8947c2018-11-05 18:06:13 -0800350 private void setAppIdleEnabled(AppStandbyController controller, boolean enabled) {
351 mInjector.mIsAppIdleEnabled = enabled;
352 if (controller != null) {
353 controller.setAppIdleEnabled(enabled);
354 }
355 }
356
Amith Yamasani17fffee2017-09-29 13:17:43 -0700357 private AppStandbyController setupController() throws Exception {
358 mInjector.mElapsedRealtime = 0;
Amith Yamasani777b1532018-01-28 23:20:07 +0000359 setupPm(mInjector.getContext().getPackageManager());
Amith Yamasani17fffee2017-09-29 13:17:43 -0700360 AppStandbyController controller = new AppStandbyController(mInjector);
Amith Yamasani777b1532018-01-28 23:20:07 +0000361 controller.initializeDefaultsForSystemApps(USER_ID);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700362 controller.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
363 controller.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
364 mInjector.setDisplayOn(false);
365 mInjector.setDisplayOn(true);
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800366 setChargingState(controller, false);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700367 controller.checkIdleStates(USER_ID);
Amith Yamasani777b1532018-01-28 23:20:07 +0000368 assertNotEquals(STANDBY_BUCKET_EXEMPTED,
369 controller.getAppStandbyBucket(PACKAGE_1, USER_ID,
370 mInjector.mElapsedRealtime, false));
Amith Yamasani17fffee2017-09-29 13:17:43 -0700371
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -0800372 controller.addListener(mListener);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700373 return controller;
374 }
375
Michael Wachenschwanz5ca5cb62018-04-25 16:12:59 -0700376 private long getCurrentTime() {
377 return TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
378 }
379
Amith Yamasani17fffee2017-09-29 13:17:43 -0700380 @Before
381 public void setUp() throws Exception {
382 MyContextWrapper myContext = new MyContextWrapper(InstrumentationRegistry.getContext());
383 mInjector = new MyInjector(myContext, Looper.getMainLooper());
Amith Yamasani93885192017-12-13 11:52:10 -0800384 mController = setupController();
Michael Wachenschwanz5ca5cb62018-04-25 16:12:59 -0700385 }
386
Amith Yamasani17fffee2017-09-29 13:17:43 -0700387 @Test
Yan Zhudf47a142019-07-30 10:31:04 -0700388 public void testBoundWidgetPackageExempt() throws Exception {
389 assumeTrue(mInjector.getContext().getSystemService(AppWidgetManager.class) != null);
Kweku Adams107be822020-05-14 08:02:45 -0700390 assertEquals(STANDBY_BUCKET_ACTIVE,
Yan Zhudf47a142019-07-30 10:31:04 -0700391 mController.getAppStandbyBucket(PACKAGE_EXEMPTED_1, USER_ID,
392 mInjector.mElapsedRealtime, false));
393 }
394
Kweku Adamse6601762020-05-01 15:06:18 -0700395 private static class TestParoleListener extends AppIdleStateChangeListener {
396 private boolean mIsParoleOn = false;
397 private CountDownLatch mLatch;
398 private boolean mIsExpecting = false;
399 private boolean mExpectedParoleState;
400
401 boolean getParoleState() {
402 synchronized (this) {
403 return mIsParoleOn;
404 }
405 }
406
407 void rearmLatch(boolean expectedParoleState) {
408 synchronized (this) {
409 mLatch = new CountDownLatch(1);
410 mIsExpecting = true;
411 mExpectedParoleState = expectedParoleState;
412 }
413 }
414
415 void awaitOnLatch(long time) throws Exception {
416 mLatch.await(time, TimeUnit.MILLISECONDS);
417 }
418
419 @Override
420 public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
421 int bucket, int reason) {
422 }
423
424 @Override
425 public void onParoleStateChanged(boolean isParoleOn) {
426 synchronized (this) {
427 // Only record information if it is being looked for
428 if (mLatch != null && mLatch.getCount() > 0) {
429 mIsParoleOn = isParoleOn;
430 if (mIsExpecting && isParoleOn == mExpectedParoleState) {
431 mLatch.countDown();
432 }
433 }
434 }
435 }
436 }
437
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800438 @Test
439 public void testIsAppIdle_Charging() throws Exception {
Kweku Adamse6601762020-05-01 15:06:18 -0700440 TestParoleListener paroleListener = new TestParoleListener();
441 mController.addListener(paroleListener);
442
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800443 setChargingState(mController, false);
444 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
445 REASON_MAIN_FORCED_BY_SYSTEM);
446 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
447 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
448 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
Kweku Adamse6601762020-05-01 15:06:18 -0700449 assertFalse(mController.isInParole());
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800450
Kweku Adamse6601762020-05-01 15:06:18 -0700451 paroleListener.rearmLatch(true);
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800452 setChargingState(mController, true);
Kweku Adamse6601762020-05-01 15:06:18 -0700453 paroleListener.awaitOnLatch(2000);
454 assertTrue(paroleListener.getParoleState());
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800455 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
456 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
457 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
Kweku Adamse6601762020-05-01 15:06:18 -0700458 assertTrue(mController.isInParole());
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800459
Kweku Adamse6601762020-05-01 15:06:18 -0700460 paroleListener.rearmLatch(false);
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800461 setChargingState(mController, false);
Kweku Adamse6601762020-05-01 15:06:18 -0700462 paroleListener.awaitOnLatch(2000);
463 assertFalse(paroleListener.getParoleState());
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800464 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
465 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
466 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
Kweku Adamse6601762020-05-01 15:06:18 -0700467 assertFalse(mController.isInParole());
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800468 }
469
470 @Test
471 public void testIsAppIdle_Enabled() throws Exception {
472 setChargingState(mController, false);
Kweku Adamse6601762020-05-01 15:06:18 -0700473 TestParoleListener paroleListener = new TestParoleListener();
474 mController.addListener(paroleListener);
475
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800476 setAppIdleEnabled(mController, true);
477 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
478 REASON_MAIN_FORCED_BY_SYSTEM);
479 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
480 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
481 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
482
Kweku Adamse6601762020-05-01 15:06:18 -0700483 paroleListener.rearmLatch(false);
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800484 setAppIdleEnabled(mController, false);
Kweku Adamse6601762020-05-01 15:06:18 -0700485 paroleListener.awaitOnLatch(2000);
486 assertTrue(paroleListener.mIsParoleOn);
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800487 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
488 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
489
Kweku Adamse6601762020-05-01 15:06:18 -0700490 paroleListener.rearmLatch(true);
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800491 setAppIdleEnabled(mController, true);
Kweku Adamse6601762020-05-01 15:06:18 -0700492 paroleListener.awaitOnLatch(2000);
493 assertFalse(paroleListener.getParoleState());
Kweku Adamsf35ed3702020-02-11 17:32:54 -0800494 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
495 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
496 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
497 }
498
Amith Yamasani17fffee2017-09-29 13:17:43 -0700499 private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket) {
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800500 assertTimeout(controller, elapsedTime, bucket, USER_ID);
501 }
502
503 private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket,
504 int userId) {
Amith Yamasani17fffee2017-09-29 13:17:43 -0700505 mInjector.mElapsedRealtime = elapsedTime;
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800506 controller.checkIdleStates(userId);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700507 assertEquals(bucket,
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800508 controller.getAppStandbyBucket(PACKAGE_1, userId, mInjector.mElapsedRealtime,
Amith Yamasani17fffee2017-09-29 13:17:43 -0700509 false));
510 }
511
Varun Shah7609b752018-10-15 15:07:47 -0700512 private void reportEvent(AppStandbyController controller, int eventType, long elapsedTime,
513 String packageName) {
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800514 // Back to ACTIVE on event
Amith Yamasanibbbad9c2018-02-10 16:46:38 -0800515 mInjector.mElapsedRealtime = elapsedTime;
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800516 UsageEvents.Event ev = new UsageEvents.Event();
Varun Shah7609b752018-10-15 15:07:47 -0700517 ev.mPackage = packageName;
Amith Yamasani803eab692017-11-09 17:47:04 -0800518 ev.mEventType = eventType;
Michael Wachenschwanz793da642020-06-11 16:14:48 -0700519 controller.reportEvent(ev, USER_ID);
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800520 }
521
Varun Shah7609b752018-10-15 15:07:47 -0700522 private int getStandbyBucket(AppStandbyController controller, String packageName) {
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -0800523 return getStandbyBucket(USER_ID, controller, packageName);
524 }
525
526 private int getStandbyBucket(int userId, AppStandbyController controller, String packageName) {
527 return controller.getAppStandbyBucket(packageName, userId, mInjector.mElapsedRealtime,
Amith Yamasani803eab692017-11-09 17:47:04 -0800528 true);
529 }
530
Kweku Adamsaa461942020-03-16 11:59:05 -0700531 private int getStandbyBucketReason(String packageName) {
532 return mController.getAppStandbyBucketReason(packageName, USER_ID,
533 mInjector.mElapsedRealtime);
534 }
535
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800536 private void assertBucket(int bucket) {
Kweku Adams95cd9522020-05-08 09:56:53 -0700537 assertBucket(bucket, PACKAGE_1);
538 }
539
540 private void assertBucket(int bucket, String pkg) {
541 assertEquals(bucket, getStandbyBucket(mController, pkg));
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800542 }
543
Kweku Adams2d79ce52020-05-05 12:31:35 -0700544 private void assertNotBucket(int bucket) {
545 assertNotEquals(bucket, getStandbyBucket(mController, PACKAGE_1));
546 }
547
Amith Yamasani17fffee2017-09-29 13:17:43 -0700548 @Test
549 public void testBuckets() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800550 assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700551
Varun Shah7609b752018-10-15 15:07:47 -0700552 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800553
Amith Yamasani17fffee2017-09-29 13:17:43 -0700554 // ACTIVE bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800555 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700556
557 // WORKING_SET bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800558 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700559
560 // WORKING_SET bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800561 assertTimeout(mController, FREQUENT_THRESHOLD - 1, STANDBY_BUCKET_WORKING_SET);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700562
563 // FREQUENT bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800564 assertTimeout(mController, FREQUENT_THRESHOLD + 1, STANDBY_BUCKET_FREQUENT);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700565
566 // RARE bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800567 assertTimeout(mController, RARE_THRESHOLD + 1, STANDBY_BUCKET_RARE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700568
Kweku Adams4297b5d2020-02-06 15:56:12 -0800569 // RESTRICTED bucket
570 assertTimeout(mController, RESTRICTED_THRESHOLD + 1, STANDBY_BUCKET_RESTRICTED);
571
Varun Shah7609b752018-10-15 15:07:47 -0700572 reportEvent(mController, USER_INTERACTION, RARE_THRESHOLD + 1, PACKAGE_1);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700573
Amith Yamasani93885192017-12-13 11:52:10 -0800574 assertTimeout(mController, RARE_THRESHOLD + 1, STANDBY_BUCKET_ACTIVE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700575
Kweku Adams4297b5d2020-02-06 15:56:12 -0800576 // RESTRICTED bucket
577 assertTimeout(mController, RESTRICTED_THRESHOLD * 2 + 2, STANDBY_BUCKET_RESTRICTED);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700578 }
579
580 @Test
Varun Shah7609b752018-10-15 15:07:47 -0700581 public void testSetAppStandbyBucket() throws Exception {
582 // For a known package, standby bucket should be set properly
583 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800584 mInjector.mElapsedRealtime = HOUR_MS;
Varun Shah7609b752018-10-15 15:07:47 -0700585 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800586 REASON_MAIN_TIMEOUT);
Varun Shah7609b752018-10-15 15:07:47 -0700587 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
588
589 // For an unknown package, standby bucket should not be set, hence NEVER is returned
590 // Ensure the unknown package is not already in history by removing it
591 mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID);
592 isPackageInstalled = false; // Mock package is not installed
593 mController.setAppStandbyBucket(PACKAGE_UNKNOWN, USER_ID, STANDBY_BUCKET_ACTIVE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800594 REASON_MAIN_TIMEOUT);
Varun Shah7609b752018-10-15 15:07:47 -0700595 isPackageInstalled = true; // Reset mocked variable for other tests
596 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN));
597 }
598
599 @Test
600 public void testAppStandbyBucketOnInstallAndUninstall() throws Exception {
601 // On package install, standby bucket should be ACTIVE
602 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_UNKNOWN);
603 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_UNKNOWN));
604
605 // On uninstall, package should not exist in history and should return a NEVER bucket
606 mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID);
607 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN));
608 // Ensure uninstalled app is not in history
609 List<AppStandbyInfo> buckets = mController.getAppStandbyBuckets(USER_ID);
610 for(AppStandbyInfo bucket : buckets) {
611 if (bucket.mPackageName.equals(PACKAGE_UNKNOWN)) {
612 fail("packageName found in app idle history after uninstall.");
613 }
614 }
615 }
616
617 @Test
Amith Yamasani17fffee2017-09-29 13:17:43 -0700618 public void testScreenTimeAndBuckets() throws Exception {
Amith Yamasani17fffee2017-09-29 13:17:43 -0700619 mInjector.setDisplayOn(false);
620
Amith Yamasani93885192017-12-13 11:52:10 -0800621 assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800622
Varun Shah7609b752018-10-15 15:07:47 -0700623 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasani84cd7b72017-11-07 13:59:37 -0800624
Amith Yamasani17fffee2017-09-29 13:17:43 -0700625 // ACTIVE bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800626 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700627
628 // WORKING_SET bucket
Amith Yamasani93885192017-12-13 11:52:10 -0800629 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700630
631 // RARE bucket, should fail because the screen wasn't ON.
Amith Yamasani301e94a2017-11-17 16:35:44 -0800632 mInjector.mElapsedRealtime = RARE_THRESHOLD + 1;
Amith Yamasani93885192017-12-13 11:52:10 -0800633 mController.checkIdleStates(USER_ID);
Varun Shah7609b752018-10-15 15:07:47 -0700634 assertNotEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani17fffee2017-09-29 13:17:43 -0700635
636 mInjector.setDisplayOn(true);
Kweku Adams4297b5d2020-02-06 15:56:12 -0800637 assertTimeout(mController, RARE_THRESHOLD + 2 * HOUR_MS + 1, STANDBY_BUCKET_RARE);
Amith Yamasani17fffee2017-09-29 13:17:43 -0700638 }
639
640 @Test
641 public void testForcedIdle() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800642 mController.forceIdleState(PACKAGE_1, USER_ID, true);
Varun Shah7609b752018-10-15 15:07:47 -0700643 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani93885192017-12-13 11:52:10 -0800644 assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
Amith Yamasani17fffee2017-09-29 13:17:43 -0700645
Amith Yamasani93885192017-12-13 11:52:10 -0800646 mController.forceIdleState(PACKAGE_1, USER_ID, false);
647 assertEquals(STANDBY_BUCKET_ACTIVE, mController.getAppStandbyBucket(PACKAGE_1, USER_ID, 0,
Amith Yamasani17fffee2017-09-29 13:17:43 -0700648 true));
Amith Yamasani93885192017-12-13 11:52:10 -0800649 assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
Amith Yamasani17fffee2017-09-29 13:17:43 -0700650 }
Amith Yamasani803eab692017-11-09 17:47:04 -0800651
652 @Test
653 public void testNotificationEvent() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -0700654 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
655 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani803eab692017-11-09 17:47:04 -0800656 mInjector.mElapsedRealtime = 1;
Varun Shah7609b752018-10-15 15:07:47 -0700657 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1);
658 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani803eab692017-11-09 17:47:04 -0800659
Amith Yamasani93885192017-12-13 11:52:10 -0800660 mController.forceIdleState(PACKAGE_1, USER_ID, true);
Varun Shah7609b752018-10-15 15:07:47 -0700661 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1);
662 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani803eab692017-11-09 17:47:04 -0800663 }
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800664
665 @Test
Jason Monk1918ef72018-03-14 09:20:39 -0400666 public void testSlicePinnedEvent() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -0700667 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
668 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Jason Monk1918ef72018-03-14 09:20:39 -0400669 mInjector.mElapsedRealtime = 1;
Varun Shah7609b752018-10-15 15:07:47 -0700670 reportEvent(mController, SLICE_PINNED, mInjector.mElapsedRealtime, PACKAGE_1);
671 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Jason Monk1918ef72018-03-14 09:20:39 -0400672
673 mController.forceIdleState(PACKAGE_1, USER_ID, true);
Varun Shah7609b752018-10-15 15:07:47 -0700674 reportEvent(mController, SLICE_PINNED, mInjector.mElapsedRealtime, PACKAGE_1);
675 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
Jason Monk1918ef72018-03-14 09:20:39 -0400676 }
677
678 @Test
679 public void testSlicePinnedPrivEvent() throws Exception {
Jason Monk1918ef72018-03-14 09:20:39 -0400680 mController.forceIdleState(PACKAGE_1, USER_ID, true);
Varun Shah7609b752018-10-15 15:07:47 -0700681 reportEvent(mController, SLICE_PINNED_PRIV, mInjector.mElapsedRealtime, PACKAGE_1);
682 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Jason Monk1918ef72018-03-14 09:20:39 -0400683 }
684
685 @Test
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800686 public void testPredictionTimedOut() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800687 // Set it to timeout or usage, so that prediction can override it
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800688 mInjector.mElapsedRealtime = HOUR_MS;
Amith Yamasani93885192017-12-13 11:52:10 -0800689 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800690 REASON_MAIN_TIMEOUT);
Varun Shah7609b752018-10-15 15:07:47 -0700691 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani93885192017-12-13 11:52:10 -0800692
693 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800694 REASON_MAIN_PREDICTED);
Varun Shah7609b752018-10-15 15:07:47 -0700695 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800696
697 // Fast forward 12 hours
698 mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD;
Amith Yamasani93885192017-12-13 11:52:10 -0800699 mController.checkIdleStates(USER_ID);
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800700 // Should still be in predicted bucket, since prediction timeout is 1 day since prediction
Varun Shah7609b752018-10-15 15:07:47 -0700701 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800702 // Fast forward two more hours
703 mInjector.mElapsedRealtime += 2 * HOUR_MS;
Amith Yamasani93885192017-12-13 11:52:10 -0800704 mController.checkIdleStates(USER_ID);
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800705 // Should have now applied prediction timeout
Varun Shah7609b752018-10-15 15:07:47 -0700706 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800707
708 // Fast forward RARE bucket
709 mInjector.mElapsedRealtime += RARE_THRESHOLD;
Amith Yamasani93885192017-12-13 11:52:10 -0800710 mController.checkIdleStates(USER_ID);
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800711 // Should continue to apply prediction timeout
Varun Shah7609b752018-10-15 15:07:47 -0700712 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani93885192017-12-13 11:52:10 -0800713 }
714
715 @Test
716 public void testOverrides() throws Exception {
Amith Yamasani93885192017-12-13 11:52:10 -0800717 // Can force to NEVER
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800718 mInjector.mElapsedRealtime = HOUR_MS;
Amith Yamasani93885192017-12-13 11:52:10 -0800719 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
Kweku Adamsc182d5e2020-01-08 18:37:26 -0800720 REASON_MAIN_FORCED_BY_USER);
Varun Shah7609b752018-10-15 15:07:47 -0700721 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani93885192017-12-13 11:52:10 -0800722
Kweku Adamsc182d5e2020-01-08 18:37:26 -0800723 // Prediction can't override FORCED reasons
724 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
725 REASON_MAIN_FORCED_BY_SYSTEM);
726 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
727 REASON_MAIN_PREDICTED);
728 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
729
Amith Yamasani93885192017-12-13 11:52:10 -0800730 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc182d5e2020-01-08 18:37:26 -0800731 REASON_MAIN_FORCED_BY_USER);
Amith Yamasani93885192017-12-13 11:52:10 -0800732 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800733 REASON_MAIN_PREDICTED);
Varun Shah7609b752018-10-15 15:07:47 -0700734 assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani93885192017-12-13 11:52:10 -0800735
736 // Prediction can't override NEVER
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800737 mInjector.mElapsedRealtime = 2 * HOUR_MS;
Amith Yamasani93885192017-12-13 11:52:10 -0800738 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800739 REASON_MAIN_DEFAULT);
Amith Yamasani93885192017-12-13 11:52:10 -0800740 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800741 REASON_MAIN_PREDICTED);
Varun Shah7609b752018-10-15 15:07:47 -0700742 assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasani93885192017-12-13 11:52:10 -0800743
744 // Prediction can't set to NEVER
745 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800746 REASON_MAIN_USAGE);
Amith Yamasani93885192017-12-13 11:52:10 -0800747 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800748 REASON_MAIN_PREDICTED);
Varun Shah7609b752018-10-15 15:07:47 -0700749 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800750
751 // Prediction can't remove from RESTRICTED
752 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
753 REASON_MAIN_FORCED_BY_USER);
754 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
755 REASON_MAIN_PREDICTED);
756 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
757
758 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
759 REASON_MAIN_FORCED_BY_SYSTEM);
760 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
761 REASON_MAIN_PREDICTED);
762 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
763
764 // Force from user can remove from RESTRICTED
765 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
766 REASON_MAIN_FORCED_BY_USER);
767 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
768 REASON_MAIN_FORCED_BY_USER);
769 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
770
771 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
772 REASON_MAIN_FORCED_BY_SYSTEM);
773 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
774 REASON_MAIN_FORCED_BY_USER);
775 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
776
777 // Force from system can remove from RESTRICTED if it was put it in due to system
778 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
779 REASON_MAIN_FORCED_BY_SYSTEM);
780 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
781 REASON_MAIN_FORCED_BY_SYSTEM);
782 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
783
784 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
785 REASON_MAIN_FORCED_BY_USER);
786 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
787 REASON_MAIN_FORCED_BY_SYSTEM);
788 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
789
790 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
791 REASON_MAIN_PREDICTED);
792 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
793 REASON_MAIN_FORCED_BY_SYSTEM);
794 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
795
796 // Non-user usage can't remove from RESTRICTED
797 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
798 REASON_MAIN_FORCED_BY_SYSTEM);
799 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
800 REASON_MAIN_USAGE);
801 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
802 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
803 REASON_MAIN_USAGE | REASON_SUB_USAGE_SYSTEM_INTERACTION);
804 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
805 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
806 REASON_MAIN_USAGE | REASON_SUB_USAGE_SYNC_ADAPTER);
807 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
808 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
809 REASON_MAIN_USAGE | REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE);
810 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
811
812 // Explicit user usage can remove from RESTRICTED
813 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
814 REASON_MAIN_FORCED_BY_USER);
815 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
816 REASON_MAIN_USAGE | REASON_SUB_USAGE_USER_INTERACTION);
817 assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
818 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
819 REASON_MAIN_FORCED_BY_SYSTEM);
820 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
821 REASON_MAIN_USAGE | REASON_SUB_USAGE_MOVE_TO_FOREGROUND);
822 assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
Amith Yamasanibd7b3022017-12-06 17:40:25 -0800823 }
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800824
825 @Test
826 public void testTimeout() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -0700827 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800828 assertBucket(STANDBY_BUCKET_ACTIVE);
829
830 mInjector.mElapsedRealtime = 2000;
831 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc4ee9982020-01-08 11:14:39 -0800832 REASON_MAIN_PREDICTED);
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800833 assertBucket(STANDBY_BUCKET_ACTIVE);
834
835 // bucketing works after timeout
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700836 mInjector.mElapsedRealtime = mController.mPredictionTimeoutMillis - 100;
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800837 mController.checkIdleStates(USER_ID);
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700838 // Use recent prediction
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800839 assertBucket(STANDBY_BUCKET_FREQUENT);
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700840
841 // Way past prediction timeout, use system thresholds
Kweku Adams4297b5d2020-02-06 15:56:12 -0800842 mInjector.mElapsedRealtime = RARE_THRESHOLD;
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700843 mController.checkIdleStates(USER_ID);
844 assertBucket(STANDBY_BUCKET_RARE);
Sudheer Shanka101c3532018-01-08 16:28:42 -0800845 }
Amith Yamasani53f06ea2018-01-05 17:53:46 -0800846
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800847 /**
848 * Test that setAppStandbyBucket to RESTRICTED doesn't change the bucket until the usage
849 * timeout has passed.
850 */
851 @Test
852 public void testTimeoutBeforeRestricted() throws Exception {
853 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
854 assertBucket(STANDBY_BUCKET_ACTIVE);
855
856 mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD;
857 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
858 REASON_MAIN_FORCED_BY_SYSTEM);
859 // Bucket shouldn't change
860 assertBucket(STANDBY_BUCKET_ACTIVE);
861
862 // bucketing works after timeout
863 mInjector.mElapsedRealtime += DAY_MS;
864 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
865 REASON_MAIN_FORCED_BY_SYSTEM);
866 assertBucket(STANDBY_BUCKET_RESTRICTED);
867
868 // Way past all timeouts. Make sure timeout processing doesn't raise bucket.
Kweku Adams4297b5d2020-02-06 15:56:12 -0800869 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800870 mController.checkIdleStates(USER_ID);
871 assertBucket(STANDBY_BUCKET_RESTRICTED);
872 }
873
874 /**
875 * Test that an app is put into the RESTRICTED bucket after enough time has passed.
876 */
877 @Test
878 public void testRestrictedDelay() throws Exception {
879 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
880 assertBucket(STANDBY_BUCKET_ACTIVE);
881
Kweku Adams109cd9c2020-02-11 11:10:52 -0800882 mInjector.mElapsedRealtime += mInjector.getAutoRestrictedBucketDelayMs() - 5000;
883 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
884 REASON_MAIN_FORCED_BY_SYSTEM);
885 // Bucket shouldn't change
886 assertBucket(STANDBY_BUCKET_ACTIVE);
887
888 // bucketing works after timeout
889 mInjector.mElapsedRealtime += 6000;
890
891 Thread.sleep(6000);
892 // Enough time has passed. The app should automatically be put into the RESTRICTED bucket.
893 assertBucket(STANDBY_BUCKET_RESTRICTED);
894 }
895
896 /**
897 * Test that an app is put into the RESTRICTED bucket after enough time has passed.
898 */
899 @Test
900 public void testRestrictedDelay_DelayChange() throws Exception {
901 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
902 assertBucket(STANDBY_BUCKET_ACTIVE);
903
904 mInjector.mAutoRestrictedBucketDelayMs = 2 * HOUR_MS;
905 mInjector.mElapsedRealtime += 2 * HOUR_MS - 5000;
Kweku Adamsc6a9b342020-01-08 18:37:26 -0800906 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
907 REASON_MAIN_FORCED_BY_SYSTEM);
908 // Bucket shouldn't change
909 assertBucket(STANDBY_BUCKET_ACTIVE);
910
911 // bucketing works after timeout
912 mInjector.mElapsedRealtime += 6000;
913
914 Thread.sleep(6000);
915 // Enough time has passed. The app should automatically be put into the RESTRICTED bucket.
916 assertBucket(STANDBY_BUCKET_RESTRICTED);
917 }
918
Kweku Adams54391332020-04-08 14:56:46 -0700919 /**
920 * Test that an app is "timed out" into the RESTRICTED bucket if prediction tries to put it into
921 * a low bucket after the RESTRICTED timeout.
922 */
923 @Test
924 public void testRestrictedTimeoutOverridesRestoredLowBucketPrediction() {
925 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
926 assertBucket(STANDBY_BUCKET_ACTIVE);
927
928 // Predict to RARE Not long enough to time out into RESTRICTED.
929 mInjector.mElapsedRealtime += RARE_THRESHOLD;
930 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
931 REASON_MAIN_PREDICTED);
932 assertBucket(STANDBY_BUCKET_RARE);
933
934 // Add a short timeout event
935 mInjector.mElapsedRealtime += 1000;
936 reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
937 assertBucket(STANDBY_BUCKET_ACTIVE);
938 mInjector.mElapsedRealtime += 1000;
939 mController.checkIdleStates(USER_ID);
940 assertBucket(STANDBY_BUCKET_ACTIVE);
941
942 // Long enough that it could have timed out into RESTRICTED. Instead of reverting to
943 // predicted RARE, should go into RESTRICTED
944 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
945 mController.checkIdleStates(USER_ID);
946 assertBucket(STANDBY_BUCKET_RESTRICTED);
947
948 // Ensure that prediction can still raise it out despite this override.
949 mInjector.mElapsedRealtime += 1;
950 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
951 REASON_MAIN_PREDICTED);
952 assertBucket(STANDBY_BUCKET_ACTIVE);
953 }
954
955 /**
956 * Test that an app is "timed out" into the RESTRICTED bucket if prediction tries to put it into
957 * a low bucket after the RESTRICTED timeout.
958 */
959 @Test
960 public void testRestrictedTimeoutOverridesPredictionLowBucket() {
961 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
962
963 // Not long enough to time out into RESTRICTED.
964 mInjector.mElapsedRealtime += RARE_THRESHOLD;
965 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
966 REASON_MAIN_PREDICTED);
967 assertBucket(STANDBY_BUCKET_RARE);
968
969 mInjector.mElapsedRealtime += 1;
970 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
971
972 // Long enough that it could have timed out into RESTRICTED.
973 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
974 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
975 REASON_MAIN_PREDICTED);
976 assertBucket(STANDBY_BUCKET_ACTIVE);
977 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
978 REASON_MAIN_PREDICTED);
979 assertBucket(STANDBY_BUCKET_RESTRICTED);
980 }
981
Sudheer Shanka101c3532018-01-08 16:28:42 -0800982 @Test
Kweku Adams2d79ce52020-05-05 12:31:35 -0700983 public void testRestrictedBucketDisabled() {
984 mInjector.mIsRestrictedBucketEnabled = false;
985 // Get the controller to read the new value. Capturing the ContentObserver isn't possible
986 // at the moment.
987 mController.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
988
989 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
990 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD;
991
992 // Nothing should be able to put it into the RESTRICTED bucket.
993 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
994 REASON_MAIN_TIMEOUT);
995 assertNotBucket(STANDBY_BUCKET_RESTRICTED);
996 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
997 REASON_MAIN_PREDICTED);
998 assertNotBucket(STANDBY_BUCKET_RESTRICTED);
999 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1000 REASON_MAIN_FORCED_BY_SYSTEM);
1001 assertNotBucket(STANDBY_BUCKET_RESTRICTED);
1002 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1003 REASON_MAIN_FORCED_BY_USER);
1004 assertNotBucket(STANDBY_BUCKET_RESTRICTED);
1005 }
1006
1007 @Test
1008 public void testRestrictedBucket_EnabledToDisabled() {
1009 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
1010 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD;
1011 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1012 REASON_MAIN_FORCED_BY_SYSTEM);
1013 assertBucket(STANDBY_BUCKET_RESTRICTED);
1014
1015 mInjector.mIsRestrictedBucketEnabled = false;
1016 // Get the controller to read the new value. Capturing the ContentObserver isn't possible
1017 // at the moment.
1018 mController.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
1019
1020 mController.checkIdleStates(USER_ID);
1021 assertNotBucket(STANDBY_BUCKET_RESTRICTED);
1022 }
1023
1024 @Test
Kweku Adams496594c2020-03-16 12:26:01 -07001025 public void testPredictionRaiseFromRestrictedTimeout_highBucket() {
Kweku Adams4297b5d2020-02-06 15:56:12 -08001026 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
1027
1028 // Way past all timeouts. App times out into RESTRICTED bucket.
1029 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
1030 mController.checkIdleStates(USER_ID);
1031 assertBucket(STANDBY_BUCKET_RESTRICTED);
1032
1033 // Since the app timed out into RESTRICTED, prediction should be able to remove from the
1034 // bucket.
1035 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD;
1036 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
1037 REASON_MAIN_PREDICTED);
Kweku Adams496594c2020-03-16 12:26:01 -07001038 assertBucket(STANDBY_BUCKET_ACTIVE);
1039 }
1040
1041 @Test
1042 public void testPredictionRaiseFromRestrictedTimeout_lowBucket() {
1043 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
1044
1045 // Way past all timeouts. App times out into RESTRICTED bucket.
1046 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
1047 mController.checkIdleStates(USER_ID);
1048 assertBucket(STANDBY_BUCKET_RESTRICTED);
1049
1050 // Prediction into a low bucket means no expectation of the app being used, so we shouldn't
1051 // elevate the app from RESTRICTED.
1052 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD;
1053 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
1054 REASON_MAIN_PREDICTED);
1055 assertBucket(STANDBY_BUCKET_RESTRICTED);
Kweku Adams4297b5d2020-02-06 15:56:12 -08001056 }
1057
1058 @Test
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001059 public void testCascadingTimeouts() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -07001060 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001061 assertBucket(STANDBY_BUCKET_ACTIVE);
1062
Varun Shah7609b752018-10-15 15:07:47 -07001063 reportEvent(mController, NOTIFICATION_SEEN, 1000, PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001064 assertBucket(STANDBY_BUCKET_ACTIVE);
1065
1066 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
Kweku Adamsc4ee9982020-01-08 11:14:39 -08001067 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001068 assertBucket(STANDBY_BUCKET_ACTIVE);
1069
Kweku Adamsc4ee9982020-01-08 11:14:39 -08001070 mInjector.mElapsedRealtime = 2000 + mController.mStrongUsageTimeoutMillis;
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001071 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc4ee9982020-01-08 11:14:39 -08001072 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001073 assertBucket(STANDBY_BUCKET_WORKING_SET);
1074
Kweku Adamsc4ee9982020-01-08 11:14:39 -08001075 mInjector.mElapsedRealtime = 2000 + mController.mNotificationSeenTimeoutMillis;
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001076 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc4ee9982020-01-08 11:14:39 -08001077 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001078 assertBucket(STANDBY_BUCKET_FREQUENT);
1079 }
1080
1081 @Test
1082 public void testOverlappingTimeouts() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -07001083 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001084 assertBucket(STANDBY_BUCKET_ACTIVE);
1085
Varun Shah7609b752018-10-15 15:07:47 -07001086 reportEvent(mController, NOTIFICATION_SEEN, 1000, PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001087 assertBucket(STANDBY_BUCKET_ACTIVE);
1088
1089 // Overlapping USER_INTERACTION before previous one times out
Varun Shah7609b752018-10-15 15:07:47 -07001090 reportEvent(mController, USER_INTERACTION, mController.mStrongUsageTimeoutMillis - 1000,
1091 PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001092 assertBucket(STANDBY_BUCKET_ACTIVE);
1093
1094 // Still in ACTIVE after first USER_INTERACTION times out
1095 mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis + 1000;
1096 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc4ee9982020-01-08 11:14:39 -08001097 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001098 assertBucket(STANDBY_BUCKET_ACTIVE);
1099
1100 // Both timed out, so NOTIFICATION_SEEN timeout should be effective
1101 mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis * 2 + 2000;
1102 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc4ee9982020-01-08 11:14:39 -08001103 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001104 assertBucket(STANDBY_BUCKET_WORKING_SET);
1105
1106 mInjector.mElapsedRealtime = mController.mNotificationSeenTimeoutMillis + 2000;
1107 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -08001108 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001109 assertBucket(STANDBY_BUCKET_RARE);
1110 }
1111
1112 @Test
Amith Yamasani7f53c7b2018-03-25 21:55:50 -07001113 public void testSystemInteractionTimeout() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -07001114 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasani7f53c7b2018-03-25 21:55:50 -07001115 // Fast forward to RARE
1116 mInjector.mElapsedRealtime = RARE_THRESHOLD + 100;
1117 mController.checkIdleStates(USER_ID);
1118 assertBucket(STANDBY_BUCKET_RARE);
1119
1120 // Trigger a SYSTEM_INTERACTION and verify bucket
Varun Shah7609b752018-10-15 15:07:47 -07001121 reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
Amith Yamasani7f53c7b2018-03-25 21:55:50 -07001122 assertBucket(STANDBY_BUCKET_ACTIVE);
1123
1124 // Verify it's still in ACTIVE close to end of timeout
1125 mInjector.mElapsedRealtime += mController.mSystemInteractionTimeoutMillis - 100;
1126 mController.checkIdleStates(USER_ID);
1127 assertBucket(STANDBY_BUCKET_ACTIVE);
1128
1129 // Verify bucket moves to RARE after timeout
1130 mInjector.mElapsedRealtime += 200;
1131 mController.checkIdleStates(USER_ID);
1132 assertBucket(STANDBY_BUCKET_RARE);
1133 }
1134
1135 @Test
Michael Wachenschwanz6ced0ee2019-04-15 16:43:28 -07001136 public void testInitialForegroundServiceTimeout() throws Exception {
Michael Wachenschwanz6ced0ee2019-04-15 16:43:28 -07001137 mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100;
1138 // Make sure app is in NEVER bucket
1139 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
Kweku Adamsc182d5e2020-01-08 18:37:26 -08001140 REASON_MAIN_FORCED_BY_USER);
Michael Wachenschwanz6ced0ee2019-04-15 16:43:28 -07001141 mController.checkIdleStates(USER_ID);
1142 assertBucket(STANDBY_BUCKET_NEVER);
1143
1144 mInjector.mElapsedRealtime += 100;
1145
1146 // Trigger a FOREGROUND_SERVICE_START and verify bucket
1147 reportEvent(mController, FOREGROUND_SERVICE_START, mInjector.mElapsedRealtime, PACKAGE_1);
1148 mController.checkIdleStates(USER_ID);
1149 assertBucket(STANDBY_BUCKET_ACTIVE);
1150
1151 // Verify it's still in ACTIVE close to end of timeout
1152 mInjector.mElapsedRealtime += mController.mInitialForegroundServiceStartTimeoutMillis - 100;
1153 mController.checkIdleStates(USER_ID);
1154 assertBucket(STANDBY_BUCKET_ACTIVE);
1155
1156 // Verify bucket moves to RARE after timeout
1157 mInjector.mElapsedRealtime += 200;
1158 mController.checkIdleStates(USER_ID);
1159 assertBucket(STANDBY_BUCKET_RARE);
1160
1161 // Trigger a FOREGROUND_SERVICE_START again
1162 reportEvent(mController, FOREGROUND_SERVICE_START, mInjector.mElapsedRealtime, PACKAGE_1);
1163 mController.checkIdleStates(USER_ID);
1164 // Bucket should not be immediately elevated on subsequent service starts
1165 assertBucket(STANDBY_BUCKET_RARE);
1166 }
1167
1168 @Test
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001169 public void testPredictionNotOverridden() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -07001170 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001171 assertBucket(STANDBY_BUCKET_ACTIVE);
1172
1173 mInjector.mElapsedRealtime = WORKING_SET_THRESHOLD - 1000;
Varun Shah7609b752018-10-15 15:07:47 -07001174 reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime, PACKAGE_1);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001175 assertBucket(STANDBY_BUCKET_ACTIVE);
1176
1177 // Falls back to WORKING_SET
1178 mInjector.mElapsedRealtime += 5000;
1179 mController.checkIdleStates(USER_ID);
1180 assertBucket(STANDBY_BUCKET_WORKING_SET);
1181
1182 // Predict to ACTIVE
1183 mInjector.mElapsedRealtime += 1000;
1184 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
Kweku Adamsc4ee9982020-01-08 11:14:39 -08001185 REASON_MAIN_PREDICTED);
Amith Yamasanibbbad9c2018-02-10 16:46:38 -08001186 assertBucket(STANDBY_BUCKET_ACTIVE);
1187
1188 // CheckIdleStates should not change the prediction
1189 mInjector.mElapsedRealtime += 1000;
1190 mController.checkIdleStates(USER_ID);
1191 assertBucket(STANDBY_BUCKET_ACTIVE);
1192 }
1193
1194 @Test
Amith Yamasani3154dcf2018-03-27 18:24:04 -07001195 public void testPredictionStrikesBack() throws Exception {
Varun Shah7609b752018-10-15 15:07:47 -07001196 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
Amith Yamasani3154dcf2018-03-27 18:24:04 -07001197 assertBucket(STANDBY_BUCKET_ACTIVE);
1198
1199 // Predict to FREQUENT
1200 mInjector.mElapsedRealtime = RARE_THRESHOLD;
1201 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
Kweku Adamsc4ee9982020-01-08 11:14:39 -08001202 REASON_MAIN_PREDICTED);
Amith Yamasani3154dcf2018-03-27 18:24:04 -07001203 assertBucket(STANDBY_BUCKET_FREQUENT);
1204
1205 // Add a short timeout event
1206 mInjector.mElapsedRealtime += 1000;
Varun Shah7609b752018-10-15 15:07:47 -07001207 reportEvent(mController, SYSTEM_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
Amith Yamasani3154dcf2018-03-27 18:24:04 -07001208 assertBucket(STANDBY_BUCKET_ACTIVE);
1209 mInjector.mElapsedRealtime += 1000;
1210 mController.checkIdleStates(USER_ID);
1211 assertBucket(STANDBY_BUCKET_ACTIVE);
1212
1213 // Verify it reverted to predicted
1214 mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD / 2;
1215 mController.checkIdleStates(USER_ID);
1216 assertBucket(STANDBY_BUCKET_FREQUENT);
1217 }
1218
1219 @Test
Kweku Adamsaa461942020-03-16 11:59:05 -07001220 public void testSystemForcedFlags_NotAddedForUserForce() throws Exception {
1221 final int expectedReason = REASON_MAIN_FORCED_BY_USER;
1222 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1223 REASON_MAIN_FORCED_BY_USER);
1224 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
1225 assertEquals(expectedReason, getStandbyBucketReason(PACKAGE_1));
1226
1227 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1228 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE);
1229 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
1230 assertEquals(expectedReason, getStandbyBucketReason(PACKAGE_1));
1231 }
1232
1233 @Test
1234 public void testSystemForcedFlags_AddedForSystemForce() throws Exception {
1235 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
1236 REASON_MAIN_DEFAULT);
1237 mInjector.mElapsedRealtime += 4 * RESTRICTED_THRESHOLD;
1238
1239 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1240 REASON_MAIN_FORCED_BY_SYSTEM
1241 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE);
1242 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
1243 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM
1244 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE,
1245 getStandbyBucketReason(PACKAGE_1));
1246
1247 mController.restrictApp(PACKAGE_1, USER_ID, REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE);
1248 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
1249 // Flags should be combined
1250 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM
1251 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE
1252 | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE, getStandbyBucketReason(PACKAGE_1));
1253 }
1254
1255 @Test
1256 public void testSystemForcedFlags_SystemForceChangesBuckets() throws Exception {
1257 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
1258 REASON_MAIN_DEFAULT);
1259 mInjector.mElapsedRealtime += 4 * RESTRICTED_THRESHOLD;
1260
1261 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
1262 REASON_MAIN_FORCED_BY_SYSTEM
1263 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE);
1264 assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1));
1265 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM
1266 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE,
1267 getStandbyBucketReason(PACKAGE_1));
1268
1269 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
1270 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE);
1271 assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1));
1272 // Flags should be combined
1273 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM
1274 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE
1275 | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE,
1276 getStandbyBucketReason(PACKAGE_1));
1277
1278 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
1279 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);
1280 assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
1281 // Flags should be combined
1282 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY,
1283 getStandbyBucketReason(PACKAGE_1));
1284
1285 mController.restrictApp(PACKAGE_1, USER_ID, REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED);
1286 assertEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
1287 // Flags should not be combined since the bucket changed.
1288 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED,
1289 getStandbyBucketReason(PACKAGE_1));
1290 }
1291
1292 @Test
Sudheer Shanka101c3532018-01-08 16:28:42 -08001293 public void testAddActiveDeviceAdmin() {
1294 assertActiveAdmins(USER_ID, (String[]) null);
1295 assertActiveAdmins(USER_ID2, (String[]) null);
1296
1297 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID);
1298 assertActiveAdmins(USER_ID, ADMIN_PKG);
1299 assertActiveAdmins(USER_ID2, (String[]) null);
1300
1301 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID);
1302 assertActiveAdmins(USER_ID, ADMIN_PKG);
1303 assertActiveAdmins(USER_ID2, (String[]) null);
1304
1305 mController.addActiveDeviceAdmin(ADMIN_PKG2, USER_ID2);
1306 assertActiveAdmins(USER_ID, ADMIN_PKG);
1307 assertActiveAdmins(USER_ID2, ADMIN_PKG2);
1308 }
1309
1310 @Test
1311 public void testSetActiveAdminApps() {
1312 assertActiveAdmins(USER_ID, (String[]) null);
1313 assertActiveAdmins(USER_ID2, (String[]) null);
1314
1315 setActiveAdmins(USER_ID, ADMIN_PKG, ADMIN_PKG2);
1316 assertActiveAdmins(USER_ID, ADMIN_PKG, ADMIN_PKG2);
1317 assertActiveAdmins(USER_ID2, (String[]) null);
1318
1319 mController.addActiveDeviceAdmin(ADMIN_PKG2, USER_ID2);
1320 setActiveAdmins(USER_ID2, ADMIN_PKG);
1321 assertActiveAdmins(USER_ID, ADMIN_PKG, ADMIN_PKG2);
1322 assertActiveAdmins(USER_ID2, ADMIN_PKG);
1323
1324 mController.setActiveAdminApps(null, USER_ID);
1325 assertActiveAdmins(USER_ID, (String[]) null);
1326 }
1327
1328 @Test
1329 public void isActiveDeviceAdmin() {
1330 assertActiveAdmins(USER_ID, (String[]) null);
1331 assertActiveAdmins(USER_ID2, (String[]) null);
1332
1333 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID);
1334 assertIsActiveAdmin(ADMIN_PKG, USER_ID);
1335 assertIsNotActiveAdmin(ADMIN_PKG, USER_ID2);
1336
1337 mController.addActiveDeviceAdmin(ADMIN_PKG2, USER_ID2);
1338 mController.addActiveDeviceAdmin(ADMIN_PKG, USER_ID2);
1339 assertIsActiveAdmin(ADMIN_PKG, USER_ID);
1340 assertIsNotActiveAdmin(ADMIN_PKG2, USER_ID);
1341 assertIsActiveAdmin(ADMIN_PKG, USER_ID2);
1342 assertIsActiveAdmin(ADMIN_PKG2, USER_ID2);
1343
1344 setActiveAdmins(USER_ID2, ADMIN_PKG2);
1345 assertIsActiveAdmin(ADMIN_PKG2, USER_ID2);
1346 assertIsNotActiveAdmin(ADMIN_PKG, USER_ID2);
1347 assertIsActiveAdmin(ADMIN_PKG, USER_ID);
1348 assertIsNotActiveAdmin(ADMIN_PKG2, USER_ID);
1349 }
1350
Michael Wachenschwanz9a3501d2020-02-10 23:17:28 -08001351 @Test
1352 public void testUserInteraction_CrossProfile() throws Exception {
1353 mInjector.mRunningUsers = new int[] {USER_ID, USER_ID2, USER_ID3};
1354 mInjector.mCrossProfileTargets = Arrays.asList(USER_HANDLE_USER2);
1355 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
1356 assertEquals("Cross profile connected package bucket should be elevated on usage",
1357 STANDBY_BUCKET_ACTIVE, getStandbyBucket(USER_ID2, mController, PACKAGE_1));
1358 assertEquals("Not Cross profile connected package bucket should not be elevated on usage",
1359 STANDBY_BUCKET_NEVER, getStandbyBucket(USER_ID3, mController, PACKAGE_1));
1360
1361 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE, USER_ID);
1362 assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE, USER_ID2);
1363
1364 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET, USER_ID);
1365 assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET, USER_ID2);
1366
1367 mInjector.mCrossProfileTargets = Collections.emptyList();
1368 reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
1369 assertEquals("No longer cross profile connected package bucket should not be "
1370 + "elevated on usage",
1371 STANDBY_BUCKET_WORKING_SET, getStandbyBucket(USER_ID2, mController, PACKAGE_1));
1372 }
1373
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -08001374 @Test
1375 public void testUnexemptedSyncScheduled() throws Exception {
1376 mStateChangedLatch = new CountDownLatch(1);
1377 mController.addListener(mListener);
1378 assertEquals("Test package did not start in the Never bucket", STANDBY_BUCKET_NEVER,
1379 getStandbyBucket(mController, PACKAGE_1));
1380
1381 mController.postReportSyncScheduled(PACKAGE_1, USER_ID, false);
1382 mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
1383 assertEquals("Unexempted sync scheduled should bring the package out of the Never bucket",
1384 STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
1385
1386 setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
1387
1388 mStateChangedLatch = new CountDownLatch(1);
1389 mController.postReportSyncScheduled(PACKAGE_1, USER_ID, false);
1390 mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
1391 assertEquals("Unexempted sync scheduled should not elevate a non Never bucket",
1392 STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
1393 }
1394
1395 @Test
1396 public void testExemptedSyncScheduled() throws Exception {
1397 setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
1398 mInjector.mDeviceIdleMode = true;
1399 mStateChangedLatch = new CountDownLatch(1);
1400 mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true);
1401 mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
1402 assertEquals("Exempted sync scheduled in doze should set bucket to working set",
1403 STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
1404
1405 setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
1406 mInjector.mDeviceIdleMode = false;
1407 mStateChangedLatch = new CountDownLatch(1);
1408 mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true);
1409 mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
1410 assertEquals("Exempted sync scheduled while not in doze should set bucket to active",
1411 STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
1412 }
1413
Kweku Adams917f8a42020-02-26 17:18:03 -08001414 @Test
1415 public void testAppUpdateOnRestrictedBucketStatus() {
1416 // Updates shouldn't change bucket if the app timed out.
1417 // Way past all timeouts. App times out into RESTRICTED bucket.
1418 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
1419 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
1420 mController.checkIdleStates(USER_ID);
1421 assertBucket(STANDBY_BUCKET_RESTRICTED);
1422
1423 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID);
1424 assertBucket(STANDBY_BUCKET_RESTRICTED);
1425 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2);
1426 assertBucket(STANDBY_BUCKET_RESTRICTED);
1427 mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID);
1428 assertBucket(STANDBY_BUCKET_RESTRICTED);
1429
1430 // Updates shouldn't change bucket if the app was forced by the system for a non-buggy
1431 // reason.
1432 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
1433 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
1434 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1435 REASON_MAIN_FORCED_BY_SYSTEM
1436 | REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE);
1437
1438 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID);
1439 assertBucket(STANDBY_BUCKET_RESTRICTED);
1440 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2);
1441 assertBucket(STANDBY_BUCKET_RESTRICTED);
1442 mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID);
1443 assertBucket(STANDBY_BUCKET_RESTRICTED);
1444
1445 // Updates should change bucket if the app was forced by the system for a buggy reason.
1446 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
1447 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
1448 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1449 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);
1450
1451 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2);
1452 assertBucket(STANDBY_BUCKET_RESTRICTED);
1453 mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID);
1454 assertBucket(STANDBY_BUCKET_RESTRICTED);
1455 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID);
1456 assertNotEquals(STANDBY_BUCKET_RESTRICTED, getStandbyBucket(mController, PACKAGE_1));
1457
1458 // Updates shouldn't change bucket if the app was forced by the system for more than just
1459 // a buggy reason.
1460 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
1461 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
1462 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1463 REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE
1464 | REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);
1465
1466 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID);
1467 assertBucket(STANDBY_BUCKET_RESTRICTED);
1468 assertEquals(REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE,
1469 getStandbyBucketReason(PACKAGE_1));
1470 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2);
1471 assertBucket(STANDBY_BUCKET_RESTRICTED);
1472 mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID);
1473 assertBucket(STANDBY_BUCKET_RESTRICTED);
1474
1475 // Updates shouldn't change bucket if the app was forced by the user.
1476 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
1477 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD * 4;
1478 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED,
1479 REASON_MAIN_FORCED_BY_USER);
1480
1481 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID);
1482 assertBucket(STANDBY_BUCKET_RESTRICTED);
1483 mController.maybeUnrestrictBuggyApp(PACKAGE_1, USER_ID2);
1484 assertBucket(STANDBY_BUCKET_RESTRICTED);
1485 mController.maybeUnrestrictBuggyApp("com.random.package", USER_ID);
1486 assertBucket(STANDBY_BUCKET_RESTRICTED);
1487 }
1488
Kweku Adams95cd9522020-05-08 09:56:53 -07001489 @Test
1490 public void testSystemHeadlessAppElevated() {
1491 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
1492 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime,
1493 PACKAGE_SYSTEM_HEADFULL);
1494 reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime,
1495 PACKAGE_SYSTEM_HEADLESS);
1496 mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD;
1497
1498
1499 mController.setAppStandbyBucket(PACKAGE_SYSTEM_HEADFULL, USER_ID, STANDBY_BUCKET_RARE,
1500 REASON_MAIN_TIMEOUT);
1501 assertBucket(STANDBY_BUCKET_RARE, PACKAGE_SYSTEM_HEADFULL);
1502
1503 // Make sure headless system apps don't get lowered.
1504 mController.setAppStandbyBucket(PACKAGE_SYSTEM_HEADLESS, USER_ID, STANDBY_BUCKET_RARE,
1505 REASON_MAIN_TIMEOUT);
1506 assertBucket(STANDBY_BUCKET_ACTIVE, PACKAGE_SYSTEM_HEADLESS);
1507
1508 // Package 1 doesn't have activities and is headless, but is not a system app, so it can
1509 // be lowered.
1510 mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
1511 REASON_MAIN_TIMEOUT);
1512 assertBucket(STANDBY_BUCKET_RARE, PACKAGE_1);
1513 }
1514
Sudheer Shanka101c3532018-01-08 16:28:42 -08001515 private String getAdminAppsStr(int userId) {
1516 return getAdminAppsStr(userId, mController.getActiveAdminAppsForTest(userId));
1517 }
1518
1519 private String getAdminAppsStr(int userId, Set<String> adminApps) {
1520 return "admin apps for u" + userId + ": "
1521 + (adminApps == null ? "null" : Arrays.toString(adminApps.toArray()));
1522 }
1523
1524 private void assertIsActiveAdmin(String adminApp, int userId) {
1525 assertTrue(adminApp + " should be an active admin; " + getAdminAppsStr(userId),
1526 mController.isActiveDeviceAdmin(adminApp, userId));
1527 }
1528
1529 private void assertIsNotActiveAdmin(String adminApp, int userId) {
1530 assertFalse(adminApp + " shouldn't be an active admin; " + getAdminAppsStr(userId),
1531 mController.isActiveDeviceAdmin(adminApp, userId));
1532 }
1533
1534 private void assertActiveAdmins(int userId, String... admins) {
1535 final Set<String> actualAdminApps = mController.getActiveAdminAppsForTest(userId);
1536 if (admins == null) {
1537 if (actualAdminApps != null && !actualAdminApps.isEmpty()) {
1538 fail("Admin apps should be null; " + getAdminAppsStr(userId, actualAdminApps));
1539 }
1540 return;
1541 }
1542 assertEquals("No. of admin apps not equal; " + getAdminAppsStr(userId, actualAdminApps)
1543 + "; expected=" + Arrays.toString(admins), admins.length, actualAdminApps.size());
1544 final Set<String> adminAppsCopy = new ArraySet<>(actualAdminApps);
1545 for (String admin : admins) {
1546 adminAppsCopy.remove(admin);
1547 }
1548 assertTrue("Unexpected admin apps; " + getAdminAppsStr(userId, actualAdminApps)
1549 + "; expected=" + Arrays.toString(admins), adminAppsCopy.isEmpty());
1550 }
1551
1552 private void setActiveAdmins(int userId, String... admins) {
1553 mController.setActiveAdminApps(new ArraySet<>(Arrays.asList(admins)), userId);
Amith Yamasani53f06ea2018-01-05 17:53:46 -08001554 }
Michael Wachenschwanz1103ff22020-02-11 20:40:26 -08001555
1556 private void setAndAssertBucket(String pkg, int user, int bucket, int reason) throws Exception {
1557 mStateChangedLatch = new CountDownLatch(1);
1558 mController.setAppStandbyBucket(pkg, user, bucket, reason);
1559 mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
1560 assertEquals("Failed to set package bucket", bucket,
1561 getStandbyBucket(mController, PACKAGE_1));
1562 }
Amith Yamasani17fffee2017-09-29 13:17:43 -07001563}