• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.am;
18 
19 import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
20 import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
21 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
22 import static android.Manifest.permission.CAMERA;
23 import static android.Manifest.permission.RECORD_AUDIO;
24 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
25 import static android.app.ActivityManager.PROCESS_STATE_TOP;
26 import static android.app.ActivityManager.RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
27 import static android.app.ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
28 import static android.app.ActivityManager.RESTRICTION_LEVEL_EXEMPTED;
29 import static android.app.ActivityManager.RESTRICTION_LEVEL_RESTRICTED_BUCKET;
30 import static android.app.ActivityManager.isLowRamDeviceStatic;
31 import static android.app.AppOpsManager.MODE_ALLOWED;
32 import static android.app.AppOpsManager.MODE_IGNORED;
33 import static android.app.AppOpsManager.OP_ACTIVATE_PLATFORM_VPN;
34 import static android.app.AppOpsManager.OP_ACTIVATE_VPN;
35 import static android.app.AppOpsManager.OP_CAMERA;
36 import static android.app.AppOpsManager.OP_FINE_LOCATION;
37 import static android.app.AppOpsManager.OP_NONE;
38 import static android.app.AppOpsManager.OP_RECORD_AUDIO;
39 import static android.app.AppOpsManager.OP_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS;
40 import static android.app.usage.UsageStatsManager.REASON_MAIN_DEFAULT;
41 import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_SYSTEM;
42 import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER;
43 import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK;
44 import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
45 import static android.app.usage.UsageStatsManager.REASON_SUB_DEFAULT_UNDEFINED;
46 import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE;
47 import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_USER_FLAG_INTERACTION;
48 import static android.app.usage.UsageStatsManager.REASON_SUB_MASK;
49 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACTION;
50 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
51 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
52 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
53 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
54 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
55 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RESTRICTED;
56 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
57 import static android.content.pm.PackageManager.PERMISSION_DENIED;
58 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
59 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
60 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
61 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK;
62 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE;
63 import static android.os.PowerExemptionManager.REASON_CARRIER_PRIVILEGED_APP;
64 import static android.os.PowerExemptionManager.REASON_DENIED;
65 
66 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
67 
68 import static com.android.internal.notification.SystemNotificationChannels.ABUSIVE_BACKGROUND_APPS;
69 import static com.android.server.am.AppBatteryTracker.AppBatteryPolicy.getFloatArray;
70 import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_BACKGROUND;
71 import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_CACHED;
72 import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND;
73 import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND_SERVICE;
74 import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATT_DIMENS;
75 import static com.android.server.am.AppPermissionTracker.AppPermissionPolicy;
76 import static com.android.server.am.AppRestrictionController.STOCK_PM_FLAGS;
77 import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_FGS_LOCATION;
78 import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_FGS_MEDIA_PLAYBACK;
79 import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_FGS_WITH_NOTIFICATION;
80 import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_MEDIA_SESSION;
81 import static com.android.server.am.BaseAppStateTracker.STATE_TYPE_PERMISSION;
82 
83 import static org.junit.Assert.assertEquals;
84 import static org.junit.Assert.assertTrue;
85 import static org.junit.Assert.fail;
86 import static org.mockito.ArgumentMatchers.any;
87 import static org.mockito.ArgumentMatchers.eq;
88 import static org.mockito.Mockito.anyBoolean;
89 import static org.mockito.Mockito.anyInt;
90 import static org.mockito.Mockito.anyLong;
91 import static org.mockito.Mockito.any;
92 import static org.mockito.Mockito.anyString;
93 import static org.mockito.Mockito.atLeast;
94 import static org.mockito.Mockito.clearInvocations;
95 import static org.mockito.Mockito.doAnswer;
96 import static org.mockito.Mockito.doReturn;
97 import static org.mockito.Mockito.mock;
98 import static org.mockito.Mockito.never;
99 import static org.mockito.Mockito.spy;
100 import static org.mockito.Mockito.timeout;
101 import static org.mockito.Mockito.times;
102 import static org.mockito.Mockito.verify;
103 
104 import android.annotation.UserIdInt;
105 import android.app.ActivityManagerInternal;
106 import android.app.ActivityManagerInternal.AppBackgroundRestrictionListener;
107 import android.app.ActivityManagerInternal.BindServiceEventListener;
108 import android.app.ActivityManagerInternal.BroadcastEventListener;
109 import android.app.AppOpsManager;
110 import android.app.IActivityManager;
111 import android.app.IUidObserver;
112 import android.app.Notification;
113 import android.app.NotificationManager;
114 import android.app.role.RoleManager;
115 import android.app.usage.AppStandbyInfo;
116 import android.companion.virtual.VirtualDeviceManager;
117 import android.content.Context;
118 import android.content.Intent;
119 import android.content.pm.PackageManager;
120 import android.content.pm.PackageManagerInternal;
121 import android.media.session.MediaController;
122 import android.media.session.MediaSession;
123 import android.media.session.MediaSessionManager;
124 import android.media.session.MediaSessionManager.OnActiveSessionsChangedListener;
125 import android.os.BatteryManagerInternal;
126 import android.os.BatteryStatsInternal;
127 import android.os.BatteryUsageStats;
128 import android.os.Handler;
129 import android.os.Looper;
130 import android.os.MessageQueue;
131 import android.os.Process;
132 import android.os.RemoteException;
133 import android.os.SystemClock;
134 import android.os.UidBatteryConsumer;
135 import android.os.UserHandle;
136 import android.permission.PermissionManager;
137 import android.provider.DeviceConfig;
138 import android.service.notification.StatusBarNotification;
139 import android.telephony.TelephonyManager;
140 import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
141 import android.util.Log;
142 import android.util.Pair;
143 import android.util.SparseArray;
144 
145 import androidx.test.runner.AndroidJUnit4;
146 
147 import com.android.internal.R;
148 import com.android.internal.app.IAppOpsService;
149 import com.android.server.AppStateTracker;
150 import com.android.server.DeviceIdleInternal;
151 import com.android.server.am.AppBatteryExemptionTracker.AppBatteryExemptionPolicy;
152 import com.android.server.am.AppBatteryExemptionTracker.UidBatteryStates;
153 import com.android.server.am.AppBatteryExemptionTracker.UidStateEventWithBattery;
154 import com.android.server.am.AppBatteryTracker.AppBatteryPolicy;
155 import com.android.server.am.AppBatteryTracker.ImmutableBatteryUsage;
156 import com.android.server.am.AppBindServiceEventsTracker.AppBindServiceEventsPolicy;
157 import com.android.server.am.AppBroadcastEventsTracker.AppBroadcastEventsPolicy;
158 import com.android.server.am.AppFGSTracker.AppFGSPolicy;
159 import com.android.server.am.AppMediaSessionTracker.AppMediaSessionPolicy;
160 import com.android.server.am.AppRestrictionController.ConstantsObserver;
161 import com.android.server.am.AppRestrictionController.NotificationHelper;
162 import com.android.server.am.AppRestrictionController.RestrictionSettings;
163 import com.android.server.am.AppRestrictionController.UidBatteryUsageProvider;
164 import com.android.server.am.BaseAppStateTimeEvents.BaseTimeEvent;
165 import com.android.server.apphibernation.AppHibernationManagerInternal;
166 import com.android.server.notification.NotificationManagerInternal;
167 import com.android.server.pm.UserManagerInternal;
168 import com.android.server.pm.permission.PermissionManagerServiceInternal;
169 import com.android.server.usage.AppStandbyInternal;
170 import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
171 
172 import org.junit.After;
173 import org.junit.Before;
174 import org.junit.Test;
175 import org.junit.runner.RunWith;
176 import org.mockito.ArgumentCaptor;
177 import org.mockito.Captor;
178 import org.mockito.Mock;
179 import org.mockito.MockitoAnnotations;
180 import org.mockito.verification.VerificationMode;
181 
182 import java.io.File;
183 import java.time.Duration;
184 import java.util.ArrayList;
185 import java.util.Arrays;
186 import java.util.Collections;
187 import java.util.LinkedList;
188 import java.util.List;
189 import java.util.Set;
190 import java.util.concurrent.CountDownLatch;
191 import java.util.concurrent.Executor;
192 import java.util.concurrent.TimeUnit;
193 import java.util.concurrent.TimeoutException;
194 import java.util.function.BiConsumer;
195 import java.util.stream.Collectors;
196 
197 /**
198  * Tests for {@link AppRestrictionController}.
199  *
200  * Build/Install/Run:
201  *  atest FrameworksMockingServicesTests:BackgroundRestrictionTest
202  */
203 @RunWith(AndroidJUnit4.class)
204 public final class BackgroundRestrictionTest {
205     private static final String TAG = BackgroundRestrictionTest.class.getSimpleName();
206 
207     private static final int TEST_USER0 = UserHandle.USER_SYSTEM;
208     private static final int TEST_USER1 = UserHandle.MIN_SECONDARY_USER_ID;
209     private static final int[] TEST_USERS = new int[] {TEST_USER0, TEST_USER1};
210     private static final String TEST_PACKAGE_BASE = "test_";
211     private static final int TEST_PACKAGE_APPID_BASE = Process.FIRST_APPLICATION_UID;
212     private static final int[] TEST_PACKAGE_USER0_UIDS = new int[] {
213         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 0),
214         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 1),
215         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 2),
216         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 3),
217         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 4),
218         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 5),
219         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 6),
220     };
221     private static final int[] TEST_PACKAGE_USER1_UIDS = new int[] {
222         UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 0),
223         UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 1),
224         UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 2),
225         UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 3),
226         UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 4),
227         UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 5),
228         UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 6),
229     };
230     private static final int[][] TEST_UIDS = new int[][] {
231         TEST_PACKAGE_USER0_UIDS,
232         TEST_PACKAGE_USER1_UIDS,
233     };
234     private static final int[] TEST_STANDBY_BUCKETS = new int[] {
235         STANDBY_BUCKET_EXEMPTED,
236         STANDBY_BUCKET_ACTIVE,
237         STANDBY_BUCKET_WORKING_SET,
238         STANDBY_BUCKET_FREQUENT,
239         STANDBY_BUCKET_RARE,
240         STANDBY_BUCKET_RESTRICTED,
241         STANDBY_BUCKET_NEVER,
242     };
243 
244     private static final int BATTERY_FULL_CHARGE_MAH = 5_000;
245 
246     private static final String[] MOCK_PRIVILEGED_PACKAGES_0 = new String[] {
247         TEST_PACKAGE_BASE + 0,
248         TEST_PACKAGE_BASE + 1,
249     };
250     private static final String[] MOCK_PRIVILEGED_PACKAGES_1 = new String[] {
251         TEST_PACKAGE_BASE + 2,
252         TEST_PACKAGE_BASE + 3,
253     };
254     private static final String[] MOCK_PRIVILEGED_PACKAGES_2 = new String[] {
255         TEST_PACKAGE_BASE + 4,
256         TEST_PACKAGE_BASE + 5,
257     };
258     private static final int[] MOCK_PRIVILEGED_UIDS_0 = new int[] {
259         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 0),
260         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 1),
261     };
262     private static final int[] MOCK_PRIVILEGED_UIDS_1 = new int[] {
263         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 2),
264         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 3),
265     };
266     private static final int[] MOCK_PRIVILEGED_UIDS_2 = new int[] {
267         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 4),
268         UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 5),
269     };
270     private static final String[][] MOCK_PRIVILEGED_PACKAGES = new String[][] {
271         MOCK_PRIVILEGED_PACKAGES_0,
272         MOCK_PRIVILEGED_PACKAGES_1,
273     };
274     private static final int[][] MOCK_PRIVILEGED_UIDS = new int[][] {
275         MOCK_PRIVILEGED_UIDS_0,
276         MOCK_PRIVILEGED_UIDS_1,
277     };
278 
279     @Mock private ActivityManagerInternal mActivityManagerInternal;
280     @Mock private ActivityManagerService mActivityManagerService;
281     @Mock private ActivityManagerConstants mActivityManagerConstants;
282     @Mock private AppOpsManager mAppOpsManager;
283     @Mock private AppStandbyInternal mAppStandbyInternal;
284     @Mock private AppHibernationManagerInternal mAppHibernationInternal;
285     @Mock private AppStateTracker mAppStateTracker;
286     @Mock private BatteryManagerInternal mBatteryManagerInternal;
287     @Mock private BatteryStatsInternal mBatteryStatsInternal;
288     @Mock private DeviceIdleInternal mDeviceIdleInternal;
289     @Mock private IActivityManager mIActivityManager;
290     @Mock private UserManagerInternal mUserManagerInternal;
291     @Mock private PackageManager mPackageManager;
292     @Mock private PackageManagerInternal mPackageManagerInternal;
293     @Mock private NotificationManager mNotificationManager;
294     @Mock private NotificationManagerInternal mNotificationManagerInternal;
295     @Mock private PermissionManager mPermissionManager;
296     @Mock private PermissionManagerServiceInternal mPermissionManagerServiceInternal;
297     @Mock private MediaSessionManager mMediaSessionManager;
298     @Mock private RoleManager mRoleManager;
299     @Mock private TelephonyManager mTelephonyManager;
300     @Mock private IAppOpsService mIAppOpsService;
301 
302     private PhoneCarrierPrivileges mPhoneCarrierPrivileges;
303 
304     private long mCurrentTimeMillis;
305 
306     @Captor private ArgumentCaptor<AppStateTracker.BackgroundRestrictedAppListener> mFasListenerCap;
307     private AppStateTracker.BackgroundRestrictedAppListener mFasListener;
308 
309     @Captor private ArgumentCaptor<AppIdleStateChangeListener> mIdleStateListenerCap;
310     private AppIdleStateChangeListener mIdleStateListener;
311 
312     @Captor private ArgumentCaptor<IUidObserver> mUidObserversCap;
313     private IUidObserver mUidObservers;
314 
315     @Captor private ArgumentCaptor<OnActiveSessionsChangedListener> mActiveSessionListenerCap;
316     private OnActiveSessionsChangedListener mActiveSessionListener;
317 
318     @Captor private ArgumentCaptor<BroadcastEventListener> mBroadcastEventListenerCap;
319     private BroadcastEventListener mBroadcastEventListener;
320 
321     @Captor private ArgumentCaptor<BindServiceEventListener> mBindServiceEventListenerCap;
322     private BindServiceEventListener mBindServiceEventListener;
323 
324     private Context mContext = getInstrumentation().getTargetContext();
325     private Handler mDefaultHandler = new Handler(Looper.getMainLooper());
326     private TestBgRestrictionInjector mInjector;
327     private AppRestrictionController mBgRestrictionController;
328     private AppBatteryTracker mAppBatteryTracker;
329     private AppBatteryPolicy mAppBatteryPolicy;
330     private AppBatteryExemptionTracker mAppBatteryExemptionTracker;
331     private AppBroadcastEventsTracker mAppBroadcastEventsTracker;
332     private AppBindServiceEventsTracker mAppBindServiceEventsTracker;
333     private AppFGSTracker mAppFGSTracker;
334     private AppMediaSessionTracker mAppMediaSessionTracker;
335     private AppPermissionTracker mAppPermissionTracker;
336 
337     @Before
setUp()338     public void setUp() throws Exception {
339         MockitoAnnotations.initMocks(this);
340         initController();
341     }
342 
initController()343     private void initController() throws Exception {
344         mInjector = spy(new TestBgRestrictionInjector(mContext));
345         mBgRestrictionController = spy(new AppRestrictionController(mInjector,
346                     mActivityManagerService));
347 
348         mActivityManagerService.mConstants = mActivityManagerConstants;
349         mPhoneCarrierPrivileges = new PhoneCarrierPrivileges(
350                 mInjector.getTelephonyManager(), MOCK_PRIVILEGED_PACKAGES.length);
351 
352         doReturn(PROCESS_STATE_FOREGROUND_SERVICE).when(mActivityManagerInternal)
353                 .getUidProcessState(anyInt());
354         doReturn(TEST_USERS).when(mUserManagerInternal).getUserIds();
355         for (int userId: TEST_USERS) {
356             final ArrayList<AppStandbyInfo> appStandbyInfoList = new ArrayList<>();
357             for (int i = 0; i < TEST_STANDBY_BUCKETS.length; i++) {
358                 final String packageName = TEST_PACKAGE_BASE + i;
359                 final int uid = UserHandle.getUid(userId, TEST_PACKAGE_APPID_BASE + i);
360                 appStandbyInfoList.add(new AppStandbyInfo(packageName, TEST_STANDBY_BUCKETS[i]));
361                 doReturn(uid)
362                         .when(mPackageManagerInternal)
363                         .getPackageUid(packageName, STOCK_PM_FLAGS, userId);
364                 doReturn(false)
365                         .when(mAppStateTracker)
366                         .isAppBackgroundRestricted(uid, packageName);
367                 doReturn(TEST_STANDBY_BUCKETS[i])
368                         .when(mAppStandbyInternal)
369                         .getAppStandbyBucket(eq(packageName), eq(userId), anyLong(), anyBoolean());
370                 doReturn(new String[]{packageName})
371                         .when(mPackageManager)
372                         .getPackagesForUid(eq(uid));
373                 final int[] ops = new int[] {
374                     OP_ACTIVATE_VPN,
375                     OP_ACTIVATE_PLATFORM_VPN,
376                     OP_FINE_LOCATION,
377                     OP_CAMERA,
378                     OP_RECORD_AUDIO,
379                     OP_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS,
380                 };
381                 for (int op : ops) {
382                     setAppOpState(packageName, uid, op, false);
383                 }
384                 final String[] permissions = new String[] {ACCESS_BACKGROUND_LOCATION,
385                         ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION, CAMERA, RECORD_AUDIO,
386                 };
387                 for (String permission : permissions) {
388                     setPermissionState(packageName, uid, permission, false);
389                 }
390             }
391             doReturn(appStandbyInfoList).when(mAppStandbyInternal).getAppStandbyBuckets(userId);
392         }
393 
394         doReturn(BATTERY_FULL_CHARGE_MAH * 1000).when(mBatteryManagerInternal)
395                 .getBatteryFullCharge();
396 
397         mBgRestrictionController.onSystemReady();
398 
399         verify(mInjector.getAppStateTracker())
400                 .addBackgroundRestrictedAppListener(mFasListenerCap.capture());
401         mFasListener = mFasListenerCap.getValue();
402         verify(mInjector.getAppStandbyInternal())
403                 .addListener(mIdleStateListenerCap.capture());
404         mIdleStateListener = mIdleStateListenerCap.getValue();
405         verify(mInjector.getIActivityManager())
406                 .registerUidObserver(mUidObserversCap.capture(),
407                     anyInt(), anyInt(), anyString());
408         mUidObservers = mUidObserversCap.getValue();
409         verify(mAppMediaSessionTracker.mInjector.getMediaSessionManager())
410                 .addOnActiveSessionsChangedListener(any(), any(), any(),
411                         mActiveSessionListenerCap.capture());
412         mActiveSessionListener = mActiveSessionListenerCap.getValue();
413         verify(mAppBroadcastEventsTracker.mInjector.getActivityManagerInternal())
414                 .addBroadcastEventListener(mBroadcastEventListenerCap.capture());
415         mBroadcastEventListener = mBroadcastEventListenerCap.getValue();
416         verify(mAppBindServiceEventsTracker.mInjector.getActivityManagerInternal())
417                 .addBindServiceEventListener(mBindServiceEventListenerCap.capture());
418         mBindServiceEventListener = mBindServiceEventListenerCap.getValue();
419         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
420     }
421 
422     @After
tearDown()423     public void tearDown() {
424         mBgRestrictionController.tearDown();
425         mBgRestrictionController.getBackgroundHandlerThread().quitSafely();
426     }
427 
428     @Test
testInitialLevels()429     public void testInitialLevels() throws Exception {
430         final int[] expectedLevels = {
431             RESTRICTION_LEVEL_EXEMPTED,
432             RESTRICTION_LEVEL_ADAPTIVE_BUCKET,
433             RESTRICTION_LEVEL_ADAPTIVE_BUCKET,
434             RESTRICTION_LEVEL_ADAPTIVE_BUCKET,
435             RESTRICTION_LEVEL_ADAPTIVE_BUCKET,
436             RESTRICTION_LEVEL_RESTRICTED_BUCKET,
437             RESTRICTION_LEVEL_BACKGROUND_RESTRICTED,
438         };
439         for (int i = 0; i < TEST_UIDS.length; i++) {
440             final int[] uids = TEST_UIDS[i];
441             for (int j = 0; j < uids.length; j++) {
442                 assertEquals(expectedLevels[j],
443                         mBgRestrictionController.getRestrictionLevel(uids[j]));
444                 assertEquals(expectedLevels[j],
445                         mBgRestrictionController.getRestrictionLevel(uids[j],
446                                 TEST_PACKAGE_BASE + j));
447             }
448         }
449     }
450 
451     @Test
testTogglingBackgroundRestrict()452     public void testTogglingBackgroundRestrict() throws Exception {
453         DeviceConfigSession<Boolean> bgAutoRestrictedBucketOnBgRestriction = null;
454         try {
455             bgAutoRestrictedBucketOnBgRestriction = new DeviceConfigSession<>(
456                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
457                     ConstantsObserver.KEY_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION,
458                     DeviceConfig::getBoolean,
459                     ConstantsObserver.DEFAULT_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION);
460             bgAutoRestrictedBucketOnBgRestriction.set(true);
461 
462             testTogglingBackgroundRestrictInternal();
463         } finally {
464             closeIfNotNull(bgAutoRestrictedBucketOnBgRestriction);
465         }
466     }
467 
testTogglingBackgroundRestrictInternal()468     private void testTogglingBackgroundRestrictInternal() throws Exception {
469         final int testPkgIndex = 2;
470         final String testPkgName = TEST_PACKAGE_BASE + testPkgIndex;
471         final int testUser = TEST_USER0;
472         final int testUid = UserHandle.getUid(testUser, TEST_PACKAGE_APPID_BASE + testPkgIndex);
473         final TestAppRestrictionLevelListener listener = new TestAppRestrictionLevelListener();
474         final long timeout = 1_000; // ms
475 
476         mBgRestrictionController.addAppBackgroundRestrictionListener(listener);
477 
478         setBackgroundRestrict(testPkgName, testUid, false, listener);
479 
480         // Verify the current settings.
481         verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid);
482         assertEquals(STANDBY_BUCKET_WORKING_SET, mInjector.getAppStandbyInternal()
483                 .getAppStandbyBucket(testPkgName, testUser, SystemClock.elapsedRealtime(), false));
484 
485         // Now toggling ON the background restrict.
486         setBackgroundRestrict(testPkgName, testUid, true, listener);
487 
488         // We should have been in the background restricted level.
489         verifyRestrictionLevel(RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, testPkgName, testUid);
490 
491         listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
492 
493         // The app should have been put into the restricted standby bucket.
494         verify(mInjector.getAppStandbyInternal(), atLeast(1)).restrictApp(
495                 eq(testPkgName),
496                 eq(testUser),
497                 eq(REASON_MAIN_FORCED_BY_USER),
498                 eq(REASON_SUB_FORCED_USER_FLAG_INTERACTION));
499 
500         // Changing to the restricted standby bucket won't make a difference.
501         listener.mLatchHolder[0] = new CountDownLatch(1);
502         mIdleStateListener.onAppIdleStateChanged(testPkgName, testUser, false,
503                 STANDBY_BUCKET_RESTRICTED, REASON_MAIN_USAGE);
504         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
505         verifyRestrictionLevel(RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, testPkgName, testUid);
506         try {
507             listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
508             fail("There shouldn't be any level change events");
509         } catch (Exception e) {
510             // Expected.
511         }
512 
513         clearInvocations(mInjector.getAppStandbyInternal());
514 
515         // Toggling back.
516         setBackgroundRestrict(testPkgName, testUid, false, listener);
517 
518         // It should have gone back to adaptive level.
519         verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid);
520 
521         // The app standby bucket should be the rare.
522         verify(mInjector.getAppStandbyInternal(), atLeast(1)).maybeUnrestrictApp(
523                 eq(testPkgName),
524                 eq(testUser),
525                 eq(REASON_MAIN_FORCED_BY_USER),
526                 eq(REASON_SUB_FORCED_USER_FLAG_INTERACTION),
527                 eq(REASON_MAIN_USAGE),
528                 eq(REASON_SUB_USAGE_USER_INTERACTION));
529 
530         listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
531 
532         clearInvocations(mInjector.getAppStandbyInternal());
533 
534         // Now set its UID state active.
535         mUidObservers.onUidActive(testUid);
536 
537         // Now toggling ON the background restrict.
538         setBackgroundRestrict(testPkgName, testUid, true, listener);
539 
540         // We should have been in the background restricted level.
541         verifyRestrictionLevel(RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, testPkgName, testUid);
542 
543         listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
544 
545         // The app should have NOT been put into the restricted standby bucket.
546         verify(mInjector.getAppStandbyInternal(), never()).restrictApp(
547                 eq(testPkgName),
548                 eq(testUser),
549                 eq(REASON_MAIN_FORCED_BY_USER),
550                 eq(REASON_SUB_FORCED_USER_FLAG_INTERACTION));
551 
552         // Now set its UID to idle.
553         mUidObservers.onUidIdle(testUid, false);
554 
555         // The app should have been put into the restricted standby bucket because we're idle now.
556         verify(mInjector.getAppStandbyInternal(), timeout(timeout).times(1)).restrictApp(
557                 eq(testPkgName),
558                 eq(testUser),
559                 eq(REASON_MAIN_FORCED_BY_USER),
560                 eq(REASON_SUB_FORCED_USER_FLAG_INTERACTION));
561     }
562 
563     @Test
testTogglingStandbyBucket()564     public void testTogglingStandbyBucket() throws Exception {
565         final int testPkgIndex = 2;
566         final String testPkgName = TEST_PACKAGE_BASE + testPkgIndex;
567         final int testUser = TEST_USER0;
568         final int testUid = UserHandle.getUid(testUser, TEST_PACKAGE_APPID_BASE + testPkgIndex);
569         final TestAppRestrictionLevelListener listener = new TestAppRestrictionLevelListener();
570         final long timeout = 1_000; // ms
571 
572         mBgRestrictionController.addAppBackgroundRestrictionListener(listener);
573 
574         setBackgroundRestrict(testPkgName, testUid, false, listener);
575 
576         // Verify the current settings.
577         verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid);
578 
579         for (int bucket: Arrays.asList(STANDBY_BUCKET_ACTIVE, STANDBY_BUCKET_WORKING_SET,
580                 STANDBY_BUCKET_FREQUENT, STANDBY_BUCKET_RARE)) {
581             listener.mLatchHolder[0] = new CountDownLatch(1);
582             mIdleStateListener.onAppIdleStateChanged(testPkgName, testUser, false,
583                     bucket, REASON_MAIN_USAGE);
584             waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
585             verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid);
586 
587             try {
588                 listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
589                 fail("There shouldn't be any level change events");
590             } catch (Exception e) {
591                 // Expected.
592             }
593         }
594 
595         // Toggling restricted bucket.
596         listener.mLatchHolder[0] = new CountDownLatch(1);
597         mIdleStateListener.onAppIdleStateChanged(testPkgName, testUser, false,
598                 STANDBY_BUCKET_RESTRICTED, REASON_MAIN_USAGE);
599         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
600         verifyRestrictionLevel(RESTRICTION_LEVEL_RESTRICTED_BUCKET, testPkgName, testUid);
601         listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_RESTRICTED_BUCKET);
602 
603         // Toggling exempted bucket.
604         listener.mLatchHolder[0] = new CountDownLatch(1);
605         mIdleStateListener.onAppIdleStateChanged(testPkgName, testUser, false,
606                 STANDBY_BUCKET_EXEMPTED, REASON_MAIN_FORCED_BY_SYSTEM);
607         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
608         verifyRestrictionLevel(RESTRICTION_LEVEL_EXEMPTED, testPkgName, testUid);
609         listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_EXEMPTED);
610     }
611 
612     @Test
testBgCurrentDrainMonitor()613     public void testBgCurrentDrainMonitor() throws Exception {
614         final BatteryUsageStats stats = mock(BatteryUsageStats.class);
615         final List<BatteryUsageStats> statsList = Arrays.asList(stats);
616         final int testPkgIndex = 2;
617         final String testPkgName = TEST_PACKAGE_BASE + testPkgIndex;
618         final int testUser = TEST_USER0;
619         final int testUid = UserHandle.getUid(testUser,
620                 TEST_PACKAGE_APPID_BASE + testPkgIndex);
621         final int testUid2 = UserHandle.getUid(testUser,
622                 TEST_PACKAGE_APPID_BASE + testPkgIndex + 1);
623         final TestAppRestrictionLevelListener listener = new TestAppRestrictionLevelListener();
624         final long timeout =
625                 AppBatteryTracker.BATTERY_USAGE_STATS_POLLING_INTERVAL_MS_DEBUG * 2;
626         final long windowMs = 2_000;
627         final float restrictBucketThreshold = 2.0f;
628         final float restrictBucketThresholdMah =
629                 BATTERY_FULL_CHARGE_MAH * restrictBucketThreshold / 100.0f;
630         final float bgRestrictedThreshold = 4.0f;
631         final float bgRestrictedThresholdMah =
632                 BATTERY_FULL_CHARGE_MAH * bgRestrictedThreshold / 100.0f;
633         final int testPid = 1234;
634         final int notificationId = 1000;
635 
636         DeviceConfigSession<Boolean> bgCurrentDrainMonitor = null;
637         DeviceConfigSession<Long> bgCurrentDrainWindow = null;
638         DeviceConfigSession<Long> bgCurrentDrainInteractionGracePeriod = null;
639         DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketThreshold = null;
640         DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null;
641         DeviceConfigSession<Boolean> bgCurrentDrainAutoRestrictAbusiveApps = null;
642         DeviceConfigSession<Boolean> bgPromptFgsWithNotiToBgRestricted = null;
643         DeviceConfigSession<Boolean> bgPromptAbusiveAppToBgRestricted = null;
644         DeviceConfigSession<Long> bgNotificationMinInterval = null;
645         DeviceConfigSession<Integer> bgBatteryExemptionTypes = null;
646         DeviceConfigSession<Boolean> bgCurrentDrainDecoupleThresholds = null;
647 
648         mBgRestrictionController.addAppBackgroundRestrictionListener(listener);
649 
650         setBackgroundRestrict(testPkgName, testUid, false, listener);
651 
652         // Verify the current settings.
653         verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid);
654 
655         final double[] zeros = new double[]{0.0f, 0.0f};
656         final int[] uids = new int[]{testUid, testUid2};
657 
658         try {
659             bgCurrentDrainMonitor = new DeviceConfigSession<>(
660                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
661                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_MONITOR_ENABLED,
662                     DeviceConfig::getBoolean,
663                     mContext.getResources().getBoolean(
664                             R.bool.config_bg_current_drain_monitor_enabled));
665             bgCurrentDrainMonitor.set(true);
666 
667             bgCurrentDrainWindow = new DeviceConfigSession<>(
668                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
669                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_WINDOW,
670                     DeviceConfig::getLong,
671                     (long) mContext.getResources().getInteger(
672                             R.integer.config_bg_current_drain_window));
673             bgCurrentDrainWindow.set(windowMs);
674 
675             bgCurrentDrainInteractionGracePeriod = new DeviceConfigSession<>(
676                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
677                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD,
678                     DeviceConfig::getLong,
679                     (long) mContext.getResources().getInteger(
680                             R.integer.config_bg_current_drain_window));
681             bgCurrentDrainInteractionGracePeriod.set(windowMs);
682 
683             bgCurrentDrainRestrictedBucketThreshold = new DeviceConfigSession<>(
684                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
685                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET,
686                     DeviceConfig::getFloat,
687                     getFloatArray(mContext.getResources().obtainTypedArray(
688                             R.array.config_bg_current_drain_threshold_to_restricted_bucket))[
689                             isLowRamDeviceStatic() ? 1 : 0]);
690             bgCurrentDrainRestrictedBucketThreshold.set(restrictBucketThreshold);
691 
692             bgCurrentDrainBgRestrictedThreshold = new DeviceConfigSession<>(
693                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
694                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_BG_RESTRICTED,
695                     DeviceConfig::getFloat,
696                     getFloatArray(mContext.getResources().obtainTypedArray(
697                             R.array.config_bg_current_drain_threshold_to_bg_restricted))[
698                             isLowRamDeviceStatic() ? 1 : 0]);
699             bgCurrentDrainBgRestrictedThreshold.set(bgRestrictedThreshold);
700 
701             bgCurrentDrainAutoRestrictAbusiveApps = new DeviceConfigSession<>(
702                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
703                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_AUTO_RESTRICT_ABUSIVE_APPS_ENABLED,
704                     DeviceConfig::getBoolean,
705                     mContext.getResources().getBoolean(
706                             R.bool.config_bg_current_drain_auto_restrict_abusive_apps));
707             bgCurrentDrainAutoRestrictAbusiveApps.set(true);
708 
709             bgPromptFgsWithNotiToBgRestricted = new DeviceConfigSession<>(
710                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
711                     ConstantsObserver.KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_TO_BG_RESTRICTED,
712                     DeviceConfig::getBoolean,
713                     mContext.getResources().getBoolean(
714                             R.bool.config_bg_prompt_fgs_with_noti_to_bg_restricted));
715             bgPromptFgsWithNotiToBgRestricted.set(true);
716 
717             bgPromptAbusiveAppToBgRestricted = new DeviceConfigSession<>(
718                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
719                     ConstantsObserver.KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED,
720                     DeviceConfig::getBoolean,
721                     mContext.getResources().getBoolean(
722                             R.bool.config_bg_prompt_abusive_apps_to_bg_restricted));
723             bgPromptAbusiveAppToBgRestricted.set(true);
724 
725             bgNotificationMinInterval = new DeviceConfigSession<>(
726                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
727                     ConstantsObserver.KEY_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL,
728                     DeviceConfig::getLong,
729                     ConstantsObserver.DEFAULT_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL_MS);
730             bgNotificationMinInterval.set(windowMs);
731 
732             bgBatteryExemptionTypes = new DeviceConfigSession<>(
733                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
734                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_EXEMPTED_TYPES,
735                     DeviceConfig::getInt,
736                     mContext.getResources().getInteger(
737                             R.integer.config_bg_current_drain_exempted_types));
738             bgBatteryExemptionTypes.set(0);
739 
740             bgCurrentDrainDecoupleThresholds = new DeviceConfigSession<>(
741                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
742                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLDS,
743                     DeviceConfig::getBoolean,
744                     AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLD);
745             bgCurrentDrainDecoupleThresholds.set(true);
746 
747             mCurrentTimeMillis = 10_000L;
748             doReturn(mCurrentTimeMillis - windowMs).when(stats).getStatsStartTimestamp();
749             doReturn(mCurrentTimeMillis).when(stats).getStatsEndTimestamp();
750             doReturn(statsList).when(mBatteryStatsInternal).getBatteryUsageStats(any());
751             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName, testUid,
752                     testPid, true);
753             mAppFGSTracker.onForegroundServiceNotificationUpdated(
754                     testPkgName, testUid, notificationId, false);
755             mAppFGSTracker.mNotificationListener.onNotificationPosted(new StatusBarNotification(
756                     testPkgName, null, notificationId, null, testUid, testPid,
757                     new Notification(), UserHandle.of(testUser), null, mCurrentTimeMillis), null);
758 
759             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
760                     new double[]{restrictBucketThresholdMah - 1, 0},
761                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
762                     () -> {
763                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
764                         doReturn(mCurrentTimeMillis + windowMs)
765                                 .when(stats).getStatsEndTimestamp();
766                         mCurrentTimeMillis += windowMs + 1;
767                         try {
768                             listener.verify(timeout, testUid, testPkgName,
769                                     RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
770                             fail("There shouldn't be any level change events");
771                         } catch (Exception e) {
772                             // Expected.
773                         }
774                     });
775 
776             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
777                     new double[]{restrictBucketThresholdMah + 1, 0},
778                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
779                     () -> {
780                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
781                         doReturn(mCurrentTimeMillis + windowMs)
782                                 .when(stats).getStatsEndTimestamp();
783                         mCurrentTimeMillis += windowMs + 1;
784                         // It should have gone to the restricted bucket.
785                         listener.verify(timeout, testUid, testPkgName,
786                                 RESTRICTION_LEVEL_RESTRICTED_BUCKET);
787                         verify(mInjector.getAppStandbyInternal()).restrictApp(
788                                 eq(testPkgName),
789                                 eq(testUser),
790                                 anyInt(), anyInt());
791                     });
792 
793 
794             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
795                     new double[]{restrictBucketThresholdMah - 1, 0},
796                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
797                     () -> {
798                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
799                         doReturn(mCurrentTimeMillis + windowMs)
800                                 .when(stats).getStatsEndTimestamp();
801                         mCurrentTimeMillis += windowMs + 1;
802                         // We won't change restriction level until user interactions.
803                         try {
804                             listener.verify(timeout, testUid, testPkgName,
805                                     RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
806                             fail("There shouldn't be any level change events");
807                         } catch (Exception e) {
808                             // Expected.
809                         }
810                         verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket(
811                                 eq(testPkgName),
812                                 eq(STANDBY_BUCKET_RARE),
813                                 eq(testUser),
814                                 anyInt(), anyInt());
815                     });
816 
817             // Trigger user interaction.
818             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
819                     new double[]{restrictBucketThresholdMah - 1, 0},
820                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
821                     () -> {
822                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
823                         doReturn(mCurrentTimeMillis + windowMs)
824                                 .when(stats).getStatsEndTimestamp();
825                         mCurrentTimeMillis += windowMs + 1;
826                         mIdleStateListener.onUserInteractionStarted(testPkgName, testUser);
827                         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
828                         // It should have been back to normal.
829                         listener.verify(timeout, testUid, testPkgName,
830                                 RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
831                         verify(mInjector.getAppStandbyInternal(), atLeast(1)).maybeUnrestrictApp(
832                                 eq(testPkgName),
833                                 eq(testUser),
834                                 eq(REASON_MAIN_FORCED_BY_SYSTEM),
835                                 eq(REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE),
836                                 eq(REASON_MAIN_USAGE),
837                                 eq(REASON_SUB_USAGE_USER_INTERACTION));
838                     });
839 
840             clearInvocations(mInjector.getAppStandbyInternal());
841 
842             // It won't be restricted since user just interacted with it.
843             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
844                     zeros, new double[]{0, restrictBucketThresholdMah - 1},
845                     zeros, new double[]{restrictBucketThresholdMah + 1, 0},
846                     () -> {
847                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
848                         doReturn(mCurrentTimeMillis + windowMs)
849                                 .when(stats).getStatsEndTimestamp();
850                         mCurrentTimeMillis += windowMs + 1;
851                         try {
852                             listener.verify(timeout, testUid, testPkgName,
853                                     RESTRICTION_LEVEL_RESTRICTED_BUCKET);
854                             fail("There shouldn't be any level change events");
855                         } catch (Exception e) {
856                             // Expected.
857                         }
858                         verify(mInjector.getAppStandbyInternal(), never()).restrictApp(
859                                 eq(testPkgName),
860                                 eq(testUser),
861                                 anyInt(), anyInt());
862                     });
863 
864             // Sleep a while.
865             Thread.sleep(windowMs);
866             clearInvocations(mInjector.getAppStandbyInternal());
867             // Now it should have been restricted.
868             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
869                     zeros, new double[]{0, restrictBucketThresholdMah - 1},
870                     zeros, new double[]{restrictBucketThresholdMah + 1, 0},
871                     () -> {
872                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
873                         doReturn(mCurrentTimeMillis + windowMs)
874                                 .when(stats).getStatsEndTimestamp();
875                         mCurrentTimeMillis += windowMs + 1;
876                         // It should have gone to the restricted bucket.
877                         listener.verify(timeout, testUid, testPkgName,
878                                 RESTRICTION_LEVEL_RESTRICTED_BUCKET);
879                         verify(mInjector.getAppStandbyInternal(), times(1)).restrictApp(
880                                 eq(testPkgName),
881                                 eq(testUser),
882                                 anyInt(), anyInt());
883                     });
884 
885             clearInvocations(mInjector.getAppStandbyInternal());
886             // Drain a bit more, there shouldn't be any level changes.
887             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
888                     zeros, new double[]{0, restrictBucketThresholdMah - 1},
889                     zeros, new double[]{restrictBucketThresholdMah + 2, 0},
890                     () -> {
891                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
892                         doReturn(mCurrentTimeMillis + windowMs)
893                                 .when(stats).getStatsEndTimestamp();
894                         mCurrentTimeMillis += windowMs + 1;
895                         // We won't change restriction level until user interactions.
896                         try {
897                             listener.verify(timeout, testUid, testPkgName,
898                                     RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
899                             fail("There shouldn't be any level change events");
900                         } catch (Exception e) {
901                             // Expected.
902                         }
903                         verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket(
904                                 eq(testPkgName),
905                                 eq(STANDBY_BUCKET_RARE),
906                                 eq(testUser),
907                                 anyInt(), anyInt());
908                     });
909 
910             // Pretend we have the standby buckets set above.
911             doReturn(STANDBY_BUCKET_RESTRICTED)
912                     .when(mAppStandbyInternal)
913                     .getAppStandbyBucket(eq(testPkgName), eq(testUser), anyLong(), anyBoolean());
914 
915             // Sleep a while and set a higher drain
916             Thread.sleep(windowMs);
917             clearInvocations(mInjector.getAppStandbyInternal());
918             clearInvocations(mInjector.getNotificationManager());
919             clearInvocations(mBgRestrictionController);
920 
921             // We're not going to prompt the user if the abusive app has a FGS with notification.
922             bgPromptFgsWithNotiToBgRestricted.set(false);
923 
924             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
925                     new double[]{bgRestrictedThresholdMah + 1, 0},
926                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
927                     () -> {
928                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
929                         doReturn(mCurrentTimeMillis + windowMs)
930                                 .when(stats).getStatsEndTimestamp();
931                         mCurrentTimeMillis += windowMs + 1;
932                         // We won't change restriction level automatically because it needs
933                         // user consent.
934                         try {
935                             listener.verify(timeout, testUid, testPkgName,
936                                     RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
937                             fail("There shouldn't be level change event like this");
938                         } catch (Exception e) {
939                             // Expected.
940                         }
941                         verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket(
942                                 eq(testPkgName),
943                                 eq(STANDBY_BUCKET_RARE),
944                                 eq(testUser),
945                                 anyInt(), anyInt());
946                         // We should have requested to goto background restricted level.
947                         verify(mBgRestrictionController, times(1)).handleRequestBgRestricted(
948                                 eq(testPkgName),
949                                 eq(testUid));
950                         // However, we won't have the prompt to user posted because the policy
951                         // is not to show that for FGS with notification.
952                         checkNotificationShown(new String[] {testPkgName}, never(), false);
953                     });
954 
955             // Pretend we have the notification dismissed.
956             mAppFGSTracker.onForegroundServiceNotificationUpdated(
957                     testPkgName, testUid, notificationId, true);
958             clearInvocations(mInjector.getAppStandbyInternal());
959             clearInvocations(mInjector.getNotificationManager());
960             clearInvocations(mBgRestrictionController);
961 
962             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
963                     new double[]{bgRestrictedThresholdMah + 1, 0},
964                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
965                     () -> {
966                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
967                         doReturn(mCurrentTimeMillis + windowMs)
968                                 .when(stats).getStatsEndTimestamp();
969                         mCurrentTimeMillis += windowMs + 1;
970                         // We won't change restriction level automatically because it needs
971                         // user consent.
972                         try {
973                             listener.verify(timeout, testUid, testPkgName,
974                                     RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
975                             fail("There shouldn't be level change event like this");
976                         } catch (Exception e) {
977                             // Expected.
978                         }
979                         verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket(
980                                 eq(testPkgName),
981                                 eq(STANDBY_BUCKET_RARE),
982                                 eq(testUser),
983                                 anyInt(), anyInt());
984                         // We should have requested to goto background restricted level.
985                         verify(mBgRestrictionController, times(1)).handleRequestBgRestricted(
986                                 eq(testPkgName),
987                                 eq(testUid));
988                         // Verify we have the notification posted now because its FGS is invisible.
989                         checkNotificationShown(new String[] {testPkgName}, atLeast(1), true);
990                     });
991 
992             // Pretend notification is back on.
993             mAppFGSTracker.onForegroundServiceNotificationUpdated(
994                     testPkgName, testUid, notificationId, false);
995             // Now we'll prompt the user even it has a FGS with notification.
996             bgPromptFgsWithNotiToBgRestricted.set(true);
997             clearInvocations(mInjector.getAppStandbyInternal());
998             clearInvocations(mInjector.getNotificationManager());
999             clearInvocations(mBgRestrictionController);
1000 
1001             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
1002                     new double[]{bgRestrictedThresholdMah + 1, 0},
1003                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
1004                     () -> {
1005                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
1006                         doReturn(mCurrentTimeMillis + windowMs)
1007                                 .when(stats).getStatsEndTimestamp();
1008                         mCurrentTimeMillis += windowMs + 1;
1009                         // We won't change restriction level automatically because it needs
1010                         // user consent.
1011                         try {
1012                             listener.verify(timeout, testUid, testPkgName,
1013                                     RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
1014                             fail("There shouldn't be level change event like this");
1015                         } catch (Exception e) {
1016                             // Expected.
1017                         }
1018                         verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket(
1019                                 eq(testPkgName),
1020                                 eq(STANDBY_BUCKET_RARE),
1021                                 eq(testUser),
1022                                 anyInt(), anyInt());
1023                         // We should have requested to goto background restricted level.
1024                         verify(mBgRestrictionController, times(1)).handleRequestBgRestricted(
1025                                 eq(testPkgName),
1026                                 eq(testUid));
1027                         // Verify we have the notification posted.
1028                         checkNotificationShown(new String[] {testPkgName}, atLeast(1), true);
1029                     });
1030 
1031             // Turn ON the FAS for real.
1032             setBackgroundRestrict(testPkgName, testUid, true, listener);
1033 
1034             // Verify it's background restricted now.
1035             verifyRestrictionLevel(RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, testPkgName, testUid);
1036             listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
1037 
1038             // Trigger user interaction.
1039             mIdleStateListener.onUserInteractionStarted(testPkgName, testUser);
1040             waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
1041 
1042             listener.mLatchHolder[0] = new CountDownLatch(1);
1043             try {
1044                 listener.verify(timeout, testUid, testPkgName,
1045                         RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
1046                 fail("There shouldn't be level change event like this");
1047             } catch (Exception e) {
1048                 // Expected.
1049             }
1050 
1051             // Reset the standby bucket.
1052             doReturn(STANDBY_BUCKET_RARE)
1053                     .when(mAppStandbyInternal)
1054                     .getAppStandbyBucket(eq(testPkgName), eq(testUser), anyLong(), anyBoolean());
1055 
1056             // Turn OFF the FAS.
1057             listener.mLatchHolder[0] = new CountDownLatch(1);
1058             clearInvocations(mInjector.getAppStandbyInternal());
1059             clearInvocations(mBgRestrictionController);
1060             setBackgroundRestrict(testPkgName, testUid, false, listener);
1061 
1062             // It'll go back to restricted bucket because it used to behave poorly.
1063             listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_RESTRICTED_BUCKET);
1064             verifyRestrictionLevel(RESTRICTION_LEVEL_RESTRICTED_BUCKET, testPkgName, testUid);
1065 
1066             clearInvocations(mInjector.getAppStandbyInternal());
1067             // Trigger user interaction.
1068             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
1069                     new double[]{restrictBucketThresholdMah - 1, 0},
1070                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
1071                     () -> {
1072                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
1073                         doReturn(mCurrentTimeMillis + windowMs)
1074                                 .when(stats).getStatsEndTimestamp();
1075                         mCurrentTimeMillis += windowMs + 1;
1076                         mIdleStateListener.onUserInteractionStarted(testPkgName, testUser);
1077                         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
1078                         // It should have been back to normal.
1079                         listener.verify(timeout, testUid, testPkgName,
1080                                 RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
1081                         verify(mInjector.getAppStandbyInternal(), atLeast(1)).maybeUnrestrictApp(
1082                                 eq(testPkgName),
1083                                 eq(testUser),
1084                                 eq(REASON_MAIN_USAGE),
1085                                 eq(REASON_SUB_USAGE_USER_INTERACTION),
1086                                 eq(REASON_MAIN_USAGE),
1087                                 eq(REASON_SUB_USAGE_USER_INTERACTION));
1088                     });
1089 
1090             bgCurrentDrainDecoupleThresholds.set(true);
1091             clearInvocations(mInjector.getAppStandbyInternal());
1092 
1093             // Go to the threshold right away.
1094             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
1095                     new double[]{0, restrictBucketThresholdMah - 1},
1096                     new double[]{bgRestrictedThresholdMah + 1, 0}, zeros, zeros,
1097                     () -> {
1098                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
1099                         doReturn(mCurrentTimeMillis + windowMs)
1100                                 .when(stats).getStatsEndTimestamp();
1101                         mCurrentTimeMillis += windowMs + 1;
1102                         // We won't change restriction level automatically because it needs
1103                         // user consent.
1104                         try {
1105                             listener.verify(timeout, testUid, testPkgName,
1106                                     RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
1107                             fail("There shouldn't be level change event like this");
1108                         } catch (Exception e) {
1109                             // Expected.
1110                         }
1111                         verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket(
1112                                 eq(testPkgName),
1113                                 eq(STANDBY_BUCKET_RARE),
1114                                 eq(testUser),
1115                                 anyInt(), anyInt());
1116                         // We should have requested to goto background restricted level.
1117                         verify(mBgRestrictionController, times(1)).handleRequestBgRestricted(
1118                                 eq(testPkgName),
1119                                 eq(testUid));
1120                         // Verify we have the notification posted now because its FGS is invisible.
1121                         checkNotificationShown(new String[] {testPkgName}, atLeast(1), true);
1122                     });
1123 
1124             bgCurrentDrainDecoupleThresholds.set(false);
1125             clearInvocations(mInjector.getAppStandbyInternal());
1126             clearInvocations(mBgRestrictionController);
1127 
1128             // Go to the threshold right away, but this time, it shouldn't even request to goto
1129             // bg restricted level because it requires to be in restricted bucket before that.
1130             runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
1131                     new double[]{0, restrictBucketThresholdMah - 1},
1132                     new double[]{bgRestrictedThresholdMah + 1, 0}, zeros, zeros,
1133                     () -> {
1134                         doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
1135                         doReturn(mCurrentTimeMillis + windowMs)
1136                                 .when(stats).getStatsEndTimestamp();
1137                         mCurrentTimeMillis += windowMs + 1;
1138                         // We won't change restriction level automatically because it needs
1139                         // user consent.
1140                         try {
1141                             listener.verify(timeout, testUid, testPkgName,
1142                                     RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
1143                             fail("There shouldn't be level change event like this");
1144                         } catch (Exception e) {
1145                             // Expected.
1146                         }
1147                         verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket(
1148                                 eq(testPkgName),
1149                                 eq(STANDBY_BUCKET_RARE),
1150                                 eq(testUser),
1151                                 anyInt(), anyInt());
1152                         // We should NOT have requested to goto background restricted level.
1153                         verify(mBgRestrictionController, never()).handleRequestBgRestricted(
1154                                 eq(testPkgName),
1155                                 eq(testUid));
1156                     });
1157 
1158         } finally {
1159             closeIfNotNull(bgCurrentDrainMonitor);
1160             closeIfNotNull(bgCurrentDrainWindow);
1161             closeIfNotNull(bgCurrentDrainInteractionGracePeriod);
1162             closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold);
1163             closeIfNotNull(bgCurrentDrainBgRestrictedThreshold);
1164             closeIfNotNull(bgCurrentDrainAutoRestrictAbusiveApps);
1165             closeIfNotNull(bgPromptFgsWithNotiToBgRestricted);
1166             closeIfNotNull(bgPromptAbusiveAppToBgRestricted);
1167             closeIfNotNull(bgNotificationMinInterval);
1168             closeIfNotNull(bgBatteryExemptionTypes);
1169             closeIfNotNull(bgCurrentDrainDecoupleThresholds);
1170         }
1171     }
1172 
1173     @Test
testLongFGSMonitor()1174     public void testLongFGSMonitor() throws Exception {
1175         final int testPkgIndex1 = 1;
1176         final String testPkgName1 = TEST_PACKAGE_BASE + testPkgIndex1;
1177         final int testUser1 = TEST_USER0;
1178         final int testUid1 = UserHandle.getUid(testUser1, TEST_PACKAGE_APPID_BASE + testPkgIndex1);
1179         final int testPid1 = 1234;
1180 
1181         final int testPkgIndex2 = 2;
1182         final String testPkgName2 = TEST_PACKAGE_BASE + testPkgIndex2;
1183         final int testUser2 = TEST_USER0;
1184         final int testUid2 = UserHandle.getUid(testUser2, TEST_PACKAGE_APPID_BASE + testPkgIndex2);
1185         final int testPid2 = 1235;
1186 
1187         final int fgsNotificationId = 1000;
1188 
1189         final long windowMs = 2_000;
1190         final long thresholdMs = 1_000;
1191         final long shortMs = 100;
1192 
1193         DeviceConfigSession<Boolean> longRunningFGSMonitor = null;
1194         DeviceConfigSession<Long> longRunningFGSWindow = null;
1195         DeviceConfigSession<Long> longRunningFGSThreshold = null;
1196         DeviceConfigSession<Boolean> longRunningFGSWithNotification = null;
1197         DeviceConfigSession<Boolean> longRunningFGS = null;
1198 
1199         try {
1200             longRunningFGSMonitor = new DeviceConfigSession<>(
1201                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1202                     AppFGSPolicy.KEY_BG_FGS_MONITOR_ENABLED,
1203                     DeviceConfig::getBoolean,
1204                     AppFGSPolicy.DEFAULT_BG_FGS_MONITOR_ENABLED);
1205             longRunningFGSMonitor.set(true);
1206 
1207             longRunningFGSWindow = new DeviceConfigSession<>(
1208                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1209                     AppFGSPolicy.KEY_BG_FGS_LONG_RUNNING_WINDOW,
1210                     DeviceConfig::getLong,
1211                     AppFGSPolicy.DEFAULT_BG_FGS_LONG_RUNNING_WINDOW);
1212             longRunningFGSWindow.set(windowMs);
1213 
1214             longRunningFGSThreshold = new DeviceConfigSession<>(
1215                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1216                     AppFGSPolicy.KEY_BG_FGS_LONG_RUNNING_THRESHOLD,
1217                     DeviceConfig::getLong,
1218                     AppFGSPolicy.DEFAULT_BG_FGS_LONG_RUNNING_THRESHOLD);
1219             longRunningFGSThreshold.set(thresholdMs);
1220 
1221             longRunningFGSWithNotification = new DeviceConfigSession<>(
1222                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1223                     ConstantsObserver.KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING,
1224                     DeviceConfig::getBoolean,
1225                     ConstantsObserver.DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING);
1226             longRunningFGSWithNotification.set(true);
1227 
1228             longRunningFGS = new DeviceConfigSession<>(
1229                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1230                     ConstantsObserver.KEY_BG_PROMPT_FGS_ON_LONG_RUNNING,
1231                     DeviceConfig::getBoolean,
1232                     ConstantsObserver.DEFAULT_BG_PROMPT_FGS_ON_LONG_RUNNING);
1233             longRunningFGS.set(true);
1234 
1235             // Basic case
1236             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1,
1237                     testPid1, true);
1238             // Verify we have the notification, it'll include the summary notification though.
1239             int notificationId = checkNotificationShown(
1240                     new String[] {testPkgName1}, timeout(windowMs * 2).times(2), true)[0];
1241 
1242             clearInvocations(mInjector.getNotificationManager());
1243             // Sleep a while, verify it won't show another notification.
1244             Thread.sleep(windowMs * 2);
1245             checkNotificationShown(
1246                     new String[] {testPkgName1}, timeout(windowMs * 2).times(0), false);
1247 
1248             // Stop this FGS
1249             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1,
1250                     testPid1, false);
1251             checkNotificationGone(testPkgName1, timeout(windowMs), notificationId);
1252 
1253             clearInvocations(mInjector.getNotificationManager());
1254             // Start another one and stop it.
1255             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2,
1256                     testPid2, true);
1257             Thread.sleep(shortMs);
1258             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2,
1259                     testPid2, false);
1260 
1261             // Not long enough, it shouldn't show notification in this case.
1262             checkNotificationShown(
1263                     new String[] {testPkgName2}, timeout(windowMs * 2).times(0), false);
1264 
1265             clearInvocations(mInjector.getNotificationManager());
1266             // Start the FGS again.
1267             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2,
1268                     testPid2, true);
1269             // Verify we have the notification.
1270             notificationId = checkNotificationShown(
1271                     new String[] {testPkgName2}, timeout(windowMs * 2).times(2), true)[0];
1272 
1273             // Stop this FGS
1274             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2,
1275                     testPid2, false);
1276             checkNotificationGone(testPkgName2, timeout(windowMs), notificationId);
1277 
1278             // Turn OFF the notification.
1279             longRunningFGS.set(false);
1280             clearInvocations(mInjector.getNotificationManager());
1281             mBgRestrictionController.resetRestrictionSettings();
1282             // Start the FGS again.
1283             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2,
1284                     testPid2, true);
1285             // Verify we do NOT have the notification.
1286             checkNotificationShown(
1287                     new String[] {testPkgName2}, timeout(windowMs * 2).times(0), false);
1288             // Stop this FGS
1289             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2,
1290                     testPid2, false);
1291 
1292             // Turn it back ON.
1293             longRunningFGS.set(true);
1294 
1295             // Start over with concurrent cases.
1296             clearInvocations(mInjector.getNotificationManager());
1297             mBgRestrictionController.resetRestrictionSettings();
1298             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2,
1299                     testPid2, true);
1300             Thread.sleep(shortMs);
1301             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1,
1302                     testPid1, true);
1303 
1304             // Verify we've seen both notifications, and test pkg2 should be shown before test pkg1.
1305             int[] notificationIds = checkNotificationShown(
1306                     new String[] {testPkgName2, testPkgName1},
1307                     timeout(windowMs * 2).times(4), true);
1308 
1309             // Stop both of them.
1310             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1,
1311                     testPid1, false);
1312             checkNotificationGone(testPkgName1, timeout(windowMs), notificationIds[1]);
1313             clearInvocations(mInjector.getNotificationManager());
1314             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2,
1315                     testPid2, false);
1316             checkNotificationGone(testPkgName2, timeout(windowMs), notificationIds[0]);
1317 
1318             // Test the interlaced case.
1319             clearInvocations(mInjector.getNotificationManager());
1320             mBgRestrictionController.resetRestrictionSettings();
1321             mAppFGSTracker.reset();
1322             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1,
1323                     testPid1, true);
1324 
1325             final long initialWaitMs = thresholdMs / 2;
1326             Thread.sleep(initialWaitMs);
1327 
1328             for (long remaining = thresholdMs - initialWaitMs; remaining > 0;) {
1329                 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1,
1330                         testPid1, false);
1331                 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2,
1332                         testPid2, true);
1333                 Thread.sleep(shortMs);
1334                 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1,
1335                         testPid1, true);
1336                 mAppFGSTracker.onForegroundServiceStateChanged(testPkgName2, testUid2,
1337                         testPid2, false);
1338                 Thread.sleep(shortMs);
1339                 remaining -= shortMs;
1340             }
1341 
1342             // Verify test pkg1 got the notification, but not test pkg2.
1343             notificationId = checkNotificationShown(
1344                     new String[] {testPkgName1}, timeout(windowMs).times(2), true)[0];
1345 
1346             clearInvocations(mInjector.getNotificationManager());
1347             // Stop the FGS.
1348             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1,
1349                     testPid1, false);
1350             checkNotificationGone(testPkgName1, timeout(windowMs), notificationId);
1351 
1352             // Start over with the flag to not show prompt when it has an active notification.
1353             clearInvocations(mInjector.getNotificationManager());
1354             mBgRestrictionController.resetRestrictionSettings();
1355             longRunningFGSWithNotification.set(false);
1356 
1357             // Start an FGS with notification.
1358             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1,
1359                     testPid1, true);
1360             mAppFGSTracker.onForegroundServiceNotificationUpdated(
1361                     testPkgName1, testUid1, fgsNotificationId, false);
1362             mAppFGSTracker.mNotificationListener.onNotificationPosted(new StatusBarNotification(
1363                     testPkgName1, null, fgsNotificationId, null, testUid1, testPid1,
1364                     new Notification(), UserHandle.of(testUser1), null, mCurrentTimeMillis), null);
1365 
1366             // Verify we won't prompt the user because it has a visible FGS notification.
1367             checkNotificationShown(
1368                     new String[] {testPkgName1}, timeout(windowMs * 2).times(0), false);
1369 
1370             // Pretend we have the notification dismissed.
1371             mAppFGSTracker.onForegroundServiceNotificationUpdated(
1372                     testPkgName1, testUid1, fgsNotificationId, true);
1373 
1374             // Verify we have the notification.
1375             notificationId = checkNotificationShown(
1376                     new String[] {testPkgName1}, timeout(windowMs * 2).times(2), true)[0];
1377 
1378             // Stop the FGS.
1379             mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1,
1380                     testPid1, false);
1381             checkNotificationGone(testPkgName1, timeout(windowMs), notificationId);
1382         } finally {
1383             closeIfNotNull(longRunningFGSMonitor);
1384             closeIfNotNull(longRunningFGSWindow);
1385             closeIfNotNull(longRunningFGSThreshold);
1386             closeIfNotNull(longRunningFGSWithNotification);
1387             closeIfNotNull(longRunningFGS);
1388         }
1389     }
1390 
1391     @Test
testLongFGSExemptions()1392     public void testLongFGSExemptions() throws Exception {
1393         final int testPkgIndex1 = 1;
1394         final String testPkgName1 = TEST_PACKAGE_BASE + testPkgIndex1;
1395         final int testUser1 = TEST_USER0;
1396         final int testUid1 = UserHandle.getUid(testUser1, TEST_PACKAGE_APPID_BASE + testPkgIndex1);
1397         final int testPid1 = 1234;
1398 
1399         final int testPkgIndex2 = 2;
1400         final String testPkgName2 = TEST_PACKAGE_BASE + testPkgIndex2;
1401         final int testUser2 = TEST_USER0;
1402         final int testUid2 = UserHandle.getUid(testUser2, TEST_PACKAGE_APPID_BASE + testPkgIndex2);
1403         final int testPid2 = 1235;
1404 
1405         final long windowMs = 2_000;
1406         final long thresholdMs = 1_000;
1407 
1408         DeviceConfigSession<Boolean> longRunningFGSMonitor = null;
1409         DeviceConfigSession<Long> longRunningFGSWindow = null;
1410         DeviceConfigSession<Long> longRunningFGSThreshold = null;
1411         DeviceConfigSession<Long> mediaPlaybackFGSThreshold = null;
1412         DeviceConfigSession<Long> locationFGSThreshold = null;
1413         DeviceConfigSession<Boolean> longRunningFGSWithNotification = null;
1414         DeviceConfigSession<Boolean> longRunningFGS = null;
1415 
1416         doReturn(testPkgName1).when(mInjector).getPackageName(testPid1);
1417         doReturn(testPkgName2).when(mInjector).getPackageName(testPid2);
1418 
1419         try {
1420             longRunningFGSMonitor = new DeviceConfigSession<>(
1421                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1422                     AppFGSPolicy.KEY_BG_FGS_MONITOR_ENABLED,
1423                     DeviceConfig::getBoolean,
1424                     AppFGSPolicy.DEFAULT_BG_FGS_MONITOR_ENABLED);
1425             longRunningFGSMonitor.set(true);
1426 
1427             longRunningFGSWindow = new DeviceConfigSession<>(
1428                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1429                     AppFGSPolicy.KEY_BG_FGS_LONG_RUNNING_WINDOW,
1430                     DeviceConfig::getLong,
1431                     AppFGSPolicy.DEFAULT_BG_FGS_LONG_RUNNING_WINDOW);
1432             longRunningFGSWindow.set(windowMs);
1433 
1434             longRunningFGSThreshold = new DeviceConfigSession<>(
1435                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1436                     AppFGSPolicy.KEY_BG_FGS_LONG_RUNNING_THRESHOLD,
1437                     DeviceConfig::getLong,
1438                     AppFGSPolicy.DEFAULT_BG_FGS_LONG_RUNNING_THRESHOLD);
1439             longRunningFGSThreshold.set(thresholdMs);
1440 
1441             mediaPlaybackFGSThreshold = new DeviceConfigSession<>(
1442                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1443                     AppFGSPolicy.KEY_BG_FGS_MEDIA_PLAYBACK_THRESHOLD,
1444                     DeviceConfig::getLong,
1445                     AppFGSPolicy.DEFAULT_BG_FGS_MEDIA_PLAYBACK_THRESHOLD);
1446             mediaPlaybackFGSThreshold.set(thresholdMs);
1447 
1448             locationFGSThreshold = new DeviceConfigSession<>(
1449                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1450                     AppFGSPolicy.KEY_BG_FGS_LOCATION_THRESHOLD,
1451                     DeviceConfig::getLong,
1452                     AppFGSPolicy.DEFAULT_BG_FGS_LOCATION_THRESHOLD);
1453             locationFGSThreshold.set(thresholdMs);
1454 
1455             longRunningFGSWithNotification = new DeviceConfigSession<>(
1456                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1457                     ConstantsObserver.KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING,
1458                     DeviceConfig::getBoolean,
1459                     ConstantsObserver.DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING);
1460             longRunningFGSWithNotification.set(true);
1461 
1462             longRunningFGS = new DeviceConfigSession<>(
1463                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1464                     ConstantsObserver.KEY_BG_PROMPT_FGS_ON_LONG_RUNNING,
1465                     DeviceConfig::getBoolean,
1466                     ConstantsObserver.DEFAULT_BG_PROMPT_FGS_ON_LONG_RUNNING);
1467             longRunningFGS.set(true);
1468 
1469             // Long-running FGS with type "location", but ran for a very short time.
1470             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1471                     FOREGROUND_SERVICE_TYPE_LOCATION, 0, null, OP_NONE, null, null,
1472                     timeout(windowMs * 2).times(2));
1473 
1474             // Long-running FGS with type "location", and ran for a while.
1475             // We shouldn't see notifications in this case.
1476             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1477                     FOREGROUND_SERVICE_TYPE_LOCATION, thresholdMs * 2, null, OP_NONE, null, null,
1478                     timeout(windowMs * 2).times(0));
1479 
1480             // Long-running FGS with background location permission.
1481             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1482                     FOREGROUND_SERVICE_TYPE_LOCATION, 0, ACCESS_BACKGROUND_LOCATION, OP_NONE,
1483                     null, null, timeout(windowMs * 2).times(0));
1484 
1485             // Long-running FGS with type "mediaPlayback", but ran for a very short time.
1486             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1487                     FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, 0, null, OP_NONE, null, null,
1488                     timeout(windowMs * 2).times(2));
1489 
1490             // Long-running FGS with type "mediaPlayback", and ran for a while.
1491             // We shouldn't see notifications in this case.
1492             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1493                     FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, thresholdMs * 2, null, OP_NONE,
1494                     null, null, timeout(windowMs * 2).times(0));
1495 
1496             // Long-running FGS with type "camera", and ran for a while.
1497             // We shouldn't see notifications in this case.
1498             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1499                     FOREGROUND_SERVICE_TYPE_CAMERA, thresholdMs * 2, null, OP_NONE, null, null,
1500                     timeout(windowMs * 2).times(0));
1501 
1502             // Long-running FGS with type "location|mediaPlayback", but ran for a very short time.
1503             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1504                     FOREGROUND_SERVICE_TYPE_LOCATION | FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK,
1505                     0, null, OP_NONE, null, null, timeout(windowMs * 2).times(2));
1506 
1507             // Long-running FGS with type "location|mediaPlayback", and ran for a while.
1508             // We shouldn't see notifications in this case.
1509             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1510                     FOREGROUND_SERVICE_TYPE_LOCATION | FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK,
1511                     thresholdMs * 2, null, OP_NONE, null, null, timeout(windowMs * 2).times(0));
1512 
1513             // Long-running FGS with a media session starts/stops right away.
1514             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1515                     FOREGROUND_SERVICE_TYPE_NONE, 0, null, OP_NONE,
1516                     List.of(Pair.create(createMediaControllers(
1517                             new String[] {testPkgName1}, new int[] {testUid1}), 0L)), null,
1518                     timeout(windowMs * 2).times(2));
1519 
1520             // Long-running FGS with media session, and ran for a while.
1521             // We shouldn't see notifications in this case.
1522             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1523                     FOREGROUND_SERVICE_TYPE_NONE, thresholdMs * 2, null, OP_NONE,
1524                     List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
1525                             new int[] {testUid1}), thresholdMs * 2)), null,
1526                     timeout(windowMs * 2).times(0));
1527 
1528             // Long-running FGS with 2 media sessions start/stop right away
1529             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1530                     FOREGROUND_SERVICE_TYPE_NONE, 0, null, OP_NONE,
1531                     List.of(Pair.create(createMediaControllers(
1532                             new String[] {testPkgName1, testPkgName2},
1533                             new int[] {testUid1, testUid2}), 0L)), null,
1534                     timeout(windowMs * 2).times(2));
1535 
1536             // Long-running FGS with 2 media sessions start/stop interlaced.
1537             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1538                     FOREGROUND_SERVICE_TYPE_NONE, 0, null, OP_NONE,
1539                     List.of(Pair.create(createMediaControllers(
1540                                     new String[] {testPkgName1, testPkgName2},
1541                                     new int[] {testUid1, testUid2}), thresholdMs),
1542                             Pair.create(createMediaControllers(
1543                                     new String[] {testPkgName1},
1544                                     new int[] {testUid1}), thresholdMs / 10),
1545                             Pair.create(createMediaControllers(
1546                                     new String[] {testPkgName2},
1547                                     new int[] {testUid2}), thresholdMs / 10),
1548                             Pair.create(createMediaControllers(
1549                                     new String[] {testPkgName1},
1550                                     new int[] {testUid1}), thresholdMs / 10)
1551                             ), null,
1552                     timeout(windowMs * 2).times(0));
1553 
1554             // Long-running FGS with top state for a very short time.
1555             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1556                     FOREGROUND_SERVICE_TYPE_NONE, 0, null, OP_NONE, null, List.of(0L),
1557                     timeout(windowMs * 2).times(2));
1558 
1559             // Long-running FGS with top state for extended time.
1560             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1561                     FOREGROUND_SERVICE_TYPE_NONE, 0, null, OP_NONE, null,
1562                     List.of(0L, windowMs * 2, 0L), timeout(windowMs * 2).times(0));
1563 
1564             // Long-running FGS with top state, on and off frequently.
1565             runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1,
1566                     FOREGROUND_SERVICE_TYPE_NONE, 0, null, OP_NONE, null,
1567                     List.of(0L, thresholdMs / 10, thresholdMs / 10, thresholdMs / 10,
1568                             thresholdMs / 10, thresholdMs / 10, thresholdMs / 10),
1569                     timeout(windowMs * 2).times(2));
1570         } finally {
1571             closeIfNotNull(longRunningFGSMonitor);
1572             closeIfNotNull(longRunningFGSWindow);
1573             closeIfNotNull(longRunningFGSThreshold);
1574             closeIfNotNull(mediaPlaybackFGSThreshold);
1575             closeIfNotNull(locationFGSThreshold);
1576             closeIfNotNull(longRunningFGSWithNotification);
1577             closeIfNotNull(longRunningFGS);
1578         }
1579     }
1580 
resetBgRestrictionController()1581     private void resetBgRestrictionController() {
1582         mBgRestrictionController.resetRestrictionSettings();
1583         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
1584     }
1585 
runTestLongFGSExemptionOnce(String packageName, int uid, int pid, int serviceType, long sleepMs, String perm, int op, List<Pair<List<MediaController>, Long>> mediaControllers, List<Long> topStateChanges, VerificationMode mode)1586     private void runTestLongFGSExemptionOnce(String packageName, int uid, int pid,
1587             int serviceType, long sleepMs, String perm, int op,
1588             List<Pair<List<MediaController>, Long>> mediaControllers, List<Long> topStateChanges,
1589             VerificationMode mode) throws Exception {
1590         runExemptionTestOnce(
1591                 packageName, uid, pid, serviceType, sleepMs, true, false, perm, op,
1592                 mediaControllers, topStateChanges, true, true,
1593                 () -> checkNotificationShown(new String[] {packageName}, mode, false)
1594         );
1595     }
1596 
runExemptionTestOnce(String packageName, int uid, int pid, int serviceType, long sleepMs, boolean stopAfterSleep, boolean withNotification, String perm, int op, List<Pair<List<MediaController>, Long>> mediaControllers, List<Long> topStateChanges, boolean resetFGSTracker, boolean resetController, RunnableWithException r)1597     private void runExemptionTestOnce(String packageName, int uid, int pid,
1598             int serviceType, long sleepMs, boolean stopAfterSleep,
1599             boolean withNotification, String perm, int op,
1600             List<Pair<List<MediaController>, Long>> mediaControllers,
1601             List<Long> topStateChanges, boolean resetFGSTracker, boolean resetController,
1602             RunnableWithException r) throws Exception {
1603         if (resetFGSTracker) {
1604             mAppFGSTracker.reset();
1605             mAppMediaSessionTracker.reset();
1606         }
1607         if (resetController) {
1608             resetBgRestrictionController();
1609         }
1610         clearInvocations(mInjector.getNotificationManager());
1611 
1612         Thread topStateThread = null;
1613         if (topStateChanges != null) {
1614             final CountDownLatch latch = new CountDownLatch(1);
1615             topStateThread = new Thread(() -> {
1616                 try {
1617                     latch.await();
1618                     boolean top = false;
1619                     for (long l: topStateChanges) {
1620                         mUidObservers.onUidStateChanged(uid,
1621                                 top ? PROCESS_STATE_TOP : PROCESS_STATE_FOREGROUND_SERVICE,
1622                                 0, 0);
1623                         top = !top;
1624                         Thread.sleep(l);
1625                     }
1626                     mUidObservers.onUidGone(uid, false);
1627                 } catch (InterruptedException | RemoteException e) {
1628                 }
1629             });
1630             topStateThread.start();
1631             latch.countDown();
1632         }
1633 
1634         mAppFGSTracker.onForegroundServiceStateChanged(packageName, uid, pid, true);
1635         if (serviceType != FOREGROUND_SERVICE_TYPE_NONE) {
1636             mAppFGSTracker.mProcessObserver.onForegroundServicesChanged(pid, uid, serviceType);
1637             Thread.sleep(sleepMs);
1638             if (stopAfterSleep) {
1639                 // Stop it now.
1640                 mAppFGSTracker.mProcessObserver.onForegroundServicesChanged(pid, uid,
1641                         FOREGROUND_SERVICE_TYPE_NONE);
1642             }
1643         }
1644         if (withNotification) {
1645             final int notificationId = 1000;
1646             mAppFGSTracker.onForegroundServiceNotificationUpdated(
1647                     packageName, uid, notificationId, false);
1648             final StatusBarNotification noti = new StatusBarNotification(
1649                     packageName, null, notificationId, null, uid, pid,
1650                     new Notification(), UserHandle.of(UserHandle.getUserId(uid)),
1651                     null, mCurrentTimeMillis);
1652             mAppFGSTracker.mNotificationListener.onNotificationPosted(noti, null);
1653             Thread.sleep(sleepMs);
1654             if (stopAfterSleep) {
1655                 mAppFGSTracker.mNotificationListener.onNotificationRemoved(noti, null, 0);
1656             }
1657         }
1658         if (perm != null) {
1659             setPermissionState(packageName, uid, perm, true);
1660             if (op != OP_NONE) {
1661                 setAppOpState(packageName, uid, op, true);
1662             }
1663             mInjector.getAppPermissionTracker().onPermissionsChanged(uid);
1664         }
1665 
1666         if (mediaControllers != null) {
1667             for (Pair<List<MediaController>, Long> entry: mediaControllers) {
1668                 mActiveSessionListener.onActiveSessionsChanged(entry.first);
1669                 Thread.sleep(entry.second);
1670             }
1671             if (stopAfterSleep) {
1672                 // Stop it now.
1673                 mActiveSessionListener.onActiveSessionsChanged(null);
1674             }
1675         }
1676 
1677         r.run();
1678 
1679         // Stop this FGS
1680         mAppFGSTracker.onForegroundServiceStateChanged(packageName, uid, pid, false);
1681 
1682         if (perm != null) {
1683             setPermissionState(packageName, uid, perm, false);
1684             if (op != OP_NONE) {
1685                 setAppOpState(packageName, uid, op, false);
1686             }
1687             mInjector.getAppPermissionTracker().onPermissionsChanged(uid);
1688         }
1689         if (topStateThread != null) {
1690             topStateThread.join();
1691         }
1692     }
1693 
createMediaControllers(String[] packageNames, int[] uids)1694     private List<MediaController> createMediaControllers(String[] packageNames, int[] uids) {
1695         final ArrayList<MediaController> controllers = new ArrayList<>();
1696         for (int i = 0; i < packageNames.length; i++) {
1697             controllers.add(createMediaController(packageNames[i], uids[i]));
1698         }
1699         return controllers;
1700     }
1701 
createMediaController(String packageName, int uid)1702     private MediaController createMediaController(String packageName, int uid) {
1703         final MediaController controller = mock(MediaController.class);
1704         final MediaSession.Token token = mock(MediaSession.Token.class);
1705         doReturn(packageName).when(controller).getPackageName();
1706         doReturn(token).when(controller).getSessionToken();
1707         doReturn(uid).when(token).getUid();
1708         return controller;
1709     }
1710 
1711     @Test
testBgCurrentDrainMonitorExemptions()1712     public void testBgCurrentDrainMonitorExemptions() throws Exception {
1713         final BatteryUsageStats stats = mock(BatteryUsageStats.class);
1714         final List<BatteryUsageStats> statsList = Arrays.asList(stats);
1715         final int testPkgIndex1 = 1;
1716         final String testPkgName1 = TEST_PACKAGE_BASE + testPkgIndex1;
1717         final int testUser = TEST_USER0;
1718         final int testUid1 = UserHandle.getUid(testUser,
1719                 TEST_PACKAGE_APPID_BASE + testPkgIndex1);
1720         final int testPid1 = 1234;
1721         final int testPkgIndex2 = 2;
1722         final String testPkgName2 = TEST_PACKAGE_BASE + testPkgIndex2;
1723         final int testUid2 = UserHandle.getUid(testUser,
1724                 TEST_PACKAGE_APPID_BASE + testPkgIndex2);
1725         final int testPid2 = 1235;
1726         final TestAppRestrictionLevelListener listener = new TestAppRestrictionLevelListener();
1727         final long timeout =
1728                 AppBatteryTracker.BATTERY_USAGE_STATS_POLLING_INTERVAL_MS_DEBUG * 2;
1729         final long windowMs = 2_000;
1730         final float restrictBucketThreshold = 2.0f;
1731         final float restrictBucketThresholdMah =
1732                 BATTERY_FULL_CHARGE_MAH * restrictBucketThreshold / 100.0f;
1733         final float bgRestrictedThreshold = 4.0f;
1734         final float bgRestrictedThresholdMah =
1735                 BATTERY_FULL_CHARGE_MAH * bgRestrictedThreshold / 100.0f;
1736         final float restrictBucketHighThreshold = 25.0f;
1737         final float restrictBucketHighThresholdMah =
1738                 BATTERY_FULL_CHARGE_MAH * restrictBucketHighThreshold / 100.0f;
1739         final float bgRestrictedHighThreshold = 25.0f;
1740         final float bgRestrictedHighThresholdMah =
1741                 BATTERY_FULL_CHARGE_MAH * bgRestrictedHighThreshold / 100.0f;
1742         final long bgMediaPlaybackMinDuration = 1_000L;
1743         final long bgLocationMinDuration = 1_000L;
1744 
1745         DeviceConfigSession<Boolean> bgCurrentDrainMonitor = null;
1746         DeviceConfigSession<Long> bgCurrentDrainWindow = null;
1747         DeviceConfigSession<Long> bgCurrentDrainInteractionGracePeriod = null;
1748         DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketThreshold = null;
1749         DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null;
1750         DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketHighThreshold = null;
1751         DeviceConfigSession<Float> bgCurrentDrainBgRestrictedHighThreshold = null;
1752         DeviceConfigSession<Boolean> bgCurrentDrainAutoRestrictAbusiveApps = null;
1753         DeviceConfigSession<Long> bgMediaPlaybackMinDurationThreshold = null;
1754         DeviceConfigSession<Long> bgLocationMinDurationThreshold = null;
1755         DeviceConfigSession<Boolean> bgCurrentDrainEventDurationBasedThresholdEnabled = null;
1756         DeviceConfigSession<Boolean> bgBatteryExemptionEnabled = null;
1757         DeviceConfigSession<Integer> bgBatteryExemptionTypes = null;
1758         DeviceConfigSession<Boolean> bgPermissionMonitorEnabled = null;
1759         DeviceConfigSession<String> bgPermissionsInMonitor = null;
1760         DeviceConfigSession<Boolean> bgCurrentDrainHighThresholdByBgLocation = null;
1761         DeviceConfigSession<Boolean> bgCurrentDrainDecoupleThresholds = null;
1762         DeviceConfigSession<Boolean> bgPromptAbusiveAppToBgRestricted = null;
1763 
1764         mBgRestrictionController.addAppBackgroundRestrictionListener(listener);
1765 
1766         setBackgroundRestrict(testPkgName1, testUid1, false, listener);
1767 
1768         // Verify the current settings.
1769         verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName1, testUid1);
1770 
1771         final double[] zeros = new double[]{0.0f, 0.0f};
1772         final int[] uids = new int[]{testUid1, testUid2};
1773 
1774         doReturn(testPkgName1).when(mInjector).getPackageName(testPid1);
1775         doReturn(testPkgName2).when(mInjector).getPackageName(testPid2);
1776 
1777         try {
1778             bgCurrentDrainMonitor = new DeviceConfigSession<>(
1779                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1780                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_MONITOR_ENABLED,
1781                     DeviceConfig::getBoolean,
1782                     mContext.getResources().getBoolean(
1783                             R.bool.config_bg_current_drain_monitor_enabled));
1784             bgCurrentDrainMonitor.set(true);
1785 
1786             bgCurrentDrainWindow = new DeviceConfigSession<>(
1787                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1788                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_WINDOW,
1789                     DeviceConfig::getLong,
1790                     (long) mContext.getResources().getInteger(
1791                             R.integer.config_bg_current_drain_window));
1792             bgCurrentDrainWindow.set(windowMs);
1793 
1794             bgCurrentDrainInteractionGracePeriod = new DeviceConfigSession<>(
1795                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1796                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD,
1797                     DeviceConfig::getLong,
1798                     (long) mContext.getResources().getInteger(
1799                             R.integer.config_bg_current_drain_window));
1800             bgCurrentDrainInteractionGracePeriod.set(windowMs);
1801 
1802             bgCurrentDrainRestrictedBucketThreshold = new DeviceConfigSession<>(
1803                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1804                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET,
1805                     DeviceConfig::getFloat,
1806                     getFloatArray(mContext.getResources().obtainTypedArray(
1807                             R.array.config_bg_current_drain_threshold_to_restricted_bucket))[
1808                             isLowRamDeviceStatic() ? 1 : 0]);
1809             bgCurrentDrainRestrictedBucketThreshold.set(restrictBucketThreshold);
1810 
1811             bgCurrentDrainBgRestrictedThreshold = new DeviceConfigSession<>(
1812                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1813                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_BG_RESTRICTED,
1814                     DeviceConfig::getFloat,
1815                     getFloatArray(mContext.getResources().obtainTypedArray(
1816                             R.array.config_bg_current_drain_threshold_to_bg_restricted))[
1817                             isLowRamDeviceStatic() ? 1 : 0]);
1818             bgCurrentDrainBgRestrictedThreshold.set(bgRestrictedThreshold);
1819 
1820             bgCurrentDrainRestrictedBucketHighThreshold = new DeviceConfigSession<>(
1821                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1822                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_HIGH_THRESHOLD_TO_RESTRICTED_BUCKET,
1823                     DeviceConfig::getFloat,
1824                     getFloatArray(mContext.getResources().obtainTypedArray(
1825                             R.array.config_bg_current_drain_high_threshold_to_restricted_bucket))[
1826                             isLowRamDeviceStatic() ? 1 : 0]);
1827             bgCurrentDrainRestrictedBucketHighThreshold.set(restrictBucketHighThreshold);
1828 
1829             bgCurrentDrainBgRestrictedHighThreshold = new DeviceConfigSession<>(
1830                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1831                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_HIGH_THRESHOLD_TO_BG_RESTRICTED,
1832                     DeviceConfig::getFloat,
1833                     getFloatArray(mContext.getResources().obtainTypedArray(
1834                             R.array.config_bg_current_drain_high_threshold_to_bg_restricted))[
1835                             isLowRamDeviceStatic() ? 1 : 0]);
1836             bgCurrentDrainBgRestrictedHighThreshold.set(bgRestrictedHighThreshold);
1837 
1838             bgCurrentDrainAutoRestrictAbusiveApps = new DeviceConfigSession<>(
1839                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1840                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_AUTO_RESTRICT_ABUSIVE_APPS_ENABLED,
1841                     DeviceConfig::getBoolean,
1842                     mContext.getResources().getBoolean(
1843                             R.bool.config_bg_current_drain_auto_restrict_abusive_apps));
1844             bgCurrentDrainAutoRestrictAbusiveApps.set(true);
1845 
1846             bgMediaPlaybackMinDurationThreshold = new DeviceConfigSession<>(
1847                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1848                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_MEDIA_PLAYBACK_MIN_DURATION,
1849                     DeviceConfig::getLong,
1850                     (long) mContext.getResources().getInteger(
1851                             R.integer.config_bg_current_drain_media_playback_min_duration));
1852             bgMediaPlaybackMinDurationThreshold.set(bgMediaPlaybackMinDuration);
1853 
1854             bgLocationMinDurationThreshold = new DeviceConfigSession<>(
1855                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1856                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_LOCATION_MIN_DURATION,
1857                     DeviceConfig::getLong,
1858                     (long) mContext.getResources().getInteger(
1859                             R.integer.config_bg_current_drain_location_min_duration));
1860             bgLocationMinDurationThreshold.set(bgLocationMinDuration);
1861 
1862             bgCurrentDrainEventDurationBasedThresholdEnabled = new DeviceConfigSession<>(
1863                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1864                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_EVENT_DURATION_BASED_THRESHOLD_ENABLED,
1865                     DeviceConfig::getBoolean,
1866                     mContext.getResources().getBoolean(
1867                             R.bool.config_bg_current_drain_event_duration_based_threshold_enabled));
1868             bgCurrentDrainEventDurationBasedThresholdEnabled.set(true);
1869 
1870             bgBatteryExemptionEnabled = new DeviceConfigSession<>(
1871                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1872                     AppBatteryExemptionPolicy.KEY_BG_BATTERY_EXEMPTION_ENABLED,
1873                     DeviceConfig::getBoolean,
1874                     AppBatteryExemptionPolicy.DEFAULT_BG_BATTERY_EXEMPTION_ENABLED);
1875             bgBatteryExemptionEnabled.set(false);
1876 
1877             bgBatteryExemptionTypes = new DeviceConfigSession<>(
1878                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1879                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_EXEMPTED_TYPES,
1880                     DeviceConfig::getInt,
1881                     mContext.getResources().getInteger(
1882                             R.integer.config_bg_current_drain_exempted_types));
1883             bgBatteryExemptionTypes.set(STATE_TYPE_MEDIA_SESSION | STATE_TYPE_FGS_MEDIA_PLAYBACK
1884                     | STATE_TYPE_FGS_LOCATION | STATE_TYPE_PERMISSION
1885                     | STATE_TYPE_FGS_WITH_NOTIFICATION);
1886 
1887             bgPermissionMonitorEnabled = new DeviceConfigSession<>(
1888                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1889                     AppPermissionPolicy.KEY_BG_PERMISSION_MONITOR_ENABLED,
1890                     DeviceConfig::getBoolean,
1891                     AppPermissionPolicy.DEFAULT_BG_PERMISSION_MONITOR_ENABLED);
1892             bgPermissionMonitorEnabled.set(true);
1893 
1894             bgPermissionsInMonitor = new DeviceConfigSession<>(
1895                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1896                     AppPermissionPolicy.KEY_BG_PERMISSION_MONITOR_ENABLED,
1897                     DeviceConfig::getString,
1898                     Arrays.stream(AppPermissionPolicy.DEFAULT_BG_PERMISSIONS_IN_MONITOR)
1899                     .collect(Collectors.joining(",")));
1900             bgPermissionsInMonitor.set(ACCESS_FINE_LOCATION);
1901 
1902             bgCurrentDrainHighThresholdByBgLocation = new DeviceConfigSession<>(
1903                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1904                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_HIGH_THRESHOLD_BY_BG_LOCATION,
1905                     DeviceConfig::getBoolean,
1906                     mContext.getResources().getBoolean(
1907                             R.bool.config_bg_current_drain_high_threshold_by_bg_location));
1908             bgCurrentDrainHighThresholdByBgLocation.set(true);
1909 
1910             bgCurrentDrainDecoupleThresholds = new DeviceConfigSession<>(
1911                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1912                     AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLDS,
1913                     DeviceConfig::getBoolean,
1914                     AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLD);
1915             bgCurrentDrainDecoupleThresholds.set(true);
1916 
1917             bgPromptAbusiveAppToBgRestricted = new DeviceConfigSession<>(
1918                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
1919                     ConstantsObserver.KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED,
1920                     DeviceConfig::getBoolean,
1921                     mContext.getResources().getBoolean(
1922                             R.bool.config_bg_prompt_abusive_apps_to_bg_restricted));
1923             bgPromptAbusiveAppToBgRestricted.set(true);
1924 
1925             mCurrentTimeMillis = 10_000L;
1926             doReturn(mCurrentTimeMillis - windowMs).when(stats).getStatsStartTimestamp();
1927             doReturn(mCurrentTimeMillis).when(stats).getStatsEndTimestamp();
1928             doReturn(statsList).when(mBatteryStatsInternal).getBatteryUsageStats(any());
1929 
1930             // Run with a media playback service which starts/stops immediately, we should
1931             // goto the restricted bucket.
1932             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
1933                     FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, 0, true, false,
1934                     null, OP_NONE, null, null, listener, stats, uids,
1935                     new double[]{restrictBucketThresholdMah + 1, 0},
1936                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
1937                     false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
1938                     null, windowMs, null, null, null, null);
1939 
1940             // Run with a media playback service with extended time. We should be back to normal.
1941             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
1942                     FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false,
1943                     false, null, OP_NONE, null, null, listener, stats, uids,
1944                     new double[]{restrictBucketThresholdMah + 1, 0},
1945                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
1946                     true, RESTRICTION_LEVEL_ADAPTIVE_BUCKET, timeout, false,
1947                     () -> {
1948                         // A user interaction will bring it back to normal.
1949                         mIdleStateListener.onUserInteractionStarted(testPkgName1,
1950                                 UserHandle.getUserId(testUid1));
1951                         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
1952                         // It should have been back to normal.
1953                         listener.verify(timeout, testUid1, testPkgName1,
1954                                 RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
1955                         verify(mInjector.getAppStandbyInternal(), times(1)).maybeUnrestrictApp(
1956                                 eq(testPkgName1),
1957                                 eq(UserHandle.getUserId(testUid1)),
1958                                 eq(REASON_MAIN_FORCED_BY_SYSTEM),
1959                                 eq(REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE),
1960                                 eq(REASON_MAIN_USAGE),
1961                                 eq(REASON_SUB_USAGE_USER_INTERACTION));
1962                     }, windowMs, null, null, null, null);
1963 
1964             // Start over.
1965             resetBgRestrictionController();
1966             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
1967             mAppBatteryPolicy.reset();
1968 
1969             // Run with a media playback service with extended time, with higher current drain.
1970             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
1971                     FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false,
1972                     false, null, OP_NONE, null, null, listener, stats, uids,
1973                     new double[]{restrictBucketHighThresholdMah - 1, 0},
1974                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
1975                     true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
1976                     null, windowMs, null, null, null, null);
1977 
1978             // Run with a media playback service with extended time, with even higher current drain.
1979             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
1980                     FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false,
1981                     false, null, OP_NONE, null, null, listener, stats, uids,
1982                     new double[]{restrictBucketHighThresholdMah + 1, 0},
1983                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
1984                     false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
1985                     null, windowMs, null, null, null, null);
1986 
1987             // Start over.
1988             resetBgRestrictionController();
1989             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
1990             mAppBatteryPolicy.reset();
1991 
1992             // Run with a media session with extended time, with higher current drain.
1993             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
1994                     FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false,
1995                     null, OP_NONE,
1996                     List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
1997                           new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)),
1998                     null, listener, stats, uids,
1999                     new double[]{restrictBucketHighThresholdMah - 1, 0},
2000                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2001                     true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2002                     null, windowMs, null, null, null, null);
2003 
2004             // Run with a media session with extended time, with even higher current drain.
2005             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2006                     FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false,
2007                     null, OP_NONE,
2008                     List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
2009                           new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)),
2010                     null, listener, stats, uids,
2011                     new double[]{restrictBucketHighThresholdMah + 1, 0},
2012                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2013                     false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
2014                     null, windowMs, null, null, null, null);
2015 
2016             // Start over.
2017             resetBgRestrictionController();
2018             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
2019             mAppBatteryPolicy.reset();
2020 
2021             // Run with a media session with extended time, with moderate current drain,
2022             // but it ran on the top when the location service is active.
2023             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2024                     FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false,
2025                     null, OP_NONE,
2026                     List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
2027                           new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)),
2028                     List.of(0L, timeout * 2), listener, stats, uids,
2029                     new double[]{restrictBucketThresholdMah + 1, 0},
2030                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2031                     false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2032                     null, windowMs, null, null, null, null);
2033 
2034             // Start over.
2035             resetBgRestrictionController();
2036             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
2037             mAppBatteryPolicy.reset();
2038 
2039             // Run with a location service with extended time, with higher current drain.
2040             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2041                     FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false,
2042                     null, OP_NONE, null, null, listener, stats, uids,
2043                     new double[]{restrictBucketHighThresholdMah - 1, 0},
2044                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2045                     true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2046                     null, windowMs, null, null, null, null);
2047 
2048             // Run with a location service with extended time, with even higher current drain.
2049             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2050                     FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false,
2051                     null, OP_NONE, null, null, listener, stats, uids,
2052                     new double[]{restrictBucketHighThresholdMah + 1, 0},
2053                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2054                     false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
2055                     null, windowMs, null, null, null, null);
2056 
2057             // Start over.
2058             resetBgRestrictionController();
2059             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
2060             mAppBatteryPolicy.reset();
2061 
2062             // Run with a location service with extended time, with moderate current drain,
2063             // but it ran on the top when the location service is active.
2064             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2065                     FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false,
2066                     null, OP_NONE, null, List.of(0L, timeout * 2), listener, stats, uids,
2067                     new double[]{restrictBucketThresholdMah + 1, 0},
2068                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2069                     false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2070                     null, windowMs, null, null, null, null);
2071 
2072             // Start over.
2073             resetBgRestrictionController();
2074             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
2075             mAppBatteryPolicy.reset();
2076 
2077             // Turn off the higher threshold for bg location access.
2078             bgCurrentDrainHighThresholdByBgLocation.set(false);
2079 
2080             // Run with bg location permission, with moderate current drain.
2081             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2082                     FOREGROUND_SERVICE_TYPE_NONE, 0, false, false,
2083                     ACCESS_BACKGROUND_LOCATION, OP_NONE, null, null, listener, stats, uids,
2084                     new double[]{restrictBucketThresholdMah - 1, 0},
2085                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2086                     true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2087                     null, windowMs, null, null, null, null);
2088 
2089             // Run with bg location permission, with a bit higher current drain.
2090             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2091                     FOREGROUND_SERVICE_TYPE_NONE, 0, false, false,
2092                     ACCESS_BACKGROUND_LOCATION, OP_NONE, null, null, listener, stats, uids,
2093                     new double[]{restrictBucketThresholdMah + 1, 0},
2094                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2095                     false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2096                     null, windowMs, null, null, null, null);
2097 
2098             // Start over.
2099             resetBgRestrictionController();
2100             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
2101             mAppBatteryPolicy.reset();
2102 
2103             // Turn on the higher threshold for bg location access.
2104             bgCurrentDrainHighThresholdByBgLocation.set(true);
2105 
2106             // Run with bg location permission, with higher current drain.
2107             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2108                     FOREGROUND_SERVICE_TYPE_NONE, 0, false, false,
2109                     ACCESS_BACKGROUND_LOCATION, OP_NONE, null, null, listener, stats, uids,
2110                     new double[]{restrictBucketHighThresholdMah - 1, 0},
2111                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2112                     true , RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
2113                     null, windowMs, null,  null, null, null);
2114 
2115             // Run with bg location permission, with even higher current drain.
2116             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2117                     FOREGROUND_SERVICE_TYPE_NONE, 0, false, false,
2118                     ACCESS_BACKGROUND_LOCATION, OP_NONE, null, null, listener, stats, uids,
2119                     new double[]{restrictBucketHighThresholdMah + 1, 0},
2120                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2121                     false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
2122                     null, windowMs, null,  null, null, null);
2123 
2124             // Now turn off the event duration based feature flag.
2125             bgCurrentDrainEventDurationBasedThresholdEnabled.set(false);
2126             // Turn on the battery exemption feature flag.
2127             bgBatteryExemptionEnabled.set(true);
2128 
2129             // Start over.
2130             resetBgRestrictionController();
2131             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
2132             mAppBatteryPolicy.reset();
2133 
2134             waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
2135 
2136             // Run with a media playback service which starts/stops immediately, we should
2137             // goto the restricted bucket.
2138             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2139                     FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, 0, true, false,
2140                     null, OP_NONE, null, null, listener, stats, uids,
2141                     new double[]{restrictBucketThresholdMah + 1, 0},
2142                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2143                     false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2144                     null, windowMs, null, null, null, null);
2145 
2146             // Run with a media playback service with extended time. We should be back to normal.
2147             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2148                     FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false,
2149                     false, null, OP_NONE, null, null, listener, stats, uids,
2150                     new double[]{restrictBucketThresholdMah + 1, 0},
2151                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2152                     true, RESTRICTION_LEVEL_ADAPTIVE_BUCKET, timeout, false,
2153                     () -> {
2154                         // A user interaction will bring it back to normal.
2155                         mIdleStateListener.onUserInteractionStarted(testPkgName1,
2156                                 UserHandle.getUserId(testUid1));
2157                         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
2158                         // It should have been back to normal.
2159                         listener.verify(timeout, testUid1, testPkgName1,
2160                                 RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
2161                         verify(mInjector.getAppStandbyInternal(), times(1)).maybeUnrestrictApp(
2162                                 eq(testPkgName1),
2163                                 eq(UserHandle.getUserId(testUid1)),
2164                                 eq(REASON_MAIN_FORCED_BY_SYSTEM),
2165                                 eq(REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE),
2166                                 eq(REASON_MAIN_USAGE),
2167                                 eq(REASON_SUB_USAGE_USER_INTERACTION));
2168                     }, windowMs, null, null, null, null);
2169 
2170             // Start over.
2171             resetBgRestrictionController();
2172             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
2173             mAppBatteryPolicy.reset();
2174 
2175             final double[] initialBg = {1, 1}, initialFgs = {1, 1}, initialFg = zeros,
2176                     initialCached = {1, 1};
2177 
2178             // Run with a media playback service with extended time, with higher current drain.
2179             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2180                     FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false,
2181                     false, null, OP_NONE, null, null, listener, stats, uids,
2182                     new double[]{restrictBucketHighThresholdMah - 1, 0},
2183                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2184                     true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2185                     null, windowMs, initialBg, initialFgs, initialFg, initialCached);
2186 
2187             // Run with a media playback service with extended time, with even higher current drain,
2188             // it still should stay in the current restriction level as we exempt the media
2189             // playback.
2190             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2191                     FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK, bgMediaPlaybackMinDuration * 2, false,
2192                     false, null, OP_NONE, null, null, listener, stats, uids,
2193                     new double[]{restrictBucketHighThresholdMah + 100, 0},
2194                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2195                     true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
2196                     null, windowMs, initialBg, initialFgs, initialFg, initialCached);
2197 
2198             // Set the policy to exempt media session and permission.
2199             bgBatteryExemptionTypes.set(STATE_TYPE_MEDIA_SESSION | STATE_TYPE_PERMISSION);
2200             // Start over.
2201             resetBgRestrictionController();
2202             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
2203             mAppBatteryPolicy.reset();
2204 
2205             // Run with coarse location permission, with high current drain.
2206             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2207                     FOREGROUND_SERVICE_TYPE_NONE, 0, false, false,
2208                     ACCESS_COARSE_LOCATION, OP_NONE, null, null, listener, stats, uids,
2209                     new double[]{restrictBucketThresholdMah + 1, 0},
2210                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2211                     false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2212                     null, windowMs, initialBg, initialFgs, initialFg, initialCached);
2213 
2214             // Start over.
2215             resetBgRestrictionController();
2216             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
2217             mAppBatteryPolicy.reset();
2218 
2219             // Run with fine location permission, with high current drain.
2220             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2221                     FOREGROUND_SERVICE_TYPE_NONE, 0, false, false,
2222                     ACCESS_FINE_LOCATION, OP_FINE_LOCATION, null, null, listener, stats, uids,
2223                     new double[]{restrictBucketThresholdMah + 1, 0},
2224                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2225                     true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2226                     null, windowMs, initialBg, initialFgs, initialFg, initialCached);
2227 
2228             // Start over.
2229             resetBgRestrictionController();
2230             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
2231             mAppBatteryPolicy.reset();
2232 
2233             // Run with a media session with extended time, with higher current drain.
2234             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2235                     FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false,
2236                     null, OP_NONE,
2237                     List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
2238                           new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)),
2239                     null, listener, stats, uids,
2240                     new double[]{restrictBucketHighThresholdMah - 1, 0},
2241                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2242                     true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2243                     null, windowMs, initialBg, initialFgs, initialFg, initialCached);
2244 
2245             // Run with a media session with extended time, with even higher current drain.
2246             // it still should stay in the current restriction level as we exempt the media
2247             // session.
2248             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2249                     FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false, false,
2250                     null, OP_NONE,
2251                     List.of(Pair.create(createMediaControllers(new String[] {testPkgName1},
2252                           new int[] {testUid1}), bgMediaPlaybackMinDuration * 2)),
2253                     null, listener, stats, uids,
2254                     new double[]{restrictBucketHighThresholdMah + 100, 0},
2255                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2256                     true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2257                     null, windowMs, initialBg, initialFgs, initialFg, initialCached);
2258 
2259             // Set the policy to exempt fgs with notifications.
2260             bgBatteryExemptionTypes.set(STATE_TYPE_FGS_WITH_NOTIFICATION);
2261             // Start over.
2262             resetBgRestrictionController();
2263             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
2264             mAppBatteryPolicy.reset();
2265 
2266             // Run with a FGS with notification posted/removed immediately, we should
2267             // goto the restricted bucket.
2268             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2269                     FOREGROUND_SERVICE_TYPE_NONE, 0, true, true,
2270                     null, OP_NONE, null, null, listener, stats, uids,
2271                     new double[]{restrictBucketThresholdMah + 1, 0},
2272                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2273                     false, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2274                     null, windowMs, null, null, null, null);
2275 
2276             // Run with a service with notification for extended time. We should be back to normal.
2277             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2278                     FOREGROUND_SERVICE_TYPE_NONE, bgMediaPlaybackMinDuration * 2, false,
2279                     true, null, OP_NONE, null, null, listener, stats, uids,
2280                     new double[]{restrictBucketThresholdMah + 1, 0},
2281                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2282                     true, RESTRICTION_LEVEL_ADAPTIVE_BUCKET, timeout, false,
2283                     () -> {
2284                         // A user interaction will bring it back to normal.
2285                         mIdleStateListener.onUserInteractionStarted(testPkgName1,
2286                                 UserHandle.getUserId(testUid1));
2287                         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
2288                         // It should have been back to normal.
2289                         listener.verify(timeout, testUid1, testPkgName1,
2290                                 RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
2291                         verify(mInjector.getAppStandbyInternal(), times(1)).maybeUnrestrictApp(
2292                                 eq(testPkgName1),
2293                                 eq(UserHandle.getUserId(testUid1)),
2294                                 eq(REASON_MAIN_FORCED_BY_SYSTEM),
2295                                 eq(REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE),
2296                                 eq(REASON_MAIN_USAGE),
2297                                 eq(REASON_SUB_USAGE_USER_INTERACTION));
2298                     }, windowMs, null, null, null, null);
2299 
2300             // Set the policy to exempt all.
2301             bgBatteryExemptionTypes.set(STATE_TYPE_MEDIA_SESSION | STATE_TYPE_FGS_MEDIA_PLAYBACK
2302                     | STATE_TYPE_FGS_LOCATION | STATE_TYPE_PERMISSION
2303                     | STATE_TYPE_FGS_WITH_NOTIFICATION);
2304 
2305             // Start over.
2306             resetBgRestrictionController();
2307             setUidBatteryConsumptions(stats, uids, zeros, zeros, zeros, zeros);
2308             mAppBatteryPolicy.reset();
2309 
2310             // Run with a location service with extended time, with higher current drain.
2311             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2312                     FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false,
2313                     null, OP_NONE, null, null, listener, stats, uids,
2314                     new double[]{restrictBucketHighThresholdMah - 1, 0},
2315                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2316                     true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, true,
2317                     null, windowMs, initialBg, initialFgs, initialFg, initialCached);
2318 
2319             // Run with a location service with extended time, with even higher current drain.
2320             // it still should stay in the current restriction level as we exempt the location.
2321             runTestBgCurrentDrainExemptionOnce(testPkgName1, testUid1, testPid1,
2322                     FOREGROUND_SERVICE_TYPE_LOCATION, bgMediaPlaybackMinDuration * 2, false, false,
2323                     null, OP_NONE, null, null, listener, stats, uids,
2324                     new double[]{restrictBucketHighThresholdMah + 100, 0},
2325                     new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
2326                     true, RESTRICTION_LEVEL_RESTRICTED_BUCKET, timeout, false,
2327                     null, windowMs, initialBg, initialFgs, initialFg, initialCached);
2328         } finally {
2329             closeIfNotNull(bgCurrentDrainMonitor);
2330             closeIfNotNull(bgCurrentDrainWindow);
2331             closeIfNotNull(bgCurrentDrainInteractionGracePeriod);
2332             closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold);
2333             closeIfNotNull(bgCurrentDrainBgRestrictedThreshold);
2334             closeIfNotNull(bgCurrentDrainRestrictedBucketHighThreshold);
2335             closeIfNotNull(bgCurrentDrainBgRestrictedHighThreshold);
2336             closeIfNotNull(bgCurrentDrainAutoRestrictAbusiveApps);
2337             closeIfNotNull(bgMediaPlaybackMinDurationThreshold);
2338             closeIfNotNull(bgLocationMinDurationThreshold);
2339             closeIfNotNull(bgCurrentDrainEventDurationBasedThresholdEnabled);
2340             closeIfNotNull(bgBatteryExemptionEnabled);
2341             closeIfNotNull(bgBatteryExemptionTypes);
2342             closeIfNotNull(bgPermissionMonitorEnabled);
2343             closeIfNotNull(bgPermissionsInMonitor);
2344             closeIfNotNull(bgPromptAbusiveAppToBgRestricted);
2345             closeIfNotNull(bgCurrentDrainHighThresholdByBgLocation);
2346             closeIfNotNull(bgCurrentDrainDecoupleThresholds);
2347         }
2348     }
2349 
runTestBgCurrentDrainExemptionOnce(String packageName, int uid, int pid, int serviceType, long sleepMs, boolean stopAfterSleep, boolean withNotification, String perm, int op, List<Pair<List<MediaController>, Long>> mediaControllers, List<Long> topStateChanges, TestAppRestrictionLevelListener listener, BatteryUsageStats stats, int[] uids, double[] bg, double[] fgs, double[] fg, double[] cached, boolean expectingTimeout, int expectingLevel, long timeout, boolean resetFGSTracker, RunnableWithException extraVerifiers, long windowMs, double[] initialBg, double[] initialFgs, double[] initialFg, double[] initialCached)2350     private void runTestBgCurrentDrainExemptionOnce(String packageName, int uid, int pid,
2351             int serviceType, long sleepMs, boolean stopAfterSleep, boolean withNotification,
2352             String perm, int op, List<Pair<List<MediaController>, Long>> mediaControllers,
2353             List<Long> topStateChanges, TestAppRestrictionLevelListener listener,
2354             BatteryUsageStats stats, int[] uids, double[] bg, double[] fgs, double[] fg,
2355             double[] cached, boolean expectingTimeout, int expectingLevel, long timeout,
2356             boolean resetFGSTracker, RunnableWithException extraVerifiers, long windowMs,
2357             double[] initialBg, double[] initialFgs, double[] initialFg, double[] initialCached)
2358             throws Exception {
2359         listener.mLatchHolder[0] = new CountDownLatch(1);
2360         if (initialBg != null) {
2361             doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
2362             doReturn(mCurrentTimeMillis + windowMs).when(stats).getStatsEndTimestamp();
2363             mCurrentTimeMillis += windowMs + 1;
2364             setUidBatteryConsumptions(stats, uids, initialBg, initialFgs, initialFg, initialCached);
2365             mAppBatteryExemptionTracker.reset();
2366             mAppBatteryPolicy.reset();
2367         }
2368         if (perm != null) {
2369             setPermissionState(packageName, uid, perm, true);
2370             if (op != OP_NONE) {
2371                 setAppOpState(packageName, uid, op, true);
2372             }
2373             mInjector.getAppPermissionTracker().onPermissionsChanged(uid);
2374         }
2375         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
2376         runExemptionTestOnce(
2377                 packageName, uid, pid, serviceType, sleepMs, stopAfterSleep, withNotification,
2378                 perm, op, mediaControllers, topStateChanges, resetFGSTracker, false,
2379                 () -> {
2380                     clearInvocations(mInjector.getAppStandbyInternal());
2381                     clearInvocations(mBgRestrictionController);
2382                     runTestBgCurrentDrainMonitorOnce(listener, stats, uids, bg, fgs, fg, cached,
2383                             false, () -> {
2384                                 doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
2385                                 doReturn(mCurrentTimeMillis + windowMs)
2386                                         .when(stats).getStatsEndTimestamp();
2387                                 mCurrentTimeMillis += windowMs + 1;
2388                                 if (expectingTimeout) {
2389                                     try {
2390                                         listener.verify(timeout, uid, packageName, expectingLevel);
2391                                         fail("There shouldn't be any level change events");
2392                                     } catch (Exception e) {
2393                                         // Expected.
2394                                     }
2395                                 } else {
2396                                     listener.verify(timeout, uid, packageName, expectingLevel);
2397                                 }
2398                                 if (expectingLevel == RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
2399                                     verify(mInjector.getAppStandbyInternal(),
2400                                             expectingTimeout ? never() : atLeast(1)).restrictApp(
2401                                             eq(packageName),
2402                                             eq(UserHandle.getUserId(uid)),
2403                                             anyInt(), anyInt());
2404                                 } else if (expectingLevel
2405                                          == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
2406                                     verify(mBgRestrictionController,
2407                                             expectingTimeout ? never() : atLeast(1))
2408                                             .handleRequestBgRestricted(eq(packageName), eq(uid));
2409                                 } else {
2410                                     verify(mInjector.getAppStandbyInternal(),
2411                                             expectingTimeout ? never() : atLeast(1))
2412                                             .setAppStandbyBucket(
2413                                                    eq(packageName),
2414                                                    eq(STANDBY_BUCKET_RARE),
2415                                                    eq(UserHandle.getUserId(uid)),
2416                                                    anyInt(), anyInt());
2417                                 }
2418                                 if (extraVerifiers != null) {
2419                                     extraVerifiers.run();
2420                                 }
2421                             }
2422                     );
2423                 }
2424         );
2425         if (perm != null) {
2426             setPermissionState(packageName, uid, perm, false);
2427             if (op != OP_NONE) {
2428                 setAppOpState(packageName, uid, op, false);
2429             }
2430             mInjector.getAppPermissionTracker().onPermissionsChanged(uid);
2431         }
2432     }
2433 
setPermissionState(String packageName, int uid, String perm, boolean granted)2434     private void setPermissionState(String packageName, int uid, String perm, boolean granted) {
2435         doReturn(granted ? PERMISSION_GRANTED : PERMISSION_DENIED)
2436                 .when(mPermissionManagerServiceInternal)
2437                 .checkUidPermission(uid, perm, Context.DEVICE_ID_DEFAULT);
2438         doReturn(granted ? PERMISSION_GRANTED : PERMISSION_DENIED)
2439                 .when(mPermissionManagerServiceInternal)
2440                 .checkPermission(
2441                         packageName, perm, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT,
2442                         UserHandle.getUserId(uid));
2443         try {
2444             doReturn(granted ? PERMISSION_GRANTED : PERMISSION_DENIED)
2445                     .when(mIActivityManager)
2446                     .checkPermission(perm, Process.INVALID_PID, uid);
2447         } catch (RemoteException e) {
2448             // Ignore.
2449         }
2450     }
2451 
setAppOpState(String packageName, int uid, int op, boolean granted)2452     private void setAppOpState(String packageName, int uid, int op, boolean granted) {
2453         try {
2454             doReturn(granted ? MODE_ALLOWED : MODE_IGNORED)
2455                     .when(mAppOpsManager)
2456                     .checkOpNoThrow(op, uid, packageName);
2457             doReturn(granted ? MODE_ALLOWED : MODE_IGNORED)
2458                     .when(mIAppOpsService)
2459                     .checkOperation(op, uid, packageName);
2460         } catch (RemoteException e) {
2461             // Ignore.
2462         }
2463     }
2464 
2465     @Test
testExcessiveBroadcasts()2466     public void testExcessiveBroadcasts() throws Exception {
2467         final long windowMs = 5_000;
2468         final int threshold = 10;
2469         runTestExcessiveEvent(AppBroadcastEventsPolicy.KEY_BG_BROADCAST_MONITOR_ENABLED,
2470                 AppBroadcastEventsPolicy.DEFAULT_BG_BROADCAST_MONITOR_ENABLED,
2471                 AppBroadcastEventsPolicy.KEY_BG_BROADCAST_WINDOW,
2472                 AppBroadcastEventsPolicy.DEFAULT_BG_BROADCAST_WINDOW,
2473                 AppBroadcastEventsPolicy.KEY_BG_EX_BROADCAST_THRESHOLD,
2474                 AppBroadcastEventsPolicy.DEFAULT_BG_EX_BROADCAST_THRESHOLD,
2475                 windowMs, threshold, mBroadcastEventListener::onSendingBroadcast,
2476                 mAppBroadcastEventsTracker,
2477                 new long[][] {
2478                     new long[] {1_000L, 2_000L, 2_000L},
2479                     new long[] {2_000L, 2_000L, 1_000L},
2480                 },
2481                 new int[][] {
2482                     new int[] {3, 3, 3},
2483                     new int[] {3, 3, 4},
2484                 },
2485                 new boolean[] {
2486                     true,
2487                     false,
2488                 }
2489         );
2490     }
2491 
2492     @Test
testExcessiveBindServices()2493     public void testExcessiveBindServices() throws Exception {
2494         final long windowMs = 5_000;
2495         final int threshold = 10;
2496         runTestExcessiveEvent(AppBindServiceEventsPolicy.KEY_BG_BIND_SVC_MONITOR_ENABLED,
2497                 AppBindServiceEventsPolicy.DEFAULT_BG_BIND_SVC_MONITOR_ENABLED,
2498                 AppBindServiceEventsPolicy.KEY_BG_BIND_SVC_WINDOW,
2499                 AppBindServiceEventsPolicy.DEFAULT_BG_BIND_SVC_WINDOW,
2500                 AppBindServiceEventsPolicy.KEY_BG_EX_BIND_SVC_THRESHOLD,
2501                 AppBindServiceEventsPolicy.DEFAULT_BG_EX_BIND_SVC_THRESHOLD,
2502                 windowMs, threshold, mBindServiceEventListener::onBindingService,
2503                 mAppBindServiceEventsTracker,
2504                 new long[][] {
2505                     new long[] {0L, 2_000L, 4_000L, 1_000L},
2506                     new long[] {2_000L, 2_000L, 2_000L, 2_000L},
2507                 },
2508                 new int[][] {
2509                     new int[] {8, 3, 1, 0}, // Will goto restricted bucket.
2510                     new int[] {3, 3, 3, 3},
2511                 },
2512                 new boolean[] {
2513                     false,
2514                     true,
2515                 }
2516         );
2517     }
2518 
runTestExcessiveEvent(String keyEnable, boolean defaultEnable, String keyWindow, long defaultWindow, String keyThreshold, int defaultThreshold, long windowMs, int threshold, BiConsumer<String, Integer> eventEmitter, BaseAppStateEventsTracker tracker, long[][] waitMs, int[][] events, boolean[] expectingTimeout)2519     private void runTestExcessiveEvent(String keyEnable, boolean defaultEnable,
2520             String keyWindow, long defaultWindow, String keyThreshold, int defaultThreshold,
2521             long windowMs, int threshold, BiConsumer<String, Integer> eventEmitter,
2522             BaseAppStateEventsTracker tracker, long[][] waitMs, int[][] events,
2523             boolean[] expectingTimeout) throws Exception {
2524         final int testPkgIndex = 1;
2525         final String testPkgName = TEST_PACKAGE_BASE + testPkgIndex;
2526         final int testUser = TEST_USER0;
2527         final int testUid = UserHandle.getUid(testUser, TEST_PACKAGE_APPID_BASE + testPkgIndex);
2528         final int testPid = 1234;
2529 
2530         final long timeoutMs = 2_000;
2531 
2532         final TestAppRestrictionLevelListener listener = new TestAppRestrictionLevelListener();
2533 
2534         mBgRestrictionController.addAppBackgroundRestrictionListener(listener);
2535         setBackgroundRestrict(testPkgName, testUid, false, listener);
2536 
2537         DeviceConfigSession<Boolean> enableMonitor = null;
2538         DeviceConfigSession<Long> eventsWindow = null;
2539         DeviceConfigSession<Integer> eventsThreshold = null;
2540 
2541         doReturn(testPkgName).when(mInjector).getPackageName(testPid);
2542 
2543         verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid);
2544 
2545         try {
2546             enableMonitor = new DeviceConfigSession<>(
2547                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
2548                     keyEnable,
2549                     DeviceConfig::getBoolean,
2550                     defaultEnable);
2551             enableMonitor.set(true);
2552 
2553             eventsWindow = new DeviceConfigSession<>(
2554                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
2555                     keyWindow,
2556                     DeviceConfig::getLong,
2557                     defaultWindow);
2558             eventsWindow.set(windowMs);
2559 
2560             eventsThreshold = new DeviceConfigSession<>(
2561                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
2562                     keyThreshold,
2563                     DeviceConfig::getInt,
2564                     defaultThreshold);
2565             eventsThreshold.set(threshold);
2566 
2567             for (int i = 0; i < waitMs.length; i++) {
2568                 resetBgRestrictionController();
2569                 listener.mLatchHolder[0] = new CountDownLatch(1);
2570                 tracker.reset();
2571                 clearInvocations(mInjector.getAppStandbyInternal());
2572                 clearInvocations(mBgRestrictionController);
2573                 for (int j = 0; j < waitMs[i].length; j++) {
2574                     for (int k = 0; k < events[i][j]; k++) {
2575                         eventEmitter.accept(testPkgName, testUid);
2576                     }
2577                     Thread.sleep(waitMs[i][j]);
2578                 }
2579                 waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
2580                 if (expectingTimeout[i]) {
2581                     verifyRestrictionLevel(RESTRICTION_LEVEL_ADAPTIVE_BUCKET, testPkgName, testUid);
2582                     try {
2583                         listener.verify(timeoutMs, testUid, testPkgName,
2584                                 RESTRICTION_LEVEL_RESTRICTED_BUCKET);
2585                         fail("There shouldn't be any level change events");
2586                     } catch (TimeoutException e) {
2587                         // expected.
2588                     }
2589                 } else {
2590                     verifyRestrictionLevel(RESTRICTION_LEVEL_RESTRICTED_BUCKET,
2591                             testPkgName, testUid);
2592                     listener.verify(timeoutMs, testUid, testPkgName,
2593                             RESTRICTION_LEVEL_RESTRICTED_BUCKET);
2594                 }
2595             }
2596         } finally {
2597             closeIfNotNull(enableMonitor);
2598             closeIfNotNull(eventsWindow);
2599             closeIfNotNull(eventsThreshold);
2600         }
2601     }
2602 
checkNotificationShown(String[] packageName, VerificationMode mode, boolean verifyNotification)2603     private int[] checkNotificationShown(String[] packageName, VerificationMode mode,
2604             boolean verifyNotification) throws Exception {
2605         final ArgumentCaptor<Integer> notificationIdCaptor =
2606                 ArgumentCaptor.forClass(Integer.class);
2607         final ArgumentCaptor<Notification> notificationCaptor =
2608                 ArgumentCaptor.forClass(Notification.class);
2609         verify(mInjector.getNotificationManager(), mode).notifyAsUser(any(),
2610                 notificationIdCaptor.capture(), notificationCaptor.capture(), any());
2611         final int[] notificationId = new int[packageName.length];
2612         if (verifyNotification) {
2613             for (int i = 0, j = 0; i < packageName.length; j++) {
2614                 final int id = notificationIdCaptor.getAllValues().get(j);
2615                 if (id == NotificationHelper.SUMMARY_NOTIFICATION_ID) {
2616                     continue;
2617                 }
2618                 final Notification n = notificationCaptor.getAllValues().get(j);
2619                 notificationId[i] = id;
2620                 assertTrue(NotificationHelper.SUMMARY_NOTIFICATION_ID < notificationId[i]);
2621                 assertEquals(NotificationHelper.GROUP_KEY, n.getGroup());
2622                 assertEquals(ABUSIVE_BACKGROUND_APPS, n.getChannelId());
2623                 assertEquals(packageName[i], n.extras.getString(Intent.EXTRA_PACKAGE_NAME));
2624                 i++;
2625             }
2626         }
2627         return notificationId;
2628     }
2629 
2630     private void checkNotificationGone(String packageName, VerificationMode mode,
2631             int notificationId) throws Exception {
2632         final ArgumentCaptor<Integer> notificationIdCaptor =
2633                 ArgumentCaptor.forClass(Integer.class);
2634         verify(mInjector.getNotificationManager(), mode).cancel(notificationIdCaptor.capture());
2635         assertEquals(notificationId, notificationIdCaptor.getValue().intValue());
2636     }
2637 
2638     private void closeIfNotNull(DeviceConfigSession<?> config) throws Exception {
2639         if (config != null) {
2640             config.close();
2641         }
2642     }
2643 
2644     private interface RunnableWithException {
2645         void run() throws Exception;
2646     }
2647 
2648     private void runTestBgCurrentDrainMonitorOnce(TestAppRestrictionLevelListener listener,
2649             BatteryUsageStats stats, int[] uids, double[] bg, double[] fgs, double[] fg,
2650             double[] cached, RunnableWithException runnable) throws Exception {
2651         runTestBgCurrentDrainMonitorOnce(listener, stats, uids, bg, fgs, fg, cached, true,
2652                 runnable);
2653     }
2654 
2655     private void runTestBgCurrentDrainMonitorOnce(TestAppRestrictionLevelListener listener,
2656             BatteryUsageStats stats, int[] uids, double[] bg, double[] fgs, double[] fg,
2657             double[] cached, boolean resetListener, RunnableWithException runnable)
2658             throws Exception {
2659         if (resetListener) {
2660             listener.mLatchHolder[0] = new CountDownLatch(1);
2661         }
2662         setUidBatteryConsumptions(stats, uids, bg, fgs, fg, cached);
2663         runnable.run();
2664     }
2665 
2666     private void setUidBatteryConsumptions(BatteryUsageStats stats, int[] uids, double[] bg,
2667             double[] fgs, double[] fg, double[] cached) {
2668         ArrayList<UidBatteryConsumer> consumers = new ArrayList<>();
2669         for (int i = 0; i < uids.length; i++) {
2670             consumers.add(mockUidBatteryConsumer(uids[i], bg[i], fgs[i], fg[i], cached[i]));
2671         }
2672         doReturn(consumers).when(stats).getUidBatteryConsumers();
2673     }
2674 
2675     private UidBatteryConsumer mockUidBatteryConsumer(int uid, double bg, double fgs, double fg,
2676             double cached) {
2677         UidBatteryConsumer uidConsumer = mock(UidBatteryConsumer.class);
2678         doReturn(uid).when(uidConsumer).getUid();
2679         doReturn(bg).when(uidConsumer).getConsumedPower(
2680                 eq(BATT_DIMENS[BATTERY_USAGE_INDEX_BACKGROUND]));
2681         doReturn(fgs).when(uidConsumer).getConsumedPower(
2682                 eq(BATT_DIMENS[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE]));
2683         doReturn(fg).when(uidConsumer).getConsumedPower(
2684                 eq(BATT_DIMENS[BATTERY_USAGE_INDEX_FOREGROUND]));
2685         doReturn(cached).when(uidConsumer).getConsumedPower(
2686                 eq(BATT_DIMENS[BATTERY_USAGE_INDEX_CACHED]));
2687         return uidConsumer;
2688     }
2689 
2690     private void setBackgroundRestrict(String pkgName, int uid, boolean restricted,
2691             TestAppRestrictionLevelListener listener) throws Exception {
2692         Log.i(TAG, "Setting background restrict to " + restricted + " for " + pkgName + " " + uid);
2693         listener.mLatchHolder[0] = new CountDownLatch(1);
2694         doReturn(restricted).when(mAppStateTracker).isAppBackgroundRestricted(uid, pkgName);
2695         mFasListener.updateBackgroundRestrictedForUidPackage(uid, pkgName, restricted);
2696         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
2697     }
2698 
2699     private class TestAppRestrictionLevelListener implements AppBackgroundRestrictionListener {
2700         private final CountDownLatch[] mLatchHolder = new CountDownLatch[1];
2701         final int[] mUidHolder = new int[1];
2702         final String[] mPkgNameHolder = new String[1];
2703         final int[] mLevelHolder = new int[1];
2704 
2705         @Override
2706         public void onRestrictionLevelChanged(int uid, String packageName, int newLevel) {
2707             mUidHolder[0] = uid;
2708             mPkgNameHolder[0] = packageName;
2709             mLevelHolder[0] = newLevel;
2710             mLatchHolder[0].countDown();
2711         };
2712 
2713         void verify(long timeout, int uid, String pkgName, int level) throws Exception {
2714             if (!mLatchHolder[0].await(timeout, TimeUnit.MILLISECONDS)) {
2715                 throw new TimeoutException();
2716             }
2717             assertEquals(uid, mUidHolder[0]);
2718             assertEquals(pkgName, mPkgNameHolder[0]);
2719             assertEquals(level, mLevelHolder[0]);
2720         }
2721     }
2722 
2723     private void verifyRestrictionLevel(int level, String pkgName, int uid) {
2724         assertEquals(level, mBgRestrictionController.getRestrictionLevel(uid));
2725         assertEquals(level, mBgRestrictionController.getRestrictionLevel(uid, pkgName));
2726     }
2727 
2728     private void waitForIdleHandler(Handler handler) {
2729         waitForIdleHandler(handler, Duration.ofSeconds(1));
2730     }
2731 
2732     private void waitForIdleHandler(Handler handler, Duration timeout) {
2733         final MessageQueue queue = handler.getLooper().getQueue();
2734         final CountDownLatch latch = new CountDownLatch(1);
2735         queue.addIdleHandler(() -> {
2736             latch.countDown();
2737             // Remove idle handler
2738             return false;
2739         });
2740         try {
2741             latch.await(timeout.toMillis(), TimeUnit.MILLISECONDS);
2742         } catch (InterruptedException e) {
2743             fail("Interrupted unexpectedly: " + e);
2744         }
2745     }
2746 
2747     @Test
2748     public void testMergeAppStateDurations() throws Exception {
2749         final BaseAppStateDurations testObj = new BaseAppStateDurations(0, "", 1, "", null) {};
2750         assertAppStateDurations(null, testObj.add(null, null));
2751         assertAppStateDurations(new LinkedList<BaseTimeEvent>(), testObj.add(
2752                 null, new LinkedList<BaseTimeEvent>()));
2753         assertAppStateDurations(new LinkedList<BaseTimeEvent>(), testObj.add(
2754                 new LinkedList<BaseTimeEvent>(), null));
2755         assertAppStateDurations(createDurations(1), testObj.add(
2756                 createDurations(1), new LinkedList<BaseTimeEvent>()));
2757         assertAppStateDurations(createDurations(1), testObj.add(
2758                 new LinkedList<BaseTimeEvent>(), createDurations(1)));
2759         assertAppStateDurations(createDurations(1, 4, 5, 8, 9), testObj.add(
2760                 createDurations(1, 3, 5, 7, 9), createDurations(2, 4, 6, 8, 10)));
2761         assertAppStateDurations(createDurations(1, 5), testObj.add(
2762                 createDurations(1, 2, 3, 4), createDurations(2, 3, 4, 5)));
2763         assertAppStateDurations(createDurations(1, 4, 6, 9), testObj.add(
2764                 createDurations(2, 4, 6, 9), createDurations(1, 4, 7, 8)));
2765         assertAppStateDurations(createDurations(1, 4, 5, 8, 9, 10), testObj.add(
2766                 createDurations(1, 4, 6, 8), createDurations(1, 3, 5, 8, 9, 10)));
2767     }
2768 
2769     @Test
2770     public void testSubtractAppStateDurations() throws Exception {
2771         final BaseAppStateDurations testObj = new BaseAppStateDurations(0, "", 1, "", null) {};
2772         assertAppStateDurations(null, testObj.subtract(null, null));
2773         assertAppStateDurations(null, testObj.subtract(null, new LinkedList<BaseTimeEvent>()));
2774         assertAppStateDurations(new LinkedList<BaseTimeEvent>(), testObj.subtract(
2775                 new LinkedList<BaseTimeEvent>(), null));
2776         assertAppStateDurations(createDurations(1), testObj.subtract(
2777                 createDurations(1), new LinkedList<BaseTimeEvent>()));
2778         assertAppStateDurations(new LinkedList<BaseTimeEvent>(), testObj.subtract(
2779                 new LinkedList<BaseTimeEvent>(), createDurations(1)));
2780         assertAppStateDurations(new LinkedList<BaseTimeEvent>(), testObj.subtract(
2781                 createDurations(1), createDurations(1)));
2782         assertAppStateDurations(createDurations(1, 2, 5, 6, 9, 10), testObj.subtract(
2783                 createDurations(1, 3, 5, 7, 9), createDurations(2, 4, 6, 8, 10)));
2784         assertAppStateDurations(createDurations(1, 2, 3, 4), testObj.subtract(
2785                 createDurations(1, 4, 6, 7, 9, 10), createDurations(2, 3, 5, 8, 9, 10)));
2786         assertAppStateDurations(createDurations(3, 4, 9, 10), testObj.subtract(
2787                 createDurations(1, 4, 6, 8, 9, 10), createDurations(1, 3, 5, 8)));
2788         assertAppStateDurations(createDurations(1, 2, 3, 4, 5, 6, 7, 8), testObj.subtract(
2789                 createDurations(1, 6, 7, 8), createDurations(2, 3, 4, 5, 8, 10)));
2790         assertAppStateDurations(createDurations(5, 6), testObj.subtract(
2791                 createDurations(2, 3, 5, 6), createDurations(1, 4, 7, 8)));
2792         assertAppStateDurations(createDurations(2, 3, 4, 5, 6, 7, 8), testObj.subtract(
2793                 createDurations(1), createDurations(1, 2, 3, 4, 5, 6, 7, 8)));
2794     }
2795 
2796     private void assertAppStateDurations(LinkedList<BaseTimeEvent> expected,
2797             LinkedList<BaseTimeEvent> actual) throws Exception {
2798         assertListEquals(expected, actual);
2799     }
2800 
2801     private <T> void assertListEquals(LinkedList<T> expected, LinkedList<T> actual) {
2802         assertEquals(expected == null || expected.isEmpty(), actual == null || actual.isEmpty());
2803         if (expected != null) {
2804             if (expected.size() > 0) {
2805                 assertEquals(expected.size(), actual.size());
2806             }
2807             while (expected.peek() != null) {
2808                 assertTrue(expected.poll().equals(actual.poll()));
2809             }
2810         }
2811     }
2812 
createDurations(long... timestamps)2813     private LinkedList<BaseTimeEvent> createDurations(long... timestamps) {
2814         return Arrays.stream(timestamps).mapToObj(BaseTimeEvent::new)
2815                 .collect(LinkedList<BaseTimeEvent>::new, LinkedList<BaseTimeEvent>::add,
2816                 (a, b) -> a.addAll(b));
2817     }
2818 
createIntLinkedList(int[] vals)2819     private LinkedList<Integer> createIntLinkedList(int[] vals) {
2820         return Arrays.stream(vals).collect(LinkedList<Integer>::new, LinkedList<Integer>::add,
2821                 (a, b) -> a.addAll(b));
2822     }
2823 
2824     @Test
testAppStateTimeSlotEvents()2825     public void testAppStateTimeSlotEvents() throws Exception {
2826         final long maxTrackingDuration = 5_000L;
2827         assertAppStateTimeSlotEvents(new int[] {2, 2, 0, 0, 1},
2828                 new long[] {1_500, 1_500, 2_100, 2_999, 5_999}, 5_000);
2829         assertAppStateTimeSlotEvents(new int[] {2, 2, 0, 0, 1, 1},
2830                 new long[] {1_500, 1_500, 2_100, 2_999, 5_999, 6_000}, 6_000);
2831         assertAppStateTimeSlotEvents(new int[] {2, 0, 0, 1, 1, 1},
2832                 new long[] {1_500, 1_500, 2_100, 2_999, 5_999, 6_000, 7_000}, 7_000);
2833         assertMergeAppStateTimeSlotEvents(new int[] {}, new long[] {}, new long[] {}, 0);
2834         assertMergeAppStateTimeSlotEvents(new int[] {1}, new long[] {}, new long[] {1_500}, 1_000);
2835         assertMergeAppStateTimeSlotEvents(new int[] {1}, new long[] {1_500}, new long[] {}, 1_000);
2836         assertMergeAppStateTimeSlotEvents(new int[] {1, 1},
2837                 new long[] {1_500}, new long[] {2_500}, 2_000);
2838         assertMergeAppStateTimeSlotEvents(new int[] {1, 1},
2839                 new long[] {2_500}, new long[] {1_500}, 2_000);
2840         assertMergeAppStateTimeSlotEvents(new int[] {1, 2, 1},
2841                 new long[] {1_500, 2_500}, new long[] {2_600, 3_000}, 3_000);
2842         assertMergeAppStateTimeSlotEvents(new int[] {2, 1, 1},
2843                 new long[] {2_600, 3_500}, new long[] {1_500, 1_600}, 3_000);
2844         assertMergeAppStateTimeSlotEvents(new int[] {1, 2, 1},
2845                 new long[] {1_500, 3_500}, new long[] {2_600, 2_700}, 3_000);
2846         assertMergeAppStateTimeSlotEvents(new int[] {1, 2, 1},
2847                 new long[] {2_500, 2_600}, new long[] {1_500, 3_700}, 3_000);
2848         assertMergeAppStateTimeSlotEvents(new int[] {1, 0, 0, 0, 0, 1},
2849                 new long[] {2_500, 8_600}, new long[] {1_500, 3_700}, 8_000);
2850     }
2851 
createBaseAppStateTimeSlotEvents( long slotSize, long maxTrackingDuration, long[] timestamps)2852     private BaseAppStateTimeSlotEvents createBaseAppStateTimeSlotEvents(
2853             long slotSize, long maxTrackingDuration, long[] timestamps) {
2854         final BaseAppStateTimeSlotEvents testObj = new BaseAppStateTimeSlotEvents(
2855                 0, "", 1, slotSize, "", () -> maxTrackingDuration) {};
2856         for (int i = 0; i < timestamps.length; i++) {
2857             testObj.addEvent(timestamps[i], 0);
2858         }
2859         return testObj;
2860     }
2861 
assertAppStateTimeSlotEvents(int[] expectedEvents, long[] timestamps, long expectedCurTimeslot)2862     private void assertAppStateTimeSlotEvents(int[] expectedEvents, long[] timestamps,
2863             long expectedCurTimeslot) {
2864         final BaseAppStateTimeSlotEvents testObj = createBaseAppStateTimeSlotEvents(1_000L,
2865                 5_000L, timestamps);
2866         assertEquals(expectedCurTimeslot, testObj.getCurrentSlotStartTime(0));
2867         assertListEquals(createIntLinkedList(expectedEvents), testObj.getRawEvents(0));
2868     }
2869 
assertMergeAppStateTimeSlotEvents(int[] expectedEvents, long[] timestamps1, long[] timestamps2, long expectedCurTimeslot)2870     private void assertMergeAppStateTimeSlotEvents(int[] expectedEvents, long[] timestamps1,
2871             long[] timestamps2, long expectedCurTimeslot) {
2872         final BaseAppStateTimeSlotEvents testObj1 = createBaseAppStateTimeSlotEvents(1_000L,
2873                 5_000L, timestamps1);
2874         final BaseAppStateTimeSlotEvents testObj2 = createBaseAppStateTimeSlotEvents(1_000L,
2875                 5_000L, timestamps2);
2876         testObj1.add(testObj2);
2877         assertEquals(expectedCurTimeslot, testObj1.getCurrentSlotStartTime(0));
2878         assertListEquals(createIntLinkedList(expectedEvents), testObj1.getRawEvents(0));
2879     }
2880 
2881     @Test
testMergeUidBatteryUsage()2882     public void testMergeUidBatteryUsage() throws Exception {
2883         final UidBatteryStates testObj = new UidBatteryStates(0, "", null);
2884         assertListEquals(null, testObj.add(null, null));
2885         assertListEquals(new LinkedList<UidStateEventWithBattery>(), testObj.add(
2886                 null, new LinkedList<UidStateEventWithBattery>()));
2887         assertListEquals(new LinkedList<UidStateEventWithBattery>(), testObj.add(
2888                 new LinkedList<UidStateEventWithBattery>(), null));
2889         assertListEquals(createUidStateEventWithBatteryList(
2890                 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}),
2891                 testObj.add(createUidStateEventWithBatteryList(
2892                 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}),
2893                 new LinkedList<UidStateEventWithBattery>()));
2894         assertListEquals(createUidStateEventWithBatteryList(
2895                 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}),
2896                 testObj.add(new LinkedList<UidStateEventWithBattery>(),
2897                 createUidStateEventWithBatteryList(
2898                 new boolean[] {true}, new long[] {10L}, new double[] {10.0d})));
2899         assertListEquals(createUidStateEventWithBatteryList(
2900                 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}),
2901                 testObj.add(createUidStateEventWithBatteryList(
2902                 new boolean[] {true}, new long[] {11L}, new double[] {11.0d}),
2903                 createUidStateEventWithBatteryList(
2904                 new boolean[] {true}, new long[] {10L}, new double[] {10.0d})));
2905         assertListEquals(createUidStateEventWithBatteryList(
2906                 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}),
2907                 testObj.add(createUidStateEventWithBatteryList(
2908                 new boolean[] {true, false}, new long[] {11L, 12L}, new double[] {11.0d, 1.0d}),
2909                 createUidStateEventWithBatteryList(
2910                 new boolean[] {true}, new long[] {10L}, new double[] {10.0d})));
2911         assertListEquals(createUidStateEventWithBatteryList(
2912                 new boolean[] {true}, new long[] {10L}, new double[] {10.0d}),
2913                 testObj.add(createUidStateEventWithBatteryList(
2914                 new boolean[] {true, false, true}, new long[] {11L, 12L, 13L},
2915                 new double[] {11.0d, 1.0d, 13.0d}),
2916                 createUidStateEventWithBatteryList(
2917                 new boolean[] {true}, new long[] {10L}, new double[] {10.0d})));
2918         assertListEquals(createUidStateEventWithBatteryList(
2919                 new boolean[] {true, false}, new long[] {10L, 13L}, new double[] {10.0d, 3.0d}),
2920                 testObj.add(createUidStateEventWithBatteryList(
2921                 new boolean[] {true, false}, new long[] {11L, 13L}, new double[] {11.0d, 2.0d}),
2922                 createUidStateEventWithBatteryList(
2923                 new boolean[] {true, false}, new long[] {10L, 12L}, new double[] {10.0d, 2.0d})));
2924         assertListEquals(createUidStateEventWithBatteryList(
2925                 new boolean[] {true, false, true}, new long[] {10L, 13L, 14L},
2926                 new double[] {10.0d, 3.0d, 14.0d}),
2927                 testObj.add(createUidStateEventWithBatteryList(
2928                 new boolean[] {true, false, true}, new long[] {11L, 13L, 14L},
2929                 new double[] {11.0d, 2.0d, 14.0d}),
2930                 createUidStateEventWithBatteryList(
2931                 new boolean[] {true, false}, new long[] {10L, 12L}, new double[] {10.0d, 2.0d})));
2932         assertListEquals(createUidStateEventWithBatteryList(
2933                 new boolean[] {true, false, true, false, true, false},
2934                 new long[] {10L, 13L, 14L, 17L, 18L, 21L},
2935                 new double[] {10.0d, 3.0d, 14.0d, 3.0d, 18.0d, 3.0d}),
2936                 testObj.add(createUidStateEventWithBatteryList(
2937                 new boolean[] {true, false, true, false, true, false},
2938                 new long[] {11L, 13L, 15L, 17L, 19L, 21L},
2939                 new double[] {11.0d, 2.0d, 15.0d, 2.0d, 19.0d, 2.0d}),
2940                 createUidStateEventWithBatteryList(
2941                 new boolean[] {true, false, true, false, true, false},
2942                 new long[] {10L, 12L, 14L, 16L, 18L, 20L},
2943                 new double[] {10.0d, 2.0d, 14.0d, 2.0d, 18.0d, 2.0d})));
2944         assertListEquals(createUidStateEventWithBatteryList(
2945                 new boolean[] {true, false, true, false, true, false, true, false, true, false},
2946                 new long[] {10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L},
2947                 new double[] {10.0d, 1.0d, 12.0d, 1.0d, 14.0d, 1.0d, 16.0d, 1.0d, 18.0d, 1.0d}),
2948                 testObj.add(createUidStateEventWithBatteryList(
2949                 new boolean[] {true, false, true, false},
2950                 new long[] {12L, 13L, 16L, 17L},
2951                 new double[] {12.0d, 1.0d, 16.0d, 1.0d}),
2952                 createUidStateEventWithBatteryList(
2953                 new boolean[] {true, false, true, false, true, false},
2954                 new long[] {10L, 11L, 14L, 15L, 18L, 19L},
2955                 new double[] {10.0d, 1.0d, 14.0d, 1.0d, 18.0d, 1.0d})));
2956         assertListEquals(createUidStateEventWithBatteryList(
2957                 new boolean[] {true, false, true, false},
2958                 new long[] {10L, 14L, 18L, 19L},
2959                 new double[] {10.0d, 4.0d, 18.0d, 1.0d}),
2960                 testObj.add(createUidStateEventWithBatteryList(
2961                 new boolean[] {true, false, true, false},
2962                 new long[] {11L, 12L, 13L, 14L},
2963                 new double[] {11.0d, 1.0d, 13.0d, 1.0d}),
2964                 createUidStateEventWithBatteryList(
2965                 new boolean[] {true, false, true, false, true, false},
2966                 new long[] {10L, 11L, 12L, 13L, 18L, 19L},
2967                 new double[] {10.0d, 1.0d, 12.0d, 1.0d, 18.0d, 1.0d})));
2968         assertListEquals(createUidStateEventWithBatteryList(
2969                 new boolean[] {true, false, true, false},
2970                 new long[] {10L, 14L, 18L, 19L},
2971                 new double[] {10.0d, 4.0d, 18.0d, 1.0d}),
2972                 testObj.add(createUidStateEventWithBatteryList(
2973                 new boolean[] {true, false, true, false},
2974                 new long[] {10L, 14L, 18L, 19L},
2975                 new double[] {10.0d, 4.0d, 18.0d, 1.0d}),
2976                 createUidStateEventWithBatteryList(
2977                 new boolean[] {true, false, true, false, true, false},
2978                 new long[] {10L, 11L, 12L, 13L, 18L, 19L},
2979                 new double[] {10.0d, 1.0d, 12.0d, 1.0d, 18.0d, 1.0d})));
2980     }
2981 
2982     @SuppressWarnings("GuardedBy")
2983     @Test
testPersistRestrictionSettings()2984     public void testPersistRestrictionSettings() throws Exception {
2985         final RestrictionSettings settings = mBgRestrictionController.mRestrictionSettings;
2986         final String testPkg0 = TEST_PACKAGE_BASE + 0;
2987         final String testPkg1 = TEST_PACKAGE_BASE + 1;
2988         final String testPkg2 = TEST_PACKAGE_BASE + 2;
2989         final String testPkg3 = TEST_PACKAGE_BASE + 3;
2990         final int testUid0 = UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 0);
2991         final int testUid1 = UserHandle.getUid(TEST_USER0, TEST_PACKAGE_APPID_BASE + 1);
2992         final int testUid2 = UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 2);
2993         final int testUid3 = UserHandle.getUid(TEST_USER1, TEST_PACKAGE_APPID_BASE + 3);
2994         settings.reset();
2995         setRestrictionSettings(settings, testPkg0, testUid0,
2996                 RESTRICTION_LEVEL_ADAPTIVE_BUCKET,
2997                 10_000L, REASON_MAIN_DEFAULT | REASON_SUB_DEFAULT_UNDEFINED,
2998                 new long[] {0L, 0L}, false);
2999         setRestrictionSettings(settings, testPkg1, testUid1,
3000                 RESTRICTION_LEVEL_RESTRICTED_BUCKET,
3001                 20_000L, REASON_MAIN_FORCED_BY_SYSTEM | REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE,
3002                 new long[] {10_000L, 0L}, false);
3003         setRestrictionSettings(settings, testPkg2, testUid2,
3004                 RESTRICTION_LEVEL_BACKGROUND_RESTRICTED,
3005                 25_000L, REASON_MAIN_FORCED_BY_USER | REASON_SUB_FORCED_USER_FLAG_INTERACTION,
3006                 new long[] {0L, 15_000L}, false);
3007         setRestrictionSettings(settings, testPkg3, testUid3,
3008                 RESTRICTION_LEVEL_RESTRICTED_BUCKET,
3009                 30_000L, REASON_MAIN_DEFAULT | REASON_SUB_DEFAULT_UNDEFINED,
3010                 new long[] {0L, 0L}, false);
3011         RestrictionSettings test = (RestrictionSettings) settings.clone();
3012 
3013         // Verify our clone works correctly.
3014         assertTrue(settings.equals(test));
3015 
3016         // Reset the test object.
3017         test.resetToDefault();
3018 
3019         // Save the original data into xml.
3020         settings.persistToXml(TEST_USER0);
3021         settings.persistToXml(TEST_USER1);
3022 
3023         // Load it to our test object.
3024         test.loadFromXml(false);
3025         // Verify we restored it correctly.
3026         assertTrue(settings.equals(test));
3027 
3028         // Remove one package.
3029         settings.removePackage(testPkg3, testUid3);
3030         // Verify it.
3031         verifyLoadedSettings(settings);
3032 
3033         // Add it back.
3034         setRestrictionSettings(settings, testPkg3, testUid3,
3035                 RESTRICTION_LEVEL_RESTRICTED_BUCKET,
3036                 30_000L, REASON_MAIN_DEFAULT | REASON_SUB_DEFAULT_UNDEFINED,
3037                 new long[] {0L, 1_000L}, true);
3038         // Verify it.
3039         verifyLoadedSettings(settings);
3040 
3041         // Remove one user.
3042         settings.removeUser(TEST_USER1);
3043         // Verify it.
3044         verifyLoadedSettings(settings);
3045     }
3046 
3047     @Test
testCarrierPrivilegedAppListener()3048     public void testCarrierPrivilegedAppListener() throws Exception {
3049         for (int i = 0; i < MOCK_PRIVILEGED_PACKAGES.length; i++) {
3050             mPhoneCarrierPrivileges.addNewPrivilegePackages(i,
3051                     MOCK_PRIVILEGED_PACKAGES[i], MOCK_PRIVILEGED_UIDS[i]);
3052         }
3053 
3054         final long shortMs = 1_000L;
3055         for (int i = 0; i < MOCK_PRIVILEGED_PACKAGES.length; i++) {
3056             verifyPotentialSystemExemptionReason(REASON_CARRIER_PRIVILEGED_APP,
3057                     MOCK_PRIVILEGED_PACKAGES[i],
3058                     MOCK_PRIVILEGED_UIDS[i]);
3059         }
3060         verifyPotentialSystemExemptionReason(REASON_DENIED,
3061                 MOCK_PRIVILEGED_PACKAGES_2,
3062                 MOCK_PRIVILEGED_UIDS_2);
3063 
3064         mPhoneCarrierPrivileges.addNewPrivilegePackages(0,
3065                 MOCK_PRIVILEGED_PACKAGES_2,
3066                 MOCK_PRIVILEGED_UIDS_2);
3067         Thread.sleep(shortMs);
3068 
3069         verifyPotentialSystemExemptionReason(REASON_CARRIER_PRIVILEGED_APP,
3070                 MOCK_PRIVILEGED_PACKAGES_2,
3071                 MOCK_PRIVILEGED_UIDS_2);
3072 
3073         verifyPotentialSystemExemptionReason(REASON_DENIED,
3074                 MOCK_PRIVILEGED_PACKAGES_0,
3075                 MOCK_PRIVILEGED_UIDS_0);
3076 
3077         verifyPotentialSystemExemptionReason(REASON_CARRIER_PRIVILEGED_APP,
3078                 MOCK_PRIVILEGED_PACKAGES_1,
3079                 MOCK_PRIVILEGED_UIDS_1);
3080 
3081         mPhoneCarrierPrivileges.addNewPrivilegePackages(1,
3082                 new String[0], new int[0]);
3083         Thread.sleep(shortMs);
3084 
3085         verifyPotentialSystemExemptionReason(REASON_CARRIER_PRIVILEGED_APP,
3086                 MOCK_PRIVILEGED_PACKAGES_2,
3087                 MOCK_PRIVILEGED_UIDS_2);
3088 
3089         verifyPotentialSystemExemptionReason(REASON_DENIED,
3090                 MOCK_PRIVILEGED_PACKAGES_0,
3091                 MOCK_PRIVILEGED_UIDS_0);
3092 
3093         verifyPotentialSystemExemptionReason(REASON_DENIED,
3094                 MOCK_PRIVILEGED_PACKAGES_1,
3095                 MOCK_PRIVILEGED_UIDS_1);
3096 
3097         mPhoneCarrierPrivileges.addNewPrivilegePackages(0,
3098                 MOCK_PRIVILEGED_PACKAGES_0,
3099                 MOCK_PRIVILEGED_UIDS_0);
3100         Thread.sleep(shortMs);
3101 
3102         verifyPotentialSystemExemptionReason(REASON_DENIED,
3103                 MOCK_PRIVILEGED_PACKAGES_2,
3104                 MOCK_PRIVILEGED_UIDS_2);
3105 
3106         verifyPotentialSystemExemptionReason(REASON_CARRIER_PRIVILEGED_APP,
3107                 MOCK_PRIVILEGED_PACKAGES_0,
3108                 MOCK_PRIVILEGED_UIDS_0);
3109 
3110         verifyPotentialSystemExemptionReason(REASON_DENIED,
3111                 MOCK_PRIVILEGED_PACKAGES_1,
3112                 MOCK_PRIVILEGED_UIDS_1);
3113     }
3114 
verifyPotentialSystemExemptionReason(int expectedReason, String[] packages, int[] uids)3115     private void verifyPotentialSystemExemptionReason(int expectedReason,
3116             String[] packages, int[] uids) throws Exception {
3117         for (int i = 0; i < packages.length; i++) {
3118             assertEquals(expectedReason,
3119                     mBgRestrictionController.getPotentialSystemExemptionReason(
3120                             uids[i], packages[i]));
3121         }
3122     }
3123 
verifyLoadedSettings(RestrictionSettings settings)3124     private void verifyLoadedSettings(RestrictionSettings settings) throws Exception {
3125         // Make a new copy and reset it.
3126         RestrictionSettings test = (RestrictionSettings) settings.clone();
3127         test.resetToDefault();
3128 
3129         // Wait for the idleness so the data is persisted.
3130         waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
3131         // Load it to our test object.
3132         test.loadFromXml(false);
3133         // Verify we restored it correctly.
3134         assertTrue(settings.equals(test));
3135     }
3136 
3137     @SuppressWarnings("GuardedBy")
setRestrictionSettings(RestrictionSettings settings, String pkgName, int uid, int level, long levelTs, int reason, long[] notificationTime, boolean persist)3138     private void setRestrictionSettings(RestrictionSettings settings, String pkgName, int uid,
3139             int level, long levelTs, int reason, long[] notificationTime, boolean persist) {
3140         mCurrentTimeMillis = levelTs;
3141         settings.update(pkgName, uid, level, reason & REASON_MAIN_MASK, reason & REASON_SUB_MASK);
3142         final RestrictionSettings.PkgSettings pkgSettings = settings.getRestrictionSettingsLocked(
3143                 uid, pkgName);
3144         for (int i = 0; i < notificationTime.length; i++) {
3145             pkgSettings.setLastNotificationTime(i, notificationTime[i], persist);
3146         }
3147     }
3148 
createUidStateEventWithBatteryList( boolean[] isStart, long[] timestamps, double[] batteryUsage)3149     private LinkedList<UidStateEventWithBattery> createUidStateEventWithBatteryList(
3150             boolean[] isStart, long[] timestamps, double[] batteryUsage) {
3151         final LinkedList<UidStateEventWithBattery> result = new LinkedList<>();
3152         for (int i = 0; i < isStart.length; i++) {
3153             result.add(new UidStateEventWithBattery(isStart[i], timestamps[i],
3154                         new ImmutableBatteryUsage(0.0d, 0.0d, batteryUsage[i], 0.0d, 0.0d), null));
3155         }
3156         return result;
3157     }
3158 
3159     private class PhoneCarrierPrivileges {
3160         private final SparseArray<Pair<String[], int[]>> mPackages = new SparseArray<>();
3161         private final SparseArray<Pair<Executor, CarrierPrivilegesCallback>> mListeners =
3162                 new SparseArray<>();
3163 
PhoneCarrierPrivileges(TelephonyManager telephonyManager, int phoneIds)3164         PhoneCarrierPrivileges(TelephonyManager telephonyManager, int phoneIds) {
3165             doReturn(phoneIds).when(telephonyManager).getActiveModemCount();
3166             doAnswer(inv -> {
3167                 registerCarrierPrivilegesCallback(
3168                         inv.getArgument(0),
3169                         inv.getArgument(1),
3170                         inv.getArgument(2));
3171                 return null;
3172             }).when(telephonyManager).registerCarrierPrivilegesCallback(
3173                     anyInt(), any(), any());
3174         }
3175 
registerCarrierPrivilegesCallback(int phoneId, Executor executor, CarrierPrivilegesCallback callback)3176         public void registerCarrierPrivilegesCallback(int phoneId, Executor executor,
3177                 CarrierPrivilegesCallback callback) {
3178             mListeners.put(phoneId, Pair.create(executor, callback));
3179             final Pair<String[], int[]> pkgs = mPackages.get(phoneId);
3180             final Set<String> pkgNames = pkgs != null
3181                     ? Arrays.stream(pkgs.first).collect(Collectors.toUnmodifiableSet())
3182                     : Collections.emptySet();
3183             final Set<Integer> uids = pkgs != null
3184                     ? Arrays.stream(pkgs.second).boxed().collect(Collectors.toUnmodifiableSet())
3185                     : Collections.emptySet();
3186             executor.execute(() -> callback.onCarrierPrivilegesChanged(pkgNames, uids));
3187         }
3188 
addNewPrivilegePackages(int phoneId, String[] pkgNames, int[] uids)3189         public void addNewPrivilegePackages(int phoneId, String[] pkgNames, int[] uids) {
3190             mPackages.put(phoneId, Pair.create(pkgNames, uids));
3191             final Pair<Executor, CarrierPrivilegesCallback> callback = mListeners.get(phoneId);
3192             if (callback != null) {
3193                 callback.first.execute(() -> callback.second.onCarrierPrivilegesChanged(
3194                         Arrays.stream(pkgNames).collect(Collectors.toUnmodifiableSet()),
3195                         Arrays.stream(uids).boxed().collect(Collectors.toUnmodifiableSet())));
3196             }
3197         }
3198     }
3199 
3200     private class TestBgRestrictionInjector extends AppRestrictionController.Injector {
3201         private Context mContext;
3202 
TestBgRestrictionInjector(Context context)3203         TestBgRestrictionInjector(Context context) {
3204             super(context);
3205             mContext = context;
3206         }
3207 
3208         @Override
initAppStateTrackers(AppRestrictionController controller)3209         void initAppStateTrackers(AppRestrictionController controller) {
3210             try {
3211                 mAppBatteryTracker = new AppBatteryTracker(mContext, controller,
3212                         TestAppBatteryTrackerInjector.class.getDeclaredConstructor(
3213                                 BackgroundRestrictionTest.class),
3214                         BackgroundRestrictionTest.this);
3215                 controller.addAppStateTracker(mAppBatteryTracker);
3216                 mAppBatteryExemptionTracker = new AppBatteryExemptionTracker(mContext, controller,
3217                         TestAppBatteryExemptionTrackerInjector.class.getDeclaredConstructor(
3218                                 BackgroundRestrictionTest.class),
3219                         BackgroundRestrictionTest.this);
3220                 controller.addAppStateTracker(mAppBatteryExemptionTracker);
3221                 mAppFGSTracker = new AppFGSTracker(mContext, controller,
3222                         TestAppFGSTrackerInjector.class.getDeclaredConstructor(
3223                                 BackgroundRestrictionTest.class),
3224                         BackgroundRestrictionTest.this);
3225                 controller.addAppStateTracker(mAppFGSTracker);
3226                 mAppMediaSessionTracker = new AppMediaSessionTracker(mContext, controller,
3227                         TestAppMediaSessionTrackerInjector.class.getDeclaredConstructor(
3228                                 BackgroundRestrictionTest.class),
3229                         BackgroundRestrictionTest.this);
3230                 controller.addAppStateTracker(mAppMediaSessionTracker);
3231                 mAppBroadcastEventsTracker = new AppBroadcastEventsTracker(mContext, controller,
3232                         TestAppBroadcastEventsTrackerInjector.class.getDeclaredConstructor(
3233                                 BackgroundRestrictionTest.class),
3234                         BackgroundRestrictionTest.this);
3235                 controller.addAppStateTracker(mAppBroadcastEventsTracker);
3236                 mAppBindServiceEventsTracker = new AppBindServiceEventsTracker(mContext, controller,
3237                         TestAppBindServiceEventsTrackerInjector.class.getDeclaredConstructor(
3238                                 BackgroundRestrictionTest.class),
3239                         BackgroundRestrictionTest.this);
3240                 controller.addAppStateTracker(mAppBindServiceEventsTracker);
3241                 mAppPermissionTracker = new AppPermissionTracker(mContext, controller,
3242                         TestAppPermissionTrackerInjector.class.getDeclaredConstructor(
3243                                 BackgroundRestrictionTest.class),
3244                         BackgroundRestrictionTest.this);
3245                 controller.addAppStateTracker(mAppPermissionTracker);
3246             } catch (NoSuchMethodException e) {
3247                 // Won't happen.
3248             }
3249         }
3250 
3251         @Override
getActivityManagerInternal()3252         ActivityManagerInternal getActivityManagerInternal() {
3253             return mActivityManagerInternal;
3254         }
3255 
3256         @Override
getAppRestrictionController()3257         AppRestrictionController getAppRestrictionController() {
3258             return mBgRestrictionController;
3259         }
3260 
3261         @Override
getAppOpsManager()3262         AppOpsManager getAppOpsManager() {
3263             return mAppOpsManager;
3264         }
3265 
3266         @Override
getAppStandbyInternal()3267         AppStandbyInternal getAppStandbyInternal() {
3268             return mAppStandbyInternal;
3269         }
3270 
3271         @Override
getAppHibernationInternal()3272         AppHibernationManagerInternal getAppHibernationInternal() {
3273             return mAppHibernationInternal;
3274         }
3275 
3276         @Override
getAppStateTracker()3277         AppStateTracker getAppStateTracker() {
3278             return mAppStateTracker;
3279         }
3280 
3281         @Override
getIActivityManager()3282         IActivityManager getIActivityManager() {
3283             return mIActivityManager;
3284         }
3285 
3286         @Override
getUserManagerInternal()3287         UserManagerInternal getUserManagerInternal() {
3288             return mUserManagerInternal;
3289         }
3290 
3291         @Override
getPackageManagerInternal()3292         PackageManagerInternal getPackageManagerInternal() {
3293             return mPackageManagerInternal;
3294         }
3295 
3296         @Override
getPackageManager()3297         PackageManager getPackageManager() {
3298             return mPackageManager;
3299         }
3300 
3301         @Override
getNotificationManager()3302         NotificationManager getNotificationManager() {
3303             return mNotificationManager;
3304         }
3305 
3306         @Override
getRoleManager()3307         RoleManager getRoleManager() {
3308             return mRoleManager;
3309         }
3310 
3311         @Override
getTelephonyManager()3312         TelephonyManager getTelephonyManager() {
3313             return mTelephonyManager;
3314         }
3315 
3316         @Override
getAppFGSTracker()3317         AppFGSTracker getAppFGSTracker() {
3318             return mAppFGSTracker;
3319         }
3320 
3321         @Override
getAppMediaSessionTracker()3322         AppMediaSessionTracker getAppMediaSessionTracker() {
3323             return mAppMediaSessionTracker;
3324         }
3325 
3326         @Override
getActivityManagerService()3327         ActivityManagerService getActivityManagerService() {
3328             return mActivityManagerService;
3329         }
3330 
3331         @Override
getUidBatteryUsageProvider()3332         UidBatteryUsageProvider getUidBatteryUsageProvider() {
3333             return mAppBatteryTracker;
3334         }
3335 
3336         @Override
getAppBatteryExemptionTracker()3337         AppBatteryExemptionTracker getAppBatteryExemptionTracker() {
3338             return mAppBatteryExemptionTracker;
3339         }
3340 
3341         @Override
getAppPermissionTracker()3342         AppPermissionTracker getAppPermissionTracker() {
3343             return mAppPermissionTracker;
3344         }
3345 
3346         @Override
scheduleInitTrackers(Handler handler, Runnable initializers)3347         void scheduleInitTrackers(Handler handler, Runnable initializers) {
3348             initializers.run();
3349         }
3350 
3351         @Override
getDataSystemDeDirectory(@serIdInt int userId)3352         File getDataSystemDeDirectory(@UserIdInt int userId) {
3353             return new File(mContext.getFilesDir(), Integer.toString(userId));
3354         }
3355 
3356         @Override
currentTimeMillis()3357         long currentTimeMillis() {
3358             return mCurrentTimeMillis;
3359         }
3360 
3361         @Override
getDefaultHandler()3362         Handler getDefaultHandler() {
3363             return mDefaultHandler;
3364         }
3365 
3366         @Override
isTest()3367         boolean isTest() {
3368             return true;
3369         }
3370     }
3371 
3372     private class TestBaseTrackerInjector<T extends BaseAppStatePolicy>
3373             extends BaseAppStateTracker.Injector<T> {
3374         @Override
onSystemReady()3375         void onSystemReady() {
3376             getPolicy().onSystemReady();
3377         }
3378 
3379         @Override
getActivityManagerInternal()3380         ActivityManagerInternal getActivityManagerInternal() {
3381             return BackgroundRestrictionTest.this.mActivityManagerInternal;
3382         }
3383 
3384         @Override
getBatteryManagerInternal()3385         BatteryManagerInternal getBatteryManagerInternal() {
3386             return BackgroundRestrictionTest.this.mBatteryManagerInternal;
3387         }
3388 
3389         @Override
getBatteryStatsInternal()3390         BatteryStatsInternal getBatteryStatsInternal() {
3391             return BackgroundRestrictionTest.this.mBatteryStatsInternal;
3392         }
3393 
3394         @Override
getDeviceIdleInternal()3395         DeviceIdleInternal getDeviceIdleInternal() {
3396             return BackgroundRestrictionTest.this.mDeviceIdleInternal;
3397         }
3398 
3399         @Override
getUserManagerInternal()3400         UserManagerInternal getUserManagerInternal() {
3401             return BackgroundRestrictionTest.this.mUserManagerInternal;
3402         }
3403 
3404         @Override
currentTimeMillis()3405         long currentTimeMillis() {
3406             return BackgroundRestrictionTest.this.mCurrentTimeMillis;
3407         }
3408 
3409         @Override
getPackageManager()3410         PackageManager getPackageManager() {
3411             return BackgroundRestrictionTest.this.mPackageManager;
3412         }
3413 
3414         @Override
getPermissionManagerServiceInternal()3415         PermissionManagerServiceInternal getPermissionManagerServiceInternal() {
3416             return BackgroundRestrictionTest.this.mPermissionManagerServiceInternal;
3417         }
3418 
3419         @Override
getAppOpsManager()3420         AppOpsManager getAppOpsManager() {
3421             return BackgroundRestrictionTest.this.mAppOpsManager;
3422         }
3423 
3424         @Override
getMediaSessionManager()3425         MediaSessionManager getMediaSessionManager() {
3426             return BackgroundRestrictionTest.this.mMediaSessionManager;
3427         }
3428 
3429         @Override
getNotificationManagerInternal()3430         NotificationManagerInternal getNotificationManagerInternal() {
3431             return BackgroundRestrictionTest.this.mNotificationManagerInternal;
3432         }
3433 
getPackageManagerInternal()3434         PackageManagerInternal getPackageManagerInternal() {
3435             return BackgroundRestrictionTest.this.mPackageManagerInternal;
3436         }
3437 
getPermissionManager()3438         PermissionManager getPermissionManager() {
3439             return BackgroundRestrictionTest.this.mPermissionManager;
3440         }
3441 
3442         @Override
getServiceStartForegroundTimeout()3443         long getServiceStartForegroundTimeout() {
3444             return 1_000; // ms
3445         }
3446 
3447         @Override
getRoleManager()3448         RoleManager getRoleManager() {
3449             return BackgroundRestrictionTest.this.mRoleManager;
3450         }
3451 
3452         @Override
getIAppOpsService()3453         IAppOpsService getIAppOpsService() {
3454             return BackgroundRestrictionTest.this.mIAppOpsService;
3455         }
3456 
3457         @Override
checkPermission(String perm, int pid, int uid)3458         int checkPermission(String perm, int pid, int uid) {
3459             try {
3460                 return BackgroundRestrictionTest.this.mIActivityManager.checkPermission(
3461                         perm, pid, uid);
3462             } catch (RemoteException e) {
3463                 return PERMISSION_DENIED;
3464             }
3465         }
3466     }
3467 
3468     private class TestAppBatteryTrackerInjector extends TestBaseTrackerInjector<AppBatteryPolicy> {
3469         @Override
setPolicy(AppBatteryPolicy policy)3470         void setPolicy(AppBatteryPolicy policy) {
3471             super.setPolicy(policy);
3472             BackgroundRestrictionTest.this.mAppBatteryPolicy = policy;
3473         }
3474     }
3475 
3476     private class TestAppBatteryExemptionTrackerInjector
3477             extends TestBaseTrackerInjector<AppBatteryExemptionPolicy> {
3478     }
3479 
3480     private class TestAppFGSTrackerInjector extends TestBaseTrackerInjector<AppFGSPolicy> {
3481     }
3482 
3483     private class TestAppMediaSessionTrackerInjector
3484             extends TestBaseTrackerInjector<AppMediaSessionPolicy> {
3485     }
3486 
3487     private class TestAppPermissionTrackerInjector
3488             extends TestBaseTrackerInjector<AppPermissionPolicy> {
3489     }
3490 
3491     private class TestAppBroadcastEventsTrackerInjector
3492             extends TestBaseTrackerInjector<AppBroadcastEventsPolicy> {
3493         @Override
setPolicy(AppBroadcastEventsPolicy policy)3494         void setPolicy(AppBroadcastEventsPolicy policy) {
3495             super.setPolicy(policy);
3496             policy.setTimeSlotSize(1_000L);
3497         }
3498     }
3499 
3500     private class TestAppBindServiceEventsTrackerInjector
3501             extends TestBaseTrackerInjector<AppBindServiceEventsPolicy> {
3502         @Override
setPolicy(AppBindServiceEventsPolicy policy)3503         void setPolicy(AppBindServiceEventsPolicy policy) {
3504             super.setPolicy(policy);
3505             policy.setTimeSlotSize(1_000L);
3506         }
3507     }
3508 }
3509