• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 android.app.cts;
18 
19 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
20 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
21 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
22 import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
23 import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
24 import static android.app.stubs.LocalForegroundService.ACTION_START_FGS_RESULT;
25 import static android.app.stubs.LocalForegroundServiceLocation.ACTION_START_FGSL_RESULT;
26 import static android.os.PowerExemptionManager.REASON_PUSH_MESSAGING;
27 import static android.os.PowerExemptionManager.REASON_PUSH_MESSAGING_OVER_QUOTA;
28 import static android.os.PowerExemptionManager.REASON_UNKNOWN;
29 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
30 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
31 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;
32 
33 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
34 
35 import static junit.framework.Assert.assertNotNull;
36 import static junit.framework.Assert.assertTrue;
37 import static junit.framework.Assert.fail;
38 
39 import android.accessibilityservice.AccessibilityService;
40 import android.app.ActivityManager;
41 import android.app.BroadcastOptions;
42 import android.app.ForegroundServiceStartNotAllowedException;
43 import android.app.Instrumentation;
44 import android.app.cts.android.app.cts.tools.WaitForBroadcast;
45 import android.app.cts.android.app.cts.tools.WatchUidRunner;
46 import android.app.stubs.CommandReceiver;
47 import android.app.stubs.LocalForegroundService;
48 import android.app.stubs.LocalForegroundServiceLocation;
49 import android.content.ComponentName;
50 import android.content.Context;
51 import android.content.Intent;
52 import android.content.ServiceConnection;
53 import android.content.pm.ApplicationInfo;
54 import android.content.pm.ServiceInfo;
55 import android.os.Bundle;
56 import android.os.IBinder;
57 import android.os.PowerExemptionManager;
58 import android.os.SystemClock;
59 import android.permission.cts.PermissionUtils;
60 import android.platform.test.annotations.AsbSecurityTest;
61 import android.provider.DeviceConfig;
62 import android.provider.Settings;
63 import android.server.wm.settings.SettingsSession;
64 import android.support.test.uiautomator.UiDevice;
65 import android.util.Log;
66 
67 import androidx.test.InstrumentationRegistry;
68 import androidx.test.ext.junit.runners.AndroidJUnit4;
69 import androidx.test.filters.LargeTest;
70 
71 import com.android.compatibility.common.util.SystemUtil;
72 
73 import org.junit.After;
74 import org.junit.Before;
75 import org.junit.Ignore;
76 import org.junit.Test;
77 import org.junit.runner.RunWith;
78 
79 @RunWith(AndroidJUnit4.class)
80 public class ActivityManagerFgsBgStartTest {
81     private static final String TAG = ActivityManagerFgsBgStartTest.class.getName();
82 
83     static final String STUB_PACKAGE_NAME = "android.app.stubs";
84     static final String PACKAGE_NAME_APP1 = "com.android.app1";
85     static final String PACKAGE_NAME_APP2 = "com.android.app2";
86     static final String PACKAGE_NAME_APP3 = "com.android.app3";
87 
88     private static final String KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED =
89             "default_fgs_starts_restriction_enabled";
90 
91     private static final String KEY_FGS_START_FOREGROUND_TIMEOUT =
92             "fgs_start_foreground_timeout";
93 
94     private static final String KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR =
95             "push_messaging_over_quota_behavior";
96 
97     private static final int DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS = 10 * 1000;
98 
99     public static final Integer LOCAL_SERVICE_PROCESS_CAPABILITY = new Integer(
100             PROCESS_CAPABILITY_FOREGROUND_CAMERA
101             | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
102             | PROCESS_CAPABILITY_NETWORK);
103 
104     static final int WAITFOR_MSEC = 10000;
105 
106     private static final int TEMP_ALLOWLIST_DURATION_MS = 2000;
107 
108     private static final String[] PACKAGE_NAMES = {
109             PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, PACKAGE_NAME_APP3
110     };
111 
112     private Context mContext;
113     private Instrumentation mInstrumentation;
114     private Context mTargetContext;
115 
116     private int mOrigDeviceDemoMode = 0;
117 
118     @Before
setUp()119     public void setUp() throws Exception {
120         mInstrumentation = InstrumentationRegistry.getInstrumentation();
121         mContext = mInstrumentation.getContext();
122         mTargetContext = mInstrumentation.getTargetContext();
123         for (int i = 0; i < PACKAGE_NAMES.length; ++i) {
124             CtsAppTestUtils.makeUidIdle(mInstrumentation, PACKAGE_NAMES[i]);
125             // The manifest file gives test app SYSTEM_ALERT_WINDOW permissions, which also exempt
126             // the app from BG-FGS-launch restriction. Remove SYSTEM_ALERT_WINDOW permission to test
127             // other BG-FGS-launch exemptions.
128             allowBgActivityStart(PACKAGE_NAMES[i], false);
129         }
130         CtsAppTestUtils.turnScreenOn(mInstrumentation, mContext);
131         cleanupResiduals();
132         enableFgsRestriction(true, true, null);
133         // Press home key to ensure stopAppSwitches is called so the grace period of
134         // the background start will be ignored if there's any.
135         UiDevice.getInstance(mInstrumentation).pressHome();
136     }
137 
138     @After
tearDown()139     public void tearDown() throws Exception {
140         for (int i = 0; i < PACKAGE_NAMES.length; ++i) {
141             CtsAppTestUtils.makeUidIdle(mInstrumentation, PACKAGE_NAMES[i]);
142             allowBgActivityStart(PACKAGE_NAMES[i], true);
143         }
144         cleanupResiduals();
145         enableFgsRestriction(true, true, null);
146         for (String packageName: PACKAGE_NAMES) {
147             resetFgsRestriction(packageName);
148         }
149     }
150 
cleanupResiduals()151     private void cleanupResiduals() {
152         // Stop all the packages to avoid residual impact
153         final ActivityManager am = mContext.getSystemService(ActivityManager.class);
154         for (int i = 0; i < PACKAGE_NAMES.length; i++) {
155             final String pkgName = PACKAGE_NAMES[i];
156             SystemUtil.runWithShellPermissionIdentity(() -> {
157                 am.forceStopPackage(pkgName);
158             });
159         }
160         // Make sure we are in Home screen
161         mInstrumentation.getUiAutomation().performGlobalAction(
162                 AccessibilityService.GLOBAL_ACTION_HOME);
163     }
164 
165     /**
166      * APP1 is in BG state, it can start FGSL, but it won't get location capability.
167      * APP1 is in TOP state, it gets location capability.
168      * @throws Exception
169      */
170     @Test
testFgsLocationStartFromBG()171     public void testFgsLocationStartFromBG() throws Exception {
172         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
173                 PACKAGE_NAME_APP1, 0);
174         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
175                 WAITFOR_MSEC);
176 
177         try {
178             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
179             waiter.prepare(ACTION_START_FGSL_RESULT);
180             // APP1 is in BG state, Start FGSL in APP1, it won't get location capability.
181             Bundle bundle = new Bundle();
182             bundle.putInt(LocalForegroundServiceLocation.EXTRA_FOREGROUND_SERVICE_TYPE,
183                     ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION);
184             // start FGSL.
185             enableFgsRestriction(false, true, null);
186             CommandReceiver.sendCommand(mContext,
187                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION,
188                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, bundle);
189             // APP1 is in FGS state, but won't get location capability.
190             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
191                     WatchUidRunner.STATE_FG_SERVICE,
192                     new Integer(PROCESS_CAPABILITY_NETWORK));
193             waiter.doWait(WAITFOR_MSEC);
194             // stop FGSL
195             CommandReceiver.sendCommand(mContext,
196                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
197                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
198             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
199                     WatchUidRunner.STATE_CACHED_EMPTY,
200                     new Integer(PROCESS_CAPABILITY_NONE));
201 
202             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
203             waiter.prepare(ACTION_START_FGS_RESULT);
204             // APP1 is in FGS state,
205             CommandReceiver.sendCommand(mContext,
206                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
207                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, bundle);
208             // start FGSL in app1, it won't get location capability.
209             CommandReceiver.sendCommand(mContext,
210                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION,
211                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, bundle);
212             // APP1 is in STATE_FG_SERVICE, but won't get location capability.
213             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
214                     WatchUidRunner.STATE_FG_SERVICE,
215                     new Integer(PROCESS_CAPABILITY_NETWORK));
216             waiter.doWait(WAITFOR_MSEC);
217             // stop FGS.
218             CommandReceiver.sendCommand(mContext,
219                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
220                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
221             // stop FGSL.
222             CommandReceiver.sendCommand(mContext,
223                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
224                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
225 
226             // Put APP1 in TOP state, now it gets location capability (because the TOP process
227             // gets all while-in-use permission (not from FGSL).
228             allowBgActivityStart(PACKAGE_NAME_APP1, true);
229             CommandReceiver.sendCommand(mContext,
230                     CommandReceiver.COMMAND_START_ACTIVITY,
231                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
232             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
233                     WatchUidRunner.STATE_TOP,
234                     new Integer(PROCESS_CAPABILITY_ALL));
235 
236             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
237             waiter.prepare(ACTION_START_FGSL_RESULT);
238             // APP1 is in TOP state, start the FGSL in APP1, it will get location capability.
239             CommandReceiver.sendCommand(mContext,
240                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION,
241                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, bundle);
242             // Stop the activity.
243             CommandReceiver.sendCommand(mContext,
244                     CommandReceiver.COMMAND_STOP_ACTIVITY,
245                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
246             // The FGSL still has location capability because it is started from TOP.
247             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
248                     WatchUidRunner.STATE_FG_SERVICE,
249                     new Integer(PROCESS_CAPABILITY_ALL));
250             waiter.doWait(WAITFOR_MSEC);
251             // Stop FGSL.
252             CommandReceiver.sendCommand(mContext,
253                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
254                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
255             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
256                     WatchUidRunner.STATE_CACHED_EMPTY,
257                     new Integer(PROCESS_CAPABILITY_NONE));
258         } finally {
259             uid1Watcher.finish();
260         }
261     }
262 
263     /**
264      * APP1 is in BG state, it can start FGSL in APP2, but the FGS won't get location
265      * capability.
266      * APP1 is in TOP state, it can start FGSL in APP2, FGSL gets location capability.
267      * @throws Exception
268      */
269     @Test
testFgsLocationStartFromBGTwoProcesses()270     public void testFgsLocationStartFromBGTwoProcesses() throws Exception {
271         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
272                 PACKAGE_NAME_APP1, 0);
273         ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
274                 PACKAGE_NAME_APP2, 0);
275         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
276                 WAITFOR_MSEC);
277         WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
278                 WAITFOR_MSEC);
279 
280         try {
281             // APP1 is in BG state, start FGSL in APP2.
282             Bundle bundle = new Bundle();
283             bundle.putInt(LocalForegroundServiceLocation.EXTRA_FOREGROUND_SERVICE_TYPE,
284                     ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION);
285             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
286             waiter.prepare(ACTION_START_FGSL_RESULT);
287             enableFgsRestriction(false, true, null);
288             CommandReceiver.sendCommand(mContext,
289                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION,
290                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, bundle);
291             // APP2 won't have location capability because APP1 is not in TOP state.
292             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
293                     WatchUidRunner.STATE_FG_SERVICE,
294                     new Integer(PROCESS_CAPABILITY_NETWORK));
295             waiter.doWait(WAITFOR_MSEC);
296 
297             CommandReceiver.sendCommand(mContext,
298                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
299                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
300             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
301                     WatchUidRunner.STATE_CACHED_EMPTY,
302                     new Integer(PROCESS_CAPABILITY_NONE));
303 
304             // Put APP1 in TOP state
305             allowBgActivityStart(PACKAGE_NAME_APP1, true);
306             CommandReceiver.sendCommand(mContext,
307                     CommandReceiver.COMMAND_START_ACTIVITY,
308                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
309             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
310                     WatchUidRunner.STATE_TOP,
311                     new Integer(PROCESS_CAPABILITY_ALL));
312 
313             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
314             waiter.prepare(ACTION_START_FGSL_RESULT);
315             // From APP1, start FGSL in APP2.
316             CommandReceiver.sendCommand(mContext,
317                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION,
318                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, bundle);
319             // Now APP2 gets location capability.
320             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
321                     WatchUidRunner.STATE_FG_SERVICE,
322                     new Integer(PROCESS_CAPABILITY_ALL));
323             waiter.doWait(WAITFOR_MSEC);
324 
325             CommandReceiver.sendCommand(mContext,
326                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
327                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null);
328 
329             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
330                     WatchUidRunner.STATE_CACHED_EMPTY,
331                     new Integer(PROCESS_CAPABILITY_NONE));
332 
333             CommandReceiver.sendCommand(mContext,
334                     CommandReceiver.COMMAND_STOP_ACTIVITY,
335                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
336 
337             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
338                     WatchUidRunner.STATE_CACHED_EMPTY,
339                     new Integer(PROCESS_CAPABILITY_NONE));
340         } finally {
341             uid1Watcher.finish();
342             uid2Watcher.finish();
343         }
344     }
345 
346     /**
347      * APP1 is in BG state, by a PendingIntent, it can start FGSL in APP2,
348      * but the FGS won't get location capability.
349      * APP1 is in TOP state, by a PendingIntent, it can start FGSL in APP2,
350      * FGSL gets location capability.
351      * @throws Exception
352      */
353     @Test
testFgsLocationPendingIntent()354     public void testFgsLocationPendingIntent() throws Exception {
355         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
356                 PACKAGE_NAME_APP1, 0);
357         ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
358                 PACKAGE_NAME_APP2, 0);
359         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
360                 WAITFOR_MSEC);
361         WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
362                 WAITFOR_MSEC);
363 
364         try {
365             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
366             waiter.prepare(ACTION_START_FGSL_RESULT);
367             // APP1 is in BG state, start FGSL in APP2.
368             enableFgsRestriction(false, true, null);
369             CommandReceiver.sendCommand(mContext,
370                     CommandReceiver.COMMAND_CREATE_FGSL_PENDING_INTENT,
371                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
372             CommandReceiver.sendCommand(mContext,
373                     CommandReceiver.COMMAND_SEND_FGSL_PENDING_INTENT,
374                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
375             // APP2 won't have location capability.
376             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
377                     WatchUidRunner.STATE_FG_SERVICE,
378                     new Integer(PROCESS_CAPABILITY_NETWORK));
379             waiter.doWait(WAITFOR_MSEC);
380             // Stop FGSL in APP2.
381             CommandReceiver.sendCommand(mContext,
382                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
383                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
384             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
385                     WatchUidRunner.STATE_CACHED_EMPTY,
386                     new Integer(PROCESS_CAPABILITY_NONE));
387 
388             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
389             waiter.prepare(ACTION_START_FGS_RESULT);
390             // Put APP1 in FGS state, start FGSL in APP2.
391             CommandReceiver.sendCommand(mContext,
392                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
393                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
394             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
395                     WatchUidRunner.STATE_FG_SERVICE,
396                     new Integer(PROCESS_CAPABILITY_NETWORK));
397             waiter.doWait(WAITFOR_MSEC);
398             CommandReceiver.sendCommand(mContext,
399                     CommandReceiver.COMMAND_CREATE_FGSL_PENDING_INTENT,
400                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
401 
402             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
403             waiter.prepare(ACTION_START_FGSL_RESULT);
404             CommandReceiver.sendCommand(mContext,
405                     CommandReceiver.COMMAND_SEND_FGSL_PENDING_INTENT,
406                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
407             // APP2 won't have location capability.
408             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
409                     WatchUidRunner.STATE_FG_SERVICE,
410                     new Integer(PROCESS_CAPABILITY_NETWORK));
411             waiter.doWait(WAITFOR_MSEC);
412             // stop FGSL in APP2.
413             CommandReceiver.sendCommand(mContext,
414                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
415                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
416             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
417                     WatchUidRunner.STATE_CACHED_EMPTY,
418                     new Integer(PROCESS_CAPABILITY_NONE));
419 
420             // put APP1 in TOP state, start FGSL in APP2.
421             allowBgActivityStart(PACKAGE_NAME_APP1, true);
422             CommandReceiver.sendCommand(mContext,
423                     CommandReceiver.COMMAND_START_ACTIVITY,
424                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
425             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
426                     WatchUidRunner.STATE_TOP,
427                     new Integer(PROCESS_CAPABILITY_ALL));
428             CommandReceiver.sendCommand(mContext,
429                     CommandReceiver.COMMAND_CREATE_FGSL_PENDING_INTENT,
430                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
431 
432             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
433             waiter.prepare(ACTION_START_FGSL_RESULT);
434             CommandReceiver.sendCommand(mContext,
435                     CommandReceiver.COMMAND_SEND_FGSL_PENDING_INTENT,
436                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
437             // APP2 now have location capability (because APP1 is TOP)
438             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
439                     WatchUidRunner.STATE_FG_SERVICE,
440                     new Integer(PROCESS_CAPABILITY_ALL));
441             waiter.doWait(WAITFOR_MSEC);
442 
443             // stop FGSL in APP2.
444             CommandReceiver.sendCommand(mContext,
445                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
446                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
447             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
448                     WatchUidRunner.STATE_CACHED_EMPTY,
449                     new Integer(PROCESS_CAPABILITY_NONE));
450 
451             // stop FGS in APP1,
452             CommandReceiver.sendCommand(mContext,
453                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
454                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
455             // stop TOP activity in APP1.
456             CommandReceiver.sendCommand(mContext,
457                     CommandReceiver.COMMAND_STOP_ACTIVITY,
458                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
459             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
460                     WatchUidRunner.STATE_CACHED_EMPTY,
461                     new Integer(PROCESS_CAPABILITY_NONE));
462         } finally {
463             uid1Watcher.finish();
464             uid2Watcher.finish();
465         }
466     }
467 
468     /**
469      * Test a FGS start by bind from BG does not get get while-in-use capability.
470      * @throws Exception
471      */
472     @Test
473     @AsbSecurityTest(cveBugId = 173516292)
testFgsLocationStartFromBGWithBind()474     public void testFgsLocationStartFromBGWithBind() throws Exception {
475         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
476                 PACKAGE_NAME_APP1, 0);
477         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
478                 WAITFOR_MSEC);
479 
480         try {
481             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
482             waiter.prepare(ACTION_START_FGSL_RESULT);
483             // APP1 is in BG state, bind FGSL in APP1 first.
484             enableFgsRestriction(false, true, null);
485             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_FOREGROUND_SERVICE,
486                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
487             Bundle bundle = new Bundle();
488             bundle.putInt(LocalForegroundServiceLocation.EXTRA_FOREGROUND_SERVICE_TYPE,
489                     ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION);
490             // Then start FGSL in APP1, it won't get location capability.
491             CommandReceiver.sendCommand(mContext,
492                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION,
493                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, bundle);
494 
495             // APP1 is in FGS state, but won't get location capability.
496             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
497                     WatchUidRunner.STATE_FG_SERVICE,
498                     new Integer(PROCESS_CAPABILITY_NETWORK));
499             waiter.doWait(WAITFOR_MSEC);
500 
501             // unbind service.
502             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
503                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
504             // stop FGSL
505             CommandReceiver.sendCommand(mContext,
506                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
507                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
508             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
509                     WatchUidRunner.STATE_CACHED_EMPTY,
510                     new Integer(PROCESS_CAPABILITY_NONE));
511         } finally {
512             uid1Watcher.finish();
513         }
514     }
515 
516     @Test
testUpdateUidProcState()517     public void testUpdateUidProcState() throws Exception {
518         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
519                 PACKAGE_NAME_APP1, 0);
520         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
521                 WAITFOR_MSEC);
522         ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
523                 PACKAGE_NAME_APP2, 0);
524         WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
525                 WAITFOR_MSEC);
526         ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo(
527                 PACKAGE_NAME_APP3, 0);
528         WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid,
529                 WAITFOR_MSEC);
530 
531         try {
532             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
533             waiter.prepare(ACTION_START_FGS_RESULT);
534 
535             enableFgsRestriction(false, true, null);
536 
537             // START FGS in APP2.
538             CommandReceiver.sendCommand(mContext,
539                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
540                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null);
541             // APP2 proc state is 4.
542             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
543                     WatchUidRunner.STATE_FG_SERVICE);
544             waiter.doWait(WAITFOR_MSEC);
545 
546             // APP2 binds to APP1.
547             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
548                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP1, Context.BIND_INCLUDE_CAPABILITIES, null);
549             // APP1 gets proc state 4.
550             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
551                     WatchUidRunner.STATE_FG_SERVICE);
552 
553             // Start activity in APP3, this put APP3 in TOP state.
554             allowBgActivityStart(PACKAGE_NAME_APP3, true);
555             CommandReceiver.sendCommand(mContext,
556                     CommandReceiver.COMMAND_START_ACTIVITY,
557                     PACKAGE_NAME_APP3, PACKAGE_NAME_APP3, 0, null);
558             // APP3 gets proc state 2.
559             uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
560 
561             // APP3 repeatedly bind/unbind with APP2, observer APP1 proc state change.
562             // Observe updateUidProcState() call latency.
563             for (int i = 0; i < 10; ++i) {
564                 // APP3 bind to APP2
565                 CommandReceiver.sendCommand(mContext,
566                         CommandReceiver.COMMAND_BIND_SERVICE,
567                         PACKAGE_NAME_APP3, PACKAGE_NAME_APP2, Context.BIND_INCLUDE_CAPABILITIES,
568                         null);
569                 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_BOUND_TOP);
570 
571                 CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
572                         PACKAGE_NAME_APP3, PACKAGE_NAME_APP2, 0, null);
573                 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
574             }
575 
576             // unbind service.
577             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_ACTIVITY,
578                     PACKAGE_NAME_APP3, PACKAGE_NAME_APP3, 0, null);
579             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
580                     PACKAGE_NAME_APP3, PACKAGE_NAME_APP2, 0, null);
581             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
582                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP1, 0, null);
583             CommandReceiver.sendCommand(mContext,
584                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
585                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null);
586 
587         } finally {
588             uid1Watcher.finish();
589             uid2Watcher.finish();
590             uid3Watcher.finish();
591             allowBgActivityStart(PACKAGE_NAME_APP3, false);
592         }
593     }
594 
595     /**
596      * Test FGS background startForeground() restriction, use DeviceConfig to turn on restriction.
597      * @throws Exception
598      */
599     @Test
testFgsStartFromBG1()600     public void testFgsStartFromBG1() throws Exception {
601         testFgsStartFromBG(true);
602     }
603 
604     /**
605      * Test FGS background startForeground() restriction, use AppCompat CHANGE ID to turn on
606      * restriction.
607      * @throws Exception
608      */
609     @Test
testFgsStartFromBG2()610     public void testFgsStartFromBG2() throws Exception {
611         testFgsStartFromBG(false);
612     }
613 
testFgsStartFromBG(boolean useDeviceConfig)614     private void testFgsStartFromBG(boolean useDeviceConfig) throws Exception {
615         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
616                 PACKAGE_NAME_APP1, 0);
617         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
618                 WAITFOR_MSEC);
619         try {
620             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
621             waiter.prepare(ACTION_START_FGS_RESULT);
622             // disable the FGS background startForeground() restriction.
623             enableFgsRestriction(false, true, null);
624             enableFgsRestriction(false, useDeviceConfig, PACKAGE_NAME_APP1);
625             // APP1 is in BG state, Start FGS in APP1.
626             CommandReceiver.sendCommand(mContext,
627                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
628                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
629             // APP1 is in STATE_FG_SERVICE.
630             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
631             waiter.doWait(WAITFOR_MSEC);
632             // stop FGS.
633             CommandReceiver.sendCommand(mContext,
634                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
635                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
636             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
637 
638             // Enable the FGS background startForeground() restriction.
639             allowBgActivityStart(PACKAGE_NAME_APP1, false);
640             enableFgsRestriction(true, true, null);
641             enableFgsRestriction(true, useDeviceConfig, PACKAGE_NAME_APP1);
642             // Start FGS in BG state.
643             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
644             waiter.prepare(ACTION_START_FGS_RESULT);
645             CommandReceiver.sendCommand(mContext,
646                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
647                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
648             // APP1 does not enter FGS state
649             try {
650                 waiter.doWait(WAITFOR_MSEC);
651                 fail("Service should not enter foreground service state");
652             } catch (Exception e) {
653             }
654 
655             // Put APP1 in TOP state.
656             allowBgActivityStart(PACKAGE_NAME_APP1, true);
657             CommandReceiver.sendCommand(mContext,
658                     CommandReceiver.COMMAND_START_ACTIVITY,
659                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
660             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
661             allowBgActivityStart(PACKAGE_NAME_APP1, false);
662 
663             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
664             waiter.prepare(ACTION_START_FGS_RESULT);
665             // Now it can start FGS.
666             CommandReceiver.sendCommand(mContext,
667                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
668                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
669             // Stop activity.
670             CommandReceiver.sendCommand(mContext,
671                     CommandReceiver.COMMAND_STOP_ACTIVITY,
672                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
673             // FGS is still running.
674             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
675             waiter.doWait(WAITFOR_MSEC);
676             // Stop the FGS.
677             CommandReceiver.sendCommand(mContext,
678                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
679                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
680             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
681         } finally {
682             uid1Watcher.finish();
683         }
684     }
685 
686     /**
687      * Test a FGS can start from a process that is at BOUND_TOP state.
688      * @throws Exception
689      */
690     @Test
testFgsStartFromBoundTopState()691     public void testFgsStartFromBoundTopState() throws Exception {
692         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
693                 PACKAGE_NAME_APP1, 0);
694         ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
695                 PACKAGE_NAME_APP2, 0);
696         ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo(
697                 PACKAGE_NAME_APP3, 0);
698         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
699                 WAITFOR_MSEC);
700         WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
701                 WAITFOR_MSEC);
702         WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid,
703                 WAITFOR_MSEC);
704         try {
705             // Enable the FGS background startForeground() restriction.
706             enableFgsRestriction(true, true, null);
707 
708             // Put APP1 in TOP state.
709             allowBgActivityStart(PACKAGE_NAME_APP1, true);
710             CommandReceiver.sendCommand(mContext,
711                     CommandReceiver.COMMAND_START_ACTIVITY,
712                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
713             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
714 
715             // APP1 bound to service in APP2, APP2 get BOUND_TOP state.
716             CommandReceiver.sendCommand(mContext,
717                     CommandReceiver.COMMAND_BIND_SERVICE,
718                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
719             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_BOUND_TOP);
720 
721             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
722             waiter.prepare(ACTION_START_FGS_RESULT);
723             // APP2 can start FGS in APP3.
724             CommandReceiver.sendCommand(mContext,
725                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
726                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);
727             uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
728             waiter.doWait(WAITFOR_MSEC);
729 
730             // Stop activity.
731             CommandReceiver.sendCommand(mContext,
732                     CommandReceiver.COMMAND_STOP_ACTIVITY,
733                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
734             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
735             // unbind service.
736             CommandReceiver.sendCommand(mContext,
737                     CommandReceiver.COMMAND_UNBIND_SERVICE,
738                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
739             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
740             // Stop the FGS.
741             CommandReceiver.sendCommand(mContext,
742                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
743                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);
744             uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
745         } finally {
746             uid1Watcher.finish();
747             uid2Watcher.finish();
748             uid3Watcher.finish();
749         }
750     }
751 
752     /**
753      * Test a FGS can start from a process that is at FOREGROUND_SERVICE state.
754      * @throws Exception
755      */
756     @Test
testFgsStartFromFgsState()757     public void testFgsStartFromFgsState() throws Exception {
758         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
759                 PACKAGE_NAME_APP1, 0);
760         ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
761                 PACKAGE_NAME_APP2, 0);
762         ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo(
763                 PACKAGE_NAME_APP3, 0);
764         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
765                 WAITFOR_MSEC);
766         WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
767                 WAITFOR_MSEC);
768         WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid,
769                 WAITFOR_MSEC);
770         try {
771             // Enable the FGS background startForeground() restriction.
772             enableFgsRestriction(true, true, null);
773 
774             // Put APP1 in TOP state.
775             allowBgActivityStart(PACKAGE_NAME_APP1, true);
776             CommandReceiver.sendCommand(mContext,
777                     CommandReceiver.COMMAND_START_ACTIVITY,
778                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
779             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
780 
781             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
782             waiter.prepare(ACTION_START_FGS_RESULT);
783             // APP1 can start FGS in APP2, APP2 gets FOREGROUND_SERVICE state.
784             CommandReceiver.sendCommand(mContext,
785                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
786                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
787             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
788             waiter.doWait(WAITFOR_MSEC);
789 
790             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
791             waiter.prepare(ACTION_START_FGS_RESULT);
792             // APP2 can start FGS in APP3.
793             CommandReceiver.sendCommand(mContext,
794                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
795                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);
796             uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
797             waiter.doWait(WAITFOR_MSEC);
798 
799             // Stop activity in APP1.
800             CommandReceiver.sendCommand(mContext,
801                     CommandReceiver.COMMAND_STOP_ACTIVITY,
802                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
803             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
804             // Stop FGS in APP2.
805             CommandReceiver.sendCommand(mContext,
806                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
807                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
808             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
809             // Stop FGS in APP3.
810             CommandReceiver.sendCommand(mContext,
811                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
812                     PACKAGE_NAME_APP3, PACKAGE_NAME_APP3, 0, null);
813             uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
814         } finally {
815             uid1Watcher.finish();
816             uid2Watcher.finish();
817             uid3Watcher.finish();
818         }
819     }
820 
821     /**
822      * When the service is started by bindService() command, test when BG-FGS-launch
823      * restriction is disabled, FGS can start from background.
824      * @throws Exception
825      */
826     @Test
testFgsStartFromBGWithBind()827     public void testFgsStartFromBGWithBind() throws Exception {
828         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
829                 PACKAGE_NAME_APP1, 0);
830         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
831                 WAITFOR_MSEC);
832 
833         try {
834             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
835             waiter.prepare(ACTION_START_FGSL_RESULT);
836             // APP1 is in BG state, bind FGSL in APP1 first.
837             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_FOREGROUND_SERVICE,
838                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
839             // Then start FGSL in APP1
840             enableFgsRestriction(false, true, null);
841             CommandReceiver.sendCommand(mContext,
842                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION,
843                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
844             // APP1 is in FGS state
845             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
846             waiter.doWait(WAITFOR_MSEC);
847 
848             // stop FGS
849             CommandReceiver.sendCommand(mContext,
850                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
851                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
852             // unbind service.
853             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
854                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
855             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
856         } finally {
857             uid1Watcher.finish();
858         }
859     }
860 
861     /**
862      * When the service is started by bindService() command, test when BG-FGS-launch
863      * restriction is enabled, FGS can NOT start from background.
864      * @throws Exception
865      */
866     @Test
testFgsStartFromBGWithBindWithRestriction()867     public void testFgsStartFromBGWithBindWithRestriction() throws Exception {
868         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
869                 PACKAGE_NAME_APP1, 0);
870         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
871                 WAITFOR_MSEC);
872 
873         try {
874             enableFgsRestriction(true, true, null);
875             // APP1 is in BG state, bind FGSL in APP1 first.
876             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_FOREGROUND_SERVICE,
877                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
878             // Then start FGS in APP1
879             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
880             waiter.prepare(ACTION_START_FGS_RESULT);
881             CommandReceiver.sendCommand(mContext,
882                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
883                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
884             // APP1 does not enter FGS state
885             try {
886                 waiter.doWait(WAITFOR_MSEC);
887                 fail("Service should not enter foreground service state");
888             } catch (Exception e) {
889             }
890 
891             // stop FGS
892             CommandReceiver.sendCommand(mContext,
893                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
894                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
895             // unbind service.
896             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
897                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
898             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
899         } finally {
900             uid1Watcher.finish();
901         }
902     }
903 
904     /**
905      * Test BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS flag.
906      * Shell has START_ACTIVITIES_FROM_BACKGROUND permission, it can use this bind flag to
907      * pass BG-Activity-launch ability to APP2, then APP2 can start APP2 FGS from background.
908      */
909     @Test
testFgsBindingFlagActivity()910     public void testFgsBindingFlagActivity() throws Exception {
911         testFgsBindingFlag(Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS);
912     }
913 
914     /**
915      * Test BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND flag.
916      * Shell has START_FOREGROUND_SERVICES_FROM_BACKGROUND permission, it can use this bind flag to
917      * pass BG-FGS-launch ability to APP2, then APP2 can start APP3 FGS from background.
918      */
919     @Test
testFgsBindingFlagFGS()920     public void testFgsBindingFlagFGS() throws Exception {
921         testFgsBindingFlag(Context.BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND);
922     }
923 
924     /**
925      * Test no binding flag.
926      * Shell has START_FOREGROUND_SERVICES_FROM_BACKGROUND permission, without any bind flag,
927      * the BG-FGS-launch ability can be passed to APP2 by service binding, then APP2 can start
928      * APP3 FGS from background.
929      */
930     @Test
testFgsBindingFlagNone()931     public void testFgsBindingFlagNone() throws Exception {
932         testFgsBindingFlag(0);
933     }
934 
testFgsBindingFlag(int bindingFlag)935     private void testFgsBindingFlag(int bindingFlag) throws Exception {
936         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
937                 PACKAGE_NAME_APP1, 0);
938         ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
939                 PACKAGE_NAME_APP2, 0);
940         ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo(
941                 PACKAGE_NAME_APP3, 0);
942         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
943                 WAITFOR_MSEC);
944         WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
945                 WAITFOR_MSEC);
946         WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid,
947                 WAITFOR_MSEC);
948         try {
949             // Enable the FGS background startForeground() restriction.
950             enableFgsRestriction(true, true, null);
951 
952             // testapp is in background.
953             // testapp binds to service in APP2, APP2 still in background state.
954             final Intent intent = new Intent().setClassName(
955                     PACKAGE_NAME_APP2, "android.app.stubs.LocalService");
956 
957             /*
958             final ServiceConnection connection = new ServiceConnection() {
959                 @Override
960                 public void onServiceConnected(ComponentName name, IBinder service) {
961                 }
962                 @Override
963                 public void onServiceDisconnected(ComponentName name) {
964                 }
965             };
966             runWithShellPermissionIdentity(() -> {
967                 mTargetContext.bindService(intent, connection,
968                         Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY);
969             });
970 
971             // APP2 can not start FGS in APP3.
972             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
973             waiter.prepare(ACTION_START_FGS_RESULT);
974             CommandReceiver.sendCommand(mContext,
975                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
976                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);
977             try {
978                 waiter.doWait(WAITFOR_MSEC);
979                 fail("Service should not enter foreground service state");
980             } catch (Exception e) {
981             }
982 
983             // testapp unbind service in APP2.
984             runWithShellPermissionIdentity(() -> mTargetContext.unbindService(connection));
985             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
986             */
987 
988             // testapp is in background.
989             // testapp binds to service in APP2 using the binding flag.
990             // APP2 still in background state.
991             final ServiceConnection connection2 = new ServiceConnection() {
992                 @Override
993                 public void onServiceConnected(ComponentName name, IBinder service) {
994                 }
995                 @Override
996                 public void onServiceDisconnected(ComponentName name) {
997                 }
998             };
999             runWithShellPermissionIdentity(() -> mTargetContext.bindService(intent, connection2,
1000                     Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
1001                             | bindingFlag));
1002 
1003             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1004             waiter.prepare(ACTION_START_FGS_RESULT);
1005             // Because the binding flag,
1006             // APP2 can start FGS from background.
1007             CommandReceiver.sendCommand(mContext,
1008                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1009                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);
1010             uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1011             waiter.doWait(WAITFOR_MSEC);
1012 
1013             // testapp unbind service in APP2.
1014             runWithShellPermissionIdentity(() -> mTargetContext.unbindService(connection2));
1015             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
1016             // Stop the FGS in APP3.
1017             CommandReceiver.sendCommand(mContext,
1018                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
1019                     PACKAGE_NAME_APP3, PACKAGE_NAME_APP3, 0, null);
1020             uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
1021         } finally {
1022             uid1Watcher.finish();
1023             uid2Watcher.finish();
1024             uid3Watcher.finish();
1025         }
1026     }
1027 
1028     /**
1029      * Test a FGS can start from BG if the app has SYSTEM_ALERT_WINDOW permission.
1030      */
1031     @Test
testFgsStartSystemAlertWindow()1032     public void testFgsStartSystemAlertWindow() throws Exception {
1033         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1034                 PACKAGE_NAME_APP1, 0);
1035         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
1036                 WAITFOR_MSEC);
1037         try {
1038             // Enable the FGS background startForeground() restriction.
1039             enableFgsRestriction(true, true, null);
1040             // Start FGS in BG state.
1041             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1042             waiter.prepare(ACTION_START_FGS_RESULT);
1043             CommandReceiver.sendCommand(mContext,
1044                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1045                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1046             // APP1 does not enter FGS state
1047             try {
1048                 waiter.doWait(WAITFOR_MSEC);
1049                 fail("Service should not enter foreground service state");
1050             } catch (Exception e) {
1051             }
1052 
1053             PermissionUtils.grantPermission(
1054                     PACKAGE_NAME_APP1, android.Manifest.permission.SYSTEM_ALERT_WINDOW);
1055             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1056             waiter.prepare(ACTION_START_FGS_RESULT);
1057             // Now it can start FGS.
1058             CommandReceiver.sendCommand(mContext,
1059                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1060                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1061             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1062             waiter.doWait(WAITFOR_MSEC);
1063             // Stop the FGS.
1064             CommandReceiver.sendCommand(mContext,
1065                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
1066                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1067             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
1068         } finally {
1069             uid1Watcher.finish();
1070         }
1071     }
1072 
1073     /**
1074      * Test a FGS can start from BG if the device is in retail demo mode.
1075      */
1076     @Test
1077     // Change Settings.Global.DEVICE_DEMO_MODE on device may trigger other listener and put
1078     // the device in undesired state, for example, the battery charge level is set to 35%
1079     // permanently, ignore this test for now.
1080     @Ignore
testFgsStartRetailDemoMode()1081     public void testFgsStartRetailDemoMode() throws Exception {
1082         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1083                 PACKAGE_NAME_APP1, 0);
1084         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
1085                 WAITFOR_MSEC);
1086         runWithShellPermissionIdentity(()-> {
1087             mOrigDeviceDemoMode = Settings.Global.getInt(mContext.getContentResolver(),
1088                     Settings.Global.DEVICE_DEMO_MODE, 0); });
1089 
1090         try {
1091             // Enable the FGS background startForeground() restriction.
1092             enableFgsRestriction(true, true, null);
1093             // Start FGS in BG state.
1094             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1095             waiter.prepare(ACTION_START_FGS_RESULT);
1096             CommandReceiver.sendCommand(mContext,
1097                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1098                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1099             // APP1 does not enter FGS state
1100             try {
1101                 waiter.doWait(WAITFOR_MSEC);
1102                 fail("Service should not enter foreground service state");
1103             } catch (Exception e) {
1104             }
1105 
1106             runWithShellPermissionIdentity(()-> {
1107                 Settings.Global.putInt(mContext.getContentResolver(),
1108                         Settings.Global.DEVICE_DEMO_MODE, 1); });
1109             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1110             waiter.prepare(ACTION_START_FGS_RESULT);
1111             // Now it can start FGS.
1112             CommandReceiver.sendCommand(mContext,
1113                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1114                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1115             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1116             waiter.doWait(WAITFOR_MSEC);
1117             // Stop the FGS.
1118             CommandReceiver.sendCommand(mContext,
1119                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
1120                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1121             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
1122         } finally {
1123             uid1Watcher.finish();
1124             runWithShellPermissionIdentity(()-> {
1125                 Settings.Global.putInt(mContext.getContentResolver(),
1126                         Settings.Global.DEVICE_DEMO_MODE, mOrigDeviceDemoMode); });
1127         }
1128     }
1129 
1130     // At Context.startForegroundService() or Service.startForeground() calls, if the FGS is
1131     // restricted by background restriction and the app's targetSdkVersion is at least S, the
1132     // framework throws a ForegroundServiceStartNotAllowedException with error message.
1133     @Test
1134     @Ignore("The instrumentation is allowed to star FGS, it does not throw the exception")
testFgsStartFromBGException()1135     public void testFgsStartFromBGException() throws Exception {
1136         ForegroundServiceStartNotAllowedException expectedException = null;
1137         final Intent intent = new Intent().setClassName(
1138                 PACKAGE_NAME_APP1, "android.app.stubs.LocalForegroundService");
1139         try {
1140             allowBgActivityStart("android.app.stubs", false);
1141             enableFgsRestriction(true, true, null);
1142             mContext.startForegroundService(intent);
1143         } catch (ForegroundServiceStartNotAllowedException e) {
1144             expectedException = e;
1145         } finally {
1146             mContext.stopService(intent);
1147             allowBgActivityStart("android.app.stubs", true);
1148         }
1149         String expectedMessage = "mAllowStartForeground false";
1150         assertNotNull(expectedException);
1151         assertTrue(expectedException.getMessage().contains(expectedMessage));
1152     }
1153 
1154     /**
1155      * Test a FGS can start from BG if the app is in the DeviceIdleController's AllowList.
1156      */
1157     @Test
testFgsStartAllowList()1158     public void testFgsStartAllowList() throws Exception {
1159         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1160                 PACKAGE_NAME_APP1, 0);
1161         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
1162                 WAITFOR_MSEC);
1163         try {
1164             // Enable the FGS background startForeground() restriction.
1165             enableFgsRestriction(true, true, null);
1166             // Start FGS in BG state.
1167             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1168             waiter.prepare(ACTION_START_FGS_RESULT);
1169             CommandReceiver.sendCommand(mContext,
1170                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1171                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1172             // APP1 does not enter FGS state
1173             try {
1174                 waiter.doWait(WAITFOR_MSEC);
1175                 fail("Service should not enter foreground service state");
1176             } catch (Exception e) {
1177             }
1178 
1179             // Add package to AllowList.
1180             CtsAppTestUtils.executeShellCmd(mInstrumentation,
1181                     "dumpsys deviceidle whitelist +" + PACKAGE_NAME_APP1);
1182             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1183             waiter.prepare(ACTION_START_FGS_RESULT);
1184             // Now it can start FGS.
1185             CommandReceiver.sendCommand(mContext,
1186                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1187                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1188             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1189             waiter.doWait(WAITFOR_MSEC);
1190             // Stop the FGS.
1191             CommandReceiver.sendCommand(mContext,
1192                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
1193                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1194             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
1195         } finally {
1196             uid1Watcher.finish();
1197             // Remove package from AllowList.
1198             CtsAppTestUtils.executeShellCmd(mInstrumentation,
1199                     "dumpsys deviceidle whitelist -" + PACKAGE_NAME_APP1);
1200         }
1201     }
1202 
1203     /**
1204      * Test temp allowlist types in BroadcastOptions.
1205      */
1206     @Test
testTempAllowListType()1207     public void testTempAllowListType() throws Exception {
1208         testTempAllowListTypeInternal(TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED);
1209         testTempAllowListTypeInternal(TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED);
1210     }
1211 
testTempAllowListTypeInternal(int type)1212     private void testTempAllowListTypeInternal(int type) throws Exception {
1213         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1214                 PACKAGE_NAME_APP1, 0);
1215         ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
1216                 PACKAGE_NAME_APP2, 0);
1217         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
1218                 WAITFOR_MSEC);
1219         WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
1220                 WAITFOR_MSEC);
1221         try {
1222             // Enable the FGS background startForeground() restriction.
1223             enableFgsRestriction(true, true, null);
1224             // Start FGS in BG state.
1225             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1226             waiter.prepare(ACTION_START_FGS_RESULT);
1227             CommandReceiver.sendCommand(mContext,
1228                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1229                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
1230             // APP1 does not enter FGS state
1231             try {
1232                 waiter.doWait(WAITFOR_MSEC);
1233                 fail("Service should not enter foreground service state");
1234             } catch (Exception e) {
1235             }
1236 
1237             // Now it can start FGS.
1238             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1239             waiter.prepare(ACTION_START_FGS_RESULT);
1240             runWithShellPermissionIdentity(()-> {
1241                 final BroadcastOptions options = BroadcastOptions.makeBasic();
1242                 // setTemporaryAppAllowlist API requires
1243                 // START_FOREGROUND_SERVICES_FROM_BACKGROUND permission.
1244                 options.setTemporaryAppAllowlist(TEMP_ALLOWLIST_DURATION_MS, type, REASON_UNKNOWN,
1245                         "");
1246                 // Must use Shell to issue this command because Shell has
1247                 // START_FOREGROUND_SERVICES_FROM_BACKGROUND permission.
1248                 CommandReceiver.sendCommandWithBroadcastOptions(mContext,
1249                         CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1250                         PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null,
1251                         options.toBundle());
1252             });
1253             if (type == TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
1254                 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1255                 waiter.doWait(WAITFOR_MSEC);
1256                 // Stop the FGS.
1257                 CommandReceiver.sendCommand(mContext,
1258                         CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
1259                         PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
1260                 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1261                         WatchUidRunner.STATE_CACHED_EMPTY);
1262             } else if (type == TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED) {
1263                 // APP1 does not enter FGS state
1264                 try {
1265                     waiter.doWait(WAITFOR_MSEC);
1266                     fail("Service should not enter foreground service state");
1267                 } catch (Exception e) {
1268                 }
1269             }
1270         } finally {
1271             uid1Watcher.finish();
1272             uid2Watcher.finish();
1273             // Sleep 10 seconds to let the temp allowlist expire so it won't affect next test case.
1274             SystemClock.sleep(TEMP_ALLOWLIST_DURATION_MS);
1275         }
1276 
1277     }
1278 
1279     /**
1280      * Test a FGS can start from BG if the process had a visible activity recently.
1281      */
1282     @LargeTest
1283     @Test
testVisibleActivityGracePeriod()1284     public void testVisibleActivityGracePeriod() throws Exception {
1285         ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
1286                 PACKAGE_NAME_APP2, 0);
1287         WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
1288                 WAITFOR_MSEC);
1289         final String namespaceActivityManager = "activity_manager";
1290         final String keyFgToBgFgsGraceDuration = "fg_to_bg_fgs_grace_duration";
1291         final long[] curFgToBgFgsGraceDuration = {-1};
1292         try {
1293             // Enable the FGS background startForeground() restriction.
1294             enableFgsRestriction(true, true, null);
1295             // Allow bg actvity start from APP1.
1296             allowBgActivityStart(PACKAGE_NAME_APP1, true);
1297 
1298             SystemUtil.runWithShellPermissionIdentity(() -> {
1299                 curFgToBgFgsGraceDuration[0] = DeviceConfig.getInt(
1300                         namespaceActivityManager,
1301                         keyFgToBgFgsGraceDuration, -1);
1302                 DeviceConfig.setProperty(namespaceActivityManager,
1303                         keyFgToBgFgsGraceDuration,
1304                         Long.toString(WAITFOR_MSEC), false);
1305             });
1306 
1307             testVisibleActivityGracePeriodInternal(uid2Watcher, "KEYCODE_HOME");
1308             testVisibleActivityGracePeriodInternal(uid2Watcher, "KEYCODE_BACK");
1309         } finally {
1310             uid2Watcher.finish();
1311             // Remove package from AllowList.
1312             allowBgActivityStart(PACKAGE_NAME_APP1, false);
1313             if (curFgToBgFgsGraceDuration[0] >= 0) {
1314                 SystemUtil.runWithShellPermissionIdentity(() -> {
1315                     DeviceConfig.setProperty(namespaceActivityManager,
1316                             keyFgToBgFgsGraceDuration,
1317                             Long.toString(curFgToBgFgsGraceDuration[0]), false);
1318                 });
1319             } else {
1320                 CtsAppTestUtils.executeShellCmd(mInstrumentation,
1321                         "device_config delete " + namespaceActivityManager
1322                         + " " + keyFgToBgFgsGraceDuration);
1323             }
1324         }
1325     }
1326 
testVisibleActivityGracePeriodInternal(WatchUidRunner uidWatcher, String keyCode)1327     private void testVisibleActivityGracePeriodInternal(WatchUidRunner uidWatcher, String keyCode)
1328             throws Exception {
1329         testVisibleActivityGracePeriodInternal(uidWatcher, keyCode, null,
1330                 () -> uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1331                                          WatchUidRunner.STATE_FG_SERVICE), true);
1332 
1333         testVisibleActivityGracePeriodInternal(uidWatcher, keyCode,
1334                 () -> SystemClock.sleep(WAITFOR_MSEC + 2000), // Wait for the grace period to expire
1335                 () -> {
1336                     try {
1337                         uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1338                                 WatchUidRunner.STATE_FG_SERVICE);
1339                         fail("Service should not enter foreground service state");
1340                     } catch (Exception e) {
1341                         // Expected.
1342                     }
1343                 }, false);
1344     }
1345 
testVisibleActivityGracePeriodInternal(WatchUidRunner uidWatcher, String keyCode, Runnable prep, Runnable verifier, boolean stopFgs)1346     private void testVisibleActivityGracePeriodInternal(WatchUidRunner uidWatcher,
1347             String keyCode, Runnable prep, Runnable verifier, boolean stopFgs) throws Exception {
1348         // Put APP2 in TOP state.
1349         CommandReceiver.sendCommand(mContext,
1350                 CommandReceiver.COMMAND_START_ACTIVITY,
1351                 PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
1352         uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
1353 
1354         // Take a nap to wait for the UI to settle down.
1355         SystemClock.sleep(2000);
1356 
1357         // Now inject key event.
1358         CtsAppTestUtils.executeShellCmd(mInstrumentation, "input keyevent " + keyCode);
1359 
1360         // It should go to the cached state.
1361         uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
1362 
1363         if (prep != null) {
1364             prep.run();
1365         }
1366 
1367         // Start FGS from APP2.
1368         CommandReceiver.sendCommand(mContext,
1369                 CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1370                 PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null);
1371 
1372         if (verifier != null) {
1373             verifier.run();
1374         }
1375 
1376         if (stopFgs) {
1377             // Stop the FGS.
1378             CommandReceiver.sendCommand(mContext,
1379                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
1380                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null);
1381             uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
1382         }
1383     }
1384 
1385     /**
1386      * After background service is started, after 10 seconds timeout, the startForeground() can
1387      * succeed or not depends on the service's app proc state.
1388      * Test starService() -> startForeground()
1389      */
1390     @Test
testStartForegroundTimeout()1391     public void testStartForegroundTimeout() throws Exception {
1392         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1393                 PACKAGE_NAME_APP1, 0);
1394         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
1395                 WAITFOR_MSEC);
1396         try {
1397             // Enable the FGS background startForeground() restriction.
1398             enableFgsRestriction(true, true, null);
1399             setFgsStartForegroundTimeout(DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS);
1400 
1401             // Put app to a TOP proc state.
1402             allowBgActivityStart(PACKAGE_NAME_APP1, true);
1403             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_ACTIVITY,
1404                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1405             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);
1406             allowBgActivityStart(PACKAGE_NAME_APP1, false);
1407 
1408             // start background service.
1409             Bundle extras = LocalForegroundService.newCommand(
1410                     LocalForegroundService.COMMAND_START_NO_FOREGROUND);
1411             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE,
1412                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras);
1413 
1414             // stop the activity.
1415             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_ACTIVITY,
1416                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1417             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
1418 
1419             // Sleep after the timeout DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS
1420             SystemClock.sleep(DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS + 1000);
1421 
1422             extras = LocalForegroundService.newCommand(
1423                     LocalForegroundService.COMMAND_START_FOREGROUND);
1424             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE,
1425                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras);
1426             // APP1 does not enter FGS state
1427             // startForeground() is called after 10 seconds FgsStartForegroundTimeout.
1428             try {
1429                 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1430                 fail("Service should not enter foreground service state");
1431             } catch (Exception e) {
1432             }
1433 
1434             // Put app to a TOP proc state.
1435             allowBgActivityStart(PACKAGE_NAME_APP1, true);
1436             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_ACTIVITY,
1437                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1438             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1439                     WatchUidRunner.STATE_TOP, new Integer(PROCESS_CAPABILITY_ALL));
1440             allowBgActivityStart(PACKAGE_NAME_APP1, false);
1441 
1442             // Call startForeground().
1443             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1444             waiter.prepare(ACTION_START_FGS_RESULT);
1445             extras = LocalForegroundService.newCommand(
1446                     LocalForegroundService.COMMAND_START_FOREGROUND);
1447             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE,
1448                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras);
1449             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_ACTIVITY,
1450                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1451 
1452             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1453             waiter.doWait(WAITFOR_MSEC);
1454 
1455             // Stop the FGS.
1456             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_SERVICE,
1457                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1458             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY,
1459                     new Integer(PROCESS_CAPABILITY_NONE));
1460         } finally {
1461             uid1Watcher.finish();
1462             setFgsStartForegroundTimeout(DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS);
1463         }
1464     }
1465 
1466     /**
1467      * After startForeground() and stopForeground(), the second startForeground() can succeed or not
1468      * depends on the service's app proc state.
1469      * Test startForegroundService() -> startForeground() -> stopForeground() -> startForeground()
1470      * -> startForeground().
1471      */
1472     @Test
testSecondStartForeground()1473     public void testSecondStartForeground() throws Exception {
1474         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1475                 PACKAGE_NAME_APP1, 0);
1476         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
1477                 WAITFOR_MSEC);
1478         try {
1479             // Enable the FGS background startForeground() restriction.
1480             enableFgsRestriction(true, true, null);
1481             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1482             waiter.prepare(ACTION_START_FGS_RESULT);
1483             // Bypass bg-service-start restriction.
1484             CtsAppTestUtils.executeShellCmd(mInstrumentation,
1485                     "dumpsys deviceidle whitelist +" + PACKAGE_NAME_APP1);
1486             // Start foreground service from APP1, the service can enter FGS.
1487             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1488                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1489             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1490             waiter.doWait(WAITFOR_MSEC);
1491             CtsAppTestUtils.executeShellCmd(mInstrumentation,
1492                     "dumpsys deviceidle whitelist -" + PACKAGE_NAME_APP1);
1493 
1494             // stopForeground(), the service exits FGS, become a background service.
1495             Bundle extras = LocalForegroundService.newCommand(
1496                     LocalForegroundService.COMMAND_STOP_FOREGROUND_REMOVE_NOTIFICATION);
1497             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE,
1498                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras);
1499             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE,
1500                     new Integer(PROCESS_CAPABILITY_NONE));
1501 
1502             // APP2 is in the background, from APP2, call startForeground().
1503             // When APP2 calls Context.startService(), setFgsRestrictionLocked() is called,
1504             // because APP2 is in the background, mAllowStartForeground is set to false.
1505             // When Service.startForeground() is called, setFgsRestrictionLocked() is called again,
1506             // APP1's proc state is in the background and mAllowStartForeground is set to false.
1507             extras = LocalForegroundService.newCommand(
1508                     LocalForegroundService.COMMAND_START_FOREGROUND);
1509             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE,
1510                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP1, 0, extras);
1511             try {
1512                 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1513                 fail("Service should not enter foreground service state");
1514             } catch (Exception e) {
1515             }
1516 
1517             // Put APP1 to a TOP proc state.
1518             allowBgActivityStart(PACKAGE_NAME_APP1, true);
1519             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_ACTIVITY,
1520                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1521             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP,
1522                     new Integer(PROCESS_CAPABILITY_ALL));
1523             allowBgActivityStart(PACKAGE_NAME_APP1, false);
1524 
1525             // APP2 is in the background, from APP2, call startForeground() second time.
1526             // When APP2 calls Context.startService(), setFgsRestrictionLocked() is called,
1527             // because APP2 is in the background, mAllowStartForeground is set to false.
1528             // When Service.startForeground() is called, setFgsRestrictionLocked() is called again,
1529             // because APP1's proc state is in the foreground and mAllowStartForeground is set to
1530             // true.
1531             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1532             waiter.prepare(ACTION_START_FGS_RESULT);
1533             extras = LocalForegroundService.newCommand(
1534                     LocalForegroundService.COMMAND_START_FOREGROUND);
1535             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE,
1536                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP1, 0, extras);
1537             waiter.doWait(WAITFOR_MSEC);
1538             // Stop app1's activity.
1539             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_ACTIVITY,
1540                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1541             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE,
1542                     LOCAL_SERVICE_PROCESS_CAPABILITY);
1543 
1544             // Stop the FGS.
1545             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
1546                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1547             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY,
1548                     new Integer(PROCESS_CAPABILITY_NONE));
1549         } finally {
1550             uid1Watcher.finish();
1551         }
1552     }
1553 
1554     /**
1555      * Test OP_ACTIVATE_VPN and OP_ACTIVATE_PLATFORM_VPN are exempted from BG-FGS-launch
1556      * restriction.
1557      * @throws Exception
1558      */
1559     @Test
testFgsStartVpn()1560     public void testFgsStartVpn() throws Exception {
1561         testFgsStartVpnInternal("ACTIVATE_VPN");
1562         testFgsStartVpnInternal("ACTIVATE_PLATFORM_VPN");
1563     }
1564 
testFgsStartVpnInternal(String vpnAppOp)1565     private void testFgsStartVpnInternal(String vpnAppOp) throws Exception {
1566         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1567                 PACKAGE_NAME_APP1, 0);
1568         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
1569                 WAITFOR_MSEC);
1570         try {
1571             // Enable the FGS background startForeground() restriction.
1572             enableFgsRestriction(true, true, null);
1573             // Start FGS in BG state.
1574             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1575             waiter.prepare(ACTION_START_FGS_RESULT);
1576             CommandReceiver.sendCommand(mContext,
1577                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1578                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1579             // APP1 does not enter FGS state
1580             try {
1581                 waiter.doWait(WAITFOR_MSEC);
1582                 fail("Service should not enter foreground service state");
1583             } catch (Exception e) {
1584             }
1585 
1586             setAppOp(PACKAGE_NAME_APP1, vpnAppOp, true);
1587 
1588             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1589             waiter.prepare(ACTION_START_FGS_RESULT);
1590             // Now it can start FGS.
1591             CommandReceiver.sendCommand(mContext,
1592                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1593                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1594             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1595             waiter.doWait(WAITFOR_MSEC);
1596             // Stop the FGS.
1597             CommandReceiver.sendCommand(mContext,
1598                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
1599                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1600             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
1601         } finally {
1602             uid1Watcher.finish();
1603             CtsAppTestUtils.executeShellCmd(mInstrumentation,
1604                     "appops reset " + PACKAGE_NAME_APP1);
1605         }
1606     }
1607 
1608     /**
1609      * The default behavior for temp allowlist reasonCode REASON_PUSH_MESSAGING_OVER_QUOTA
1610      * is TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED (not allowed to start FGS). But
1611      * the behavior can be changed by device config command. There are three possible values:
1612      * {@link TEMPORARY_ALLOW_LIST_TYPE_NONE} (-1):
1613      *      not temp allowlisted.
1614      * {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED} (0):
1615      *      temp allowlisted and allow FGS.
1616      * {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED} (1):
1617      *      temp allowlisted, not allow FGS.
1618      * @throws Exception
1619      */
1620     @Test
testPushMessagingOverQuota()1621     public void testPushMessagingOverQuota() throws Exception {
1622         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1623                 PACKAGE_NAME_APP1, 0);
1624         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
1625                 WAITFOR_MSEC);
1626         final int defaultBehavior = getPushMessagingOverQuotaBehavior();
1627         try {
1628             // Enable the FGS background startForeground() restriction.
1629             enableFgsRestriction(true, true, null);
1630             // Default behavior is TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED.
1631             setPushMessagingOverQuotaBehavior(
1632                     TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED);
1633             // Start FGS in BG state.
1634             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1635             waiter.prepare(ACTION_START_FGS_RESULT);
1636             CommandReceiver.sendCommand(mContext,
1637                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1638                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1639             // APP1 does not enter FGS state
1640             try {
1641                 waiter.doWait(WAITFOR_MSEC);
1642                 fail("Service should not enter foreground service state");
1643             } catch (Exception e) {
1644             }
1645 
1646             setPushMessagingOverQuotaBehavior(TEMPORARY_ALLOW_LIST_TYPE_NONE);
1647             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1648             waiter.prepare(ACTION_START_FGS_RESULT);
1649             runWithShellPermissionIdentity(() -> {
1650                 mContext.getSystemService(PowerExemptionManager.class).addToTemporaryAllowList(
1651                         PACKAGE_NAME_APP1, PowerExemptionManager.REASON_PUSH_MESSAGING_OVER_QUOTA,
1652                         "", TEMP_ALLOWLIST_DURATION_MS);
1653             });
1654             CommandReceiver.sendCommand(mContext,
1655                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1656                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1657             // APP1 does not enter FGS state
1658             try {
1659                 waiter.doWait(WAITFOR_MSEC);
1660                 fail("Service should not enter foreground service state");
1661             } catch (Exception e) {
1662             }
1663 
1664             // Change behavior to TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED.
1665             setPushMessagingOverQuotaBehavior(
1666                     TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED);
1667             runWithShellPermissionIdentity(() -> {
1668                 mContext.getSystemService(PowerExemptionManager.class).addToTemporaryAllowList(
1669                         PACKAGE_NAME_APP1, PowerExemptionManager.REASON_PUSH_MESSAGING_OVER_QUOTA,
1670                         "", TEMP_ALLOWLIST_DURATION_MS);
1671             });
1672             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1673             waiter.prepare(ACTION_START_FGS_RESULT);
1674             // Now it can start FGS.
1675             CommandReceiver.sendCommand(mContext,
1676                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1677                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1678             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1679             waiter.doWait(WAITFOR_MSEC);
1680             // Stop the FGS.
1681             CommandReceiver.sendCommand(mContext,
1682                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
1683                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1684             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
1685         } finally {
1686             uid1Watcher.finish();
1687             // Change back to default behavior.
1688             setPushMessagingOverQuotaBehavior(defaultBehavior);
1689             // allow temp allowlist to expire.
1690             SystemClock.sleep(TEMP_ALLOWLIST_DURATION_MS);
1691         }
1692     }
1693 
1694     /**
1695      * Test temp allowlist reasonCode in BroadcastOptions.
1696      * When REASON_PUSH_MESSAGING_OVER_QUOTA, DeviceIdleController changes temp allowlist type to
1697      * TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED so FGS start is not allowed.
1698      * When REASON_DENIED (-1), DeviceIdleController changes temp allowlist type to
1699      * TEMPORARY_ALLOWLIST_TYPE_NONE, the temp allowlist itself is not allowed.
1700      * All other reason codes, DeviceIdleController does not change temp allowlist type.
1701      */
1702     @Test
testTempAllowListReasonCode()1703     public void testTempAllowListReasonCode() throws Exception {
1704         // FGS start is temp allowed.
1705         testTempAllowListReasonCodeInternal(REASON_PUSH_MESSAGING);
1706         // FGS start is not allowed.
1707         testTempAllowListReasonCodeInternal(REASON_PUSH_MESSAGING_OVER_QUOTA);
1708         // Temp allowlist itself is not allowed. REASON_DENIED is not exposed in
1709         // PowerExemptionManager, just use its value "-1" here.
1710         testTempAllowListReasonCodeInternal(-1);
1711     }
1712 
testTempAllowListReasonCodeInternal(int reasonCode)1713     private void testTempAllowListReasonCodeInternal(int reasonCode) throws Exception {
1714         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1715                 PACKAGE_NAME_APP1, 0);
1716         ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
1717                 PACKAGE_NAME_APP2, 0);
1718         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
1719                 WAITFOR_MSEC);
1720         WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
1721                 WAITFOR_MSEC);
1722         final int defaultBehavior = getPushMessagingOverQuotaBehavior();
1723         try {
1724             setPushMessagingOverQuotaBehavior(
1725                     TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED);
1726             // Enable the FGS background startForeground() restriction.
1727             enableFgsRestriction(true, true, null);
1728             // Now it can start FGS.
1729             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1730             waiter.prepare(ACTION_START_FGS_RESULT);
1731             runWithShellPermissionIdentity(()-> {
1732                 final BroadcastOptions options = BroadcastOptions.makeBasic();
1733                 // setTemporaryAppAllowlist API requires
1734                 // START_FOREGROUND_SERVICES_FROM_BACKGROUND permission.
1735                 options.setTemporaryAppAllowlist(TEMP_ALLOWLIST_DURATION_MS,
1736                         TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, reasonCode,
1737                         "");
1738                 // Must use Shell to issue this command because Shell has
1739                 // START_FOREGROUND_SERVICES_FROM_BACKGROUND permission.
1740                 CommandReceiver.sendCommandWithBroadcastOptions(mContext,
1741                         CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1742                         PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null,
1743                         options.toBundle());
1744             });
1745             if (reasonCode == REASON_PUSH_MESSAGING) {
1746                 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1747                 waiter.doWait(WAITFOR_MSEC);
1748                 // Stop the FGS.
1749                 CommandReceiver.sendCommand(mContext,
1750                         CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
1751                         PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
1752                 uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1753                         WatchUidRunner.STATE_CACHED_EMPTY);
1754             } else if (reasonCode == REASON_PUSH_MESSAGING_OVER_QUOTA) {
1755                 // APP1 does not enter FGS state
1756                 try {
1757                     waiter.doWait(WAITFOR_MSEC);
1758                     fail("Service should not enter foreground service state");
1759                 } catch (Exception e) {
1760                 }
1761             }
1762         } finally {
1763             uid1Watcher.finish();
1764             uid2Watcher.finish();
1765             setPushMessagingOverQuotaBehavior(defaultBehavior);
1766             // Sleep to let the temp allowlist expire so it won't affect next test case.
1767             SystemClock.sleep(TEMP_ALLOWLIST_DURATION_MS);
1768         }
1769     }
1770 
1771     /**
1772      * Test default_input_method is exempted from BG-FGS-start restriction.
1773      * @throws Exception
1774      */
1775     @Test
testFgsStartInputMethod()1776     public void testFgsStartInputMethod() throws Exception {
1777         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1778                 PACKAGE_NAME_APP1, 0);
1779         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
1780                 WAITFOR_MSEC);
1781         final String defaultInputMethod = CtsAppTestUtils.executeShellCmd(mInstrumentation,
1782                 "settings get --user current secure default_input_method");
1783         try {
1784             // Enable the FGS background startForeground() restriction.
1785             enableFgsRestriction(true, true, null);
1786             // Start FGS in BG state.
1787             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1788             waiter.prepare(ACTION_START_FGS_RESULT);
1789             CommandReceiver.sendCommand(mContext,
1790                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1791                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1792             // APP1 does not enter FGS state
1793             try {
1794                 waiter.doWait(WAITFOR_MSEC);
1795                 fail("Service should not enter foreground service state");
1796             } catch (Exception e) {
1797             }
1798 
1799             // Change default_input_method to PACKAGE_NAME_APP1.
1800             final ComponentName cn = new ComponentName(PACKAGE_NAME_APP1, "xxx");
1801             CtsAppTestUtils.executeShellCmd(mInstrumentation,
1802                     "settings put --user current secure default_input_method "
1803                             + cn.flattenToShortString());
1804 
1805             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1806             waiter.prepare(ACTION_START_FGS_RESULT);
1807             // Now it can start FGS.
1808             CommandReceiver.sendCommand(mContext,
1809                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1810                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1811             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
1812             waiter.doWait(WAITFOR_MSEC);
1813             // Stop the FGS.
1814             CommandReceiver.sendCommand(mContext,
1815                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
1816                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1817             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
1818         } finally {
1819             uid1Watcher.finish();
1820             CtsAppTestUtils.executeShellCmd(mInstrumentation,
1821                     "settings put --user current secure default_input_method "
1822                             + defaultInputMethod);
1823         }
1824     }
1825 
1826     @Test
testFgsStartInBackgroundRestrictions()1827     public void testFgsStartInBackgroundRestrictions() throws Exception {
1828         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1829                 PACKAGE_NAME_APP1, 0);
1830         ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
1831                 PACKAGE_NAME_APP2, 0);
1832         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
1833                 WAITFOR_MSEC);
1834         WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
1835                 WAITFOR_MSEC);
1836         WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1837         final String dumpCommand = "dumpsys activity services " + PACKAGE_NAME_APP2
1838                 + "/android.app.stubs.LocalForegroundService";
1839         final long shortWaitMsec = 5_000;
1840         try {
1841             // Enable the FGS background startForeground() restriction.
1842             enableFgsRestriction(true, true, null);
1843 
1844             // Set background restriction for APP2
1845             setAppOp(PACKAGE_NAME_APP2, "RUN_ANY_IN_BACKGROUND", false);
1846 
1847             // Start the APP1 into the TOP state.
1848             allowBgActivityStart(PACKAGE_NAME_APP1, true);
1849             CommandReceiver.sendCommand(mContext,
1850                     CommandReceiver.COMMAND_START_ACTIVITY,
1851                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1852             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1853                     WatchUidRunner.STATE_TOP);
1854 
1855             // APP1 binds to APP2.
1856             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
1857                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, Context.BIND_INCLUDE_CAPABILITIES, null);
1858 
1859             // APP2 gets proc state BOUND_TOP.
1860             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1861                     WatchUidRunner.STATE_BOUND_TOP);
1862 
1863             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1864             waiter.prepare(ACTION_START_FGS_RESULT);
1865 
1866             // START FGS in APP2.
1867             CommandReceiver.sendCommand(mContext,
1868                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1869                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null);
1870             waiter.doWait(WAITFOR_MSEC);
1871 
1872             SystemClock.sleep(shortWaitMsec);
1873 
1874             String[] dumpLines = CtsAppTestUtils.executeShellCmd(
1875                     mInstrumentation, dumpCommand).split("\n");
1876             assertNotNull(findLine(dumpLines, "isForeground=true"));
1877 
1878             // Finish the activity in APP1
1879             CommandReceiver.sendCommand(mContext,
1880                     CommandReceiver.COMMAND_STOP_ACTIVITY,
1881                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1882             mInstrumentation.getUiAutomation().performGlobalAction(
1883                     AccessibilityService.GLOBAL_ACTION_HOME);
1884 
1885             // APP1 should have been cached state now.
1886             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1887                     WatchUidRunner.STATE_CACHED_EMPTY);
1888 
1889             // Th FGS in APP2 should have been normal service state now.
1890             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1891                     WatchUidRunner.STATE_SERVICE);
1892 
1893             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1894             waiter.prepare(ACTION_START_FGS_RESULT);
1895 
1896             // START FGS in APP1
1897             CommandReceiver.sendCommand(mContext,
1898                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1899                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1900             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1901                     WatchUidRunner.STATE_FG_SERVICE);
1902             waiter.doWait(WAITFOR_MSEC);
1903 
1904             // APP2 should be in FGS state too now.
1905             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1906                     WatchUidRunner.STATE_FG_SERVICE);
1907 
1908             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1909             waiter.prepare(ACTION_START_FGS_RESULT);
1910 
1911             // START FGS in APP2.
1912             CommandReceiver.sendCommand(mContext,
1913                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1914                     PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null);
1915             waiter.doWait(WAITFOR_MSEC);
1916 
1917             SystemClock.sleep(shortWaitMsec);
1918 
1919             dumpLines = CtsAppTestUtils.executeShellCmd(
1920                     mInstrumentation, dumpCommand).split("\n");
1921             assertNotNull(findLine(dumpLines, "isForeground=true"));
1922 
1923             // Set background restriction for APP1.
1924             setAppOp(PACKAGE_NAME_APP1, "RUN_ANY_IN_BACKGROUND", false);
1925 
1926             // Both of them should have normal service state now.
1927             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1928                     WatchUidRunner.STATE_SERVICE);
1929             uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
1930                     WatchUidRunner.STATE_SERVICE);
1931         } finally {
1932             uid1Watcher.finish();
1933             uid2Watcher.finish();
1934             CtsAppTestUtils.executeShellCmd(mInstrumentation,
1935                     "appops reset " + PACKAGE_NAME_APP1);
1936             CtsAppTestUtils.executeShellCmd(mInstrumentation,
1937                     "appops reset " + PACKAGE_NAME_APP2);
1938         }
1939     }
1940 
1941     /**
1942      * Find a line containing {@code label} in {@code lines}.
1943      */
findLine(String[] lines, CharSequence label)1944     private String findLine(String[] lines, CharSequence label) {
1945         for (String line: lines) {
1946             if (line.contains(label)) {
1947                 return line;
1948             }
1949         }
1950         return null;
1951     }
1952 
1953     /**
1954      * When PowerExemptionManager.addToTemporaryAllowList() is called more than one time, the second
1955      * call can extend the duration of the first call if the first call has not expired yet.
1956      * @throws Exception
1957      */
1958     @Test
testOverlappedTempAllowList()1959     public void testOverlappedTempAllowList() throws Exception {
1960         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
1961                 PACKAGE_NAME_APP1, 0);
1962         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
1963                 WAITFOR_MSEC);
1964         try {
1965             // Enable the FGS background startForeground() restriction.
1966             enableFgsRestriction(true, true, null);
1967             // Start FGS in BG state.
1968             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1969             waiter.prepare(ACTION_START_FGS_RESULT);
1970             CommandReceiver.sendCommand(mContext,
1971                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
1972                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
1973             // APP1 does not enter FGS state
1974             try {
1975                 waiter.doWait(WAITFOR_MSEC);
1976                 fail("Service should not enter foreground service state");
1977             } catch (Exception e) {
1978             }
1979 
1980             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1981             waiter.prepare(ACTION_START_FGS_RESULT);
1982             runWithShellPermissionIdentity(() -> {
1983                 mContext.getSystemService(PowerExemptionManager.class).addToTemporaryAllowList(
1984                         PACKAGE_NAME_APP1, PowerExemptionManager.REASON_PUSH_MESSAGING,
1985                         "", 10000);
1986             });
1987 
1988             SystemClock.sleep(5000);
1989             runWithShellPermissionIdentity(() -> {
1990                 mContext.getSystemService(PowerExemptionManager.class).addToTemporaryAllowList(
1991                         PACKAGE_NAME_APP1, PowerExemptionManager.REASON_PUSH_MESSAGING,
1992                         "", 10000);
1993             });
1994             SystemClock.sleep(5000);
1995 
1996             // The first addToTemporaryAllowList()'s 10000ms duration has expired.
1997             // Now FGS start is allowed by second addToTemporaryAllowList()'s 10000ms duration.
1998             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
1999             waiter.prepare(ACTION_START_FGS_RESULT);
2000             // Now it can start FGS.
2001             CommandReceiver.sendCommand(mContext,
2002                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
2003                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
2004             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
2005             waiter.doWait(WAITFOR_MSEC);
2006             // Stop the FGS.
2007             CommandReceiver.sendCommand(mContext,
2008                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
2009                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
2010             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
2011         } finally {
2012             uid1Watcher.finish();
2013             // allow temp allowlist to expire.
2014             SystemClock.sleep(5000);
2015         }
2016     }
2017 
2018     /**
2019      * IActivityManager.startService() is called directly (does not go through
2020      * {@link Context#startForegroundService(Intent)}, a spoofed packageName "com.google.android.as"
2021      * is used as callingPackage. Although "com.google.android.as" is allowlisted to start
2022      * foreground service from the background, but framework will detect this is a spoofed
2023      * packageName and disallow foreground service start from the background.
2024      * @throws Exception
2025      */
2026     @Test
testSpoofPackageName()2027     public void testSpoofPackageName() throws Exception {
2028         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
2029                 PACKAGE_NAME_APP1, 0);
2030         WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
2031                 WAITFOR_MSEC);
2032         // CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_SPOOF_PACKAGE_NAME needs access
2033         // to hidden API PackageManager.getAttentionServicePackageName() and
2034         // PackageManager.getSystemCaptionsServicePackageName(), so we need to call
2035         // hddenApiSettings.set("*") to exempt the hidden APIs.
2036         SettingsSession<String> hiddenApiSettings = new SettingsSession<>(
2037                 Settings.Global.getUriFor(
2038                         Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS),
2039                 Settings.Global::getString, Settings.Global::putString);
2040         hiddenApiSettings.set("*");
2041         try {
2042             // Enable the FGS background startForeground() restriction.
2043             enableFgsRestriction(true, true, null);
2044             // Start FGS in BG state.
2045             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
2046             waiter.prepare(ACTION_START_FGS_RESULT);
2047             CommandReceiver.sendCommand(mContext,
2048                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_SPOOF_PACKAGE_NAME,
2049                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
2050             // APP1 does not enter FGS state
2051             try {
2052                 waiter.doWait(WAITFOR_MSEC);
2053                 fail("Service should not enter foreground service state");
2054             } catch (Exception e) {
2055             }
2056         } finally {
2057             uid1Watcher.finish();
2058             if (hiddenApiSettings != null) {
2059                 hiddenApiSettings.close();
2060             }
2061         }
2062     }
2063 
2064     /**
2065      * Turn on the FGS BG-launch restriction. DeviceConfig can turn on restriction on the whole
2066      * device (across all apps). AppCompat can turn on restriction on a single app package.
2067      * @param enable true to turn on restriction, false to turn off.
2068      * @param useDeviceConfig true to use DeviceConfig, false to use AppCompat CHANGE ID.
2069      * @param packageName the packageName if using AppCompat CHANGE ID.
2070      * @throws Exception
2071      */
enableFgsRestriction(boolean enable, boolean useDeviceConfig, String packageName)2072     private void enableFgsRestriction(boolean enable, boolean useDeviceConfig, String packageName)
2073             throws Exception {
2074         if (useDeviceConfig) {
2075             runWithShellPermissionIdentity(() -> {
2076                         DeviceConfig.setProperty("activity_manager",
2077                                 KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED,
2078                                 Boolean.toString(enable), false);
2079                     }
2080             );
2081         } else {
2082             CtsAppTestUtils.executeShellCmd(mInstrumentation,
2083                     "am compat " + (enable ? "enable" : "disable")
2084                             + " FGS_BG_START_RESTRICTION_CHANGE_ID " + packageName);
2085         }
2086     }
2087 
2088     /**
2089      * Clean up the FGS BG-launch restriction.
2090      * @param packageName the packageName that will have its changeid override reset.
2091      * @throws Exception
2092      */
resetFgsRestriction(String packageName)2093     private void resetFgsRestriction(String packageName)
2094             throws Exception {
2095         CtsAppTestUtils.executeShellCmd(mInstrumentation,
2096                 "am compat reset FGS_BG_START_RESTRICTION_CHANGE_ID " + packageName);
2097     }
2098 
2099     /**
2100      * SYSTEM_ALERT_WINDOW permission will allow both BG-activity start and BG-FGS start.
2101      * Some cases we want to grant this permission to allow activity start to bring the app up to
2102      * TOP state.
2103      * Some cases we want to revoke this permission to test other BG-FGS-launch exemptions.
2104      * @param packageName
2105      * @param allow
2106      * @throws Exception
2107      */
allowBgActivityStart(String packageName, boolean allow)2108     private void allowBgActivityStart(String packageName, boolean allow) throws Exception {
2109         if (allow) {
2110             PermissionUtils.grantPermission(
2111                     packageName, android.Manifest.permission.SYSTEM_ALERT_WINDOW);
2112         } else {
2113             PermissionUtils.revokePermission(
2114                     packageName, android.Manifest.permission.SYSTEM_ALERT_WINDOW);
2115         }
2116     }
2117 
setFgsStartForegroundTimeout(int timeoutMs)2118     private void setFgsStartForegroundTimeout(int timeoutMs) throws Exception {
2119         runWithShellPermissionIdentity(() -> {
2120                     DeviceConfig.setProperty("activity_manager",
2121                             KEY_FGS_START_FOREGROUND_TIMEOUT,
2122                             Integer.toString(timeoutMs), false);
2123                 }
2124         );
2125     }
2126 
setAppOp(String packageName, String opStr, boolean allow)2127     private void setAppOp(String packageName, String opStr, boolean allow) throws Exception {
2128         CtsAppTestUtils.executeShellCmd(mInstrumentation,
2129                 "appops set " + packageName + " " + opStr + " "
2130                         + (allow ? "allow" : "deny"));
2131     }
2132 
setPushMessagingOverQuotaBehavior( int type)2133     private void setPushMessagingOverQuotaBehavior(
2134             /* @PowerExemptionManager.TempAllowListType */ int type) throws Exception {
2135         runWithShellPermissionIdentity(() -> {
2136                     DeviceConfig.setProperty("activity_manager",
2137                             KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR,
2138                             Integer.toString(type), false);
2139                 }
2140         );
2141         // Sleep 2 seconds to allow the device config change to be applied.
2142         SystemClock.sleep(2000);
2143     }
2144 
getPushMessagingOverQuotaBehavior()2145     private int getPushMessagingOverQuotaBehavior() throws Exception {
2146         final String defaultBehaviorStr = CtsAppTestUtils.executeShellCmd(mInstrumentation,
2147                 "device_config get activity_manager "
2148                         + KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR).trim();
2149         int defaultBehavior = TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
2150         if (!defaultBehaviorStr.equals("null")) {
2151             try {
2152                 defaultBehavior = Integer.parseInt(defaultBehaviorStr);
2153             } catch (NumberFormatException e) {
2154                 Log.e("ActivityManagerFgsBgStartTest",
2155                         "getPushMessagingOverQuotaBehavior:", e);
2156             }
2157         }
2158         return defaultBehavior;
2159     }
2160 }
2161