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