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.server.wm;
18 
19 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
20 import static android.app.AppOpsManager.MODE_ALLOWED;
21 import static android.app.AppOpsManager.MODE_ERRORED;
22 import static android.server.wm.BuildUtils.HW_TIMEOUT_MULTIPLIER;
23 import static android.server.wm.ShellCommandHelper.executeShellCommand;
24 import static android.server.wm.UiDeviceUtils.pressHomeButton;
25 import static android.server.wm.backgroundactivity.common.CommonComponents.EVENT_NOTIFIER_EXTRA;
26 import static android.view.Display.DEFAULT_DISPLAY;
27 
28 import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
29 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
30 
31 import static com.google.common.truth.Truth.assertThat;
32 import static com.google.common.truth.Truth.assertWithMessage;
33 import static com.google.common.truth.TruthJUnit.assume;
34 
35 import android.Manifest;
36 import android.app.ActivityOptions;
37 import android.app.BroadcastOptions;
38 import android.app.PendingIntent;
39 import android.app.RemoteAction;
40 import android.app.UiAutomation;
41 import android.appwidget.AppWidgetHost;
42 import android.appwidget.AppWidgetManager;
43 import android.content.ComponentName;
44 import android.content.Context;
45 import android.content.Intent;
46 import android.content.pm.PackageManager;
47 import android.content.pm.ResolveInfo;
48 import android.content.pm.UserInfo;
49 import android.graphics.Bitmap;
50 import android.graphics.drawable.Icon;
51 import android.os.Bundle;
52 import android.os.RemoteException;
53 import android.os.ResultReceiver;
54 import android.os.SystemClock;
55 import android.os.UserHandle;
56 import android.os.UserManager;
57 import android.platform.test.annotations.AsbSecurityTest;
58 import android.platform.test.annotations.Presubmit;
59 import android.platform.test.annotations.RequiresFlagsDisabled;
60 import android.platform.test.annotations.RequiresFlagsEnabled;
61 import android.platform.test.flag.junit.CheckFlagsRule;
62 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
63 import android.provider.Settings;
64 import android.server.wm.backgroundactivity.appa.Components;
65 import android.server.wm.backgroundactivity.common.CommonComponents.Event;
66 import android.server.wm.backgroundactivity.common.EventReceiver;
67 import android.util.Log;
68 import android.view.textclassifier.TextClassification;
69 
70 import androidx.test.filters.FlakyTest;
71 import androidx.test.platform.app.InstrumentationRegistry;
72 import androidx.test.uiautomator.By;
73 import androidx.test.uiautomator.BySelector;
74 import androidx.test.uiautomator.UiDevice;
75 import androidx.test.uiautomator.UiObject2;
76 import androidx.test.uiautomator.Until;
77 
78 import com.android.bedstead.harrier.BedsteadJUnit4;
79 import com.android.bedstead.harrier.DeviceState;
80 import com.android.bedstead.harrier.annotations.RequireDoesNotHaveFeature;
81 import com.android.bedstead.harrier.annotations.RequireFeature;
82 import com.android.compatibility.common.util.AppOpsUtils;
83 import com.android.modules.utils.build.SdkLevel;
84 import com.android.window.flags.Flags;
85 
86 import org.junit.ClassRule;
87 import org.junit.Ignore;
88 import org.junit.Rule;
89 import org.junit.Test;
90 import org.junit.runner.RunWith;
91 
92 import java.util.List;
93 import java.util.concurrent.TimeoutException;
94 
95 /**
96  * This class covers all test cases for starting/blocking background activities.
97  * As instrumentation tests started by shell are allowlisted to allow starting background activity,
98  * tests can't be done in this app alone.
99  * Hence, there are 2 extra apps, appA and appB. This class will send commands to appA/appB, for
100  * example, send a broadcast to appA and ask it to start a background activity, and we will monitor
101  * the result and see if it starts an activity successfully.
102  */
103 @Presubmit
104 @RunWith(BedsteadJUnit4.class)
105 public class BackgroundActivityLaunchTest extends BackgroundActivityTestBase {
106 
107     @Rule
108     public final CheckFlagsRule mCheckFlagsRule =
109             DeviceFlagsValueProvider.createCheckFlagsRule();
110 
111     @ClassRule
112     @Rule
113     public static final DeviceState sDeviceState = new DeviceState();
114 
115     private static final String TAG = "BackgroundActivityLaunchTest";
116 
117     private static final Icon EMPTY_ICON = Icon.createWithBitmap(
118             Bitmap.createBitmap(8, 8, Bitmap.Config.ARGB_8888));
119 
120     private static final long ACTIVITY_BG_START_GRACE_PERIOD_MS = 10 * 1000;
121     private static final int ACTIVITY_START_TIMEOUT_MS = 5000;
122     private static final int ACTIVITY_NOT_RESUMED_TIMEOUT_MS = 5000;
123 
124     /**
125      * Tests can be executed as soon as the device has booted. When that happens the broadcast queue
126      * is long and it takes some time to process the broadcast we just sent.
127      */
128     private static final int BROADCAST_DELIVERY_TIMEOUT_MS = 60000;
129     public static final Bundle SEND_OPTIONS_ALLOW_BAL = ActivityOptions.makeBasic()
130             .setPendingIntentBackgroundActivityStartMode(
131                     ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED).toBundle();
132     public static final Bundle SEND_BROADCAST_OPTIONS_ALLOW_BAL = BroadcastOptions.makeBasic()
133             .setPendingIntentBackgroundActivityStartMode(
134                     ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED).toBundle();
135     public static final Bundle CREATE_OPTIONS_DENY_BAL =
136             ActivityOptions.makeBasic().setPendingIntentCreatorBackgroundActivityStartMode(
137                     ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED).toBundle();
138     public static final Bundle CREATE_OPTIONS_ALLOW_BAL =
139             ActivityOptions.makeBasic().setPendingIntentCreatorBackgroundActivityStartMode(
140                     ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED).toBundle();
141 
142     @Test
testBackgroundActivityBlocked()143     public void testBackgroundActivityBlocked() throws Exception {
144         // Start AppA background activity and blocked
145         sendBroadcastAndWait(APP_A.SIMPLE_BROADCAST_RECEIVER);
146         startBackgroundActivity(APP_A);
147         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
148         assertTaskStackIsEmpty(APP_A.BACKGROUND_ACTIVITY);
149     }
150 
151     @Test
testBackgroundActivityBlockedInStartNextMatchingActivity()152     public void testBackgroundActivityBlockedInStartNextMatchingActivity() throws TimeoutException {
153         EventReceiver receiver = new EventReceiver(
154                 Event.APP_A_LAUNCHER_MOVING_TO_BACKGROUND_ACTIVITY);
155         Intent intent = new Intent("StartNextMatchingActivityAction");
156         intent.setComponent(APP_A.START_NEXT_MATCHING_ACTIVITY);
157         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
158         intent.putExtra(EVENT_NOTIFIER_EXTRA, receiver.getNotifier());
159         mContext.startActivity(intent);
160         receiver.waitForEventOrThrow(ACTIVITY_START_TIMEOUT_MS);
161         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
162     }
163 
164     @Test
testStartBgActivity_usingStartActivitiesFromBackgroundPermission()165     public void testStartBgActivity_usingStartActivitiesFromBackgroundPermission()
166             throws Exception {
167         // Disable SAW app op for shell, since that can also allow starting activities from bg.
168         grantSystemAlertWindow(SHELL_PACKAGE, false);
169 
170         // Launch the activity via a shell command, this way the system doesn't have info on which
171         // app launched the activity and thus won't use instrumentation privileges to launch it. But
172         // the shell has the START_ACTIVITIES_FROM_BACKGROUND permission, so we expect it to
173         // succeed.
174         // See testBackgroundActivityBlocked() for a case where an app without the
175         // START_ACTIVITIES_FROM_BACKGROUND permission is blocked from launching the activity from
176         // the background.
177         launchActivity(APP_A.BACKGROUND_ACTIVITY);
178 
179         // If the activity launches, it means the START_ACTIVITIES_FROM_BACKGROUND permission works.
180         assertWithMessage("Launched activity should be at the top")
181                 .that(mWmState.getTopActivityName(0))
182                 .isEqualTo(ComponentNameUtils.getActivityName(APP_A.BACKGROUND_ACTIVITY));
183     }
184 
185     @Test
testBackgroundActivity_withinGracePeriodAndSdk33_isNotBlocked()186     public void testBackgroundActivity_withinGracePeriodAndSdk33_isNotBlocked() throws Exception {
187         // Start AppA foreground activity
188         startActivity(APP_A_33.FOREGROUND_ACTIVITY);
189         // Don't press home button to avoid stop app switches
190         mContext.sendBroadcast(new Intent(APP_A_33.FOREGROUND_ACTIVITY_ACTIONS.FINISH_ACTIVITY));
191         mWmState.waitAndAssertActivityRemoved(APP_A_33.FOREGROUND_ACTIVITY);
192         startBackgroundActivity(APP_A_33);
193         assertActivityFocused(APP_A_33.BACKGROUND_ACTIVITY);
194     }
195 
196     @Test
testBackgroundActivity_withinASMGracePeriod_isBlocked()197     public void testBackgroundActivity_withinASMGracePeriod_isBlocked() throws Exception {
198         assumeSdkNewerThanUpsideDownCake();
199         // Start AppA foreground activity
200         startActivity(APP_A.FOREGROUND_ACTIVITY);
201         // Don't press home button to avoid stop app switches
202         mContext.sendBroadcast(new Intent(APP_A.FOREGROUND_ACTIVITY_ACTIONS.FINISH_ACTIVITY));
203         mWmState.waitAndAssertActivityRemoved(APP_A.FOREGROUND_ACTIVITY);
204         startBackgroundActivity(APP_A);
205         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
206     }
207 
208     @Test
209     @FlakyTest(bugId = 297339382)
testBackgroundActivity_withinBalAfterAsmGracePeriod_isBlocked()210     public void testBackgroundActivity_withinBalAfterAsmGracePeriod_isBlocked()
211             throws Exception {
212         assumeSdkNewerThanUpsideDownCake();
213         // Start AppA foreground activity
214         startActivity(APP_A.FOREGROUND_ACTIVITY);
215         // Don't press home button to avoid stop app switches
216         mContext.sendBroadcast(new Intent(APP_A.FOREGROUND_ACTIVITY_ACTIONS.FINISH_ACTIVITY));
217         mWmState.waitAndAssertActivityRemoved(APP_A.FOREGROUND_ACTIVITY);
218         Thread.sleep(1000 * 5);
219         startBackgroundActivity(APP_A);
220         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
221     }
222 
223     @Test
testBackgroundActivityWhenSystemAlertWindowGranted_isNotBlocked()224     public void testBackgroundActivityWhenSystemAlertWindowGranted_isNotBlocked()
225             throws Exception {
226         grantSystemAlertWindow(APP_A_33);
227 
228         // Start AppA background activity successfully as the package has SAW
229         startBackgroundActivity(APP_A_33);
230         assertActivityFocused(APP_A_33.BACKGROUND_ACTIVITY);
231     }
232 
233     @Test
testBackgroundActivityBlockedWhenForegroundActivityNotTop()234     public void testBackgroundActivityBlockedWhenForegroundActivityNotTop() throws Exception {
235         assumeSdkNewerThanUpsideDownCake();
236 
237         startActivity(APP_A.FOREGROUND_ACTIVITY);
238         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A, APP_B.FOREGROUND_ACTIVITY));
239         mWmState.waitForValidState(APP_B.FOREGROUND_ACTIVITY);
240         mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
241         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
242                 APP_B.FOREGROUND_ACTIVITY,
243                 APP_A.FOREGROUND_ACTIVITY);
244 
245         // Start AppA background activity fails as AppA not on top of stack
246         startBackgroundActivity(APP_A);
247         mWmState.waitForValidState(APP_A.BACKGROUND_ACTIVITY);
248         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
249                 APP_B.FOREGROUND_ACTIVITY,
250                 APP_A.FOREGROUND_ACTIVITY);
251         assertTaskStackIsEmpty(APP_A.BACKGROUND_ACTIVITY);
252     }
253 
254     @Test
testBackgroundActivityNotBlockedWhenForegroundActivityTop()255     public void testBackgroundActivityNotBlockedWhenForegroundActivityTop() throws Exception {
256         startActivity(APP_A.FOREGROUND_ACTIVITY);
257         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
258 
259         // Start AppA background activity successfully in new task as there's a foreground activity
260         startBackgroundActivity(APP_A);
261         mWmState.waitForValidState(APP_A.BACKGROUND_ACTIVITY);
262         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
263         assertTaskStackHasComponents(APP_A.BACKGROUND_ACTIVITY, APP_A.BACKGROUND_ACTIVITY);
264     }
265 
266     @Test
testBackgroundActivityWhenForegroundActivityNotTopUsingSdk33_IsNotBlocked()267     public void testBackgroundActivityWhenForegroundActivityNotTopUsingSdk33_IsNotBlocked()
268             throws Exception {
269         startActivity(APP_A_33.FOREGROUND_ACTIVITY);
270         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A_33, APP_B.FOREGROUND_ACTIVITY));
271         mWmState.waitForValidState(APP_B.FOREGROUND_ACTIVITY);
272         assertTaskStackHasComponents(APP_A_33.FOREGROUND_ACTIVITY,
273                         APP_B.FOREGROUND_ACTIVITY,
274                         APP_A_33.FOREGROUND_ACTIVITY);
275 
276         // Start AppA background activity successfully as there's a foreground activity
277         startBackgroundActivity(APP_A_33);
278         mWmState.waitForValidState(APP_A_33.BACKGROUND_ACTIVITY);
279         assertTaskStackHasComponents(APP_A_33.FOREGROUND_ACTIVITY,
280                 APP_B.FOREGROUND_ACTIVITY,
281                 APP_A_33.FOREGROUND_ACTIVITY);
282         assertTaskStackHasComponents(APP_A_33.BACKGROUND_ACTIVITY, APP_A_33.BACKGROUND_ACTIVITY);
283     }
284 
285     @Test
testActivityNotBlockedWhenForegroundActivityLaunch()286     public void testActivityNotBlockedWhenForegroundActivityLaunch() throws Exception {
287         // Start foreground activity, and foreground activity able to launch background activity
288         // successfully
289         startActivity(APP_A.FOREGROUND_ACTIVITY);
290 
291         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A, APP_A.BACKGROUND_ACTIVITY));
292         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
293 
294         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
295                 APP_A.BACKGROUND_ACTIVITY,
296                 APP_A.FOREGROUND_ACTIVITY);
297     }
298 
299     @Test
testActivityBroughtToTopOfTaskWhenLaunchedInTheBackground()300     public void testActivityBroughtToTopOfTaskWhenLaunchedInTheBackground() throws Exception {
301         // Start foreground activity, and foreground activity able to launch background activity
302         // successfully
303         startActivity(APP_A.FOREGROUND_ACTIVITY);
304         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
305         // We can't resume app switching after pressing home button, otherwise the grace period
306         // will allow the starts.
307         pressHomeAndWaitHomeResumed();
308 
309         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A, APP_A.BACKGROUND_ACTIVITY));
310 
311         assertActivityNotFocused(APP_A.FOREGROUND_ACTIVITY);
312         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
313         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
314                 APP_A.BACKGROUND_ACTIVITY,
315                 APP_A.FOREGROUND_ACTIVITY);
316     }
317 
318     @Test
testActivityBlockedFromBgActivityInFgTask()319     public void testActivityBlockedFromBgActivityInFgTask() {
320         assumeSdkNewerThanUpsideDownCake();
321         // Launch Activity A, B in the same task with different processes.
322         startActivity(APP_A.FOREGROUND_ACTIVITY);
323         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A, APP_B.FOREGROUND_ACTIVITY));
324         mWmState.waitForValidState(APP_B.FOREGROUND_ACTIVITY);
325         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
326                 APP_B.FOREGROUND_ACTIVITY,
327                 APP_A.FOREGROUND_ACTIVITY);
328 
329         // Refresh last-stop-app-switch-time by returning to home and then make the task foreground.
330         pressHomeAndResumeAppSwitch();
331         startActivityUnchecked(APP_A.FOREGROUND_ACTIVITY);
332         mWmState.waitForValidState(APP_B.FOREGROUND_ACTIVITY);
333         // As A is not visible, it can not start activities.
334         mContext.sendBroadcast(new Intent(
335                 APP_A.FOREGROUND_ACTIVITY_ACTIONS.LAUNCH_BACKGROUND_ACTIVITIES)
336                 .putExtra(APP_A.FOREGROUND_ACTIVITY_EXTRA.LAUNCH_INTENTS,
337                         new Intent[]{ new Intent()
338                                 .setComponent(APP_A.BACKGROUND_ACTIVITY)
339                                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }));
340         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
341         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
342                 APP_B.FOREGROUND_ACTIVITY,
343                 APP_A.FOREGROUND_ACTIVITY);
344     }
345 
346     @Test
testActivityFromBgActivityInFgTaskSdk33_isNotBlocked()347     public void testActivityFromBgActivityInFgTaskSdk33_isNotBlocked() {
348         // Launch Activity A, B in the same task with different processes.
349         startActivity(APP_A_33.FOREGROUND_ACTIVITY);
350         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A_33, APP_B.FOREGROUND_ACTIVITY));
351         mWmState.waitForValidState(APP_B.FOREGROUND_ACTIVITY);
352         assertTaskStackHasComponents(APP_A_33.FOREGROUND_ACTIVITY,
353                 APP_B.FOREGROUND_ACTIVITY,
354                 APP_A_33.FOREGROUND_ACTIVITY);
355 
356         // Refresh last-stop-app-switch-time by returning to home and then make the task foreground.
357         pressHomeAndResumeAppSwitch();
358         startActivityUnchecked(APP_A_33.FOREGROUND_ACTIVITY);
359         mWmState.waitForValidState(APP_B.FOREGROUND_ACTIVITY);
360         // Though process A is in background, it is in a visible Task (top is B) so it should be
361         // able to start activity successfully.
362         mContext.sendBroadcast(new Intent(
363                 APP_A_33.FOREGROUND_ACTIVITY_ACTIONS.LAUNCH_BACKGROUND_ACTIVITIES)
364                 .putExtra(APP_A_33.FOREGROUND_ACTIVITY_EXTRA.LAUNCH_INTENTS,
365                         new Intent[]{ new Intent()
366                                 .setComponent(APP_A_33.BACKGROUND_ACTIVITY)
367                                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }));
368         mWmState.waitForValidState(APP_A_33.BACKGROUND_ACTIVITY);
369         mWmState.assertFocusedActivity(
370                 "The background activity must be able to launch from a visible task",
371                 APP_A_33.BACKGROUND_ACTIVITY);
372     }
373 
374     @Test
375     @FlakyTest(bugId = 130800326)
376     @Ignore  // TODO(b/145981637): Make this test work
testActivityBlockedWhenForegroundActivityRestartsItself()377     public void testActivityBlockedWhenForegroundActivityRestartsItself() throws Exception {
378         // Start AppA foreground activity
379         startActivity(APP_A.FOREGROUND_ACTIVITY,
380                 APP_A.FOREGROUND_ACTIVITY_EXTRA.RELAUNCH_FOREGROUND_ACTIVITY_EXTRA);
381         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
382 
383         // The foreground activity will be paused but will attempt to restart itself in onPause()
384         pressHomeAndResumeAppSwitch();
385 
386         assertActivityNotFocused(APP_A.FOREGROUND_ACTIVITY);
387     }
388 
389     @Test
testSecondActivityNotBlockedWhenForegroundActivityLaunch()390     public void testSecondActivityNotBlockedWhenForegroundActivityLaunch() throws Exception {
391         // Start AppA foreground activity, which will immediately launch one activity
392         // and then the second.
393         startActivity(APP_A.FOREGROUND_ACTIVITY);
394 
395         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A, APP_A.BACKGROUND_ACTIVITY));
396         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
397         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A, APP_A.SECOND_BACKGROUND_ACTIVITY));
398         assertActivityFocused(APP_A.SECOND_BACKGROUND_ACTIVITY);
399 
400         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
401                 APP_A.SECOND_BACKGROUND_ACTIVITY,
402                 APP_A.BACKGROUND_ACTIVITY,
403                 APP_A.FOREGROUND_ACTIVITY);
404     }
405 
406     @Test
testSecondActivityBlockedWhenBackgroundActivityLaunch()407     public void testSecondActivityBlockedWhenBackgroundActivityLaunch() throws Exception {
408         startActivity(APP_A.FOREGROUND_ACTIVITY);
409         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
410         // We can't resume app switching after pressing home button, otherwise the grace period
411         // will allow the starts.
412         pressHomeAndWaitHomeResumed();
413 
414         // The activity, now in the background, will attempt to start 2 activities in quick
415         // succession
416         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A,
417                 APP_A.BACKGROUND_ACTIVITY,
418                 APP_A.SECOND_BACKGROUND_ACTIVITY));
419 
420         // There should be 2 activities in the background (not focused) INITIALIZING
421         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
422         assertActivityNotFocused(APP_A.SECOND_BACKGROUND_ACTIVITY);
423         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
424                 APP_A.SECOND_BACKGROUND_ACTIVITY,
425                 APP_A.BACKGROUND_ACTIVITY,
426                 APP_A.FOREGROUND_ACTIVITY);
427     }
428 
429     @Test
testPendingIntentActivityBlocked()430     public void testPendingIntentActivityBlocked() throws Exception {
431         TestServiceClient serviceA = getTestService(APP_A);
432         TestServiceClient serviceB = getTestService(APP_B);
433 
434         // Cannot start activity by pending intent, as both appA and appB are in background
435         PendingIntent pi = generatePendingIntent(serviceA, APP_A.BACKGROUND_ACTIVITY);
436         sendPendingIntent(pi, serviceB);
437         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
438         assertTaskStackIsEmpty(APP_A.BACKGROUND_ACTIVITY);
439     }
440 
441     @Test
testPendingIntentActivity_whenSenderAllowsBal_isNotBlocked()442     public void testPendingIntentActivity_whenSenderAllowsBal_isNotBlocked() throws Exception {
443         // creator (appa) is not privileged
444         grantSystemAlertWindow(APP_A, false);
445         // sender (appb) is privileged, and grants
446         grantSystemAlertWindow(APP_B);
447 
448         startPendingIntentSenderActivity(APP_A, APP_B, /* allowBalBySender */ true);
449         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
450         assertTaskStackHasComponents(APP_A.BACKGROUND_ACTIVITY, APP_A.BACKGROUND_ACTIVITY);
451     }
452 
453     @Test
454     @RequiresFlagsDisabled(Flags.FLAG_BAL_DONT_BRING_EXISTING_BACKGROUND_TASK_STACK_TO_FG)
testPI_onlyCreatorAllowsBALInSameTask_isNotBlocked()455     public void testPI_onlyCreatorAllowsBALInSameTask_isNotBlocked() throws Exception {
456         // creator (appa) is not privileged
457         grantSystemAlertWindow(APP_A, false);
458         // sender (appb) is privileged, and grants
459         grantSystemAlertWindow(APP_B);
460 
461         startActivity(APP_A.FOREGROUND_ACTIVITY);
462 
463         pressHomeAndWaitHomeResumed();
464 
465         TestServiceClient serviceB = getTestService(APP_B);
466         PendingIntent pi = serviceB.generatePendingIntent(APP_B.BACKGROUND_ACTIVITY,
467                 CREATE_OPTIONS_ALLOW_BAL);
468         TestServiceClient serviceA = getTestService(APP_A);
469         // send the pending intent in the same task.
470         serviceA.sendPendingIntentWithActivity(pi, Bundle.EMPTY);
471 
472         assertActivityFocused(APP_B.BACKGROUND_ACTIVITY);
473         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_B.BACKGROUND_ACTIVITY,
474                 APP_A.FOREGROUND_ACTIVITY);
475     }
476 
477     @Test
478     @RequiresFlagsEnabled(Flags.FLAG_BAL_DONT_BRING_EXISTING_BACKGROUND_TASK_STACK_TO_FG)
testPI_onlyCreatorAllowsBALInSameTask_isBlocked()479     public void testPI_onlyCreatorAllowsBALInSameTask_isBlocked() throws Exception {
480         // sender (appa) is not privileged
481         grantSystemAlertWindow(APP_A, false);
482         // creator (appb) is privileged, and grants
483         grantSystemAlertWindow(APP_B);
484 
485         startActivity(APP_A.FOREGROUND_ACTIVITY);
486 
487         pressHomeAndWaitHomeResumed();
488 
489         TestServiceClient serviceB = getTestService(APP_B);
490         PendingIntent pi = serviceB.generatePendingIntent(APP_B.BACKGROUND_ACTIVITY,
491                 CREATE_OPTIONS_ALLOW_BAL);
492         TestServiceClient serviceA = getTestService(APP_A);
493         // send the pending intent in the same task.
494         serviceA.sendPendingIntentWithActivity(pi, Bundle.EMPTY);
495 
496         assertActivityNotFocused(APP_B.BACKGROUND_ACTIVITY);
497     }
498 
499     @Test
500     @RequiresFlagsEnabled(Flags.FLAG_BAL_REQUIRE_OPT_IN_BY_PENDING_INTENT_CREATOR)
501     @RequiresFlagsDisabled(Flags.FLAG_BAL_DONT_BRING_EXISTING_BACKGROUND_TASK_STACK_TO_FG)
testPI_onlyCreatorAllowsBALwithOptIn_isNotBlocked()502     public void testPI_onlyCreatorAllowsBALwithOptIn_isNotBlocked() throws Exception {
503         // sender (appa) is not privileged
504         grantSystemAlertWindow(APP_A, false);
505         // creator (appb) is privileged, and grants
506         grantSystemAlertWindow(APP_B);
507 
508         startActivity(APP_A.FOREGROUND_ACTIVITY);
509 
510         pressHomeAndWaitHomeResumed();
511 
512         TestServiceClient serviceB = getTestService(APP_B);
513         PendingIntent pi = serviceB.generatePendingIntent(APP_B.BACKGROUND_ACTIVITY,
514                 CREATE_OPTIONS_ALLOW_BAL);
515         TestServiceClient serviceA = getTestService(APP_A);
516         serviceA.sendPendingIntentWithActivity(pi, Bundle.EMPTY);
517 
518         assertActivityFocused(APP_B.BACKGROUND_ACTIVITY);
519         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_B.BACKGROUND_ACTIVITY,
520                 APP_A.FOREGROUND_ACTIVITY);
521     }
522 
523     @Test
524     @RequiresFlagsEnabled(Flags.FLAG_BAL_REQUIRE_OPT_IN_BY_PENDING_INTENT_CREATOR)
525     @RequiresFlagsDisabled(Flags.FLAG_BAL_DONT_BRING_EXISTING_BACKGROUND_TASK_STACK_TO_FG)
testPI_onlyCreatorAllowsBALwithoutOptInSdk33_isNotBlocked()526     public void testPI_onlyCreatorAllowsBALwithoutOptInSdk33_isNotBlocked() throws Exception {
527         // A (privileged) creates PI, B (non-privileged) sends PI from BG, C is started
528         grantSystemAlertWindow(APP_A_33);
529         grantSystemAlertWindow(APP_B, false);
530 
531         startActivity(APP_B.FOREGROUND_ACTIVITY);
532 
533         pressHomeAndWaitHomeResumed();
534 
535         TestServiceClient servicePiCreator = getTestService(APP_A_33);
536         PendingIntent pi = servicePiCreator.generatePendingIntent(APP_C.BACKGROUND_ACTIVITY,
537                 CREATE_OPTIONS_ALLOW_BAL);
538         TestServiceClient servicePiSender = getTestService(APP_B);
539         servicePiSender.sendPendingIntentWithActivity(pi, Bundle.EMPTY);
540 
541         assertActivityFocused(APP_C.BACKGROUND_ACTIVITY);
542         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_C.BACKGROUND_ACTIVITY,
543                 APP_B.FOREGROUND_ACTIVITY);
544     }
545 
546     @Test
547     @RequiresFlagsEnabled({Flags.FLAG_BAL_REQUIRE_OPT_IN_BY_PENDING_INTENT_CREATOR,
548             Flags.FLAG_BAL_DONT_BRING_EXISTING_BACKGROUND_TASK_STACK_TO_FG})
testPI_onlyCreatorAllowsBALwithOptIn_isStartedInBackground()549     public void testPI_onlyCreatorAllowsBALwithOptIn_isStartedInBackground() throws Exception {
550         // sender (appa) is not privileged
551         grantSystemAlertWindow(APP_A, false);
552         // creator (appb) is privileged, and grants
553         grantSystemAlertWindow(APP_B);
554 
555         startActivity(APP_A.FOREGROUND_ACTIVITY);
556 
557         pressHomeAndWaitHomeResumed();
558 
559         TestServiceClient serviceB = getTestService(APP_B);
560         PendingIntent pi = serviceB.generatePendingIntent(APP_B.BACKGROUND_ACTIVITY,
561                 CREATE_OPTIONS_ALLOW_BAL);
562         TestServiceClient serviceA = getTestService(APP_A);
563         serviceA.sendPendingIntentWithActivity(pi, Bundle.EMPTY);
564 
565         assertActivityNotFocused(APP_B.BACKGROUND_ACTIVITY);
566         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_B.BACKGROUND_ACTIVITY,
567                 APP_A.FOREGROUND_ACTIVITY);
568     }
569 
570     @Test
testPI_onlySenderAllowsBALwithoutOptInForResult_isNotBlocked()571     public void testPI_onlySenderAllowsBALwithoutOptInForResult_isNotBlocked() throws Exception {
572         startActivity(APP_A.FOREGROUND_ACTIVITY);
573 
574         TestServiceClient serviceB = getTestService(APP_B);
575         PendingIntent pi = serviceB.generatePendingIntent(APP_B.BACKGROUND_ACTIVITY);
576         TestServiceClient serviceA = getTestService(APP_A);
577         // there is no explicit opt-in, but using sendPendingIntentForResult implicitly grants
578         serviceA.sendPendingIntentWithActivityForResult(pi, Bundle.EMPTY);
579 
580         assertActivityFocused(APP_B.BACKGROUND_ACTIVITY);
581         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_B.BACKGROUND_ACTIVITY,
582                 APP_A.FOREGROUND_ACTIVITY);
583     }
584 
585     @Test
586     @RequiresFlagsEnabled(Flags.FLAG_BAL_REQUIRE_OPT_IN_BY_PENDING_INTENT_CREATOR)
testPI_onlyCreatorAllowsBALwithoutOptInForResult_isBlocked()587     public void testPI_onlyCreatorAllowsBALwithoutOptInForResult_isBlocked() throws Exception {
588         // creator (appb) is privileged, and grants
589         grantSystemAlertWindow(APP_B);
590 
591         startActivity(APP_A.FOREGROUND_ACTIVITY);
592         pressHomeAndWaitHomeResumed();
593 
594         TestServiceClient serviceB = getTestService(APP_B);
595         PendingIntent pi = serviceB.generatePendingIntent(APP_B.BACKGROUND_ACTIVITY);
596         TestServiceClient serviceA = getTestService(APP_A);
597         // sendPendingIntentForResult does not opt in the creator of the PI
598         serviceA.sendPendingIntentWithActivityForResult(pi, Bundle.EMPTY);
599 
600         assertActivityNotFocused(APP_B.BACKGROUND_ACTIVITY);
601         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
602     }
603 
604     @Test
605     @RequiresFlagsEnabled(Flags.FLAG_BAL_REQUIRE_OPT_IN_BY_PENDING_INTENT_CREATOR)
testPI_onlySenderAllowsBALwithoutOptInIntentSender_isNotBlocked()606     public void testPI_onlySenderAllowsBALwithoutOptInIntentSender_isNotBlocked() throws Exception {
607         startActivity(APP_A.FOREGROUND_ACTIVITY);
608 
609         TestServiceClient serviceB = getTestService(APP_B);
610         PendingIntent pi = serviceB.generatePendingIntent(APP_B.BACKGROUND_ACTIVITY);
611         TestServiceClient serviceA = getTestService(APP_A);
612         // there is no explicit opt-in, but using IntentSender.sendIntent implicitly grants
613         serviceA.sendIntentSender(pi.getIntentSender(), Bundle.EMPTY);
614 
615         assertActivityFocused(APP_B.BACKGROUND_ACTIVITY);
616         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
617         assertTaskStackHasComponents(APP_B.BACKGROUND_ACTIVITY, APP_B.BACKGROUND_ACTIVITY);
618     }
619 
620     @Test
621     @RequiresFlagsEnabled(Flags.FLAG_BAL_REQUIRE_OPT_IN_BY_PENDING_INTENT_CREATOR)
testPI_onlyCreatorAllowsBALwithoutOptIn_isBlocked()622     public void testPI_onlyCreatorAllowsBALwithoutOptIn_isBlocked() throws Exception {
623         // sender (appa) is not privileged
624         grantSystemAlertWindow(APP_A, false);
625         // creator (appb) is privileged, and grants
626         grantSystemAlertWindow(APP_B);
627 
628         startActivity(APP_A.FOREGROUND_ACTIVITY);
629 
630         pressHomeAndWaitHomeResumed();
631 
632         TestServiceClient serviceB = getTestService(APP_B);
633         PendingIntent pi = serviceB.generatePendingIntent(APP_B.BACKGROUND_ACTIVITY);
634         TestServiceClient serviceA = getTestService(APP_A);
635         serviceA.sendPendingIntentWithActivity(pi, Bundle.EMPTY);
636 
637         assertActivityNotFocused(APP_B.BACKGROUND_ACTIVITY);
638     }
639 
640     @Test
testPendingIntentActivity_whenSenderDoesNotAllowBal_isBlocked()641     public void testPendingIntentActivity_whenSenderDoesNotAllowBal_isBlocked() throws Exception {
642         // creator (appa) is not privileged
643         grantSystemAlertWindow(APP_A, false);
644         // sender (appb) is privileged, but revokes
645         grantSystemAlertWindow(APP_B);
646 
647         startPendingIntentSenderActivity(APP_A, APP_B, /* allowBalBySender */ false);
648 
649         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
650     }
651 
652     @Test
testPI_appAIsForegroundDenyCreatorPrivilege_launchAppB_isBlocked()653     public void testPI_appAIsForegroundDenyCreatorPrivilege_launchAppB_isBlocked()
654             throws Exception {
655         // Start AppA foreground activity
656         startActivity(APP_A.FOREGROUND_ACTIVITY);
657         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
658 
659         // App A create a PendingIntent with ActivityOption that denies PendingIntent sender to use
660         // creator's privilege to launch itself. The PendingIntent itself is to launch App B. Since
661         // App B is in the background, it should be blocked even though the creator (App A) is in
662         // the foreground.
663         TestServiceClient serviceA = getTestService(APP_A);
664         PendingIntent pi = serviceA.generatePendingIntent(APP_B.BACKGROUND_ACTIVITY,
665                 CREATE_OPTIONS_DENY_BAL);
666         TestServiceClient serviceB = getTestService(APP_B);
667         sendPendingIntent(pi, serviceB);
668         assertActivityNotFocused(APP_B.FOREGROUND_ACTIVITY);
669     }
670 
671     @Test
672     @SuppressWarnings("MissingFail") // TODO(b/320664730) expect Exception after V release
testPI_appAIsFgDenyCreatorPrivilege_appBTryOverrideCreatorPrivilege_isBlocked()673     public void testPI_appAIsFgDenyCreatorPrivilege_appBTryOverrideCreatorPrivilege_isBlocked()
674             throws Exception {
675         // Start AppB foreground activity
676         startActivity(APP_A.FOREGROUND_ACTIVITY);
677         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
678 
679         // App A create a PendingIntent with ActivityOption that denies PendingIntent sender to use
680         // creator's privilege to launch itself. The PendingIntent itself is to launch App B.
681         // App B is in the background, it should be blocked even though the creator (App A) is in
682         // the foreground. However, The sender (App B) also tries to override the creator option by
683         // setting the creator option from the sender side. This should not work. Creator option
684         // cannot be set from the sender side.
685         TestServiceClient serviceA = getTestService(APP_A);
686         PendingIntent pi =
687                 serviceA.generatePendingIntent(APP_B.BACKGROUND_ACTIVITY,
688                         CREATE_OPTIONS_DENY_BAL);
689         TestServiceClient serviceB = getTestService(APP_B);
690         try {
691             serviceB.sendPendingIntent(pi, CREATE_OPTIONS_ALLOW_BAL);
692         } catch (IllegalArgumentException e) {
693             assertThat(e).hasMessageThat()
694                     .contains("pendingIntentCreatorBackgroundActivityStartMode");
695             // If sending the PendingIntent failed because we detected a mismatch in the bundle,
696             // the result should be the same as suppressing the start (just earlier).
697         }
698         assertActivityNotFocused(APP_B.FOREGROUND_ACTIVITY);
699     }
700 
701     @Test
702     @RequiresFlagsDisabled(Flags.FLAG_BAL_REQUIRE_OPT_IN_BY_PENDING_INTENT_CREATOR)
testPendingIntentActivity_appAIsForeground_isNotBlocked()703     public void testPendingIntentActivity_appAIsForeground_isNotBlocked() throws Exception {
704         // Start AppA foreground activity
705         Components appA = APP_A;
706         startActivity(appA.FOREGROUND_ACTIVITY);
707         assertTaskStackHasComponents(appA.FOREGROUND_ACTIVITY, appA.FOREGROUND_ACTIVITY);
708 
709         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
710         // activity in App A
711         TestServiceClient serviceA = getTestService(appA);
712         PendingIntent pi = generatePendingIntent(serviceA, appA.BACKGROUND_ACTIVITY);
713         TestServiceClient serviceB = getTestService(APP_B);
714         sendPendingIntent(pi, serviceB);
715 
716         assertActivityFocused(appA.BACKGROUND_ACTIVITY);
717         assertTaskStackHasComponents(appA.FOREGROUND_ACTIVITY, appA.FOREGROUND_ACTIVITY);
718         assertTaskStackHasComponents(appA.BACKGROUND_ACTIVITY, appA.BACKGROUND_ACTIVITY);
719     }
720 
721     @Test
722     @RequiresFlagsEnabled(Flags.FLAG_BAL_REQUIRE_OPT_IN_BY_PENDING_INTENT_CREATOR)
testPendingIntentActivity_appAIsForeground_isBlocked()723     public void testPendingIntentActivity_appAIsForeground_isBlocked() throws Exception {
724         // Start AppA foreground activity
725         Components appA = APP_A;
726         startActivity(appA.FOREGROUND_ACTIVITY);
727         assertTaskStackHasComponents(appA.FOREGROUND_ACTIVITY, appA.FOREGROUND_ACTIVITY);
728 
729         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
730         // activity in App A
731         TestServiceClient serviceA = getTestService(appA);
732         PendingIntent pi = generatePendingIntent(serviceA, appA.BACKGROUND_ACTIVITY);
733         TestServiceClient serviceB = getTestService(APP_B);
734         sendPendingIntent(pi, serviceB);
735 
736         assertActivityNotFocused(appA.BACKGROUND_ACTIVITY);
737     }
738 
739     @Test
testPendingIntentActivity_appA33IsForeground_isNotBlocked()740     public void testPendingIntentActivity_appA33IsForeground_isNotBlocked() throws Exception {
741         // Start AppA foreground activity
742         Components appA = APP_A_33;
743         startActivity(appA.FOREGROUND_ACTIVITY);
744         assertTaskStackHasComponents(appA.FOREGROUND_ACTIVITY, appA.FOREGROUND_ACTIVITY);
745 
746         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
747         // activity in App A
748         TestServiceClient serviceA = getTestService(appA);
749         PendingIntent pi = generatePendingIntent(serviceA, appA.BACKGROUND_ACTIVITY);
750         TestServiceClient serviceB = getTestService(APP_B);
751         sendPendingIntent(pi, serviceB);
752 
753         assertActivityFocused(appA.BACKGROUND_ACTIVITY);
754         assertTaskStackHasComponents(appA.FOREGROUND_ACTIVITY, appA.FOREGROUND_ACTIVITY);
755         assertTaskStackHasComponents(appA.BACKGROUND_ACTIVITY, appA.BACKGROUND_ACTIVITY);
756     }
757 
758     @Test
testPendingIntentBroadcastActivity_appBIsForeground_isBlocked()759     public void testPendingIntentBroadcastActivity_appBIsForeground_isBlocked() throws Exception {
760         // Start AppB foreground activity
761         startActivity(APP_B.FOREGROUND_ACTIVITY);
762         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
763 
764         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
765         // activity in App A
766         TestServiceClient serviceA = getTestService(APP_A);
767         PendingIntent pi = generatePendingIntent(serviceA, APP_A.BACKGROUND_ACTIVITY);
768         TestServiceClient serviceB = getTestService(APP_B);
769         sendPendingIntent(pi, serviceB);
770 
771         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
772         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
773     }
774 
775     @Test
testPendingIntentBroadcastActivity_appBIsForegroundAndSdk33_isNotBlocked()776     public void testPendingIntentBroadcastActivity_appBIsForegroundAndSdk33_isNotBlocked()
777             throws Exception {
778 
779         // setup
780         TestServiceClient appATestService = getTestService(APP_A);
781         TestServiceClient appBTestService = getTestService(APP_B_33);
782 
783         // create PI in appA
784         PendingIntent pi = generatePendingIntent(appATestService, APP_A.BACKGROUND_ACTIVITY);
785 
786         // bring app B to foreground
787         startActivity(APP_B_33.FOREGROUND_ACTIVITY);
788 
789         // pass to appB and send PI
790         appBTestService.sendPendingIntent(pi, null);
791 
792         // assert that start succeeded
793         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
794     }
795 
796     @Test
797     @SuppressWarnings("MissingFail") // TODO(b/320664730) expect Exception after V release
testPendingIntentBroadcastActivity_appBIsForegroundAndTryPassBalOnIntent_isBlocked()798     public void testPendingIntentBroadcastActivity_appBIsForegroundAndTryPassBalOnIntent_isBlocked()
799             throws Exception {
800         // Start AppB foreground activity
801         startActivity(APP_B.FOREGROUND_ACTIVITY);
802         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
803 
804         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
805         // activity in App A.
806         // ALLOW_BAL_EXTRA_ON_PENDING_INTENT will trigger AppA (the creator) to try to allow BAL on
807         // behalf of the sender by adding the BAL option to the Intent's extras, which should have
808         // no effect.
809         TestServiceClient serviceA = getTestService(APP_A);
810         try {
811             PendingIntent pi = serviceA.generatePendingIntent(APP_A.BACKGROUND_ACTIVITY,
812                             SEND_OPTIONS_ALLOW_BAL);
813             TestServiceClient serviceB = getTestService(APP_B);
814             sendPendingIntent(pi, serviceB);
815         } catch (IllegalArgumentException e) {
816             assertThat(e).hasMessageThat().contains("pendingIntentBackgroundActivityStartMode");
817             // If generating the PendingIntent failed because we detected a mismatch in the bundle,
818             // the result should be the same as suppressing the start (just earlier).
819         }
820         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
821         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
822     }
823 
824     @Test
825     @SuppressWarnings("MissingFail") // TODO(b/320664730) expect Exception after V release
testPendingIntentBroadcastActivity_appBIsFgAndTryPassBalOnIntentWithNullBundleOnPendingIntent_isBlocked()826     public void testPendingIntentBroadcastActivity_appBIsFgAndTryPassBalOnIntentWithNullBundleOnPendingIntent_isBlocked()
827             throws Exception {
828         // Start AppB foreground activity
829         startActivity(APP_B.FOREGROUND_ACTIVITY);
830         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
831 
832         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
833         // activity in App A
834         TestServiceClient serviceA = getTestService(APP_A);
835         try {
836             PendingIntent pi = serviceA.generatePendingIntent(APP_A.BACKGROUND_ACTIVITY,
837                     SEND_OPTIONS_ALLOW_BAL);
838             TestServiceClient serviceB = getTestService(APP_B);
839             serviceB.sendPendingIntent(pi, null);
840         } catch (IllegalArgumentException e) {
841             assertThat(e).hasMessageThat().contains("pendingIntentBackgroundActivityStartMode");
842             // If generating the PendingIntent failed because we detected a mismatch in the bundle,
843             // the result should be the same as suppressing the start (just earlier).
844         }
845 
846         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
847         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
848     }
849 
850     @Test
testPendingIntentBroadcastActivity_appBIsForegroundAndAllowsBal_isNotBlocked()851     public void testPendingIntentBroadcastActivity_appBIsForegroundAndAllowsBal_isNotBlocked()
852             throws Exception {
853         // setup
854         TestServiceClient appATestService = getTestService(APP_A);
855         TestServiceClient appBTestService = getTestService(APP_B);
856 
857         // create PI in appA
858         PendingIntent pi = generatePendingIntent(appATestService, APP_A.BACKGROUND_ACTIVITY);
859 
860         // bring app B to foreground
861         startActivity(APP_B.FOREGROUND_ACTIVITY);
862 
863         // pass to appB and send PI
864         appBTestService.sendPendingIntent(pi, SEND_OPTIONS_ALLOW_BAL);
865 
866         // assert that start succeeded
867         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
868     }
869 
870     @Test
testPendingIntentBroadcastTimeout_noDelay_isNotBlocked()871     public void testPendingIntentBroadcastTimeout_noDelay_isNotBlocked() throws Exception {
872         TestServiceClient serviceA = getTestService(APP_A);
873         TestServiceClient serviceB = getTestService(APP_B);
874 
875         // Start AppB foreground activity
876         startActivity(APP_B.FOREGROUND_ACTIVITY);
877         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
878 
879         EventReceiver receiver = new EventReceiver(Event.BROADCAST_RECEIVED);
880         PendingIntent pi = serviceA.generatePendingIntentBroadcast(APP_A.SIMPLE_BROADCAST_RECEIVER,
881                 receiver.getNotifier());
882         // PI broadcast should create token to allow serviceA to start activities later
883         serviceB.sendPendingIntent(pi, SEND_BROADCAST_OPTIONS_ALLOW_BAL);
884         receiver.waitForEventOrThrow(ACTIVITY_START_TIMEOUT_MS);
885 
886         // Grace period is still active.
887         startBackgroundActivity(serviceA, APP_A);
888 
889         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
890         assertTaskStackHasComponents(APP_A.BACKGROUND_ACTIVITY, APP_A.BACKGROUND_ACTIVITY);
891     }
892 
893     @Test
testPendingIntentBroadcastTimeout_delay1s_isNotBlocked()894     public void testPendingIntentBroadcastTimeout_delay1s_isNotBlocked() throws Exception {
895         TestServiceClient serviceA = getTestService(APP_A);
896         TestServiceClient serviceB = getTestService(APP_B);
897 
898         // Start AppB foreground activity
899         startActivity(APP_B.FOREGROUND_ACTIVITY);
900         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
901 
902         EventReceiver receiver = new EventReceiver(Event.BROADCAST_RECEIVED);
903         PendingIntent pi = serviceA.generatePendingIntentBroadcast(APP_A.SIMPLE_BROADCAST_RECEIVER,
904                 receiver.getNotifier());
905         // PI broadcast should create token to allow serviceA to start activities later
906         serviceB.sendPendingIntent(pi, SEND_BROADCAST_OPTIONS_ALLOW_BAL);
907         receiver.waitForEventOrThrow(ACTIVITY_START_TIMEOUT_MS);
908 
909         SystemClock.sleep(1000);
910         // Grace period is still active.
911         startBackgroundActivity(serviceA, APP_A);
912 
913         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
914         assertTaskStackHasComponents(APP_A.BACKGROUND_ACTIVITY, APP_A.BACKGROUND_ACTIVITY);
915     }
916 
917     @Test
testPendingIntentBroadcastTimeout_delay12s_isBlocked()918     public void testPendingIntentBroadcastTimeout_delay12s_isBlocked() throws Exception {
919         // This test is testing that activity start is blocked after broadcast allowlist token
920         // timeout. Before the timeout, the start would be allowed because app B (the PI sender) was
921         // in the foreground during PI send, so app A (the PI creator) would have
922         // (10s * hw_multiplier) to start background activity starts.
923         TestServiceClient serviceA = getTestService(APP_A);
924         TestServiceClient serviceB = getTestService(APP_B);
925 
926         // Start AppB foreground activity
927         startActivity(APP_B.FOREGROUND_ACTIVITY);
928         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
929 
930         EventReceiver receiver = new EventReceiver(Event.BROADCAST_RECEIVED);
931         PendingIntent pi = serviceA.generatePendingIntentBroadcast(APP_A.SIMPLE_BROADCAST_RECEIVER,
932                 receiver.getNotifier());
933         // PI broadcast should create token to allow serviceA to start activities later
934         serviceB.sendPendingIntent(pi, SEND_BROADCAST_OPTIONS_ALLOW_BAL);
935         receiver.waitForEventOrThrow(ACTIVITY_START_TIMEOUT_MS);
936 
937         SystemClock.sleep(12000L * HW_TIMEOUT_MULTIPLIER);
938         // Grace period is expired.
939         startBackgroundActivity(serviceA, APP_A);
940 
941         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
942         assertTaskStackIsEmpty(APP_A.BACKGROUND_ACTIVITY);
943     }
944 
945     @Test
testPendingIntentBroadcast_appBIsBackground_isBlocked()946     public void testPendingIntentBroadcast_appBIsBackground_isBlocked() throws Exception {
947         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
948         // activity in App A. Since AppB is not in foreground and has no other privileges to start
949         // an activity the start should be blocked.
950         TestServiceClient serviceA = getTestService(APP_A);
951         PendingIntent pi = serviceA.generatePendingIntentBroadcast(APP_B.FOREGROUND_ACTIVITY);
952         TestServiceClient serviceB = getTestService(APP_B);
953         serviceB.sendPendingIntent(pi, null);
954 
955         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
956         assertTaskStackIsEmpty(APP_A.BACKGROUND_ACTIVITY);
957     }
958 
959     /**
960      * Returns a list of alive users on the device
961      */
getAliveUsers()962     private List<UserInfo> getAliveUsers() {
963         // Setting the CREATE_USERS permission in AndroidManifest.xml has no effect when the test
964         // is run through the CTS harness, so instead adopt it as a shell permission. We use
965         // the CREATE_USERS permission instead of MANAGE_USERS because the shell can never use
966         // MANAGE_USERS.
967         UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
968         uiAutomation.adoptShellPermissionIdentity(Manifest.permission.CREATE_USERS);
969         List<UserInfo> userList = mContext.getSystemService(UserManager.class).getAliveUsers();
970         uiAutomation.dropShellPermissionIdentity();
971         return userList;
972     }
973 
974     /**
975      * Removes the guest user from the device if present
976      */
removeGuestUser()977     private void removeGuestUser() {
978         List<UserInfo> userList = getAliveUsers();
979         for (UserInfo info : userList) {
980             if (info.isGuest()) {
981                 removeUser(info.id);
982                 // Device is only allowed to have one alive guest user, so stop if it's found
983                 break;
984             }
985         }
986     }
987 
988     /**
989      * Removes a user from the device given their ID
990      */
removeUser(int userId)991     private void removeUser(int userId) {
992         executeShellCommand(String.format("pm remove-user %d", userId));
993     }
994 
995     @Test
testDeviceOwner()996     public void testDeviceOwner() throws Exception {
997         assume().withMessage("Device doesn't support FEATURE_DEVICE_ADMIN")
998                 .that(mContext.getPackageManager()
999                         .hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN))
1000                 .isTrue();
1001 
1002         // Remove existing guest user. The device may already have a guest present if it is
1003         // configured with config_guestUserAutoCreated.
1004         //
1005         // In production flow the DO can only be created before device provisioning finishes
1006         // (e.g. during SUW), and we make sure the guest user in only created after the device
1007         // provision is finished. Ideally this test would use the provisioning flow and Device
1008         // Owner (DO) creation in a similar manner as that of production flow.
1009         removeGuestUser();
1010 
1011         // This test might be running as current user (on devices that use headless system user
1012         // mode), so it needs to get the context for the system user.
1013         Context context = runWithShellPermissionIdentity(
1014                 () -> mContext.createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0),
1015                 INTERACT_ACROSS_USERS);
1016 
1017         String doComponent = APP_A.SIMPLE_ADMIN_RECEIVER.flattenToString();
1018         Log.d(TAG, "Setting DO as " + doComponent);
1019         String cmd = "dpm set-device-owner --user " + UserHandle.USER_SYSTEM + " " + doComponent;
1020         try {
1021             String cmdResult = runShellCommandOrThrow(cmd);
1022             assertWithMessage("Result of '%s'", cmd).that(cmdResult).contains("Success");
1023         } catch (AssertionError e) {
1024             // If failed to set the device owner, stop proceeding to the test case.
1025             // Log the error info so that we can investigate further in the future.
1026             Log.d(TAG, "Failed to set device owner.", e);
1027             String cmdResult = runShellCommandOrThrow("pm list user");
1028             Log.d(TAG, "users: " + cmdResult);
1029             cmdResult = runShellCommandOrThrow("dpm list-owner");
1030             Log.d(TAG, "device owners: " + cmdResult);
1031             assume().withMessage("This test needs to be able to set device owner")
1032                     .fail();
1033         }
1034 
1035         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
1036         // activity in App A
1037         Log.d(TAG, "Launching " + APP_A.BACKGROUND_ACTIVITY + " on " + context.getUser());
1038         // Must run with IAC permission as it might be a context from other user
1039         runWithShellPermissionIdentity(() -> startBackgroundActivity(APP_A), INTERACT_ACROSS_USERS);
1040 
1041         // Waits for final hoop in AppA to start looking for activity
1042         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
1043         assertTaskStackHasComponents(APP_A.BACKGROUND_ACTIVITY, APP_A.BACKGROUND_ACTIVITY);
1044     }
1045 
1046     @Test
testAppCannotStartBgActivityAfterHomeButton()1047     public void testAppCannotStartBgActivityAfterHomeButton() throws Exception {
1048         startActivity(APP_A.RELAUNCHING_ACTIVITY);
1049 
1050         // Click home button, and test app activity onPause() will try to start a background
1051         // activity, but we expect this will be blocked BAL logic in system, as app cannot start
1052         // any background activity even within grace period after pressing home button.
1053         pressHomeAndWaitHomeResumed();
1054 
1055         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
1056     }
1057 
1058     // Check picture-in-picture(PIP) won't allow to start BAL after pressing home.
1059     @Test
testPipCannotStartAfterHomeButton()1060     public void testPipCannotStartAfterHomeButton() throws Exception {
1061         startActivity(APP_A.PIP_ACTIVITY);
1062 
1063         // Click home button, and test app activity onPause() will trigger pip window,
1064         // test will will try to start background activity, but we expect the background activity
1065         // will be blocked even the app has a visible pip window, as we do not allow background
1066         // activity to be started after pressing home button.
1067         pressHomeAndWaitHomeResumed();
1068 
1069         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
1070     }
1071 
1072     @Test
1073     @AsbSecurityTest(cveBugId = 271576718)
testPipCannotStartFromBackground()1074     public void testPipCannotStartFromBackground() throws Exception {
1075         startActivity(APP_A.LAUNCH_INTO_PIP_ACTIVITY);
1076 
1077         pressHomeAndWaitHomeResumed();
1078         assertActivityNotFocused(APP_A.LAUNCH_INTO_PIP_ACTIVITY);
1079 
1080         Intent broadcast = new Intent(APP_A.LAUNCH_INTO_PIP_ACTIONS.LAUNCH_INTO_PIP);
1081         mContext.sendBroadcast(broadcast);
1082         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
1083 
1084         assertPinnedStackDoesNotExist();
1085     }
1086 
1087     // Check that a presentation on a virtual display won't allow BAL after pressing home.
1088     @Test
testPrivateVirtualDisplayCannotStartAfterHomeButton()1089     public void testPrivateVirtualDisplayCannotStartAfterHomeButton() throws Exception {
1090         startActivity(APP_A.VIRTUAL_DISPLAY_ACTIVITY);
1091 
1092         // Click home button, and test app activity onPause() will trigger which tries to launch
1093         // the background activity.
1094         pressHomeAndWaitHomeResumed();
1095 
1096         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
1097     }
1098 
1099     // Check that a presentation on a virtual display won't allow BAL after pressing home.
1100     @Test
testPublicVirtualDisplayCannotStartAfterHomeButton()1101     public void testPublicVirtualDisplayCannotStartAfterHomeButton() throws Exception {
1102         startActivity(APP_A.VIRTUAL_DISPLAY_ACTIVITY,
1103                 APP_A.VIRTUAL_DISPLAY_ACTIVITY_EXTRA.USE_PUBLIC_PRESENTATION);
1104 
1105         // Click home button, and test app activity onPause() will trigger which tries to launch
1106         // the background activity.
1107         pressHomeAndWaitHomeResumed();
1108 
1109         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
1110     }
1111 
1112 
1113     // Test manage space pending intent created by system cannot bypass BAL check.
1114     @Test
testManageSpacePendingIntentNoBalAllowed()1115     public void testManageSpacePendingIntentNoBalAllowed() throws Exception {
1116         TestServiceClient appATestService = getTestService(APP_A);
1117         runWithShellPermissionIdentity(() -> {
1118             runShellCommandOrThrow("cmd appops set " + APP_A.APP_PACKAGE_NAME
1119                     + " android:manage_external_storage allow");
1120         });
1121         // Make sure AppA paused at least 10s so it can't start activity because of grace period.
1122         Thread.sleep(1000 * 10);
1123         appATestService.startManageSpaceActivity();
1124         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
1125         assertTaskStackIsEmpty(APP_A.BACKGROUND_ACTIVITY);
1126     }
1127 
1128     @Test
1129     @RequireFeature(PackageManager.FEATURE_APP_WIDGETS)
1130     @RequireDoesNotHaveFeature(PackageManager.FEATURE_LEANBACK_ONLY)
testAppWidgetConfigNoBalBypass()1131     public void testAppWidgetConfigNoBalBypass() throws Exception {
1132         // Click bind widget button and then go home screen so app A will enter background state
1133         // with bind widget ability.
1134         EventReceiver receiver = new EventReceiver(Event.APP_A_START_WIDGET_CONFIG_ACTIVITY);
1135         clickAllowBindWidget(APP_A, receiver.getNotifier());
1136         pressHomeAndWaitHomeResumed();
1137 
1138         // After pressing home button, wait for appA to start widget config activity.
1139         receiver.waitForEventOrThrow(1000 * 30);
1140 
1141         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
1142         assertTaskStackIsEmpty(APP_A.BACKGROUND_ACTIVITY);
1143     }
1144 
1145     @Test
testBalOptInBindToService_whenOptedIn_allowsActivityStarts()1146     public void testBalOptInBindToService_whenOptedIn_allowsActivityStarts() {
1147         startActivityUnchecked(APP_C.BIND_SERVICE_ACTIVITY,
1148                 "android.server.wm.backgroundactivity.appc.ALLOW_BAL");
1149         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
1150     }
1151 
1152     @Test
testBalOptInBindToService_whenNotOptedIn_blocksActivityStarts()1153     public void testBalOptInBindToService_whenNotOptedIn_blocksActivityStarts() {
1154         startActivityUnchecked(APP_C.BIND_SERVICE_ACTIVITY);
1155         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
1156     }
1157 
1158     @Test
testBalOptInBindToService_whenNotOptedInAndSdk33_allowsActivityStart()1159     public void testBalOptInBindToService_whenNotOptedInAndSdk33_allowsActivityStart() {
1160         startActivityUnchecked(APP_C_33.BIND_SERVICE_ACTIVITY);
1161         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
1162     }
1163 
1164     @Test
testActivityStartbyTextClassifier_appBInFg_allowsActivityStart()1165     public void testActivityStartbyTextClassifier_appBInFg_allowsActivityStart() throws Exception {
1166         TestServiceClient appATestService = getTestService(APP_A);
1167         TestServiceClient appBTestService = getTestService(APP_B);
1168         // create PI in appA
1169         PendingIntent pi = generatePendingIntent(appATestService, APP_A.BACKGROUND_ACTIVITY);
1170 
1171         // app B in foreground
1172         startActivity(APP_B.FOREGROUND_ACTIVITY);
1173         // pass to appB and send PI
1174         TextClassification tc = new TextClassification.Builder()
1175                 .addAction(new RemoteAction(EMPTY_ICON, "myAction",
1176                         "classifiedContentDescription", pi))
1177                 .build();
1178         appBTestService.sendByTextClassification(tc);
1179 
1180         // assert that start succeeded
1181         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
1182     }
1183 
1184     @Test
testActivityStartbyTextClassifier_appBInBg_blocksActivityStart()1185     public void testActivityStartbyTextClassifier_appBInBg_blocksActivityStart() throws Exception {
1186         TestServiceClient appATestService = getTestService(APP_A);
1187         TestServiceClient appBTestService = getTestService(APP_B);
1188         // create PI in appA
1189         PendingIntent pi = generatePendingIntent(appATestService, APP_A.BACKGROUND_ACTIVITY);
1190 
1191         // app B not in FG
1192         // pass to appB and send PI
1193         TextClassification tc = new TextClassification.Builder()
1194                 .addAction(new RemoteAction(EMPTY_ICON, "myAction",
1195                         "classifiedContentDescription", pi))
1196                 .build();
1197         appBTestService.sendByTextClassification(tc);
1198 
1199         // assert that start is blocked
1200         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
1201     }
1202 
clickAllowBindWidget(Components app, ResultReceiver resultReceiver)1203     private void clickAllowBindWidget(Components app, ResultReceiver resultReceiver)
1204             throws Exception {
1205         // Create appWidgetId so we can send it to app, to request bind widget and start config
1206         // activity.
1207         UiDevice device = UiDevice.getInstance(mInstrumentation);
1208         AppWidgetHost appWidgetHost = new AppWidgetHost(mContext, 0);
1209         final int appWidgetId = appWidgetHost.allocateAppWidgetId();
1210         Intent appWidgetIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
1211         appWidgetIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
1212         appWidgetIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER,
1213                 app.WIDGET_PROVIDER);
1214 
1215         Intent intent = new Intent();
1216         intent.setComponent(app.WIDGET_CONFIG_TEST_ACTIVITY);
1217         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1218         intent.putExtra(Intent.EXTRA_INTENT, appWidgetIntent);
1219         intent.putExtra(EVENT_NOTIFIER_EXTRA, resultReceiver);
1220         mContext.startActivity(intent);
1221 
1222         // Find settings package and bind widget activity and click the create button.
1223         String settingsPkgName = "";
1224         PackageManager pm = mContext.getPackageManager();
1225         List<ResolveInfo> ris = pm.queryIntentActivities(appWidgetIntent,
1226                 PackageManager.MATCH_DEFAULT_ONLY);
1227         for (ResolveInfo ri : ris) {
1228             if (ri.activityInfo.name.contains("AllowBindAppWidgetActivity")) {
1229                 settingsPkgName = ri.activityInfo.packageName;
1230             }
1231         }
1232         assertWithMessage("Cannot find settings app").that(settingsPkgName).isNotEmpty();
1233         assertWithMessage("Unable to start AllowBindAppWidgetActivity")
1234                 .that(device.wait(Until.hasObject(By.pkg(settingsPkgName)), 1000 * 10)).isTrue();
1235         boolean buttonClicked = false;
1236         BySelector selector = By.clickable(true);
1237         List<UiObject2> objects = device.findObjects(selector);
1238         for (UiObject2 object : objects) {
1239             String objectText = object.getText();
1240             if (objectText == null) {
1241                 continue;
1242             }
1243             if (objectText.equalsIgnoreCase("CREATE") || objectText.equalsIgnoreCase("ALLOW")) {
1244                 object.click();
1245                 buttonClicked = true;
1246                 break;
1247             }
1248         }
1249         assertWithMessage("Create' button not found/clicked")
1250                 .that(device.wait(Until.gone(By.pkg(settingsPkgName)), 1000 * 10) && buttonClicked)
1251                 .isTrue();
1252 
1253         // Wait the bind widget activity goes away.
1254         waitUntilForegroundChanged(settingsPkgName, false,
1255                 ACTIVITY_NOT_RESUMED_TIMEOUT_MS);
1256     }
1257 
pressHomeAndWaitHomeResumed()1258     private void pressHomeAndWaitHomeResumed() {
1259         assumeSetupComplete();
1260         pressHomeButton();
1261         mWmState.waitForHomeActivityVisible();
1262         mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
1263     }
1264 
assumeSetupComplete()1265     private void assumeSetupComplete() {
1266         assume().that(Settings.Secure.getInt(mContext.getContentResolver(),
1267                 Settings.Secure.USER_SETUP_COMPLETE, 0)).isEqualTo(1);
1268     }
1269 
checkPackageResumed(String pkg)1270     private boolean checkPackageResumed(String pkg) {
1271         WindowManagerStateHelper helper = new WindowManagerStateHelper();
1272         helper.computeState();
1273         return ComponentName.unflattenFromString(
1274                 helper.getFocusedActivity()).getPackageName().equals(pkg);
1275     }
1276 
1277     // Return true if the state of the package is changed to target state.
waitUntilForegroundChanged(String targetPkg, boolean toBeResumed, int timeout)1278     private boolean waitUntilForegroundChanged(String targetPkg, boolean toBeResumed, int timeout)
1279             throws Exception {
1280         long startTime = System.currentTimeMillis();
1281         while (checkPackageResumed(targetPkg) != toBeResumed) {
1282             if (System.currentTimeMillis() - startTime < timeout) {
1283                 Thread.sleep(100);
1284             } else {
1285                 return false;
1286             }
1287         }
1288         return true;
1289     }
1290 
assertActivityNotResumed(Components app)1291     private void assertActivityNotResumed(Components app) throws Exception {
1292         assertWithMessage("Test activity is resumed").that(
1293                 waitUntilForegroundChanged(app.APP_PACKAGE_NAME, true,
1294                         ACTIVITY_NOT_RESUMED_TIMEOUT_MS)).isFalse();
1295     }
1296 
pressHomeAndResumeAppSwitch()1297     private void pressHomeAndResumeAppSwitch() {
1298         // Press home key to ensure stopAppSwitches is called because the last-stop-app-switch-time
1299         // is a criteria of allowing background start.
1300         pressHomeButton();
1301         // Resume the stopped state (it won't affect last-stop-app-switch-time) so we don't need to
1302         // wait extra time to prevent the next launch from being delayed.
1303         resumeAppSwitches();
1304         mWmState.waitForHomeActivityVisible();
1305         // Resuming app switches again after home became visible because the previous call might
1306         // have raced with pressHomeButton().
1307         // TODO(b/155454710): Remove previous call after making sure all the tests don't depend on
1308         // the timing here.
1309         resumeAppSwitches();
1310     }
1311 
startPendingIntentSenderActivity(Components appToCreatePendingIntent, Components appToSendPendingIntent, boolean allowBal)1312     private void startPendingIntentSenderActivity(Components appToCreatePendingIntent,
1313             Components appToSendPendingIntent, boolean allowBal) throws Exception {
1314         TestServiceClient testServiceToCreatePendingIntent =
1315                 getTestService(appToCreatePendingIntent);
1316         // Get a PendingIntent created by appToCreatePendingIntent.
1317         final PendingIntent pi;
1318         try {
1319             pi = generatePendingIntent(testServiceToCreatePendingIntent,
1320                     appToCreatePendingIntent.BACKGROUND_ACTIVITY);
1321         } catch (Exception e) {
1322             throw new AssertionError(e);
1323         }
1324 
1325         // Start app B's activity so it runs send() on PendingIntent created by app A.
1326         Intent secondIntent = new Intent();
1327         secondIntent.setComponent(appToSendPendingIntent.START_PENDING_INTENT_ACTIVITY);
1328         secondIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1329         secondIntent.putExtra(
1330                 appToSendPendingIntent.START_PENDING_INTENT_ACTIVITY_EXTRA.PENDING_INTENT, pi);
1331         secondIntent.putExtra(
1332                 appToSendPendingIntent.START_PENDING_INTENT_ACTIVITY_EXTRA.START_BUNDLE,
1333                 ActivityOptions.makeBasic().setPendingIntentBackgroundActivityStartMode(
1334                         allowBal ? ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
1335                                 : ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED)
1336                         .toBundle());
1337         mContext.startActivity(secondIntent);
1338     }
1339 
1340     /**
1341      * Start the given activity in a new task.
1342      *
1343      * After starting the activity this method asserts that the activity is actually started and is
1344      * shown as the focused activity in the foreground.
1345      *
1346      * @param componentName activity to start
1347      * @param extraTrueNames (optional) names of extras that should be set to <code>true</code>
1348      */
startActivity(ComponentName componentName, String... extraTrueNames)1349     private void startActivity(ComponentName componentName, String... extraTrueNames) {
1350         startActivityUnchecked(componentName, extraTrueNames);
1351         assertActivityFocused(componentName);
1352     }
1353 
1354     /**
1355      * Start the given activity in a new task.
1356      *
1357      * There is no check that the activity actually got started or that it is now in the foreground.
1358      *
1359      * @param componentName activity to start
1360      * @param extraTrueNames (optional) names of extras that should be set to <code>true</code>
1361      */
startActivityUnchecked(ComponentName componentName, String... extraTrueNames)1362     private void startActivityUnchecked(ComponentName componentName, String... extraTrueNames) {
1363         Intent intent = new Intent();
1364         intent.setComponent(componentName);
1365         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1366         for (String extraTrueName : extraTrueNames) {
1367             intent.putExtra(extraTrueName, true);
1368         }
1369         mContext.startActivity(intent);
1370     }
1371 
grantSystemAlertWindow(Components app)1372     private static void grantSystemAlertWindow(Components app) throws Exception {
1373         grantSystemAlertWindow(app, true);
1374     }
1375 
grantSystemAlertWindow(Components app, boolean allow)1376     private static void grantSystemAlertWindow(Components app, boolean allow) throws Exception {
1377         grantSystemAlertWindow(app.APP_PACKAGE_NAME, allow);
1378     }
1379 
grantSystemAlertWindow(String packageName, boolean allow)1380     private static void grantSystemAlertWindow(String packageName, boolean allow) throws Exception {
1381         final int mode = allow ? MODE_ALLOWED : MODE_ERRORED;
1382         final String opStr = "android:system_alert_window";
1383         AppOpsUtils.setOpMode(packageName, opStr, mode);
1384         assertThat(AppOpsUtils.getOpMode(packageName, opStr)).isEqualTo(mode);
1385     }
1386 
startBackgroundActivity(TestServiceClient service, Components app)1387     private static void startBackgroundActivity(TestServiceClient service, Components app)
1388             throws Exception {
1389         service.startActivityIntent(new Intent().setComponent(app.BACKGROUND_ACTIVITY)
1390                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
1391     }
1392 
startBackgroundActivity(Components app)1393     private void startBackgroundActivity(Components app) throws Exception {
1394         startBackgroundActivity(getTestService(app), app);
1395     }
1396 
sendBroadcastAndWait(ComponentName componentName)1397     void sendBroadcastAndWait(ComponentName componentName) throws Exception {
1398         EventReceiver receiver = new EventReceiver(Event.BROADCAST_RECEIVED);
1399         Intent intent = new Intent();
1400         intent.setComponent(componentName);
1401         intent.putExtra(EVENT_NOTIFIER_EXTRA, receiver.getNotifier());
1402         mContext.sendBroadcast(intent);
1403         receiver.waitForEventOrThrow(ACTIVITY_START_TIMEOUT_MS);
1404     }
1405 
generatePendingIntent(TestServiceClient testService, ComponentName activity)1406     private static PendingIntent generatePendingIntent(TestServiceClient testService,
1407             ComponentName activity) throws RemoteException {
1408         return testService.generatePendingIntent(activity, null);
1409     }
1410 
sendPendingIntent(PendingIntent pi, TestServiceClient service)1411     private static void sendPendingIntent(PendingIntent pi, TestServiceClient service)
1412             throws RemoteException {
1413         service.sendPendingIntent(pi, Bundle.EMPTY);
1414     }
1415 
assumeSdkNewerThanUpsideDownCake()1416     static void assumeSdkNewerThanUpsideDownCake() {
1417         // Feature flag "ActivitySecurity__asm_restrictions_enabled" is set to 1 in
1418         // BackgroundActivityTestBase. For backward compatibility reasons, it is only enabled
1419         // for apps with targetSdkVersion starting Android V.
1420         // TODO remove this assumption after V released.
1421         assume().that(SdkLevel.isAtLeastV()).isTrue();
1422     }
1423 }
1424