1 /* 2 * Copyright (C) 2022 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 com.android.tests.sdksandbox.endtoend; 18 19 import static android.app.sdksandbox.SdkSandboxManager.EXTRA_DISPLAY_ID; 20 import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS; 21 import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HOST_TOKEN; 22 import static android.app.sdksandbox.SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS; 23 import static android.app.sdksandbox.SdkSandboxManager.LOAD_SDK_INTERNAL_ERROR; 24 25 import static androidx.lifecycle.Lifecycle.State; 26 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 27 28 import static com.android.sdksandbox.flags.Flags.FLAG_SANDBOX_ACTIVITY_SDK_BASED_CONTEXT; 29 30 import static com.google.common.truth.Truth.assertThat; 31 import static com.google.common.truth.Truth.assertWithMessage; 32 33 import static org.junit.Assert.assertEquals; 34 import static org.junit.Assert.assertFalse; 35 import static org.junit.Assert.assertNotNull; 36 import static org.junit.Assert.assertThrows; 37 import static org.junit.Assert.assertTrue; 38 import static org.junit.Assert.fail; 39 import static org.junit.Assume.assumeTrue; 40 41 import android.Manifest; 42 import android.app.Activity; 43 import android.app.ActivityManager; 44 import android.app.sdksandbox.AppOwnedSdkSandboxInterface; 45 import android.app.sdksandbox.LoadSdkException; 46 import android.app.sdksandbox.SandboxedSdk; 47 import android.app.sdksandbox.SdkSandboxManager; 48 import android.app.sdksandbox.testutils.ConfigListener; 49 import android.app.sdksandbox.testutils.DeviceConfigUtils; 50 import android.app.sdksandbox.testutils.FakeLoadSdkCallback; 51 import android.app.sdksandbox.testutils.FakeRequestSurfacePackageCallback; 52 import android.app.sdksandbox.testutils.FakeSdkSandboxProcessDeathCallback; 53 import android.app.sdksandbox.testutils.SdkSandboxDeviceSupportedRule; 54 import android.content.Context; 55 import android.content.Intent; 56 import android.content.pm.PackageInfo; 57 import android.content.pm.PackageManager; 58 import android.content.pm.PermissionInfo; 59 import android.content.res.Configuration; 60 import android.os.Binder; 61 import android.os.Bundle; 62 import android.os.IBinder; 63 import android.os.RemoteException; 64 import android.platform.test.annotations.RequiresFlagsDisabled; 65 import android.platform.test.annotations.RequiresFlagsEnabled; 66 import android.platform.test.flag.junit.CheckFlagsRule; 67 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 68 import android.provider.DeviceConfig; 69 70 import androidx.lifecycle.Lifecycle; 71 import androidx.test.core.app.ActivityScenario; 72 import androidx.test.ext.junit.rules.ActivityScenarioRule; 73 import androidx.test.platform.app.InstrumentationRegistry; 74 import androidx.test.uiautomator.By; 75 import androidx.test.uiautomator.UiDevice; 76 import androidx.test.uiautomator.Until; 77 78 import com.android.compatibility.common.util.SystemUtil; 79 import com.android.ctssdkprovider.IActivityActionExecutor; 80 import com.android.ctssdkprovider.IActivityStarter; 81 import com.android.ctssdkprovider.ICtsSdkProviderApi; 82 import com.android.modules.utils.build.SdkLevel; 83 84 import com.google.common.truth.Expect; 85 86 import org.junit.After; 87 import org.junit.Before; 88 import org.junit.Rule; 89 import org.junit.Test; 90 import org.junit.runner.RunWith; 91 import org.junit.runners.JUnit4; 92 93 import java.util.Arrays; 94 import java.util.List; 95 import java.util.Random; 96 97 /** End-to-end tests of {@link SdkSandboxManager} APIs. */ 98 @RunWith(JUnit4.class) 99 public final class SdkSandboxManagerTest extends SandboxKillerBeforeTest { 100 101 private static final String TAG = SdkSandboxManagerTest.class.getSimpleName(); 102 private static final String NON_EXISTENT_SDK = "com.android.not_exist"; 103 104 private static final String APP_OWNED_SDK_SANDBOX_INTERFACE_NAME = 105 "com.android.ctsappownedsdksandboxinterface"; 106 private static final String SDK_NAME_1 = "com.android.ctssdkprovider"; 107 private static final String SDK_NAME_2 = "com.android.emptysdkprovider"; 108 109 private static final String TEST_OPTION = "test-option"; 110 private static final String OPTION_THROW_INTERNAL_ERROR = "internal-error"; 111 private static final String OPTION_THROW_REQUEST_SURFACE_PACKAGE_ERROR = "rsp-error"; 112 113 private static final String NAMESPACE_WINDOW_MANAGER = "window_manager"; 114 private static final String ASM_RESTRICTIONS_ENABLED = 115 "ActivitySecurity__asm_restrictions_enabled"; 116 private static final String UNREGISTER_BEFORE_STARTING_KEY = "UNREGISTER_BEFORE_STARTING_KEY"; 117 private static final String ACTIVITY_STARTER_KEY = "ACTIVITY_STARTER_KEY"; 118 private static final String TEXT_KEY = "TEXT_KEY"; 119 private static final int WAIT_FOR_TEXT_IN_MS = 1000; 120 private static final String ORIENTATION_PORTRAIT_MESSAGE = 121 "orientation: " + Configuration.ORIENTATION_PORTRAIT; 122 private static final String ORIENTATION_LANDSCAPE_MESSAGE = 123 "orientation: " + Configuration.ORIENTATION_LANDSCAPE; 124 private static final UiDevice sUiDevice = UiDevice.getInstance(getInstrumentation()); 125 126 @Rule(order = 0) 127 public final SdkSandboxDeviceSupportedRule supportedRule = new SdkSandboxDeviceSupportedRule(); 128 129 @Rule(order = 1) 130 public final ActivityScenarioRule<TestActivity> activityScenarioRule = 131 new ActivityScenarioRule<>(TestActivity.class); 132 133 @Rule(order = 2) 134 public final Expect expect = Expect.create(); 135 136 @Rule 137 public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); 138 139 private ActivityScenario<TestActivity> mScenario; 140 141 private SdkSandboxManager mSdkSandboxManager; 142 private String mInitialValueAsmRestrictionsEnabled; 143 144 private final Random mRandom = new Random(); 145 private ConfigListener mConfigListener; 146 private DeviceConfigUtils mDeviceConfigUtils; 147 148 @Before setup()149 public void setup() throws Exception { 150 Context context = InstrumentationRegistry.getInstrumentation().getContext(); 151 152 InstrumentationRegistry.getInstrumentation() 153 .getUiAutomation() 154 .adoptShellPermissionIdentity( 155 Manifest.permission.READ_DEVICE_CONFIG, 156 Manifest.permission.WRITE_DEVICE_CONFIG); 157 158 mSdkSandboxManager = context.getSystemService(SdkSandboxManager.class); 159 mScenario = activityScenarioRule.getScenario(); 160 161 mConfigListener = new ConfigListener(); 162 DeviceConfig.addOnPropertiesChangedListener( 163 NAMESPACE_WINDOW_MANAGER, context.getMainExecutor(), mConfigListener); 164 mDeviceConfigUtils = new DeviceConfigUtils(mConfigListener, NAMESPACE_WINDOW_MANAGER); 165 166 mInitialValueAsmRestrictionsEnabled = 167 DeviceConfig.getProperty(NAMESPACE_WINDOW_MANAGER, ASM_RESTRICTIONS_ENABLED); 168 mDeviceConfigUtils.deleteProperty(ASM_RESTRICTIONS_ENABLED); 169 sUiDevice.setOrientationNatural(); 170 } 171 172 @After tearDown()173 public void tearDown() throws Exception { 174 if (mDeviceConfigUtils != null) { 175 mDeviceConfigUtils.resetToInitialValue( 176 ASM_RESTRICTIONS_ENABLED, mInitialValueAsmRestrictionsEnabled); 177 } 178 179 InstrumentationRegistry.getInstrumentation() 180 .getUiAutomation() 181 .dropShellPermissionIdentity(); 182 183 DeviceConfig.removeOnPropertiesChangedListener(mConfigListener); 184 } 185 186 @Test testGetSdkSandboxState()187 public void testGetSdkSandboxState() { 188 int state = SdkSandboxManager.getSdkSandboxState(); 189 assertThat(state).isEqualTo(SdkSandboxManager.SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION); 190 } 191 192 @Test testLoadSdkSuccessfully()193 public void testLoadSdkSuccessfully() { 194 final FakeLoadSdkCallback callback = new FakeLoadSdkCallback(); 195 mSdkSandboxManager.loadSdk(SDK_NAME_1, new Bundle(), Runnable::run, callback); 196 callback.assertLoadSdkIsSuccessful(); 197 assertNotNull(callback.getSandboxedSdk()); 198 assertNotNull(callback.getSandboxedSdk().getInterface()); 199 } 200 201 @Test testRegisterAndGetAppOwnedSdkSandboxInterface()202 public void testRegisterAndGetAppOwnedSdkSandboxInterface() throws Exception { 203 try { 204 IBinder iBinder = new Binder(); 205 mSdkSandboxManager.registerAppOwnedSdkSandboxInterface( 206 new AppOwnedSdkSandboxInterface( 207 APP_OWNED_SDK_SANDBOX_INTERFACE_NAME, 208 /*version=*/ 0, 209 /*interfaceIBinder=*/ iBinder)); 210 final List<AppOwnedSdkSandboxInterface> appOwnedSdkSandboxInterfaceList = 211 mSdkSandboxManager.getAppOwnedSdkSandboxInterfaces(); 212 assertThat(appOwnedSdkSandboxInterfaceList).hasSize(1); 213 assertThat(appOwnedSdkSandboxInterfaceList.get(0).getName()) 214 .isEqualTo(APP_OWNED_SDK_SANDBOX_INTERFACE_NAME); 215 assertThat(appOwnedSdkSandboxInterfaceList.get(0).getVersion()).isEqualTo(0); 216 assertThat(appOwnedSdkSandboxInterfaceList.get(0).getInterface()).isEqualTo(iBinder); 217 } finally { 218 mSdkSandboxManager.unregisterAppOwnedSdkSandboxInterface( 219 APP_OWNED_SDK_SANDBOX_INTERFACE_NAME); 220 } 221 } 222 223 @Test testUnregisterAppOwnedSdkSandboxInterface()224 public void testUnregisterAppOwnedSdkSandboxInterface() throws Exception { 225 mSdkSandboxManager.registerAppOwnedSdkSandboxInterface( 226 new AppOwnedSdkSandboxInterface( 227 APP_OWNED_SDK_SANDBOX_INTERFACE_NAME, 228 /*version=*/ 0, 229 /*interfaceIBinder=*/ new Binder())); 230 mSdkSandboxManager.unregisterAppOwnedSdkSandboxInterface( 231 APP_OWNED_SDK_SANDBOX_INTERFACE_NAME); 232 assertThat(mSdkSandboxManager.getAppOwnedSdkSandboxInterfaces()).hasSize(0); 233 } 234 235 @Test testRegisterAppOwnedSdkSandboxInterfaceAlreadyRegistered()236 public void testRegisterAppOwnedSdkSandboxInterfaceAlreadyRegistered() throws Exception { 237 try { 238 mSdkSandboxManager.registerAppOwnedSdkSandboxInterface( 239 new AppOwnedSdkSandboxInterface( 240 APP_OWNED_SDK_SANDBOX_INTERFACE_NAME, 241 /*version=*/ 0, 242 /*interfaceIBinder=*/ new Binder())); 243 assertThrows( 244 RuntimeException.class, 245 () -> 246 mSdkSandboxManager.registerAppOwnedSdkSandboxInterface( 247 new AppOwnedSdkSandboxInterface( 248 APP_OWNED_SDK_SANDBOX_INTERFACE_NAME, 249 /*version=*/ 0, 250 /*interfaceIBinder=*/ new Binder()))); 251 } finally { 252 mSdkSandboxManager.unregisterAppOwnedSdkSandboxInterface( 253 APP_OWNED_SDK_SANDBOX_INTERFACE_NAME); 254 } 255 } 256 257 @Test testGetSandboxedSdkSuccessfully()258 public void testGetSandboxedSdkSuccessfully() { 259 loadSdk(); 260 261 List<SandboxedSdk> sandboxedSdks = mSdkSandboxManager.getSandboxedSdks(); 262 263 assertThat(sandboxedSdks.size()).isEqualTo(1); 264 assertThat(sandboxedSdks.get(0).getSharedLibraryInfo().getName()).isEqualTo(SDK_NAME_1); 265 266 mSdkSandboxManager.unloadSdk(SDK_NAME_1); 267 List<SandboxedSdk> sandboxedSdksAfterUnload = mSdkSandboxManager.getSandboxedSdks(); 268 assertThat(sandboxedSdksAfterUnload.size()).isEqualTo(0); 269 } 270 271 @Test testLoadSdkAndCheckClassloader()272 public void testLoadSdkAndCheckClassloader() throws Exception { 273 ICtsSdkProviderApi sdk = loadSdk(); 274 sdk.checkClassloaders(); 275 } 276 277 @Test testGetOpPackageName()278 public void testGetOpPackageName() throws Exception { 279 ICtsSdkProviderApi sdk = loadSdk(); 280 final PackageManager pm = 281 InstrumentationRegistry.getInstrumentation().getContext().getPackageManager(); 282 assertThat(sdk.getOpPackageName()).isEqualTo(pm.getSdkSandboxPackageName()); 283 } 284 285 @Test testRetryLoadSameSdkShouldFail()286 public void testRetryLoadSameSdkShouldFail() { 287 FakeLoadSdkCallback callback = new FakeLoadSdkCallback(); 288 289 mSdkSandboxManager.loadSdk(SDK_NAME_1, new Bundle(), Runnable::run, callback); 290 callback.assertLoadSdkIsSuccessful(); 291 292 callback = new FakeLoadSdkCallback(); 293 mSdkSandboxManager.loadSdk(SDK_NAME_1, new Bundle(), Runnable::run, callback); 294 callback.assertLoadSdkIsUnsuccessful(); 295 assertThat(callback.getLoadSdkErrorCode()) 296 .isEqualTo(SdkSandboxManager.LOAD_SDK_ALREADY_LOADED); 297 } 298 299 @Test testLoadNonExistentSdk()300 public void testLoadNonExistentSdk() { 301 final FakeLoadSdkCallback callback = new FakeLoadSdkCallback(); 302 303 mSdkSandboxManager.loadSdk(NON_EXISTENT_SDK, new Bundle(), Runnable::run, callback); 304 callback.assertLoadSdkIsUnsuccessful(); 305 assertThat(callback.getLoadSdkErrorCode()) 306 .isEqualTo(SdkSandboxManager.LOAD_SDK_NOT_FOUND); 307 LoadSdkException loadSdkException = callback.getLoadSdkException(); 308 assertThat(loadSdkException.getExtraInformation()).isNotNull(); 309 assertThat(loadSdkException.getExtraInformation().isEmpty()).isTrue(); 310 } 311 312 @Test testLoadSdkWithInternalErrorShouldFail()313 public void testLoadSdkWithInternalErrorShouldFail() throws Exception { 314 final FakeLoadSdkCallback callback = new FakeLoadSdkCallback(); 315 Bundle params = new Bundle(); 316 params.putString(TEST_OPTION, OPTION_THROW_INTERNAL_ERROR); 317 mSdkSandboxManager.loadSdk(SDK_NAME_1, params, Runnable::run, callback); 318 callback.assertLoadSdkIsUnsuccessful(); 319 assertThat(callback.getLoadSdkErrorCode()) 320 .isEqualTo(SdkSandboxManager.LOAD_SDK_SDK_DEFINED_ERROR); 321 } 322 323 @Test testLoadSdkPropertySdkProviderClassNameNotSet()324 public void testLoadSdkPropertySdkProviderClassNameNotSet() { 325 FakeLoadSdkCallback callback = new FakeLoadSdkCallback(); 326 mSdkSandboxManager.loadSdk( 327 "com.android.property_sdkprovider_classname_not_present", 328 new Bundle(), 329 Runnable::run, 330 callback); 331 callback.assertLoadSdkIsUnsuccessful(); 332 assertThat(callback.getLoadSdkErrorCode()).isEqualTo(SdkSandboxManager.LOAD_SDK_NOT_FOUND); 333 assertThat(callback.getLoadSdkErrorMsg()) 334 .contains("android.sdksandbox.PROPERTY_SDK_PROVIDER_CLASS_NAME property"); 335 } 336 337 @Test testUnloadAndReloadSdk()338 public void testUnloadAndReloadSdk() throws Exception { 339 final FakeLoadSdkCallback callback = new FakeLoadSdkCallback(); 340 mSdkSandboxManager.loadSdk(SDK_NAME_1, new Bundle(), Runnable::run, callback); 341 callback.assertLoadSdkIsSuccessful(); 342 343 mSdkSandboxManager.unloadSdk(SDK_NAME_1); 344 // Wait till SDK is unloaded. 345 Thread.sleep(2000); 346 347 // Calls to an unloaded SDK should fail. 348 final FakeRequestSurfacePackageCallback requestSurfacePackageCallback = 349 new FakeRequestSurfacePackageCallback(); 350 mSdkSandboxManager.requestSurfacePackage( 351 SDK_NAME_1, 352 getRequestSurfacePackageParams(), 353 Runnable::run, 354 requestSurfacePackageCallback); 355 356 assertThat(requestSurfacePackageCallback.isRequestSurfacePackageSuccessful()).isFalse(); 357 assertThat(requestSurfacePackageCallback.getSurfacePackageErrorCode()) 358 .isEqualTo(SdkSandboxManager.REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED); 359 360 // SDK can be reloaded after being unloaded. 361 final FakeLoadSdkCallback callback2 = new FakeLoadSdkCallback(); 362 mSdkSandboxManager.loadSdk(SDK_NAME_1, new Bundle(), Runnable::run, callback2); 363 callback2.assertLoadSdkIsSuccessful(); 364 } 365 366 @Test testUnloadNonexistentSdk()367 public void testUnloadNonexistentSdk() { 368 final FakeLoadSdkCallback callback = new FakeLoadSdkCallback(); 369 mSdkSandboxManager.loadSdk(SDK_NAME_1, new Bundle(), Runnable::run, callback); 370 callback.assertLoadSdkIsSuccessful(); 371 372 final String nonexistentSdk = "com.android.nonexistent"; 373 // Unloading does nothing - call should go through without error. 374 mSdkSandboxManager.unloadSdk(nonexistentSdk); 375 } 376 377 @Test testReloadingSdkDoesNotInvalidateIt()378 public void testReloadingSdkDoesNotInvalidateIt() { 379 380 final FakeLoadSdkCallback callback = new FakeLoadSdkCallback(); 381 mSdkSandboxManager.loadSdk(SDK_NAME_1, new Bundle(), Runnable::run, callback); 382 callback.assertLoadSdkIsSuccessful(); 383 SandboxedSdk sandboxedSdk = callback.getSandboxedSdk(); 384 assertNotNull(sandboxedSdk.getInterface()); 385 386 // Attempt to load the SDK again and see that it fails. 387 final FakeLoadSdkCallback reloadCallback = new FakeLoadSdkCallback(); 388 mSdkSandboxManager.loadSdk(SDK_NAME_1, new Bundle(), Runnable::run, reloadCallback); 389 reloadCallback.assertLoadSdkIsUnsuccessful(); 390 391 // SDK's interface should still be obtainable. 392 assertNotNull(sandboxedSdk.getInterface()); 393 394 // Further calls to the SDK should still be valid. 395 final FakeRequestSurfacePackageCallback surfacePackageCallback = 396 new FakeRequestSurfacePackageCallback(); 397 mSdkSandboxManager.requestSurfacePackage( 398 SDK_NAME_1, 399 getRequestSurfacePackageParams(), 400 Runnable::run, 401 surfacePackageCallback); 402 assertThat(surfacePackageCallback.isRequestSurfacePackageSuccessful()).isTrue(); 403 } 404 405 @Test testReloadingSdkAfterKillingSandboxIsSuccessful()406 public void testReloadingSdkAfterKillingSandboxIsSuccessful() throws Exception { 407 // Kill the sandbox if it already exists from previous tests 408 killSandboxIfExists(); 409 410 FakeSdkSandboxProcessDeathCallback callback = new FakeSdkSandboxProcessDeathCallback(); 411 mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run, callback); 412 assertThat(callback.waitForSandboxDeath()).isFalse(); 413 414 // Killing the sandbox and loading the same SDKs again multiple times should work 415 for (int i = 1; i <= 3; ++i) { 416 // The same SDKs should be able to be loaded again after sandbox death 417 loadMultipleSdks(); 418 callback.resetLatch(); 419 killSandbox(); 420 assertThat(callback.waitForSandboxDeath()).isTrue(); 421 } 422 } 423 424 @Test testAddSdkSandboxProcessDeathCallback_BeforeStartingSandbox()425 public void testAddSdkSandboxProcessDeathCallback_BeforeStartingSandbox() throws Exception { 426 // Kill the sandbox if it already exists from previous tests 427 killSandboxIfExists(); 428 429 // Add a sandbox lifecycle callback before starting the sandbox 430 FakeSdkSandboxProcessDeathCallback lifecycleCallback = 431 new FakeSdkSandboxProcessDeathCallback(); 432 mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run, lifecycleCallback); 433 434 // Bring up the sandbox 435 loadSdk(); 436 437 killSandbox(); 438 assertThat(lifecycleCallback.waitForSandboxDeath()).isTrue(); 439 } 440 441 @Test testAddSdkSandboxProcessDeathCallback_AfterStartingSandbox()442 public void testAddSdkSandboxProcessDeathCallback_AfterStartingSandbox() throws Exception { 443 // Bring up the sandbox 444 loadSdk(); 445 446 // Add a sandbox lifecycle callback before starting the sandbox 447 FakeSdkSandboxProcessDeathCallback lifecycleCallback = 448 new FakeSdkSandboxProcessDeathCallback(); 449 mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run, lifecycleCallback); 450 451 killSandbox(); 452 assertThat(lifecycleCallback.waitForSandboxDeath()).isTrue(); 453 } 454 455 @Test testRegisterMultipleSdkSandboxProcessDeathCallbacks()456 public void testRegisterMultipleSdkSandboxProcessDeathCallbacks() throws Exception { 457 // Kill the sandbox if it already exists from previous tests 458 killSandboxIfExists(); 459 460 // Add a sandbox lifecycle callback before starting the sandbox 461 FakeSdkSandboxProcessDeathCallback lifecycleCallback1 = 462 new FakeSdkSandboxProcessDeathCallback(); 463 mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run, lifecycleCallback1); 464 465 // Bring up the sandbox 466 loadSdk(); 467 468 // Add another sandbox lifecycle callback after starting it 469 FakeSdkSandboxProcessDeathCallback lifecycleCallback2 = 470 new FakeSdkSandboxProcessDeathCallback(); 471 mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run, lifecycleCallback2); 472 473 killSandbox(); 474 assertThat(lifecycleCallback1.waitForSandboxDeath()).isTrue(); 475 assertThat(lifecycleCallback2.waitForSandboxDeath()).isTrue(); 476 } 477 478 @Test testRemoveSdkSandboxProcessDeathCallback()479 public void testRemoveSdkSandboxProcessDeathCallback() throws Exception { 480 // Bring up the sandbox 481 loadSdk(); 482 483 // Add and remove a sandbox lifecycle callback 484 FakeSdkSandboxProcessDeathCallback lifecycleCallback1 = 485 new FakeSdkSandboxProcessDeathCallback(); 486 mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run, lifecycleCallback1); 487 mSdkSandboxManager.removeSdkSandboxProcessDeathCallback(lifecycleCallback1); 488 489 // Add a lifecycle callback but don't remove it 490 FakeSdkSandboxProcessDeathCallback lifecycleCallback2 = 491 new FakeSdkSandboxProcessDeathCallback(); 492 mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run, lifecycleCallback2); 493 494 killSandbox(); 495 assertThat(lifecycleCallback1.waitForSandboxDeath()).isFalse(); 496 assertThat(lifecycleCallback2.waitForSandboxDeath()).isTrue(); 497 } 498 499 @Test testRequestSurfacePackageSuccessfully()500 public void testRequestSurfacePackageSuccessfully() { 501 loadSdk(); 502 503 final FakeRequestSurfacePackageCallback surfacePackageCallback = 504 new FakeRequestSurfacePackageCallback(); 505 mSdkSandboxManager.requestSurfacePackage( 506 SDK_NAME_1, 507 getRequestSurfacePackageParams(), 508 Runnable::run, 509 surfacePackageCallback); 510 assertThat(surfacePackageCallback.isRequestSurfacePackageSuccessful()).isTrue(); 511 } 512 513 @Test testRequestSurfacePackageWithInternalErrorShouldFail()514 public void testRequestSurfacePackageWithInternalErrorShouldFail() { 515 loadSdk(); 516 517 final FakeRequestSurfacePackageCallback surfacePackageCallback = 518 new FakeRequestSurfacePackageCallback(); 519 Bundle params = getRequestSurfacePackageParams(); 520 params.putString(TEST_OPTION, OPTION_THROW_REQUEST_SURFACE_PACKAGE_ERROR); 521 mSdkSandboxManager.requestSurfacePackage( 522 SDK_NAME_1, params, Runnable::run, surfacePackageCallback); 523 assertThat(surfacePackageCallback.isRequestSurfacePackageSuccessful()).isFalse(); 524 assertThat(surfacePackageCallback.getSurfacePackageErrorCode()) 525 .isEqualTo(SdkSandboxManager.REQUEST_SURFACE_PACKAGE_INTERNAL_ERROR); 526 assertThat(surfacePackageCallback.getExtraErrorInformation()).isNotNull(); 527 assertThat(surfacePackageCallback.getExtraErrorInformation().isEmpty()).isTrue(); 528 } 529 530 @Test testRequestSurfacePackage_SandboxDiesAfterLoadingSdk()531 public void testRequestSurfacePackage_SandboxDiesAfterLoadingSdk() throws Exception { 532 loadSdk(); 533 534 assertThat(killSandboxIfExists()).isTrue(); 535 536 final FakeRequestSurfacePackageCallback surfacePackageCallback = 537 new FakeRequestSurfacePackageCallback(); 538 mSdkSandboxManager.requestSurfacePackage( 539 SDK_NAME_1, 540 getRequestSurfacePackageParams(), 541 Runnable::run, 542 surfacePackageCallback); 543 assertThat(surfacePackageCallback.isRequestSurfacePackageSuccessful()).isFalse(); 544 assertThat(surfacePackageCallback.getSurfacePackageErrorCode()) 545 .isEqualTo(SdkSandboxManager.REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED); 546 } 547 548 @Test testResourcesAndAssets()549 public void testResourcesAndAssets() throws Exception { 550 ICtsSdkProviderApi sdk = loadSdk(); 551 sdk.checkResourcesAndAssets(); 552 } 553 554 @Test testLoadSdkInBackgroundFails()555 public void testLoadSdkInBackgroundFails() throws Exception { 556 mScenario.moveToState(Lifecycle.State.DESTROYED); 557 558 // Wait for the activity to be destroyed 559 Thread.sleep(1000); 560 561 final FakeLoadSdkCallback callback = new FakeLoadSdkCallback(); 562 mSdkSandboxManager.loadSdk(SDK_NAME_1, new Bundle(), Runnable::run, callback); 563 564 LoadSdkException thrown = callback.getLoadSdkException(); 565 566 assertEquals(LOAD_SDK_INTERNAL_ERROR, thrown.getLoadSdkErrorCode()); 567 assertThat(thrown).hasMessageThat().contains("does not run in the foreground"); 568 } 569 570 @Test testSandboxApisAreUsableAfterUnbindingSandbox()571 public void testSandboxApisAreUsableAfterUnbindingSandbox() throws Exception { 572 FakeLoadSdkCallback callback1 = new FakeLoadSdkCallback(); 573 mSdkSandboxManager.loadSdk(SDK_NAME_1, new Bundle(), Runnable::run, callback1); 574 callback1.assertLoadSdkIsSuccessful(); 575 576 // Move the app to the background and bring it back to the foreground again. 577 mScenario.recreate(); 578 579 // Loading another sdk should work without issue 580 FakeLoadSdkCallback callback2 = new FakeLoadSdkCallback(); 581 mSdkSandboxManager.loadSdk(SDK_NAME_2, new Bundle(), Runnable::run, callback2); 582 callback2.assertLoadSdkIsSuccessful(); 583 584 // Requesting surface package from the first loaded sdk should work. 585 final FakeRequestSurfacePackageCallback surfacePackageCallback = 586 new FakeRequestSurfacePackageCallback(); 587 mSdkSandboxManager.requestSurfacePackage( 588 SDK_NAME_1, 589 getRequestSurfacePackageParams(), 590 Runnable::run, 591 surfacePackageCallback); 592 assertThat(surfacePackageCallback.isRequestSurfacePackageSuccessful()).isTrue(); 593 } 594 595 /** Checks that {@code SdkSandbox.apk} only requests normal permissions in its manifest. */ 596 // TODO: This should probably be a separate test module 597 @Test testSdkSandboxPermissions()598 public void testSdkSandboxPermissions() throws Exception { 599 final PackageManager pm = 600 InstrumentationRegistry.getInstrumentation().getContext().getPackageManager(); 601 final PackageInfo sdkSandboxPackage = 602 pm.getPackageInfo( 603 pm.getSdkSandboxPackageName(), 604 PackageManager.PackageInfoFlags.of(PackageManager.GET_PERMISSIONS)); 605 for (int i = 0; i < sdkSandboxPackage.requestedPermissions.length; i++) { 606 final String permissionName = sdkSandboxPackage.requestedPermissions[i]; 607 final PermissionInfo permissionInfo = pm.getPermissionInfo(permissionName, 0); 608 expect.withMessage("SdkSandbox.apk requests non-normal permission %s", permissionName) 609 .that(permissionInfo.getProtection()) 610 .isEqualTo(PermissionInfo.PROTECTION_NORMAL); 611 } 612 } 613 614 @Test testSdkAndAppProcessImportanceIsAligned_AppIsBackgrounded()615 public void testSdkAndAppProcessImportanceIsAligned_AppIsBackgrounded() throws Exception { 616 // Sandbox and app priority is aligned only in U+. 617 assumeTrue(SdkLevel.isAtLeastU()); 618 619 ICtsSdkProviderApi sdk = loadSdk(); 620 assertThat(sdk.getProcessImportance()).isEqualTo(getAppProcessImportance()); 621 622 // Move the app to the background. 623 mScenario.moveToState(Lifecycle.State.DESTROYED); 624 Thread.sleep(1000); 625 626 assertThat(sdk.getProcessImportance()).isEqualTo(getAppProcessImportance()); 627 } 628 629 @Test testSdkAndAppProcessImportanceIsAligned_AppIsBackgroundedAndForegrounded()630 public void testSdkAndAppProcessImportanceIsAligned_AppIsBackgroundedAndForegrounded() 631 throws Exception { 632 // Sandbox and app priority is aligned only in U+. 633 assumeTrue(SdkLevel.isAtLeastU()); 634 635 ICtsSdkProviderApi sdk = loadSdk(); 636 assertThat(sdk.getProcessImportance()).isEqualTo(getAppProcessImportance()); 637 638 // Move the app to the background and bring it back to the foreground again. 639 mScenario.recreate(); 640 641 // The sandbox should have foreground importance again. 642 assertThat(sdk.getProcessImportance()).isEqualTo(getAppProcessImportance()); 643 } 644 645 @Test testSDKCanNotStartSandboxActivityDirectlyByAction()646 public void testSDKCanNotStartSandboxActivityDirectlyByAction() { 647 assumeTrue(SdkLevel.isAtLeastU()); 648 649 final ICtsSdkProviderApi sdk = loadSdk(); 650 651 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 652 SecurityException exception = 653 assertThrows( 654 SecurityException.class, 655 () -> sdk.startSandboxActivityDirectlyByAction(getSdkSandboxPackageName())); 656 assertThat(exception.getMessage()) 657 .isEqualTo("Sandbox process is not allowed to start sandbox activities."); 658 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 659 } 660 661 @Test testSDKCanNotStartSandboxActivityDirectlyByComponent()662 public void testSDKCanNotStartSandboxActivityDirectlyByComponent() { 663 assumeTrue(SdkLevel.isAtLeastU()); 664 665 final ICtsSdkProviderApi sdk = loadSdk(); 666 667 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 668 SecurityException exception = 669 assertThrows( 670 SecurityException.class, 671 () -> 672 sdk.startSandboxActivityDirectlyByComponent( 673 getSdkSandboxPackageName())); 674 assertThat(exception.getMessage()) 675 .isEqualTo("Sandbox process is not allowed to start sandbox activities."); 676 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 677 } 678 679 @Test testSandboxProcessShouldBeRunningToHostTheSandboxActivity()680 public void testSandboxProcessShouldBeRunningToHostTheSandboxActivity() { 681 assumeTrue(SdkLevel.isAtLeastU()); 682 683 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 684 mScenario.onActivity( 685 clientActivity -> { 686 SecurityException exception = 687 assertThrows( 688 SecurityException.class, 689 () -> 690 mSdkSandboxManager.startSdkSandboxActivity( 691 clientActivity, new Binder())); 692 assertThat(exception.getMessage()) 693 .contains("There is no sandbox process running"); 694 }); 695 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 696 } 697 698 @Test testStartSdkSandboxActivity()699 public void testStartSdkSandboxActivity() { 700 assumeTrue(SdkLevel.isAtLeastU()); 701 702 ICtsSdkProviderApi sdk = loadSdk(); 703 704 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 705 ActivityStarter activityStarter = new ActivityStarter(); 706 assertThat(activityStarter.isActivityResumed()).isFalse(); 707 708 startSandboxActivity(sdk, activityStarter); 709 710 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 711 assertThat(activityStarter.isActivityResumed()).isTrue(); 712 } 713 714 @Test testStartSdkSandboxActivityOnTopOfASandboxActivity()715 public void testStartSdkSandboxActivityOnTopOfASandboxActivity() { 716 assumeTrue(SdkLevel.isAtLeastU()); 717 718 ICtsSdkProviderApi sdk = loadSdk(); 719 720 ActivityStarter sandboxActivity1Starter = new ActivityStarter(); 721 ActivityStarter sandboxActivity2Starter = new ActivityStarter(); 722 assertThat(sandboxActivity1Starter.isActivityResumed()).isFalse(); 723 assertThat(sandboxActivity2Starter.isActivityResumed()).isFalse(); 724 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 725 726 startSandboxActivity(sdk, sandboxActivity1Starter); 727 728 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 729 assertThat(sandboxActivity1Starter.isActivityResumed()).isTrue(); 730 assertThat(sandboxActivity2Starter.isActivityResumed()).isFalse(); 731 732 startSandboxActivity(sdk, sandboxActivity2Starter); 733 734 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 735 assertThat(sandboxActivity1Starter.isActivityResumed()).isFalse(); 736 assertThat(sandboxActivity2Starter.isActivityResumed()).isTrue(); 737 } 738 739 @Test testStartLocalActivityOnTopOfASandboxActivity()740 public void testStartLocalActivityOnTopOfASandboxActivity() { 741 assumeTrue(SdkLevel.isAtLeastU()); 742 743 ICtsSdkProviderApi sdk = loadSdk(); 744 745 ActivityStarter sandboxActivityStarter = new ActivityStarter(); 746 ActivityStarter otherClientActivityStarter = new ActivityStarter(); 747 assertThat(sandboxActivityStarter.isActivityResumed()).isFalse(); 748 assertThat(otherClientActivityStarter.isActivityResumed()).isFalse(); 749 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 750 751 startSandboxActivity(sdk, sandboxActivityStarter); 752 753 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 754 assertThat(otherClientActivityStarter.isActivityResumed()).isFalse(); 755 assertThat(sandboxActivityStarter.isActivityResumed()).isTrue(); 756 757 mScenario.onActivity( 758 clientActivity -> { 759 otherClientActivityStarter.setFromActivity(clientActivity); 760 }); 761 otherClientActivityStarter.startLocalActivity(); 762 763 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 764 assertThat(sandboxActivityStarter.isActivityResumed()).isFalse(); 765 assertThat(otherClientActivityStarter.isActivityResumed()).isTrue(); 766 } 767 768 @Test testClientAppCanClearTopWhileOtherActivitiesOnTopIncludingSandboxActivities()769 public void testClientAppCanClearTopWhileOtherActivitiesOnTopIncludingSandboxActivities() { 770 assumeTrue(SdkLevel.isAtLeastU()); 771 772 ICtsSdkProviderApi sdk = loadSdk(); 773 774 // Start 2 sandbox activities. 775 ActivityStarter sandboxActivity1Starter = new ActivityStarter(); 776 ActivityStarter sandboxActivity2Starter = new ActivityStarter(); 777 startSandboxActivity(sdk, sandboxActivity1Starter); 778 startSandboxActivity(sdk, sandboxActivity2Starter); 779 780 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 781 assertThat(sandboxActivity1Starter.isActivityResumed()).isFalse(); 782 assertThat(sandboxActivity2Starter.isActivityResumed()).isTrue(); 783 784 // Clear top (include the sandbox activities on top). 785 ActivityStarter clearTopActivityStarter = new ActivityStarter(); 786 mScenario.onActivity( 787 clientActivity -> { 788 clearTopActivityStarter.setFromActivity(clientActivity); 789 }); 790 clearTopActivityStarter.startLocalActivity(Intent.FLAG_ACTIVITY_CLEAR_TOP); 791 assertThat(sandboxActivity1Starter.isActivityResumed()).isFalse(); 792 assertThat(sandboxActivity2Starter.isActivityResumed()).isFalse(); 793 assertThat(clearTopActivityStarter.isActivityResumed()).isTrue(); 794 } 795 796 /** 797 * Test that the sandbox activity context is created using the SDK ApplicationInfo. 798 * 799 * @throws RemoteException 800 */ 801 @Test 802 @RequiresFlagsEnabled(FLAG_SANDBOX_ACTIVITY_SDK_BASED_CONTEXT) testSandboxActivityUseSdkBasedContextIfRequiredFlagAreEnabled()803 public void testSandboxActivityUseSdkBasedContextIfRequiredFlagAreEnabled() 804 throws RemoteException { 805 assumeTrue(SdkLevel.isAtLeastV()); 806 807 ICtsSdkProviderApi sdk = loadSdk(); 808 809 ActivityStarter sandboxActivityStarter = new ActivityStarter(); 810 IActivityActionExecutor actionExecutor = startSandboxActivity(sdk, sandboxActivityStarter); 811 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 812 assertThat(sandboxActivityStarter.isActivityResumed()).isTrue(); 813 814 String dataDir = actionExecutor.getDataDir(); 815 assertThat(dataDir).contains(SDK_NAME_1); 816 assertThat(dataDir).doesNotContain(getSdkSandboxPackageName()); 817 } 818 819 /** 820 * Test that the sandbox activity context is created using the sandbox App ApplicationInfo. 821 * 822 * @throws RemoteException 823 */ 824 @Test 825 @RequiresFlagsDisabled(FLAG_SANDBOX_ACTIVITY_SDK_BASED_CONTEXT) testSandboxActivityUseAppBasedContextIfSdkBasedFlagIDisabled()826 public void testSandboxActivityUseAppBasedContextIfSdkBasedFlagIDisabled() 827 throws RemoteException { 828 assumeTrue(SdkLevel.isAtLeastV()); 829 830 ICtsSdkProviderApi sdk = loadSdk(); 831 832 ActivityStarter sandboxActivityStarter = new ActivityStarter(); 833 IActivityActionExecutor actionExecutor = startSandboxActivity(sdk, sandboxActivityStarter); 834 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 835 assertThat(sandboxActivityStarter.isActivityResumed()).isTrue(); 836 837 String dataDir = actionExecutor.getDataDir(); 838 assertThat(dataDir).doesNotContain(SDK_NAME_1); 839 assertThat(dataDir).contains(getSdkSandboxPackageName()); 840 } 841 842 /** 843 * Ensure that SDK can lock back navigation 844 * 845 * @throws RemoteException 846 */ 847 @Test testBackNavigationControl()848 public void testBackNavigationControl() throws RemoteException { 849 assumeTrue(SdkLevel.isAtLeastU()); 850 851 ICtsSdkProviderApi sdk = loadSdk(); 852 853 ActivityStarter sandboxActivityStarter = new ActivityStarter(); 854 IActivityActionExecutor actionExecutor = startSandboxActivity(sdk, sandboxActivityStarter); 855 856 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 857 assertThat(sandboxActivityStarter.isActivityResumed()).isTrue(); 858 859 actionExecutor.disableBackButton(); 860 sUiDevice.pressBack(); 861 assertFalse( 862 sUiDevice.wait(Until.hasObject(By.text("DEFAULT_SHOW_TEXT")), WAIT_FOR_TEXT_IN_MS)); 863 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 864 assertThat(sandboxActivityStarter.isActivityResumed()).isTrue(); 865 866 actionExecutor.enableBackButton(); 867 sUiDevice.pressBack(); 868 assertTrue( 869 sUiDevice.wait(Until.hasObject(By.text("DEFAULT_SHOW_TEXT")), WAIT_FOR_TEXT_IN_MS)); 870 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 871 assertThat(sandboxActivityStarter.isActivityResumed()).isFalse(); 872 } 873 874 /** 875 * Tests that orientation work for sandbox activity 876 * 877 * @throws RemoteException 878 */ 879 @Test testSandboxActivityShouldRotateIfNotLocked()880 public void testSandboxActivityShouldRotateIfNotLocked() throws RemoteException { 881 assumeTrue(SdkLevel.isAtLeastU()); 882 883 ICtsSdkProviderApi sdk = loadSdk(); 884 885 ActivityStarter sandboxActivityStarter = new ActivityStarter(); 886 startSandboxActivity(sdk, sandboxActivityStarter); 887 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 888 assertThat(sandboxActivityStarter.isActivityResumed()).isTrue(); 889 890 // Rotate the device to portrait 891 sUiDevice.setOrientationPortrait(); 892 // Assert Portrait Rotation. 893 assertTrue( 894 sUiDevice.wait( 895 Until.hasObject(By.textContains(ORIENTATION_PORTRAIT_MESSAGE)), 896 WAIT_FOR_TEXT_IN_MS)); 897 898 sUiDevice.setOrientationLandscape(); 899 assertTrue( 900 sUiDevice.wait( 901 Until.hasObject(By.textContains(ORIENTATION_LANDSCAPE_MESSAGE)), 902 WAIT_FOR_TEXT_IN_MS)); 903 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 904 assertThat(sandboxActivityStarter.isActivityResumed()).isTrue(); 905 } 906 907 /** 908 * Tests that SDK can lock sandbox activity orientation 909 * 910 * @throws Exception 911 */ 912 @Test testSandboxActivityOrientationLocking()913 public void testSandboxActivityOrientationLocking() throws RemoteException { 914 assumeTrue(SdkLevel.isAtLeastU()); 915 916 ICtsSdkProviderApi sdk = loadSdk(); 917 918 ActivityStarter sandboxActivityStarter = new ActivityStarter(); 919 IActivityActionExecutor actionExecutor = startSandboxActivity(sdk, sandboxActivityStarter); 920 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 921 assertThat(sandboxActivityStarter.isActivityResumed()).isTrue(); 922 923 // Rotate the device to portrait 924 sUiDevice.setOrientationPortrait(); 925 // Assert Portrait Rotation. 926 assertTrue( 927 sUiDevice.wait( 928 Until.hasObject(By.textContains(ORIENTATION_PORTRAIT_MESSAGE)), 929 WAIT_FOR_TEXT_IN_MS)); 930 931 // Locking orientation to landscape 932 actionExecutor.setOrientationToLandscape(); 933 assertTrue( 934 sUiDevice.wait( 935 Until.hasObject(By.textContains(ORIENTATION_LANDSCAPE_MESSAGE)), 936 WAIT_FOR_TEXT_IN_MS)); 937 // Rotation the device should not affect the locked display orientation. 938 sUiDevice.setOrientationPortrait(); 939 assertFalse( 940 sUiDevice.wait( 941 Until.hasObject(By.textContains(ORIENTATION_PORTRAIT_MESSAGE)), 942 WAIT_FOR_TEXT_IN_MS)); 943 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 944 assertThat(sandboxActivityStarter.isActivityResumed()).isTrue(); 945 946 // Locking orientation to portrait 947 actionExecutor.setOrientationToPortrait(); 948 assertTrue( 949 sUiDevice.wait( 950 Until.hasObject(By.textContains(ORIENTATION_PORTRAIT_MESSAGE)), 951 WAIT_FOR_TEXT_IN_MS)); 952 953 // Rotation the device should not affect the locked display orientation. 954 sUiDevice.setOrientationLandscape(); 955 assertFalse( 956 sUiDevice.wait( 957 Until.hasObject(By.textContains(ORIENTATION_LANDSCAPE_MESSAGE)), 958 WAIT_FOR_TEXT_IN_MS)); 959 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 960 assertThat(sandboxActivityStarter.isActivityResumed()).isTrue(); 961 } 962 963 @Test testStartSdkSandboxedActivityFailIfTheHandlerUnregistered()964 public void testStartSdkSandboxedActivityFailIfTheHandlerUnregistered() { 965 assumeTrue(SdkLevel.isAtLeastU()); 966 967 // Load SDK in sandbox 968 ICtsSdkProviderApi sdk = loadSdk(); 969 970 ActivityStarter activityStarter = new ActivityStarter(); 971 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 972 973 Bundle extras = new Bundle(); 974 extras.putBoolean(UNREGISTER_BEFORE_STARTING_KEY, true); 975 startSandboxActivity(sdk, activityStarter, extras); 976 977 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 978 assertThat(activityStarter.isActivityResumed()).isFalse(); 979 } 980 981 @Test testSandboxActivityStartIntentViewWithNoSecurityExceptions()982 public void testSandboxActivityStartIntentViewWithNoSecurityExceptions() throws Exception { 983 assumeTrue(SdkLevel.isAtLeastU()); 984 985 ICtsSdkProviderApi sdk = loadSdk(); 986 987 ActivityStarter sandboxActivityStarter = new ActivityStarter(); 988 IActivityActionExecutor actionExecutor = startSandboxActivity(sdk, sandboxActivityStarter); 989 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 990 assertThat(sandboxActivityStarter.isActivityResumed()).isTrue(); 991 992 actionExecutor.openLandingPage(); 993 } 994 995 /** 996 * Ensure that SDK can finish the sandbox activity. 997 * 998 * @throws RemoteException 999 */ 1000 @Test testSdkCanFinishSandboxActivity()1001 public void testSdkCanFinishSandboxActivity() throws RemoteException { 1002 assumeTrue(SdkLevel.isAtLeastU()); 1003 1004 ICtsSdkProviderApi sdk = loadSdk(); 1005 1006 ActivityStarter sandboxActivityStarter = new ActivityStarter(); 1007 IActivityActionExecutor actionExecutor = startSandboxActivity(sdk, sandboxActivityStarter); 1008 assertThat(mScenario.getState()).isIn(Arrays.asList(State.CREATED, State.STARTED)); 1009 assertThat(sandboxActivityStarter.isActivityResumed()).isTrue(); 1010 1011 actionExecutor.finish(); 1012 assertTrue( 1013 sUiDevice.wait(Until.hasObject(By.text("DEFAULT_SHOW_TEXT")), WAIT_FOR_TEXT_IN_MS)); 1014 assertThat(mScenario.getState()).isEqualTo(State.RESUMED); 1015 assertThat(sandboxActivityStarter.isActivityResumed()).isFalse(); 1016 } 1017 1018 // Verifies that the test allowlists in {@link SdkSandboxManagerService#LocalImpl} are initially 1019 // empty. 1020 @Test testInitialSandboxTestAllowlistsAreEmpty()1021 public void testInitialSandboxTestAllowlistsAreEmpty() { 1022 assumeTrue(SdkLevel.isAtLeastV()); 1023 assertThat( 1024 SystemUtil.runShellCommand( 1025 "cmd sdk_sandbox get-test-allowlist content-provider")) 1026 .isEqualTo("\n"); 1027 assertThat(SystemUtil.runShellCommand("cmd sdk_sandbox get-test-allowlist send-broadcast")) 1028 .isEqualTo("\n"); 1029 } 1030 1031 // Helper method to load SDK_NAME_1 loadSdk()1032 private ICtsSdkProviderApi loadSdk() { 1033 final FakeLoadSdkCallback callback = new FakeLoadSdkCallback(); 1034 mSdkSandboxManager.loadSdk(SDK_NAME_1, new Bundle(), Runnable::run, callback); 1035 callback.assertLoadSdkIsSuccessful(); 1036 1037 final SandboxedSdk sandboxedSdk = callback.getSandboxedSdk(); 1038 assertNotNull(sandboxedSdk); 1039 return ICtsSdkProviderApi.Stub.asInterface(callback.getSandboxedSdk().getInterface()); 1040 } 1041 getAppProcessImportance()1042 private int getAppProcessImportance() { 1043 ActivityManager.RunningAppProcessInfo processInfo = 1044 new ActivityManager.RunningAppProcessInfo(); 1045 ActivityManager.getMyMemoryState(processInfo); 1046 return processInfo.importance; 1047 } 1048 startSandboxActivity( ICtsSdkProviderApi sdk, ActivityStarter activityStarter)1049 private IActivityActionExecutor startSandboxActivity( 1050 ICtsSdkProviderApi sdk, ActivityStarter activityStarter) { 1051 return startSandboxActivity(sdk, activityStarter, new Bundle()); 1052 } 1053 startSandboxActivity( ICtsSdkProviderApi sdk, ActivityStarter activityStarter, Bundle extras)1054 private IActivityActionExecutor startSandboxActivity( 1055 ICtsSdkProviderApi sdk, ActivityStarter activityStarter, Bundle extras) { 1056 final String randomText = mRandom.nextInt(Integer.MAX_VALUE) + ""; 1057 extras.putString(TEXT_KEY, randomText); 1058 ActivityExecutorContainer activityExecutorContainer = new ActivityExecutorContainer(); 1059 mScenario.onActivity( 1060 clientActivity -> { 1061 activityStarter.setFromActivity(clientActivity); 1062 IActivityActionExecutor actionExecutor = null; 1063 try { 1064 actionExecutor = 1065 (IActivityActionExecutor) 1066 sdk.startActivity(activityStarter, extras); 1067 } catch (Exception e) { 1068 fail("Got exception while starting activity: " + e.getMessage()); 1069 } 1070 activityExecutorContainer.setExecutor(actionExecutor); 1071 }); 1072 IActivityActionExecutor actionExecutor = activityExecutorContainer.getExecutor(); 1073 assertThat(actionExecutor).isNotNull(); 1074 if (extras.containsKey(UNREGISTER_BEFORE_STARTING_KEY)) { 1075 assertFalse( 1076 sUiDevice.wait( 1077 Until.hasObject(By.textContains(randomText)), WAIT_FOR_TEXT_IN_MS)); 1078 } else { 1079 assertWithMessage("Activity has random text") 1080 .that( 1081 sUiDevice.wait( 1082 Until.hasObject(By.textContains(randomText)), 1083 WAIT_FOR_TEXT_IN_MS)) 1084 .isTrue(); 1085 } 1086 return actionExecutor; 1087 } 1088 1089 // Separate class to store IActivityActionExecutor which is returned in a lambda expression. 1090 private static class ActivityExecutorContainer { 1091 private IActivityActionExecutor mExecutor; 1092 setExecutor(IActivityActionExecutor executor)1093 public void setExecutor(IActivityActionExecutor executor) { 1094 mExecutor = executor; 1095 } 1096 getExecutor()1097 public IActivityActionExecutor getExecutor() { 1098 return mExecutor; 1099 } 1100 } 1101 1102 private class ActivityStarter extends IActivityStarter.Stub { 1103 private Activity mFromActivity; 1104 private boolean mActivityResumed = false; 1105 ActivityStarter()1106 ActivityStarter() {} 1107 1108 // To be called by SDKs to start sandbox activities. 1109 @Override startSdkSandboxActivity(IBinder token)1110 public void startSdkSandboxActivity(IBinder token) throws RemoteException { 1111 assertThat(mFromActivity).isNotNull(); 1112 1113 mSdkSandboxManager.startSdkSandboxActivity(mFromActivity, token); 1114 } 1115 1116 // It is called to notify that onResume() is called against the new started Activity. 1117 @Override onActivityResumed()1118 public void onActivityResumed() { 1119 mActivityResumed = true; 1120 } 1121 1122 // It is called to notify the new started Activity is no longer in the Resumed state. 1123 @Override onLeftActivityResumed()1124 public void onLeftActivityResumed() { 1125 mActivityResumed = false; 1126 } 1127 1128 // To start local test activities (can not be called between processes). startLocalActivity()1129 public void startLocalActivity() { 1130 assertThat(mFromActivity).isNotNull(); 1131 startLocalActivity(0); 1132 } 1133 1134 // To start local test activities (can not be called between processes). startLocalActivity(int flags)1135 public void startLocalActivity(int flags) { 1136 assertThat(mFromActivity).isNotNull(); 1137 1138 final Intent intent = new Intent(mFromActivity, TestActivity.class); 1139 final Bundle params = new Bundle(); 1140 final String randomText = mRandom.nextInt(Integer.MAX_VALUE) + ""; 1141 params.putString(TEXT_KEY, randomText); 1142 params.putBinder(ACTIVITY_STARTER_KEY, this); 1143 intent.putExtras(params); 1144 intent.addFlags(flags); 1145 mFromActivity.startActivity(intent); 1146 assertTrue(sUiDevice.wait(Until.hasObject(By.text(randomText)), WAIT_FOR_TEXT_IN_MS)); 1147 } 1148 setFromActivity(Activity activity)1149 public void setFromActivity(Activity activity) { 1150 mFromActivity = activity; 1151 } 1152 isActivityResumed()1153 public boolean isActivityResumed() { 1154 return mActivityResumed; 1155 } 1156 } 1157 getRequestSurfacePackageParams()1158 private Bundle getRequestSurfacePackageParams() { 1159 Bundle params = new Bundle(); 1160 params.putInt(EXTRA_WIDTH_IN_PIXELS, 500); 1161 params.putInt(EXTRA_HEIGHT_IN_PIXELS, 500); 1162 params.putInt(EXTRA_DISPLAY_ID, 0); 1163 params.putBinder(EXTRA_HOST_TOKEN, new Binder()); 1164 1165 return params; 1166 } 1167 getSdkSandboxPackageName()1168 private String getSdkSandboxPackageName() { 1169 return InstrumentationRegistry.getInstrumentation() 1170 .getContext() 1171 .getPackageManager() 1172 .getSdkSandboxPackageName(); 1173 } 1174 loadMultipleSdks()1175 private void loadMultipleSdks() { 1176 FakeLoadSdkCallback callback = new FakeLoadSdkCallback(); 1177 mSdkSandboxManager.loadSdk(SDK_NAME_1, new Bundle(), Runnable::run, callback); 1178 callback.assertLoadSdkIsSuccessful(); 1179 1180 FakeLoadSdkCallback callback2 = new FakeLoadSdkCallback(); 1181 mSdkSandboxManager.loadSdk(SDK_NAME_2, new Bundle(), Runnable::run, callback2); 1182 callback2.assertLoadSdkIsSuccessful(); 1183 } 1184 } 1185