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