• 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.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.WindowManagerState.STATE_INITIALIZING;
26 import static android.server.wm.backgroundactivity.common.CommonComponents.EVENT_NOTIFIER_EXTRA;
27 import static android.view.Display.DEFAULT_DISPLAY;
28 
29 import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
30 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
31 
32 import static com.google.common.truth.Truth.assertWithMessage;
33 
34 import static org.hamcrest.CoreMatchers.is;
35 import static org.junit.Assert.assertEquals;
36 import static org.junit.Assert.assertFalse;
37 import static org.junit.Assert.assertNotEquals;
38 import static org.junit.Assert.assertTrue;
39 import static org.junit.Assert.fail;
40 import static org.junit.Assume.assumeThat;
41 import static org.junit.Assume.assumeTrue;
42 
43 import android.Manifest;
44 import android.app.PendingIntent;
45 import android.app.UiAutomation;
46 import android.appwidget.AppWidgetHost;
47 import android.appwidget.AppWidgetManager;
48 import android.content.ComponentName;
49 import android.content.Context;
50 import android.content.Intent;
51 import android.content.ServiceConnection;
52 import android.content.pm.PackageManager;
53 import android.content.pm.ResolveInfo;
54 import android.content.pm.UserInfo;
55 import android.os.IBinder;
56 import android.os.ResultReceiver;
57 import android.os.UserHandle;
58 import android.os.UserManager;
59 import android.platform.test.annotations.AsbSecurityTest;
60 import android.platform.test.annotations.Presubmit;
61 import android.provider.Settings;
62 import android.server.wm.backgroundactivity.appa.Components;
63 import android.server.wm.backgroundactivity.appa.IBackgroundActivityTestService;
64 import android.server.wm.backgroundactivity.common.CommonComponents.Event;
65 import android.server.wm.backgroundactivity.common.EventReceiver;
66 import android.util.Log;
67 
68 import androidx.annotation.Nullable;
69 import androidx.test.filters.FlakyTest;
70 import androidx.test.platform.app.InstrumentationRegistry;
71 import androidx.test.uiautomator.By;
72 import androidx.test.uiautomator.BySelector;
73 import androidx.test.uiautomator.UiDevice;
74 import androidx.test.uiautomator.UiObject2;
75 import androidx.test.uiautomator.Until;
76 
77 import com.android.compatibility.common.util.AppOpsUtils;
78 
79 import org.junit.Assume;
80 import org.junit.AssumptionViolatedException;
81 import org.junit.Ignore;
82 import org.junit.Test;
83 
84 import java.util.List;
85 import java.util.concurrent.CountDownLatch;
86 import java.util.concurrent.TimeUnit;
87 import java.util.concurrent.TimeoutException;
88 
89 /**
90  * This class covers all test cases for starting/blocking background activities.
91  * As instrumentation tests started by shell are whitelisted to allow starting background activity,
92  * tests can't be done in this app alone.
93  * Hence, there are 2 extra apps, appA and appB. This class will send commands to appA/appB, for
94  * example, send a broadcast to appA and ask it to start a background activity, and we will monitor
95  * the result and see if it starts an activity successfully.
96  */
97 @Presubmit
98 public class BackgroundActivityLaunchTest extends BackgroundActivityTestBase {
99 
100     private static final String TAG = "BackgroundActivityLaunchTest";
101 
102     private static final long ACTIVITY_BG_START_GRACE_PERIOD_MS = 10 * 1000;
103     private static final int ACTIVITY_START_TIMEOUT_MS = 5000;
104     private static final int ACTIVITY_NOT_RESUMED_TIMEOUT_MS = 5000;
105 
106     private static final String APP_C_PACKAGE_NAME = "android.server.wm.backgroundactivity.appc";
107     private static final String APP_C33_PACKAGE_NAME = APP_C_PACKAGE_NAME + "33";
108 
109     public static final ComponentName APP_C_FOREGROUND_ACTIVITY =
110             new ComponentName(APP_C_PACKAGE_NAME,
111                     "android.server.wm.backgroundactivity.appc.ForegroundActivity");
112     public static final ComponentName APP_C_33_FOREGROUND_ACTIVITY =
113             new ComponentName(APP_C33_PACKAGE_NAME,
114                     "android.server.wm.backgroundactivity.appc.ForegroundActivity");
115 
116     /**
117      * Tests can be executed as soon as the device has booted. When that happens the broadcast queue
118      * is long and it takes some time to process the broadcast we just sent.
119      */
120     private static final int BROADCAST_DELIVERY_TIMEOUT_MS = 60000;
121 
122     private IBackgroundActivityTestService mBackgroundActivityTestService;
123 
124     @Test
testBackgroundActivityBlocked()125     public void testBackgroundActivityBlocked() {
126         // Start AppA background activity and blocked
127         Intent intent = new Intent();
128         intent.setComponent(APP_A.START_ACTIVITY_RECEIVER);
129         mContext.sendBroadcast(intent);
130         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
131         assertFalse("Should not able to launch background activity", result);
132         assertTaskStackIsEmpty(APP_A.BACKGROUND_ACTIVITY);
133     }
134 
135     @Test
testBackgroundActivityBlockedInStartNextMatchingActivity()136     public void testBackgroundActivityBlockedInStartNextMatchingActivity() throws TimeoutException {
137         EventReceiver receiver = new EventReceiver(
138                 Event.APP_A_LAUNCHER_MOVING_TO_BACKGROUND_ACTIVITY);
139         Intent intent = new Intent("StartNextMatchingActivityAction");
140         intent.setComponent(APP_A.START_NEXT_MATCHING_ACTIVITY);
141         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
142         intent.putExtra(EVENT_NOTIFIER_EXTRA, receiver.getNotifier());
143         mContext.startActivity(intent);
144         receiver.waitForEventOrThrow(ACTIVITY_START_TIMEOUT_MS);
145         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
146         assertFalse("Should not able to launch background activity", result);
147     }
148 
149     @Test
testStartBgActivity_usingStartActivitiesFromBackgroundPermission()150     public void testStartBgActivity_usingStartActivitiesFromBackgroundPermission()
151             throws Exception {
152         // Disable SAW app op for shell, since that can also allow starting activities from bg.
153         AppOpsUtils.setOpMode(SHELL_PACKAGE, "android:system_alert_window", MODE_ERRORED);
154 
155         // Launch the activity via a shell command, this way the system doesn't have info on which
156         // app launched the activity and thus won't use instrumentation privileges to launch it. But
157         // the shell has the START_ACTIVITIES_FROM_BACKGROUND permission, so we expect it to
158         // succeed.
159         // See testBackgroundActivityBlocked() for a case where an app without the
160         // START_ACTIVITIES_FROM_BACKGROUND permission is blocked from launching the activity from
161         // the background.
162         launchActivity(APP_A.BACKGROUND_ACTIVITY);
163 
164         // If the activity launches, it means the START_ACTIVITIES_FROM_BACKGROUND permission works.
165         assertEquals("Launched activity should be at the top",
166                 ComponentNameUtils.getActivityName(APP_A.BACKGROUND_ACTIVITY),
167                 mWmState.getTopActivityName(0));
168     }
169 
170     @Test
171     @FlakyTest(bugId = 155454710)
testBackgroundActivity_withinGracePeriod_isNotBlocked()172     public void testBackgroundActivity_withinGracePeriod_isNotBlocked() {
173         // Start AppA foreground activity
174         Intent firstIntent = new Intent();
175         firstIntent.setComponent(APP_A.FOREGROUND_ACTIVITY);
176         firstIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
177         mContext.startActivity(firstIntent);
178         boolean firstResult = waitForActivityFocused(APP_A.FOREGROUND_ACTIVITY);
179         assertTrue("Not able to start foreground activity", firstResult);
180         // Don't press home button to avoid stop app switches
181         mContext.sendBroadcast(new Intent(APP_A.FOREGROUND_ACTIVITY_ACTIONS.FINISH_ACTIVITY));
182         mWmState.waitAndAssertActivityRemoved(APP_A.FOREGROUND_ACTIVITY);
183         Intent secondIntent = new Intent();
184         secondIntent.setComponent(APP_A.START_ACTIVITY_RECEIVER);
185 
186         mContext.sendBroadcast(secondIntent);
187         boolean secondResult = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
188         assertTrue("Should be able to launch background activity", secondResult);
189     }
190 
191     @Test
testBackgroundActivityWhenSystemAlertWindowGranted_isNotBlocked()192     public void testBackgroundActivityWhenSystemAlertWindowGranted_isNotBlocked()
193             throws Exception {
194         // enable appopp for SAW for this test
195         AppOpsUtils.setOpMode(APP_A_33.APP_PACKAGE_NAME, "android:system_alert_window",
196                 MODE_ALLOWED);
197         assertEquals(AppOpsUtils.getOpMode(APP_A_33.APP_PACKAGE_NAME,
198                         "android:system_alert_window"),
199                 MODE_ALLOWED);
200 
201         // Start AppA background activity successfully as the package has SAW
202         Intent intent = new Intent();
203         intent.setComponent(APP_A_33.START_ACTIVITY_RECEIVER);
204         mContext.sendBroadcast(intent);
205         boolean result = waitForActivityFocused(APP_A_33.BACKGROUND_ACTIVITY);
206         assertTrue("Not able to start foreground activity", result);
207     }
208 
209     @Test
testBackgroundActivityNotBlockedWhenForegroundActivityTop()210     public void testBackgroundActivityNotBlockedWhenForegroundActivityTop() {
211         Intent intent = new Intent();
212         intent.setComponent(APP_A.FOREGROUND_ACTIVITY);
213         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
214         mContext.startActivity(intent);
215         mWmState.waitForValidState(APP_A.FOREGROUND_ACTIVITY);
216         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
217 
218         // Start AppA background activity successfully in new task as there's a foreground activity
219         intent = new Intent();
220         intent.setComponent(APP_A.START_ACTIVITY_RECEIVER);
221         mContext.sendBroadcast(intent);
222         mWmState.waitForValidState(APP_A.BACKGROUND_ACTIVITY);
223         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
224         assertTaskStackHasComponents(APP_A.BACKGROUND_ACTIVITY, APP_A.BACKGROUND_ACTIVITY);
225     }
226 
227     @Test
testBackgroundActivityWhenForegroundActivityNotTop_IsNotBlocked()228     public void testBackgroundActivityWhenForegroundActivityNotTop_IsNotBlocked() {
229         Intent intent = new Intent();
230         intent.setComponent(APP_A.FOREGROUND_ACTIVITY);
231         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
232         mContext.startActivity(intent);
233         mWmState.waitForValidState(APP_A.FOREGROUND_ACTIVITY);
234         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A, APP_B.FOREGROUND_ACTIVITY));
235         mWmState.waitForValidState(APP_B.FOREGROUND_ACTIVITY);
236         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
237                         APP_B.FOREGROUND_ACTIVITY,
238                         APP_A.FOREGROUND_ACTIVITY);
239 
240         // Start AppA background activity successfully as there's a foreground activity
241         intent = new Intent();
242         intent.setComponent(APP_A.START_ACTIVITY_RECEIVER);
243         mContext.sendBroadcast(intent);
244         mWmState.waitForValidState(APP_A.BACKGROUND_ACTIVITY);
245         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
246                 APP_B.FOREGROUND_ACTIVITY,
247                 APP_A.FOREGROUND_ACTIVITY);
248         assertTaskStackHasComponents(APP_A.BACKGROUND_ACTIVITY, APP_A.BACKGROUND_ACTIVITY);
249     }
250 
251     @Test
testActivityNotBlockedWhenForegroundActivityLaunch()252     public void testActivityNotBlockedWhenForegroundActivityLaunch() throws Exception {
253         // Start foreground activity, and foreground activity able to launch background activity
254         // successfully
255         Intent intent = new Intent();
256         intent.setComponent(APP_A.FOREGROUND_ACTIVITY);
257         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
258         intent.putExtra(APP_A.FOREGROUND_ACTIVITY_EXTRA.LAUNCH_BACKGROUND_ACTIVITY, true);
259         mContext.startActivity(intent);
260         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
261         assertTrue("Not able to launch background activity", result);
262         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
263                 APP_A.BACKGROUND_ACTIVITY,
264                 APP_A.FOREGROUND_ACTIVITY);
265     }
266 
267     @Test
testActivityBroughtToTopOfTaskWhenLaunchedInTheBackground()268     public void testActivityBroughtToTopOfTaskWhenLaunchedInTheBackground() throws Exception {
269         // Start foreground activity, and foreground activity able to launch background activity
270         // successfully
271         Intent intent = new Intent();
272         intent.setComponent(APP_A.FOREGROUND_ACTIVITY);
273         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
274         mContext.startActivity(intent);
275         boolean result = waitForActivityFocused(ACTIVITY_FOCUS_TIMEOUT_MS,
276                 APP_A.FOREGROUND_ACTIVITY);
277         assertTrue("Not able to launch background activity", result);
278         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
279         // We can't resume app switching after pressing home button, otherwise the grace period
280         // will allow the starts.
281         pressHomeAndWaitHomeResumed();
282 
283         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A, APP_A.BACKGROUND_ACTIVITY));
284 
285         result = waitForActivityFocused(APP_A.FOREGROUND_ACTIVITY);
286         assertFalse("Previously foreground Activity should not be able to make it focused",
287                 result);
288         result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
289         assertFalse("Previously background Activity should not be able to make it focused",
290                 result);
291         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
292                 APP_A.BACKGROUND_ACTIVITY,
293                 APP_A.FOREGROUND_ACTIVITY);
294     }
295 
296     @Test
297     @FlakyTest(bugId = 272082654)
testActivityFromBgActivityInFgTask_isNotBlocked()298     public void testActivityFromBgActivityInFgTask_isNotBlocked() {
299         // Launch Activity A, B in the same task with different processes.
300         final Intent intent = new Intent()
301                 .setComponent(APP_A.FOREGROUND_ACTIVITY)
302                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
303         mContext.startActivity(intent);
304         mWmState.waitForValidState(APP_A.FOREGROUND_ACTIVITY);
305         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A, APP_B.FOREGROUND_ACTIVITY));
306         mWmState.waitForValidState(APP_B.FOREGROUND_ACTIVITY);
307         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
308                 APP_B.FOREGROUND_ACTIVITY,
309                 APP_A.FOREGROUND_ACTIVITY);
310 
311         // Refresh last-stop-app-switch-time by returning to home and then make the task foreground.
312         pressHomeAndResumeAppSwitch();
313         mContext.startActivity(intent);
314         mWmState.waitForValidState(APP_B.FOREGROUND_ACTIVITY);
315         // Though process A is in background, it is in a visible Task (top is B) so it should be
316         // able to start activity successfully.
317         mContext.sendBroadcast(new Intent(
318                 APP_A.FOREGROUND_ACTIVITY_ACTIONS.LAUNCH_BACKGROUND_ACTIVITIES)
319                 .putExtra(APP_A.FOREGROUND_ACTIVITY_EXTRA.LAUNCH_INTENTS,
320                         new Intent[]{ new Intent()
321                                 .setComponent(APP_A.BACKGROUND_ACTIVITY)
322                                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }));
323         mWmState.waitForValidState(APP_A.BACKGROUND_ACTIVITY);
324         mWmState.assertFocusedActivity(
325                 "The background activity must be able to launch from a visible task",
326                 APP_A.BACKGROUND_ACTIVITY);
327     }
328 
329     @Test
330     @FlakyTest(bugId = 130800326)
331     @Ignore  // TODO(b/145981637): Make this test work
testActivityBlockedWhenForegroundActivityRestartsItself()332     public void testActivityBlockedWhenForegroundActivityRestartsItself() throws Exception {
333         // Start AppA foreground activity
334         Intent intent = new Intent();
335         intent.setComponent(APP_A.FOREGROUND_ACTIVITY);
336         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
337         intent.putExtra(APP_A.FOREGROUND_ACTIVITY_EXTRA.RELAUNCH_FOREGROUND_ACTIVITY_EXTRA, true);
338         mContext.startActivity(intent);
339         boolean result = waitForActivityFocused(APP_A.FOREGROUND_ACTIVITY);
340         assertTrue("Not able to start foreground activity", result);
341         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
342 
343         // The foreground activity will be paused but will attempt to restart itself in onPause()
344         pressHomeAndResumeAppSwitch();
345 
346         result = waitForActivityFocused(APP_A.FOREGROUND_ACTIVITY);
347         assertFalse("Previously foreground Activity should not be able to relaunch itself",
348                 result);
349         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
350     }
351 
352     @Test
testSecondActivityNotBlockedWhenForegroundActivityLaunch()353     public void testSecondActivityNotBlockedWhenForegroundActivityLaunch() throws Exception {
354         // Start AppA foreground activity, which will immediately launch one activity
355         // and then the second.
356         Intent intent = new Intent();
357         intent.setComponent(APP_A.FOREGROUND_ACTIVITY);
358         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
359         intent.putExtra(APP_A.FOREGROUND_ACTIVITY_EXTRA.LAUNCH_BACKGROUND_ACTIVITY, true);
360         intent.putExtra(APP_A.FOREGROUND_ACTIVITY_EXTRA.LAUNCH_SECOND_BACKGROUND_ACTIVITY, true);
361         mContext.startActivity(intent);
362 
363         boolean result = waitForActivityFocused(APP_A.SECOND_BACKGROUND_ACTIVITY);
364         assertTrue("Not able to launch second background activity", result);
365 
366         waitAndAssertActivityState(APP_A.BACKGROUND_ACTIVITY, STATE_INITIALIZING,
367                 "First activity should have been created");
368         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
369                 APP_A.SECOND_BACKGROUND_ACTIVITY,
370                 APP_A.BACKGROUND_ACTIVITY,
371                 APP_A.FOREGROUND_ACTIVITY);
372     }
373 
374     @Test
testSecondActivityBlockedWhenBackgroundActivityLaunch()375     public void testSecondActivityBlockedWhenBackgroundActivityLaunch() throws Exception {
376         Intent baseActivityIntent = new Intent();
377         baseActivityIntent.setComponent(APP_A.FOREGROUND_ACTIVITY);
378         baseActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
379         mContext.startActivity(baseActivityIntent);
380         boolean result = waitForActivityFocused(APP_A.FOREGROUND_ACTIVITY);
381         assertTrue("Not able to start foreground activity", result);
382         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
383         // We can't resume app switching after pressing home button, otherwise the grace period
384         // will allow the starts.
385         pressHomeAndWaitHomeResumed();
386 
387         // The activity, now in the background, will attempt to start 2 activities in quick
388         // succession
389         mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A,
390                 APP_A.BACKGROUND_ACTIVITY,
391                 APP_A.SECOND_BACKGROUND_ACTIVITY));
392 
393         // There should be 2 activities in the background (not focused) INITIALIZING
394         result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
395         assertFalse("Activity should not have been launched in the foreground", result);
396         result = waitForActivityFocused(APP_A.SECOND_BACKGROUND_ACTIVITY);
397         assertFalse("Second activity should not have been launched in the foreground", result);
398         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY,
399                 APP_A.SECOND_BACKGROUND_ACTIVITY,
400                 APP_A.BACKGROUND_ACTIVITY,
401                 APP_A.FOREGROUND_ACTIVITY);
402     }
403 
404     @Test
testPendingIntentActivityBlocked()405     public void testPendingIntentActivityBlocked() throws Exception {
406         // Cannot start activity by pending intent, as both appA and appB are in background
407         sendPendingIntentActivity(APP_A, APP_B);
408         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
409         assertFalse("Should not able to launch background activity", result);
410         assertTaskStackIsEmpty(APP_A.BACKGROUND_ACTIVITY);
411     }
412 
413     @Test
testPendingIntentActivity_whenSenderAllowsBal_isNotBlocked()414     public void testPendingIntentActivity_whenSenderAllowsBal_isNotBlocked() throws Exception {
415         // creator (appa) is not privileged
416         AppOpsUtils.setOpMode(APP_A.APP_PACKAGE_NAME, "android:system_alert_window", MODE_ERRORED);
417         // sender (appb) is privileged, and grants
418         AppOpsUtils.setOpMode(APP_B.APP_PACKAGE_NAME, "android:system_alert_window", MODE_ALLOWED);
419 
420         startPendingIntentSenderActivity(APP_A, APP_B, /* allowBalBySender */ true);
421         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
422         assertTrue("Not able to launch background activity", result);
423         assertTaskStackHasComponents(APP_A.BACKGROUND_ACTIVITY, APP_A.BACKGROUND_ACTIVITY);
424     }
425 
426     @Test
testPendingIntentActivity_whenSenderDoesNotAllowBal_isBlocked()427     public void testPendingIntentActivity_whenSenderDoesNotAllowBal_isBlocked() throws Exception {
428         // creator (appa) is not privileged
429         AppOpsUtils.setOpMode(APP_A.APP_PACKAGE_NAME, "android:system_alert_window", MODE_ERRORED);
430         // sender (appb) is privileged, but revokes
431         AppOpsUtils.setOpMode(APP_B.APP_PACKAGE_NAME, "android:system_alert_window", MODE_ALLOWED);
432 
433         startPendingIntentSenderActivity(APP_A, APP_B, /* allowBalBySender */ false);
434 
435         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
436         assertFalse("Should not able to launch background activity", result);
437     }
438 
439     @Test
testPI_appAIsForegroundDenyCreatorPrivilege_launchAppB_isBlocked()440     public void testPI_appAIsForegroundDenyCreatorPrivilege_launchAppB_isBlocked()
441             throws Exception {
442         // Start AppA foreground activity
443         Intent intent = new Intent();
444         intent.setComponent(APP_A.FOREGROUND_ACTIVITY);
445         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
446         mContext.startActivity(intent);
447         boolean result = waitForActivityFocused(APP_A.FOREGROUND_ACTIVITY);
448         assertTrue("Not able to start foreground Activity", result);
449         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
450 
451         // App A create a PendingIntent with ActivityOption that denies PendingIntent sender to use
452         // creator's privilege to launch itself. The PendingIntent itself is to launch App B. Since
453         // App B is in the background, it should be blocked even though the creator (App A) is in
454         // the foreground.
455         sendPendingIntentActivity(APP_A, APP_B,
456                 APP_A.SEND_PENDING_INTENT_RECEIVER_EXTRA.DENY_CREATOR_BAL_PRIVILEGE,
457                 APP_A.SEND_PENDING_INTENT_RECEIVER_EXTRA.CREATE_PI_LAUNCH_APP_B);
458 
459         result = waitForActivityFocused(APP_B.FOREGROUND_ACTIVITY);
460         assertFalse("Should not able to launch background activity", result);
461     }
462 
463     @Test
testPI_appAIsFgDenyCreatorPrivilege_appBTryOverrideCreatorPrivilege_isBlocked()464     public void testPI_appAIsFgDenyCreatorPrivilege_appBTryOverrideCreatorPrivilege_isBlocked()
465             throws Exception {
466         // Start AppB foreground activity
467         Intent intent = new Intent();
468         intent.setComponent(APP_A.FOREGROUND_ACTIVITY);
469         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
470         mContext.startActivity(intent);
471         boolean result = waitForActivityFocused(APP_A.FOREGROUND_ACTIVITY);
472         assertTrue("Not able to start foreground Activity", result);
473         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
474 
475         // App A create a PendingIntent with ActivityOption that denies PendingIntent sender to use
476         // creator's privilege to launch itself. The PendingIntent itself is to launch App B.
477         // App B is in the background, it should be blocked even though the creator (App A) is in
478         // the foreground. However, The sender (App B) also tries to override the creator option by
479         // setting the creator option from the sender side. This should not work. Creator option
480         // cannot be set from the sender side.
481         sendPendingIntentActivity(APP_A, APP_B,
482                 APP_A.SEND_PENDING_INTENT_RECEIVER_EXTRA.DENY_CREATOR_BAL_PRIVILEGE,
483                 APP_A.SEND_PENDING_INTENT_RECEIVER_EXTRA.CREATE_PI_LAUNCH_APP_B,
484                 APP_B.START_PENDING_INTENT_ACTIVITY_EXTRA.ALLOW_CREATOR_BAL);
485 
486         result = waitForActivityFocused(APP_B.FOREGROUND_ACTIVITY);
487         assertFalse("Should not able to launch background activity", result);
488     }
489 
490     @Test
testPendingIntentActivity_appAIsForeground_isNotBlocked()491     public void testPendingIntentActivity_appAIsForeground_isNotBlocked() {
492         // Start AppA foreground activity
493         Intent intent = new Intent();
494         intent.setComponent(APP_A.FOREGROUND_ACTIVITY);
495         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
496         mContext.startActivity(intent);
497         boolean result = waitForActivityFocused(APP_A.FOREGROUND_ACTIVITY);
498         assertTrue("Not able to start foreground Activity", result);
499         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
500 
501         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
502         // activity in App A
503         sendPendingIntentActivity(APP_A, APP_B);
504         result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
505         assertTrue("Not able to launch background activity", result);
506         assertTaskStackHasComponents(APP_A.FOREGROUND_ACTIVITY, APP_A.FOREGROUND_ACTIVITY);
507         assertTaskStackHasComponents(APP_A.BACKGROUND_ACTIVITY, APP_A.BACKGROUND_ACTIVITY);
508     }
509 
510     @Test
testPendingIntentBroadcastActivity_appBIsForeground_isBlocked()511     public void testPendingIntentBroadcastActivity_appBIsForeground_isBlocked() {
512         // Start AppB foreground activity
513         Intent intent = new Intent();
514         intent.setComponent(APP_B.FOREGROUND_ACTIVITY);
515         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
516         mContext.startActivity(intent);
517         boolean result = waitForActivityFocused(APP_B.FOREGROUND_ACTIVITY);
518         assertTrue("Not able to start foreground Activity", result);
519         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
520 
521         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
522         // activity in App A
523         sendPendingIntentActivity(APP_A, APP_B);
524         result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
525         assertWithMessage("Able to launch background activity").that(result).isFalse();
526         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
527     }
528 
529     @Test
testPendingIntentBroadcastActivity_appBIsForegroundAndSdk33_isNotBlocked()530     public void testPendingIntentBroadcastActivity_appBIsForegroundAndSdk33_isNotBlocked() {
531         // Start AppB foreground activity
532         Intent intent = new Intent();
533         intent.setComponent(APP_B_33.FOREGROUND_ACTIVITY);
534         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
535         mContext.startActivity(intent);
536         boolean result = waitForActivityFocused(APP_B_33.FOREGROUND_ACTIVITY);
537         assertTrue("Not able to start foreground Activity", result);
538         assertTaskStackHasComponents(APP_B_33.FOREGROUND_ACTIVITY, APP_B_33.FOREGROUND_ACTIVITY);
539 
540         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
541         // activity in App A
542         sendPendingIntentActivity(APP_A, APP_B_33);
543         result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
544         assertTrue("Not able to launch background activity", result);
545         assertTaskStackHasComponents(APP_A.BACKGROUND_ACTIVITY, APP_A.BACKGROUND_ACTIVITY);
546         assertTaskStackHasComponents(APP_B_33.FOREGROUND_ACTIVITY, APP_B_33.FOREGROUND_ACTIVITY);
547     }
548 
549     @Test
testPendingIntentBroadcastActivity_appBIsForegroundAndTryPassBalOnIntent_isBlocked()550     public void testPendingIntentBroadcastActivity_appBIsForegroundAndTryPassBalOnIntent_isBlocked() {
551         // Start AppB foreground activity
552         Intent intent = new Intent();
553         intent.setComponent(APP_B.FOREGROUND_ACTIVITY);
554         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
555         mContext.startActivity(intent);
556         boolean result = waitForActivityFocused(APP_B.FOREGROUND_ACTIVITY);
557         assertTrue("Not able to start foreground Activity", result);
558         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
559 
560         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
561         // activity in App A.
562         // ALLOW_BAL_EXTRA_ON_PENDING_INTENT will trigger AppA (the creator) to try to allow BAL on
563         // behalf of the sender by adding the BAL option to the Intent's extras, which should have
564         // no effect.
565         sendPendingIntentActivity(APP_A, APP_B,
566                 APP_A.SEND_PENDING_INTENT_RECEIVER_EXTRA.ALLOW_BAL_EXTRA_ON_PENDING_INTENT);
567         result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
568         assertWithMessage("Able to launch background activity").that(result).isFalse();
569         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
570     }
571 
572     @Test
testPendingIntentBroadcastActivity_appBIsFgAndTryPassBalOnIntentWithNullBundleOnPendingIntent_isBlocked()573     public void testPendingIntentBroadcastActivity_appBIsFgAndTryPassBalOnIntentWithNullBundleOnPendingIntent_isBlocked() {
574         // Start AppB foreground activity
575         Intent intent = new Intent();
576         intent.setComponent(APP_B.FOREGROUND_ACTIVITY);
577         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
578         mContext.startActivity(intent);
579         boolean result = waitForActivityFocused(APP_B.FOREGROUND_ACTIVITY);
580         assertTrue("Not able to start foreground Activity", result);
581         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
582 
583         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
584         // activity in App A
585         sendPendingIntentActivity(APP_A, APP_B,
586                 APP_A.SEND_PENDING_INTENT_RECEIVER_EXTRA.ALLOW_BAL_EXTRA_ON_PENDING_INTENT
587                 /* on create by app A */,
588                 APP_B.START_PENDING_INTENT_ACTIVITY_EXTRA.USE_NULL_BUNDLE /* on send by app B */);
589         result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
590         assertWithMessage("Able to launch background activity").that(result).isFalse();
591         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
592     }
593 
594     @Test
testPendingIntentBroadcastActivity_appBIsForegroundAndAllowsBal_isNotBlocked()595     public void testPendingIntentBroadcastActivity_appBIsForegroundAndAllowsBal_isNotBlocked() {
596         // Start AppB foreground activity
597         Intent intent = new Intent();
598         intent.setComponent(APP_B.FOREGROUND_ACTIVITY);
599         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
600         mContext.startActivity(intent);
601         boolean result = waitForActivityFocused(APP_B.FOREGROUND_ACTIVITY);
602         assertTrue("Not able to start foreground Activity", result);
603         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
604 
605         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
606         // activity in App A
607         sendPendingIntentActivity(APP_A, APP_B, APP_B.START_PENDING_INTENT_ACTIVITY_EXTRA.ALLOW_BAL);
608         result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
609         assertTrue("Not able to launch background activity", result);
610         assertTaskStackHasComponents(APP_A.BACKGROUND_ACTIVITY, APP_A.BACKGROUND_ACTIVITY);
611         assertTaskStackHasComponents(APP_B.FOREGROUND_ACTIVITY, APP_B.FOREGROUND_ACTIVITY);
612     }
613 
614     @Test
testPendingIntentBroadcastTimeout_noDelay()615     public void testPendingIntentBroadcastTimeout_noDelay() throws Exception {
616         assertPendingIntentBroadcastTimeoutTest(APP_A, APP_B, 0, true);
617     }
618 
619     @Test
620     @FlakyTest(bugId = 141344170)
testPendingIntentBroadcastTimeout_delay1s()621     public void testPendingIntentBroadcastTimeout_delay1s() throws Exception {
622         assertPendingIntentBroadcastTimeoutTest(APP_A, APP_B, 1000, true);
623     }
624 
625     @Test
testPendingIntentBroadcastTimeout_delay12s()626     public void testPendingIntentBroadcastTimeout_delay12s() throws Exception {
627         // This test is testing that activity start is blocked after broadcast allowlist token
628         // timeout. Before the timeout, the start would be allowed because app B (the PI sender) was
629         // in the foreground during PI send, so app A (the PI creator) would have
630         // (10s * hw_multiplier) to start background activity starts.
631         assertPendingIntentBroadcastTimeoutTest(APP_A, APP_B, 12000 * HW_TIMEOUT_MULTIPLIER, false);
632     }
633 
634     @Test
testPendingIntentBroadcast_appBIsBackground()635     public void testPendingIntentBroadcast_appBIsBackground() throws Exception {
636         EventReceiver receiver = new EventReceiver(
637                 Event.APP_A_START_BACKGROUND_ACTIVITY_BROADCAST_RECEIVED);
638 
639         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
640         // activity in App A
641         sendPendingIntentBroadcast(APP_A, 0, receiver.getNotifier());
642 
643         // Waits for final hoop in AppA to start looking for activity, otherwise it could succeed
644         // if the broadcast took long time to get executed (which may happen after boot).
645         receiver.waitForEventOrThrow(BROADCAST_DELIVERY_TIMEOUT_MS);
646         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
647         assertFalse("Should not able to launch background activity", result);
648         assertTaskStackIsEmpty(APP_A.BACKGROUND_ACTIVITY);
649     }
650 
651     /**
652      * Returns a list of alive users on the device
653      */
getAliveUsers()654     private List<UserInfo> getAliveUsers() {
655         // Setting the CREATE_USERS permission in AndroidManifest.xml has no effect when the test
656         // is run through the CTS harness, so instead adopt it as a shell permission. We use
657         // the CREATE_USERS permission instead of MANAGE_USERS because the shell can never use
658         // MANAGE_USERS.
659         UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
660         uiAutomation.adoptShellPermissionIdentity(Manifest.permission.CREATE_USERS);
661         List<UserInfo> userList = mContext.getSystemService(UserManager.class).getAliveUsers();
662         uiAutomation.dropShellPermissionIdentity();
663         return userList;
664     }
665 
666     /**
667      * Removes the guest user from the device if present
668      */
removeGuestUser()669     private void removeGuestUser() {
670         List<UserInfo> userList = getAliveUsers();
671         for (UserInfo info : userList) {
672             if (info.isGuest()) {
673                 removeUser(info.id);
674                 // Device is only allowed to have one alive guest user, so stop if it's found
675                 break;
676             }
677         }
678     }
679 
680     /**
681      * Removes a user from the device given their ID
682      */
removeUser(int userId)683     private void removeUser(int userId) {
684         executeShellCommand(String.format("pm remove-user %d", userId));
685     }
686 
687     @Test
testDeviceOwner()688     public void testDeviceOwner() throws Exception {
689         assumeTrue("Device doesn't support FEATURE_DEVICE_ADMIN",
690                 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
691 
692         // Remove existing guest user. The device may already have a guest present if it is
693         // configured with config_guestUserAutoCreated.
694         //
695         // In production flow the DO can only be created before device provisioning finishes
696         // (e.g. during SUW), and we make sure the guest user in only created after the device
697         // provision is finished. Ideally this test would use the provisioning flow and Device
698         // Owner (DO) creation in a similar manner as that of production flow.
699         removeGuestUser();
700 
701         // This test might be running as current user (on devices that use headless system user
702         // mode), so it needs to get the context for the system user.
703         Context context = runWithShellPermissionIdentity(
704                 () -> mContext.createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0),
705                 INTERACT_ACROSS_USERS);
706 
707         String doComponent = APP_A.SIMPLE_ADMIN_RECEIVER.flattenToString();
708         Log.d(TAG, "Setting DO as " + doComponent);
709         String cmd = "dpm set-device-owner --user " + UserHandle.USER_SYSTEM + " " + doComponent;
710         try {
711             String cmdResult = runShellCommandOrThrow(cmd);
712             assertWithMessage("Result of '%s'", cmd).that(cmdResult).contains("Success");
713         } catch (AssertionError e) {
714             // If failed to set the device owner, stop proceeding to the test case.
715             // Log the error info so that we can investigate further in the future.
716             Log.d(TAG, "Failed to set device owner.", e);
717             String cmdResult = runShellCommandOrThrow("pm list user");
718             Log.d(TAG, "users: " + cmdResult);
719             cmdResult = runShellCommandOrThrow("dpm list-owner");
720             Log.d(TAG, "device owners: " + cmdResult);
721             throw new AssumptionViolatedException("This test needs to be able to set device owner");
722         }
723 
724         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
725         // activity in App A
726         EventReceiver receiver = new EventReceiver(
727                 Event.APP_A_START_BACKGROUND_ACTIVITY_BROADCAST_RECEIVED);
728         Intent intent = new Intent()
729                 .setComponent(APP_A.START_ACTIVITY_RECEIVER)
730                 .putExtra(EVENT_NOTIFIER_EXTRA, receiver.getNotifier());
731 
732         Log.d(TAG, "Launching " + intent + " on " + context.getUser());
733         // Must run with IAC permission as it might be a context from other user
734         runWithShellPermissionIdentity(() -> context.sendBroadcast(intent), INTERACT_ACROSS_USERS);
735 
736         // Waits for final hoop in AppA to start looking for activity
737         receiver.waitForEventOrThrow(BROADCAST_DELIVERY_TIMEOUT_MS);
738         boolean actualResult = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
739 
740         if (UserManager.isHeadlessSystemUserMode()) {
741             assertWithMessage("Launched bg activity (%s) for (headless) system user",
742                     APP_A.BACKGROUND_ACTIVITY).that(actualResult).isFalse();
743             assertTaskDoesNotHaveVisibleComponents(APP_A.BACKGROUND_ACTIVITY,
744                     APP_A.BACKGROUND_ACTIVITY);
745         } else {
746             assertWithMessage("Launched bg activity (%s) for (full) system user",
747                     APP_A.BACKGROUND_ACTIVITY).that(actualResult).isTrue();
748             assertTaskStackHasComponents(APP_A.BACKGROUND_ACTIVITY, APP_A.BACKGROUND_ACTIVITY);
749         }
750     }
751 
752     @Test
testAppCannotStartBgActivityAfterHomeButton()753     public void testAppCannotStartBgActivityAfterHomeButton() throws Exception {
754         Intent intent = new Intent();
755         intent.setComponent(APP_A.RELAUNCHING_ACTIVITY);
756         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
757         mContext.startActivity(intent);
758 
759         assertTrue("Main activity not started", waitUntilForegroundChanged(
760                 APP_A.APP_PACKAGE_NAME, true, ACTIVITY_START_TIMEOUT_MS));
761         assertActivityFocused(APP_A.RELAUNCHING_ACTIVITY);
762 
763         // Click home button, and test app activity onPause() will try to start a background
764         // activity, but we expect this will be blocked BAL logic in system, as app cannot start
765         // any background activity even within grace period after pressing home button.
766         pressHomeAndWaitHomeResumed();
767 
768         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
769         assertFalse("Should not able to launch background activity", result);
770     }
771 
772     // Check picture-in-picture(PIP) won't allow to start BAL after pressing home.
773     @Test
testPipCannotStartAfterHomeButton()774     public void testPipCannotStartAfterHomeButton() throws Exception {
775 
776         Intent intent = new Intent();
777         intent.setComponent(APP_A.PIP_ACTIVITY);
778         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
779         mContext.startActivity(intent);
780 
781         assertTrue("Pip activity not started", waitUntilForegroundChanged(
782                 APP_A.APP_PACKAGE_NAME, true, ACTIVITY_START_TIMEOUT_MS));
783 
784         // Click home button, and test app activity onPause() will trigger pip window,
785         // test will will try to start background activity, but we expect the background activity
786         // will be blocked even the app has a visible pip window, as we do not allow background
787         // activity to be started after pressing home button.
788         pressHomeAndWaitHomeResumed();
789 
790         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
791         assertFalse("Should not able to launch background activity", result);
792     }
793 
794     @Test
795     @AsbSecurityTest(cveBugId = 271576718)
testPipCannotStartFromBackground()796     public void testPipCannotStartFromBackground() throws Exception {
797         Intent intent = new Intent();
798         intent.setComponent(APP_A.LAUNCH_INTO_PIP_ACTIVITY);
799         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
800         mContext.startActivity(intent);
801 
802         boolean result = waitForActivityFocused(APP_A.LAUNCH_INTO_PIP_ACTIVITY);
803         assertTrue("Should not able to launch background activity", result);
804 
805         pressHomeAndWaitHomeResumed();
806         result = waitForActivityFocused(APP_A.LAUNCH_INTO_PIP_ACTIVITY);
807         assertFalse("Activity should be in background", result);
808 
809         Intent broadcast = new Intent(APP_A.LAUNCH_INTO_PIP_ACTIONS.LAUNCH_INTO_PIP);
810         mContext.sendBroadcast(broadcast);
811         result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
812         assertFalse("Should not able to launch LaunchIntoPip activity", result);
813 
814         assertPinnedStackDoesNotExist();
815     }
816 
817     // Check that a presentation on a virtual display won't allow BAL after pressing home.
818     @Test
testPrivateVirtualDisplayCannotStartAfterHomeButton()819     public void testPrivateVirtualDisplayCannotStartAfterHomeButton() throws Exception {
820         Intent intent = new Intent();
821         intent.setComponent(APP_A.VIRTUAL_DISPLAY_ACTIVITY);
822         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
823         intent.putExtra(APP_A.VIRTUAL_DISPLAY_ACTIVITY_EXTRA.USE_PUBLIC_PRESENTATION, false);
824         mContext.startActivity(intent);
825 
826         assertTrue("VirtualDisplay activity not started", waitUntilForegroundChanged(
827                 APP_A.APP_PACKAGE_NAME, true, ACTIVITY_START_TIMEOUT_MS));
828 
829         // Click home button, and test app activity onPause() will trigger which tries to launch
830         // the background activity.
831         pressHomeAndWaitHomeResumed();
832 
833         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
834         assertFalse("Should not able to launch background activity", result);
835     }
836 
837     // Check that a presentation on a virtual display won't allow BAL after pressing home.
838     @Test
testPublicVirtualDisplayCannotStartAfterHomeButton()839     public void testPublicVirtualDisplayCannotStartAfterHomeButton() throws Exception {
840         Intent intent = new Intent();
841         intent.setComponent(APP_A.VIRTUAL_DISPLAY_ACTIVITY);
842         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
843         intent.putExtra(APP_A.VIRTUAL_DISPLAY_ACTIVITY_EXTRA.USE_PUBLIC_PRESENTATION, true);
844         mContext.startActivity(intent);
845 
846         assertTrue("VirtualDisplay activity not started", waitUntilForegroundChanged(
847                 APP_A.APP_PACKAGE_NAME, true, ACTIVITY_START_TIMEOUT_MS));
848 
849         // Click home button, and test app activity onPause() will trigger which tries to launch
850         // the background activity.
851         pressHomeAndWaitHomeResumed();
852 
853         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
854         assertFalse("Should not able to launch background activity", result);
855     }
856 
857 
858     // Test manage space pending intent created by system cannot bypass BAL check.
859     @Test
testManageSpacePendingIntentNoBalAllowed()860     public void testManageSpacePendingIntentNoBalAllowed() throws Exception {
861         setupPendingIntentService(APP_A);
862         runWithShellPermissionIdentity(() -> {
863             runShellCommandOrThrow("cmd appops set " + APP_A.APP_PACKAGE_NAME
864                     + " android:manage_external_storage allow");
865         });
866         // Make sure AppA paused at least 10s so it can't start activity because of grace period.
867         Thread.sleep(1000 * 10);
868         mBackgroundActivityTestService.getAndStartManageSpaceActivity();
869         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
870         assertFalse("Should not able to launch background activity", result);
871         assertTaskStackIsEmpty(APP_A.BACKGROUND_ACTIVITY);
872     }
873 
874     @Test
testAppWidgetConfigNoBalBypass()875     public void testAppWidgetConfigNoBalBypass() throws Exception {
876         // Click bind widget button and then go home screen so app A will enter background state
877         // with bind widget ability.
878         EventReceiver receiver = new EventReceiver(Event.APP_A_START_WIDGET_CONFIG_ACTIVITY);
879         clickAllowBindWidget(APP_A, receiver.getNotifier());
880         pressHomeAndWaitHomeResumed();
881 
882         // After pressing home button, wait for appA to start widget config activity.
883         receiver.waitForEventOrThrow(1000 * 30);
884 
885         boolean result = waitForActivityFocused(APP_A.BACKGROUND_ACTIVITY);
886         assertFalse("Should not able to launch background activity", result);
887         assertTaskStackIsEmpty(APP_A.BACKGROUND_ACTIVITY);
888     }
889 
890     @Test
testBalOptInBindToService_whenOptedIn_allowsActivityStarts()891     public void testBalOptInBindToService_whenOptedIn_allowsActivityStarts() {
892         Intent appcIntent = new Intent()
893                 .setComponent(APP_C_FOREGROUND_ACTIVITY)
894                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
895                 .putExtra("android.server.wm.backgroundactivity.appc.ALLOW_BAL", true);
896 
897         mContext.startActivity(appcIntent);
898         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
899     }
900 
901     @Test
testBalOptInBindToService_whenNotOptedIn_blocksActivityStarts()902     public void testBalOptInBindToService_whenNotOptedIn_blocksActivityStarts() {
903         Intent appcIntent = new Intent()
904                 .setComponent(APP_C_FOREGROUND_ACTIVITY)
905                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
906 
907         mContext.startActivity(appcIntent);
908         assertActivityNotFocused(APP_A.BACKGROUND_ACTIVITY);
909     }
910 
911     @Test
testBalOptInBindToService_whenNotOptedInAndSdk33_allowsActivityStart()912     public void testBalOptInBindToService_whenNotOptedInAndSdk33_allowsActivityStart() {
913         Intent appcIntent = new Intent()
914                 .setComponent(APP_C_33_FOREGROUND_ACTIVITY)
915                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
916 
917         mContext.startActivity(appcIntent);
918         assertActivityFocused(APP_A.BACKGROUND_ACTIVITY);
919     }
920 
clickAllowBindWidget(Components appA, ResultReceiver resultReceiver)921     private void clickAllowBindWidget(Components appA, ResultReceiver resultReceiver)
922             throws Exception {
923         PackageManager pm = mContext.getPackageManager();
924         Assume.assumeTrue(pm.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS));
925         // Skip on auto and TV devices only as they don't support appwidget bind.
926         Assume.assumeFalse(pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
927         Assume.assumeFalse(pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY));
928 
929         // Create appWidgetId so we can send it to appA, to request bind widget and start config
930         // activity.
931         UiDevice device = UiDevice.getInstance(mInstrumentation);
932         AppWidgetHost appWidgetHost = new AppWidgetHost(mContext, 0);
933         final int appWidgetId = appWidgetHost.allocateAppWidgetId();
934         Intent appWidgetIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
935         appWidgetIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
936         appWidgetIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER,
937                 appA.WIDGET_PROVIDER);
938 
939         Intent intent = new Intent();
940         intent.setComponent(appA.WIDGET_CONFIG_TEST_ACTIVITY);
941         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
942         intent.putExtra(Intent.EXTRA_INTENT, appWidgetIntent);
943         intent.putExtra(EVENT_NOTIFIER_EXTRA, resultReceiver);
944         mContext.startActivity(intent);
945 
946         // Find settings package and bind widget activity and click the create button.
947         String settingsPkgName = "";
948         List<ResolveInfo> ris = pm.queryIntentActivities(appWidgetIntent,
949                 PackageManager.MATCH_DEFAULT_ONLY);
950         for (ResolveInfo ri : ris) {
951             if (ri.activityInfo.name.contains("AllowBindAppWidgetActivity")) {
952                 settingsPkgName = ri.activityInfo.packageName;
953             }
954         }
955         assertNotEquals("Cannot find settings app", "", settingsPkgName);
956 
957         if (!device.wait(Until.hasObject(By.pkg(settingsPkgName)), 1000 * 10)) {
958             fail("Unable to start AllowBindAppWidgetActivity");
959         }
960         boolean buttonClicked = false;
961         BySelector selector = By.clickable(true);
962         List<UiObject2> objects = device.findObjects(selector);
963         for (UiObject2 object : objects) {
964             String objectText = object.getText();
965             if (objectText == null) {
966                 continue;
967             }
968             if (objectText.equalsIgnoreCase("CREATE") || objectText.equalsIgnoreCase("ALLOW")) {
969                 object.click();
970                 buttonClicked = true;
971                 break;
972             }
973         }
974         if (!device.wait(Until.gone(By.pkg(settingsPkgName)), 1000 * 10) || !buttonClicked) {
975             fail("Create' button not found/clicked");
976         }
977 
978         // Wait the bind widget activity goes away.
979         waitUntilForegroundChanged(settingsPkgName, false,
980                 ACTIVITY_NOT_RESUMED_TIMEOUT_MS);
981     }
982 
pressHomeAndWaitHomeResumed()983     private void pressHomeAndWaitHomeResumed() {
984         assumeSetupComplete();
985         pressHomeButton();
986         mWmState.waitForHomeActivityVisible();
987         mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
988     }
989 
assumeSetupComplete()990     private void assumeSetupComplete() {
991         assumeThat(Settings.Secure.getInt(mContext.getContentResolver(),
992                 Settings.Secure.USER_SETUP_COMPLETE, 0), is(1));
993     }
994 
checkPackageResumed(String pkg)995     private boolean checkPackageResumed(String pkg) {
996         WindowManagerStateHelper helper = new WindowManagerStateHelper();
997         helper.computeState();
998         return ComponentName.unflattenFromString(
999                 helper.getFocusedActivity()).getPackageName().equals(pkg);
1000     }
1001 
1002     // Return true if the state of the package is changed to target state.
waitUntilForegroundChanged(String targetPkg, boolean toBeResumed, int timeout)1003     private boolean waitUntilForegroundChanged(String targetPkg, boolean toBeResumed, int timeout)
1004             throws Exception {
1005         long startTime = System.currentTimeMillis();
1006         while (checkPackageResumed(targetPkg) != toBeResumed) {
1007             if (System.currentTimeMillis() - startTime < timeout) {
1008                 Thread.sleep(100);
1009             } else {
1010                 return false;
1011             }
1012         }
1013         return true;
1014     }
1015 
assertActivityNotResumed(Components appA)1016     private void assertActivityNotResumed(Components appA) throws Exception {
1017         assertFalse("Test activity is resumed",
1018                 waitUntilForegroundChanged(appA.APP_PACKAGE_NAME, true,
1019                         ACTIVITY_NOT_RESUMED_TIMEOUT_MS));
1020     }
1021 
pressHomeAndResumeAppSwitch()1022     private void pressHomeAndResumeAppSwitch() {
1023         // Press home key to ensure stopAppSwitches is called because the last-stop-app-switch-time
1024         // is a criteria of allowing background start.
1025         pressHomeButton();
1026         // Resume the stopped state (it won't affect last-stop-app-switch-time) so we don't need to
1027         // wait extra time to prevent the next launch from being delayed.
1028         resumeAppSwitches();
1029         mWmState.waitForHomeActivityVisible();
1030         // Resuming app switches again after home became visible because the previous call might
1031         // have raced with pressHomeButton().
1032         // TODO(b/155454710): Remove previous call after making sure all the tests don't depend on
1033         // the timing here.
1034         resumeAppSwitches();
1035     }
1036 
assertPendingIntentBroadcastTimeoutTest(Components appA, android.server.wm.backgroundactivity.appb.Components appB, int delayMs, boolean expectedResult)1037     private void assertPendingIntentBroadcastTimeoutTest(Components appA,
1038             android.server.wm.backgroundactivity.appb.Components appB,
1039             int delayMs, boolean expectedResult)
1040             throws TimeoutException {
1041         // Start AppB foreground activity
1042         Intent intent = new Intent();
1043         intent.setComponent(appB.FOREGROUND_ACTIVITY);
1044         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1045         mContext.startActivity(intent);
1046         boolean result = waitForActivityFocused(appB.FOREGROUND_ACTIVITY);
1047         assertTrue("Not able to start foreground Activity", result);
1048         assertTaskStackHasComponents(appB.FOREGROUND_ACTIVITY, appB.FOREGROUND_ACTIVITY);
1049         EventReceiver receiver = new EventReceiver(
1050                 Event.APP_A_START_BACKGROUND_ACTIVITY_BROADCAST_RECEIVED);
1051 
1052         // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start
1053         // activity in App A
1054         sendPendingIntentBroadcast(appA, delayMs, receiver.getNotifier(), true);
1055 
1056         // Waits for final hoop in AppA to start looking for activity
1057         receiver.waitForEventOrThrow(BROADCAST_DELIVERY_TIMEOUT_MS);
1058         result = waitForActivityFocused(ACTIVITY_FOCUS_TIMEOUT_MS + delayMs,
1059                 appA.BACKGROUND_ACTIVITY);
1060         assertEquals(expectedResult, result);
1061         if (expectedResult) {
1062             assertTaskStackHasComponents(appA.BACKGROUND_ACTIVITY, appA.BACKGROUND_ACTIVITY);
1063         } else {
1064             assertTaskStackIsEmpty(appA.BACKGROUND_ACTIVITY);
1065         }
1066     }
1067 
setupPendingIntentService(Components appA)1068     private void setupPendingIntentService(Components appA) throws Exception {
1069         Intent bindIntent = new Intent();
1070         bindIntent.setComponent(appA.BACKGROUND_ACTIVITY_TEST_SERVICE);
1071         final CountDownLatch bindLatch = new CountDownLatch(1);
1072 
1073         mBalServiceConnection = new ServiceConnection() {
1074             @Override
1075             public void onServiceConnected(ComponentName name, IBinder service) {
1076                 mBackgroundActivityTestService =
1077                         IBackgroundActivityTestService.Stub.asInterface(service);
1078                 bindLatch.countDown();
1079             }
1080             @Override
1081             public void onServiceDisconnected(ComponentName name) {
1082                 mBackgroundActivityTestService = null;
1083             }
1084         };
1085         boolean success = mContext.bindService(bindIntent, mBalServiceConnection,
1086                 Context.BIND_AUTO_CREATE);
1087         assertTrue(success);
1088         assertTrue("Timeout connecting to test service",
1089                 bindLatch.await(1000, TimeUnit.MILLISECONDS));
1090     }
1091 
startPendingIntentSenderActivity(Components appA, android.server.wm.backgroundactivity.appb.Components appB, boolean allowBal)1092     private void startPendingIntentSenderActivity(Components appA,
1093             android.server.wm.backgroundactivity.appb.Components appB, boolean allowBal)
1094             throws Exception {
1095         setupPendingIntentService(appA);
1096         // Get a PendingIntent created by appA.
1097         final PendingIntent pi;
1098         try {
1099             pi = mBackgroundActivityTestService.generatePendingIntent(false);
1100         } catch (Exception e) {
1101             throw new AssertionError(e);
1102         }
1103 
1104         // Start app B's activity so it runs send() on PendingIntent created by app A.
1105         Intent secondIntent = new Intent();
1106         secondIntent.setComponent(appB.START_PENDING_INTENT_ACTIVITY);
1107         secondIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1108         secondIntent.putExtra(appB.START_PENDING_INTENT_RECEIVER_EXTRA.PENDING_INTENT, pi);
1109         secondIntent.putExtra(appB.START_PENDING_INTENT_ACTIVITY_EXTRA.ALLOW_BAL, allowBal);
1110         mContext.startActivity(secondIntent);
1111     }
1112 
sendPendingIntentActivity(Components appA, android.server.wm.backgroundactivity.appb.Components appB, String... booleanExtras)1113     private void sendPendingIntentActivity(Components appA,
1114             android.server.wm.backgroundactivity.appb.Components appB,
1115             String... booleanExtras) {
1116         Intent intent = new Intent();
1117         intent.setComponent(appA.SEND_PENDING_INTENT_RECEIVER);
1118         intent.putExtra(appA.SEND_PENDING_INTENT_RECEIVER_EXTRA.IS_BROADCAST, false);
1119         intent.putExtra(appA.SEND_PENDING_INTENT_RECEIVER_EXTRA.APP_B_PACKAGE,
1120                 appB.APP_PACKAGE_NAME);
1121         for (String booleanExtra : booleanExtras) {
1122             intent.putExtra(booleanExtra, true);
1123         }
1124         Log.i(
1125                 "BackgroundActivityLaunchTest",
1126                 "Send broadcast to "
1127                         + intent.getComponent()
1128                         + " with extras: "
1129                         + intent.getExtras());
1130         mContext.sendBroadcast(intent);
1131     }
1132 
sendPendingIntentBroadcast(Components appA, int delayMs, @Nullable ResultReceiver eventNotifier)1133     private void sendPendingIntentBroadcast(Components appA, int delayMs,
1134             @Nullable ResultReceiver eventNotifier) {
1135         sendPendingIntentBroadcast(appA, delayMs, eventNotifier, false);
1136     }
1137 
sendPendingIntentBroadcast(Components appA, int delayMs, @Nullable ResultReceiver eventNotifier, boolean allowBalFromStartingApp)1138     private void sendPendingIntentBroadcast(Components appA, int delayMs,
1139             @Nullable ResultReceiver eventNotifier,  boolean allowBalFromStartingApp) {
1140         Intent intent = new Intent();
1141         intent.setComponent(appA.SEND_PENDING_INTENT_RECEIVER);
1142         intent.putExtra(appA.SEND_PENDING_INTENT_RECEIVER_EXTRA.IS_BROADCAST, true);
1143         if (allowBalFromStartingApp) {
1144             intent.putExtra(APP_B.START_PENDING_INTENT_ACTIVITY_EXTRA.ALLOW_BAL, true);
1145         }
1146         if (delayMs > 0) {
1147             intent.putExtra(appA.START_ACTIVITY_RECEIVER_EXTRA.START_ACTIVITY_DELAY_MS, delayMs);
1148         }
1149         intent.putExtra(EVENT_NOTIFIER_EXTRA, eventNotifier);
1150         mContext.sendBroadcast(intent);
1151     }
1152 }
1153