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.app.AppOpsManager.MODE_ALLOWED; 20 import static android.app.AppOpsManager.MODE_ERRORED; 21 import static android.server.wm.UiDeviceUtils.pressHomeButton; 22 import static android.server.wm.WindowManagerState.STATE_INITIALIZING; 23 import static android.server.wm.backgroundactivity.appa.Components.APP_A_BACKGROUND_ACTIVITY; 24 import static android.server.wm.backgroundactivity.appa.Components.APP_A_FOREGROUND_ACTIVITY; 25 import static android.server.wm.backgroundactivity.appa.Components.APP_A_SECOND_BACKGROUND_ACTIVITY; 26 import static android.server.wm.backgroundactivity.appa.Components.APP_A_SEND_PENDING_INTENT_RECEIVER; 27 import static android.server.wm.backgroundactivity.appa.Components.APP_A_SIMPLE_ADMIN_RECEIVER; 28 import static android.server.wm.backgroundactivity.appa.Components.APP_A_START_ACTIVITY_RECEIVER; 29 import static android.server.wm.backgroundactivity.appa.Components.ForegroundActivity.ACTION_FINISH_ACTIVITY; 30 import static android.server.wm.backgroundactivity.appa.Components.ForegroundActivity.ACTION_LAUNCH_BACKGROUND_ACTIVITIES; 31 import static android.server.wm.backgroundactivity.appa.Components.ForegroundActivity.LAUNCH_BACKGROUND_ACTIVITY_EXTRA; 32 import static android.server.wm.backgroundactivity.appa.Components.ForegroundActivity.LAUNCH_INTENTS_EXTRA; 33 import static android.server.wm.backgroundactivity.appa.Components.ForegroundActivity.LAUNCH_SECOND_BACKGROUND_ACTIVITY_EXTRA; 34 import static android.server.wm.backgroundactivity.appa.Components.ForegroundActivity.RELAUNCH_FOREGROUND_ACTIVITY_EXTRA; 35 import static android.server.wm.backgroundactivity.appa.Components.ForegroundActivity.START_ACTIVITY_FROM_FG_ACTIVITY_DELAY_MS_EXTRA; 36 import static android.server.wm.backgroundactivity.appa.Components.ForegroundActivity.START_ACTIVITY_FROM_FG_ACTIVITY_NEW_TASK_EXTRA; 37 import static android.server.wm.backgroundactivity.appa.Components.SendPendingIntentReceiver.IS_BROADCAST_EXTRA; 38 import static android.server.wm.backgroundactivity.appa.Components.StartBackgroundActivityReceiver.START_ACTIVITY_DELAY_MS_EXTRA; 39 import static android.server.wm.backgroundactivity.appb.Components.APP_B_FOREGROUND_ACTIVITY; 40 import static android.server.wm.backgroundactivity.common.CommonComponents.EVENT_NOTIFIER_EXTRA; 41 42 import static com.android.compatibility.common.util.SystemUtil.runShellCommand; 43 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; 44 45 import static com.google.common.truth.Truth.assertThat; 46 47 import static org.junit.Assert.assertEquals; 48 import static org.junit.Assert.assertFalse; 49 import static org.junit.Assert.assertNull; 50 import static org.junit.Assert.assertTrue; 51 52 import android.Manifest; 53 import android.app.UiAutomation; 54 import android.content.ComponentName; 55 import android.content.Intent; 56 import android.content.pm.PackageManager; 57 import android.content.pm.UserInfo; 58 import android.os.ResultReceiver; 59 import android.os.UserManager; 60 import android.platform.test.annotations.Presubmit; 61 import android.platform.test.annotations.SystemUserOnly; 62 import android.server.wm.backgroundactivity.common.CommonComponents.Event; 63 import android.server.wm.backgroundactivity.common.EventReceiver; 64 65 import androidx.annotation.Nullable; 66 import androidx.test.filters.FlakyTest; 67 import androidx.test.platform.app.InstrumentationRegistry; 68 69 import com.android.compatibility.common.util.AppOpsUtils; 70 71 import org.junit.After; 72 import org.junit.Before; 73 import org.junit.Ignore; 74 import org.junit.Test; 75 76 import java.util.List; 77 import java.util.concurrent.TimeoutException; 78 import java.util.stream.Stream; 79 80 /** 81 * This class covers all test cases for starting/blocking background activities. 82 * As instrumentation tests started by shell are whitelisted to allow starting background activity, 83 * tests can't be done in this app alone. 84 * Hence, there are 2 extra apps, appA and appB. This class will send commands to appA/appB, for 85 * example, send a broadcast to appA and ask it to start a background activity, and we will monitor 86 * the result and see if it starts an activity successfully. 87 */ 88 @Presubmit 89 public class BackgroundActivityLaunchTest extends ActivityManagerTestBase { 90 91 private static final int ACTIVITY_FOCUS_TIMEOUT_MS = 3000; 92 private static final String APP_A_PACKAGE_NAME = APP_A_FOREGROUND_ACTIVITY.getPackageName(); 93 private static final long ACTIVITY_BG_START_GRACE_PERIOD_MS = 10 * 1000; 94 private static final int ACTIVITY_START_TIMEOUT_MS = 5000; 95 private static final int ACTIVITY_NOT_RESUMED_TIMEOUT_MS = 5000; 96 97 private static final String TEST_PACKAGE_APP_A = "android.server.wm.backgroundactivity.appa"; 98 private static final String TEST_PACKAGE_APP_B = "android.server.wm.backgroundactivity.appb"; 99 public static final ComponentName APP_A_RELAUNCHING_ACTIVITY = 100 new ComponentName(TEST_PACKAGE_APP_A, 101 "android.server.wm.backgroundactivity.appa.RelaunchingActivity"); 102 public static final ComponentName APP_A_PIP_ACTIVITY = 103 new ComponentName(TEST_PACKAGE_APP_A, 104 "android.server.wm.backgroundactivity.appa.PipActivity"); 105 public static final ComponentName APP_A_VIRTUAL_DISPLAY_ACTIVITY = 106 new ComponentName(TEST_PACKAGE_APP_A, 107 "android.server.wm.backgroundactivity.appa.VirtualDisplayActivity"); 108 private static final String SHELL_PACKAGE = "com.android.shell"; 109 110 /** 111 * Tests can be executed as soon as the device has booted. When that happens the broadcast queue 112 * is long and it takes some time to process the broadcast we just sent. 113 */ 114 private static final int BROADCAST_DELIVERY_TIMEOUT_MS = 60000; 115 116 @Override 117 @Before setUp()118 public void setUp() throws Exception { 119 // disable SAW appopp for AppA (it's granted autonatically when installed in CTS) 120 AppOpsUtils.setOpMode(APP_A_PACKAGE_NAME, "android:system_alert_window", MODE_ERRORED); 121 assertEquals(AppOpsUtils.getOpMode(APP_A_PACKAGE_NAME, "android:system_alert_window"), 122 MODE_ERRORED); 123 124 super.setUp(); 125 assertNull(mWmState.getTaskByActivity(APP_A_BACKGROUND_ACTIVITY)); 126 assertNull(mWmState.getTaskByActivity(APP_A_FOREGROUND_ACTIVITY)); 127 assertNull(mWmState.getTaskByActivity(APP_B_FOREGROUND_ACTIVITY)); 128 129 runShellCommand("cmd deviceidle tempwhitelist -d 100000 " 130 + APP_A_FOREGROUND_ACTIVITY.getPackageName()); 131 runShellCommand("cmd deviceidle tempwhitelist -d 100000 " 132 + APP_B_FOREGROUND_ACTIVITY.getPackageName()); 133 } 134 135 @After tearDown()136 public void tearDown() throws Exception { 137 // We do this before anything else, because having an active device owner can prevent us 138 // from being able to force stop apps. (b/142061276) 139 runWithShellPermissionIdentity(() -> { 140 runShellCommand("dpm remove-active-admin --user current " 141 + APP_A_SIMPLE_ADMIN_RECEIVER.flattenToString()); 142 }); 143 144 stopTestPackage(TEST_PACKAGE_APP_A); 145 stopTestPackage(TEST_PACKAGE_APP_B); 146 AppOpsUtils.reset(APP_A_PACKAGE_NAME); 147 AppOpsUtils.reset(SHELL_PACKAGE); 148 } 149 150 @Test testBackgroundActivityBlocked()151 public void testBackgroundActivityBlocked() throws Exception { 152 // Start AppA background activity and blocked 153 Intent intent = new Intent(); 154 intent.setComponent(APP_A_START_ACTIVITY_RECEIVER); 155 mContext.sendBroadcast(intent); 156 boolean result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 157 assertFalse("Should not able to launch background activity", result); 158 assertTaskStack(null, APP_A_BACKGROUND_ACTIVITY); 159 } 160 161 @Test testStartBgActivity_usingStartActivitiesFromBackgroundPermission()162 public void testStartBgActivity_usingStartActivitiesFromBackgroundPermission() 163 throws Exception { 164 // Disable SAW app op for shell, since that can also allow starting activities from bg. 165 AppOpsUtils.setOpMode(SHELL_PACKAGE, "android:system_alert_window", MODE_ERRORED); 166 167 // Launch the activity via a shell command, this way the system doesn't have info on which 168 // app launched the activity and thus won't use instrumentation privileges to launch it. But 169 // the shell has the START_ACTIVITIES_FROM_BACKGROUND permission, so we expect it to 170 // succeed. 171 // See testBackgroundActivityBlocked() for a case where an app without the 172 // START_ACTIVITIES_FROM_BACKGROUND permission is blocked from launching the activity from 173 // the background. 174 launchActivity(APP_A_BACKGROUND_ACTIVITY); 175 176 // If the activity launches, it means the START_ACTIVITIES_FROM_BACKGROUND permission works. 177 assertEquals("Launched activity should be at the top", 178 ComponentNameUtils.getActivityName(APP_A_BACKGROUND_ACTIVITY), 179 mWmState.getTopActivityName(0)); 180 } 181 182 @Test 183 @FlakyTest(bugId = 155454710) testBackgroundActivityNotBlockedWithinGracePeriod()184 public void testBackgroundActivityNotBlockedWithinGracePeriod() throws Exception { 185 // Start AppA foreground activity 186 Intent firstIntent = new Intent(); 187 firstIntent.setComponent(APP_A_FOREGROUND_ACTIVITY); 188 firstIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 189 mContext.startActivity(firstIntent); 190 boolean firstResult = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY); 191 assertTrue("Not able to start foreground activity", firstResult); 192 // Don't press home button to avoid stop app switches 193 mContext.sendBroadcast(new Intent(ACTION_FINISH_ACTIVITY)); 194 mWmState.waitAndAssertActivityRemoved(APP_A_FOREGROUND_ACTIVITY); 195 Intent secondIntent = new Intent(); 196 secondIntent.setComponent(APP_A_START_ACTIVITY_RECEIVER); 197 198 mContext.sendBroadcast(secondIntent); 199 boolean secondResult = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 200 assertTrue("Should be able to launch background activity", secondResult); 201 } 202 203 @Test testBackgroundActivityNotBlockedWhenSystemAlertWindowGranted()204 public void testBackgroundActivityNotBlockedWhenSystemAlertWindowGranted() throws Exception { 205 // enable appopp for SAW for this test 206 AppOpsUtils.setOpMode(APP_A_PACKAGE_NAME, "android:system_alert_window", MODE_ALLOWED); 207 assertEquals(AppOpsUtils.getOpMode(APP_A_PACKAGE_NAME, "android:system_alert_window"), 208 MODE_ALLOWED); 209 210 // Start AppA background activity successfully as the package has SAW 211 Intent intent = new Intent(); 212 intent.setComponent(APP_A_START_ACTIVITY_RECEIVER); 213 mContext.sendBroadcast(intent); 214 boolean result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 215 assertTrue("Not able to start foreground activity", result); 216 } 217 218 @Test testBackgroundActivityNotBlockedWhenForegroundActivityExists()219 public void testBackgroundActivityNotBlockedWhenForegroundActivityExists() throws Exception { 220 // Start AppA foreground activity 221 Intent intent = new Intent(); 222 intent.setComponent(APP_A_FOREGROUND_ACTIVITY); 223 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 224 mContext.startActivity(intent); 225 boolean result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY); 226 assertTrue("Not able to start foreground activity", result); 227 assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY); 228 229 // Start AppA background activity successfully as there's a foreground activity 230 intent = new Intent(); 231 intent.setComponent(APP_A_START_ACTIVITY_RECEIVER); 232 mContext.sendBroadcast(intent); 233 result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 234 assertTrue("Not able to launch background activity", result); 235 assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY); 236 assertTaskStack(new ComponentName[]{APP_A_BACKGROUND_ACTIVITY}, APP_A_BACKGROUND_ACTIVITY); 237 } 238 239 @Test testActivityNotBlockedWhenForegroundActivityLaunch()240 public void testActivityNotBlockedWhenForegroundActivityLaunch() throws Exception { 241 // Start foreground activity, and foreground activity able to launch background activity 242 // successfully 243 Intent intent = new Intent(); 244 intent.setComponent(APP_A_FOREGROUND_ACTIVITY); 245 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 246 intent.putExtra(LAUNCH_BACKGROUND_ACTIVITY_EXTRA, true); 247 mContext.startActivity(intent); 248 boolean result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 249 assertTrue("Not able to launch background activity", result); 250 assertTaskStack(new ComponentName[]{APP_A_BACKGROUND_ACTIVITY, APP_A_FOREGROUND_ACTIVITY}, 251 APP_A_FOREGROUND_ACTIVITY); 252 } 253 254 @Test testActivityBroughtToTopOfTaskWhenLaunchedInTheBackground()255 public void testActivityBroughtToTopOfTaskWhenLaunchedInTheBackground() throws Exception { 256 // Start foreground activity, and foreground activity able to launch background activity 257 // successfully 258 Intent intent = new Intent(); 259 intent.setComponent(APP_A_FOREGROUND_ACTIVITY); 260 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 261 mContext.startActivity(intent); 262 boolean result = waitForActivityFocused(ACTIVITY_FOCUS_TIMEOUT_MS, 263 APP_A_FOREGROUND_ACTIVITY); 264 assertTrue("Not able to launch background activity", result); 265 assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY); 266 // We can't resume app switching after pressing home button, otherwise the grace period 267 // will allow the starts. 268 pressHomeAndWaitHomeResumed(); 269 270 mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A_BACKGROUND_ACTIVITY)); 271 272 result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY); 273 assertFalse("Previously foreground Activity should not be able to make it focused", result); 274 result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 275 assertFalse("Previously background Activity should not be able to make it focused", result); 276 assertTaskStack(new ComponentName[] {APP_A_BACKGROUND_ACTIVITY, APP_A_FOREGROUND_ACTIVITY}, 277 APP_A_FOREGROUND_ACTIVITY); 278 } 279 280 @Test 281 @FlakyTest(bugId = 143522449) testActivityBlockedWhenLaunchedAfterHomePress()282 public void testActivityBlockedWhenLaunchedAfterHomePress() throws Exception { 283 Intent intent = new Intent(); 284 intent.setComponent(APP_A_FOREGROUND_ACTIVITY); 285 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 286 intent.putExtra(LAUNCH_BACKGROUND_ACTIVITY_EXTRA, true); 287 intent.putExtra(START_ACTIVITY_FROM_FG_ACTIVITY_DELAY_MS_EXTRA, 2000); 288 intent.putExtra(START_ACTIVITY_FROM_FG_ACTIVITY_NEW_TASK_EXTRA, true); 289 mContext.startActivity(intent); 290 boolean result = waitForActivityFocused(ACTIVITY_FOCUS_TIMEOUT_MS, 291 APP_A_FOREGROUND_ACTIVITY); 292 assertTrue("Not able to launch background activity", result); 293 assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY); 294 295 // We can't resume app switching after pressing home button, otherwise the grace period 296 // will allow the starts. 297 pressHomeAndWaitHomeResumed(); 298 299 result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY); 300 assertFalse("FG activity shouldn't be visible", result); 301 result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 302 assertFalse("BG activity shouldn't be visible", result); 303 assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY); 304 assertTaskStack(null, APP_A_BACKGROUND_ACTIVITY); 305 } 306 307 @Test testActivityNotBlockedFromBgActivityInFgTask()308 public void testActivityNotBlockedFromBgActivityInFgTask() { 309 // Launch Activity A, B in the same task with different processes. 310 final Intent intent = new Intent() 311 .setComponent(APP_A_FOREGROUND_ACTIVITY) 312 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 313 mContext.startActivity(intent); 314 mWmState.waitForValidState(APP_A_FOREGROUND_ACTIVITY); 315 mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_B_FOREGROUND_ACTIVITY)); 316 mWmState.waitForValidState(APP_B_FOREGROUND_ACTIVITY); 317 assertTaskStack(new ComponentName[]{APP_B_FOREGROUND_ACTIVITY, APP_A_FOREGROUND_ACTIVITY}, 318 APP_A_FOREGROUND_ACTIVITY); 319 320 // Refresh last-stop-app-switch-time by returning to home and then make the task foreground. 321 pressHomeAndResumeAppSwitch(); 322 mContext.startActivity(intent); 323 mWmState.waitForValidState(APP_B_FOREGROUND_ACTIVITY); 324 // Though process A is in background, it is in a visible Task (top is B) so it should be 325 // able to start activity successfully. 326 mContext.sendBroadcast(new Intent(ACTION_LAUNCH_BACKGROUND_ACTIVITIES) 327 .putExtra(LAUNCH_INTENTS_EXTRA, new Intent[]{ new Intent() 328 .setComponent(APP_A_BACKGROUND_ACTIVITY) 329 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })); 330 mWmState.waitForValidState(APP_A_BACKGROUND_ACTIVITY); 331 mWmState.assertFocusedActivity( 332 "The background activity must be able to launch from a visible task", 333 APP_A_BACKGROUND_ACTIVITY); 334 } 335 336 @Test 337 @FlakyTest(bugId = 130800326) 338 @Ignore // TODO(b/145981637): Make this test work testActivityBlockedWhenForegroundActivityRestartsItself()339 public void testActivityBlockedWhenForegroundActivityRestartsItself() throws Exception { 340 // Start AppA foreground activity 341 Intent intent = new Intent(); 342 intent.setComponent(APP_A_FOREGROUND_ACTIVITY); 343 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 344 intent.putExtra(RELAUNCH_FOREGROUND_ACTIVITY_EXTRA, true); 345 mContext.startActivity(intent); 346 boolean result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY); 347 assertTrue("Not able to start foreground activity", result); 348 assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY); 349 350 // The foreground activity will be paused but will attempt to restart itself in onPause() 351 pressHomeAndResumeAppSwitch(); 352 353 result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY); 354 assertFalse("Previously foreground Activity should not be able to relaunch itself", result); 355 assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY); 356 } 357 358 @Test testSecondActivityNotBlockedWhenForegroundActivityLaunch()359 public void testSecondActivityNotBlockedWhenForegroundActivityLaunch() throws Exception { 360 // Start AppA foreground activity, which will immediately launch one activity 361 // and then the second. 362 Intent intent = new Intent(); 363 intent.setComponent(APP_A_FOREGROUND_ACTIVITY); 364 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 365 intent.putExtra(LAUNCH_BACKGROUND_ACTIVITY_EXTRA, true); 366 intent.putExtra(LAUNCH_SECOND_BACKGROUND_ACTIVITY_EXTRA, true); 367 mContext.startActivity(intent); 368 369 boolean result = waitForActivityFocused(APP_A_SECOND_BACKGROUND_ACTIVITY); 370 assertTrue("Not able to launch second background activity", result); 371 372 waitAndAssertActivityState(APP_A_BACKGROUND_ACTIVITY, STATE_INITIALIZING, 373 "First activity should have been created"); 374 assertTaskStack( 375 new ComponentName[]{APP_A_SECOND_BACKGROUND_ACTIVITY, APP_A_BACKGROUND_ACTIVITY, 376 APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY); 377 } 378 379 @Test 380 @FlakyTest(bugId = 143522449) testSecondActivityBlockedWhenBackgroundActivityLaunch()381 public void testSecondActivityBlockedWhenBackgroundActivityLaunch() throws Exception { 382 Intent baseActivityIntent = new Intent(); 383 baseActivityIntent.setComponent(APP_A_FOREGROUND_ACTIVITY); 384 baseActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 385 mContext.startActivity(baseActivityIntent); 386 boolean result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY); 387 assertTrue("Not able to start foreground activity", result); 388 assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY); 389 // We can't resume app switching after pressing home button, otherwise the grace period 390 // will allow the starts. 391 pressHomeAndWaitHomeResumed(); 392 393 // The activity, now in the background, will attempt to start 2 activities in quick 394 // succession 395 mContext.sendBroadcast(getLaunchActivitiesBroadcast(APP_A_BACKGROUND_ACTIVITY, 396 APP_A_SECOND_BACKGROUND_ACTIVITY)); 397 398 // There should be 2 activities in the background (not focused) INITIALIZING 399 result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 400 assertFalse("Activity should not have been launched in the foreground", result); 401 result = waitForActivityFocused(APP_A_SECOND_BACKGROUND_ACTIVITY); 402 assertFalse("Second activity should not have been launched in the foreground", result); 403 assertTaskStack( 404 new ComponentName[]{APP_A_SECOND_BACKGROUND_ACTIVITY, APP_A_BACKGROUND_ACTIVITY, 405 APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY); 406 } 407 408 @Test testPendingIntentActivityBlocked()409 public void testPendingIntentActivityBlocked() throws Exception { 410 // Cannot start activity by pending intent, as both appA and appB are in background 411 sendPendingIntentActivity(); 412 boolean result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 413 assertFalse("Should not able to launch background activity", result); 414 assertTaskStack(null, APP_A_BACKGROUND_ACTIVITY); 415 } 416 417 @Test 418 @FlakyTest(bugId = 130800326) testPendingIntentActivityNotBlocked_appAIsForeground()419 public void testPendingIntentActivityNotBlocked_appAIsForeground() throws Exception { 420 // Start AppA foreground activity 421 Intent intent = new Intent(); 422 intent.setComponent(APP_A_FOREGROUND_ACTIVITY); 423 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 424 mContext.startActivity(intent); 425 boolean result = waitForActivityFocused(APP_A_FOREGROUND_ACTIVITY); 426 assertTrue("Not able to start foreground Activity", result); 427 assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY); 428 429 // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start 430 // activity in App A 431 sendPendingIntentActivity(); 432 result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 433 assertTrue("Not able to launch background activity", result); 434 assertTaskStack(new ComponentName[]{APP_A_FOREGROUND_ACTIVITY}, APP_A_FOREGROUND_ACTIVITY); 435 assertTaskStack(new ComponentName[]{APP_A_BACKGROUND_ACTIVITY}, APP_A_BACKGROUND_ACTIVITY); 436 } 437 438 @Test testPendingIntentBroadcastActivityNotBlocked_appBIsForeground()439 public void testPendingIntentBroadcastActivityNotBlocked_appBIsForeground() throws Exception { 440 // Start AppB foreground activity 441 Intent intent = new Intent(); 442 intent.setComponent(APP_B_FOREGROUND_ACTIVITY); 443 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 444 mContext.startActivity(intent); 445 boolean result = waitForActivityFocused(APP_B_FOREGROUND_ACTIVITY); 446 assertTrue("Not able to start foreground Activity", result); 447 assertTaskStack(new ComponentName[]{APP_B_FOREGROUND_ACTIVITY}, APP_B_FOREGROUND_ACTIVITY); 448 449 // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start 450 // activity in App A 451 sendPendingIntentActivity(); 452 result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 453 assertTrue("Not able to launch background activity", result); 454 assertTaskStack(new ComponentName[]{APP_A_BACKGROUND_ACTIVITY}, APP_A_BACKGROUND_ACTIVITY); 455 assertTaskStack(new ComponentName[]{APP_B_FOREGROUND_ACTIVITY}, APP_B_FOREGROUND_ACTIVITY); 456 } 457 458 @Test testPendingIntentBroadcastTimeout_noDelay()459 public void testPendingIntentBroadcastTimeout_noDelay() throws Exception { 460 assertPendingIntentBroadcastTimeoutTest(0, true); 461 } 462 463 @Test 464 @FlakyTest(bugId = 141344170) testPendingIntentBroadcastTimeout_delay1s()465 public void testPendingIntentBroadcastTimeout_delay1s() throws Exception { 466 assertPendingIntentBroadcastTimeoutTest(1000, true); 467 } 468 469 @Test testPendingIntentBroadcastTimeout_delay12s()470 public void testPendingIntentBroadcastTimeout_delay12s() throws Exception { 471 assertPendingIntentBroadcastTimeoutTest(12000, false); 472 } 473 474 @Test testPendingIntentBroadcast_appBIsBackground()475 public void testPendingIntentBroadcast_appBIsBackground() throws Exception { 476 EventReceiver receiver = new EventReceiver( 477 Event.APP_A_START_BACKGROUND_ACTIVITY_BROADCAST_RECEIVED); 478 479 // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start 480 // activity in App A 481 sendPendingIntentBroadcast(0, receiver.getNotifier()); 482 483 // Waits for final hoop in AppA to start looking for activity, otherwise it could succeed 484 // if the broadcast took long time to get executed (which may happen after boot). 485 receiver.waitForEventOrThrow(BROADCAST_DELIVERY_TIMEOUT_MS); 486 boolean result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 487 assertFalse("Should not able to launch background activity", result); 488 assertTaskStack(null, APP_A_BACKGROUND_ACTIVITY); 489 } 490 491 /** 492 * Returns a list of alive users on the device 493 */ getAliveUsers()494 private List<UserInfo> getAliveUsers() { 495 // Setting the CREATE_USERS permission in AndroidManifest.xml has no effect when the test 496 // is run through the CTS harness, so instead adopt it as a shell permission. We use 497 // the CREATE_USERS permission instead of MANAGE_USERS because the shell can never use 498 // MANAGE_USERS. 499 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 500 uiAutomation.adoptShellPermissionIdentity(Manifest.permission.CREATE_USERS); 501 List<UserInfo> userList = mContext.getSystemService(UserManager.class) 502 .getUsers(/* excludePartial= */ true, 503 /* excludeDying= */ true, 504 /* excludePreCreated= */ true); 505 uiAutomation.dropShellPermissionIdentity(); 506 return userList; 507 } 508 509 /** 510 * Removes the guest user from the device if present 511 */ removeGuestUser()512 private void removeGuestUser() { 513 List<UserInfo> userList = getAliveUsers(); 514 for (UserInfo info : userList) { 515 if (info.isGuest()) { 516 removeUser(info.id); 517 // Device is only allowed to have one alive guest user, so stop if it's found 518 break; 519 } 520 } 521 } 522 523 /** 524 * Removes a user from the device given their ID 525 */ removeUser(int userId)526 private void removeUser(int userId) { 527 executeShellCommand(String.format("pm remove-user %d", userId)); 528 } 529 530 @Test 531 @SystemUserOnly(reason = "Device owner must be SYSTEM user") testDeviceOwner()532 public void testDeviceOwner() throws Exception { 533 // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start 534 // activity in App A 535 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) { 536 return; 537 } 538 539 // Remove existing guest user. The device may already have a guest present if it is 540 // configured with config_guestUserAutoCreated. 541 // 542 // In production flow the DO can only be created before device provisioning finishes 543 // (e.g. during SUW), and we make sure the guest user in only created after the device 544 // provision is finished. Ideally this test would use the provisioning flow and Device 545 // Owner (DO) creation in a similar manner as that of production flow. 546 removeGuestUser(); 547 548 String cmdResult = runShellCommand("dpm set-device-owner --user 0 " 549 + APP_A_SIMPLE_ADMIN_RECEIVER.flattenToString()); 550 assertThat(cmdResult).contains("Success"); 551 EventReceiver receiver = new EventReceiver( 552 Event.APP_A_START_BACKGROUND_ACTIVITY_BROADCAST_RECEIVED); 553 Intent intent = new Intent(); 554 intent.setComponent(APP_A_START_ACTIVITY_RECEIVER); 555 intent.putExtra(EVENT_NOTIFIER_EXTRA, receiver.getNotifier()); 556 557 mContext.sendBroadcast(intent); 558 559 // Waits for final hoop in AppA to start looking for activity 560 receiver.waitForEventOrThrow(BROADCAST_DELIVERY_TIMEOUT_MS); 561 boolean result = waitForActivityFocused(APP_A_BACKGROUND_ACTIVITY); 562 assertTrue("Not able to launch background activity", result); 563 assertTaskStack(new ComponentName[]{APP_A_BACKGROUND_ACTIVITY}, APP_A_BACKGROUND_ACTIVITY); 564 } 565 566 @Test testAppCannotStartBgActivityAfterHomeButton()567 public void testAppCannotStartBgActivityAfterHomeButton() throws Exception { 568 569 Intent intent = new Intent(); 570 intent.setComponent(APP_A_RELAUNCHING_ACTIVITY); 571 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 572 mContext.startActivity(intent); 573 574 assertTrue("Main activity not started", waitUntilForegroundChanged( 575 TEST_PACKAGE_APP_A, true, ACTIVITY_START_TIMEOUT_MS)); 576 577 // Click home button, and test app activity onPause() will try to start a background 578 // activity, but we expect this will be blocked BAL logic in system, as app cannot start 579 // any background activity even within grace period after pressing home button. 580 pressHomeAndWaitHomeResumed(); 581 582 assertActivityNotResumed(); 583 } 584 585 // Check picture-in-picture(PIP) won't allow to start BAL after pressing home. 586 @Test testPipCannotStartAfterHomeButton()587 public void testPipCannotStartAfterHomeButton() throws Exception { 588 589 Intent intent = new Intent(); 590 intent.setComponent(APP_A_PIP_ACTIVITY); 591 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 592 mContext.startActivity(intent); 593 594 assertTrue("Pip activity not started", waitUntilForegroundChanged( 595 TEST_PACKAGE_APP_A, true, ACTIVITY_START_TIMEOUT_MS)); 596 597 // Click home button, and test app activity onPause() will trigger pip window, 598 // test will will try to start background activity, but we expect the background activity 599 // will be blocked even the app has a visible pip window, as we do not allow background 600 // activity to be started after pressing home button. 601 pressHomeAndWaitHomeResumed(); 602 603 assertActivityNotResumed(); 604 } 605 606 // Check that a presentation on a virtual display won't allow BAL after pressing home. 607 @Test testVirtualDisplayCannotStartAfterHomeButton()608 public void testVirtualDisplayCannotStartAfterHomeButton() throws Exception { 609 Intent intent = new Intent(); 610 intent.setComponent(APP_A_VIRTUAL_DISPLAY_ACTIVITY); 611 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 612 mContext.startActivity(intent); 613 614 assertTrue("VirtualDisplay activity not started", waitUntilForegroundChanged( 615 TEST_PACKAGE_APP_A, true, ACTIVITY_START_TIMEOUT_MS)); 616 617 // Click home button, and test app activity onPause() will trigger which tries to launch 618 // the background activity. 619 pressHomeAndWaitHomeResumed(); 620 621 assertActivityNotResumed(); 622 } 623 pressHomeAndWaitHomeResumed()624 private void pressHomeAndWaitHomeResumed() { 625 pressHomeButton(); 626 mWmState.waitForHomeActivityVisible(); 627 } 628 checkPackageResumed(String pkg)629 private boolean checkPackageResumed(String pkg) { 630 WindowManagerStateHelper helper = new WindowManagerStateHelper(); 631 helper.computeState(); 632 return ComponentName.unflattenFromString( 633 helper.getFocusedActivity()).getPackageName().equals(pkg); 634 } 635 636 // Return true if the state of the package is changed to target state. waitUntilForegroundChanged(String targetPkg, boolean toBeResumed, int timeout)637 private boolean waitUntilForegroundChanged(String targetPkg, boolean toBeResumed, int timeout) 638 throws Exception { 639 long startTime = System.currentTimeMillis(); 640 while (checkPackageResumed(targetPkg) != toBeResumed) { 641 if (System.currentTimeMillis() - startTime < timeout) { 642 Thread.sleep(100); 643 } else { 644 return false; 645 } 646 } 647 return true; 648 } 649 assertActivityNotResumed()650 private void assertActivityNotResumed() throws Exception { 651 assertFalse("Test activity is resumed", 652 waitUntilForegroundChanged(TEST_PACKAGE_APP_A, true, 653 ACTIVITY_NOT_RESUMED_TIMEOUT_MS)); 654 } 655 getLaunchActivitiesBroadcast(ComponentName... componentNames)656 private Intent getLaunchActivitiesBroadcast(ComponentName... componentNames) { 657 Intent broadcastIntent = new Intent(ACTION_LAUNCH_BACKGROUND_ACTIVITIES); 658 Intent[] intents = Stream.of(componentNames) 659 .map(c -> { 660 Intent intent = new Intent(); 661 intent.setComponent(c); 662 return intent; 663 }) 664 .toArray(Intent[]::new); 665 broadcastIntent.putExtra(LAUNCH_INTENTS_EXTRA, intents); 666 return broadcastIntent; 667 } 668 pressHomeAndResumeAppSwitch()669 private void pressHomeAndResumeAppSwitch() { 670 // Press home key to ensure stopAppSwitches is called because the last-stop-app-switch-time 671 // is a criteria of allowing background start. 672 pressHomeButton(); 673 // Resume the stopped state (it won't affect last-stop-app-switch-time) so we don't need to 674 // wait extra time to prevent the next launch from being delayed. 675 resumeAppSwitches(); 676 mWmState.waitForHomeActivityVisible(); 677 // Resuming app switches again after home became visible because the previous call might 678 // have raced with pressHomeButton(). 679 // TODO(b/155454710): Remove previous call after making sure all the tests don't depend on 680 // the timing here. 681 resumeAppSwitches(); 682 } 683 assertTaskStack(ComponentName[] expectedComponents, ComponentName sourceComponent)684 private void assertTaskStack(ComponentName[] expectedComponents, 685 ComponentName sourceComponent) { 686 if (expectedComponents == null) { 687 assertNull(mWmState.getTaskByActivity(sourceComponent)); 688 return; 689 } 690 List<WindowManagerState.Activity> actual = mWmState.getTaskByActivity( 691 sourceComponent).mActivities; 692 assertEquals(expectedComponents.length, actual.size()); 693 int size = expectedComponents.length; 694 for (int i = 0; i < size; i++) { 695 assertEquals(expectedComponents[i].flattenToShortString(), actual.get(i).getName()); 696 } 697 } 698 assertPendingIntentBroadcastTimeoutTest(int delayMs, boolean expectedResult)699 private void assertPendingIntentBroadcastTimeoutTest(int delayMs, boolean expectedResult) 700 throws TimeoutException { 701 // Start AppB foreground activity 702 Intent intent = new Intent(); 703 intent.setComponent(APP_B_FOREGROUND_ACTIVITY); 704 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 705 mContext.startActivity(intent); 706 boolean result = waitForActivityFocused(APP_B_FOREGROUND_ACTIVITY); 707 assertTrue("Not able to start foreground Activity", result); 708 assertTaskStack(new ComponentName[]{APP_B_FOREGROUND_ACTIVITY}, APP_B_FOREGROUND_ACTIVITY); 709 EventReceiver receiver = new EventReceiver( 710 Event.APP_A_START_BACKGROUND_ACTIVITY_BROADCAST_RECEIVED); 711 712 // Send pendingIntent from AppA to AppB, and the AppB launch the pending intent to start 713 // activity in App A 714 sendPendingIntentBroadcast(delayMs, receiver.getNotifier()); 715 716 // Waits for final hoop in AppA to start looking for activity 717 receiver.waitForEventOrThrow(BROADCAST_DELIVERY_TIMEOUT_MS); 718 result = waitForActivityFocused(ACTIVITY_FOCUS_TIMEOUT_MS + delayMs, 719 APP_A_BACKGROUND_ACTIVITY); 720 assertEquals(expectedResult, result); 721 if (expectedResult) { 722 assertTaskStack(new ComponentName[]{APP_A_BACKGROUND_ACTIVITY}, 723 APP_A_BACKGROUND_ACTIVITY); 724 } else { 725 assertTaskStack(null, APP_A_BACKGROUND_ACTIVITY); 726 } 727 } 728 waitForActivityFocused(ComponentName componentName)729 private boolean waitForActivityFocused(ComponentName componentName) { 730 return waitForActivityFocused(ACTIVITY_FOCUS_TIMEOUT_MS, componentName); 731 } 732 sendPendingIntentActivity()733 private void sendPendingIntentActivity() { 734 Intent intent = new Intent(); 735 intent.setComponent(APP_A_SEND_PENDING_INTENT_RECEIVER); 736 intent.putExtra(IS_BROADCAST_EXTRA, false); 737 mContext.sendBroadcast(intent); 738 } 739 sendPendingIntentBroadcast(int delayMs, @Nullable ResultReceiver eventNotifier)740 private void sendPendingIntentBroadcast(int delayMs, @Nullable ResultReceiver eventNotifier) { 741 Intent intent = new Intent(); 742 intent.setComponent(APP_A_SEND_PENDING_INTENT_RECEIVER); 743 intent.putExtra(IS_BROADCAST_EXTRA, true); 744 if (delayMs > 0) { 745 intent.putExtra(START_ACTIVITY_DELAY_MS_EXTRA, delayMs); 746 } 747 intent.putExtra(EVENT_NOTIFIER_EXTRA, eventNotifier); 748 mContext.sendBroadcast(intent); 749 } 750 } 751