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