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