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