diff options
Diffstat (limited to 'sdksandbox/tests/unittest')
13 files changed, 1030 insertions, 417 deletions
diff --git a/sdksandbox/tests/unittest/Android.bp b/sdksandbox/tests/unittest/Android.bp index a86f995818..cb4a10715f 100644 --- a/sdksandbox/tests/unittest/Android.bp +++ b/sdksandbox/tests/unittest/Android.bp @@ -19,7 +19,7 @@ package { java_defaults { name: "SdkSandboxUnitTestsDefault", min_sdk_version: "Tiramisu", - target_sdk_version: "current", + target_sdk_version: "Tiramisu", test_suites: [ "mts-adservices", "general-tests" @@ -91,7 +91,7 @@ android_test { android_test { name: "SdkSandboxFrameworkUnitTests", srcs: [ - "src/android/app/sdksandbox/*.java", + "src/android/app/sdksandbox/**/*.java", ":framework-sdksandbox-sources", ], defaults: ["SdkSandboxUnitTestsDefault"], diff --git a/sdksandbox/tests/unittest/SdkSandboxFrameworkTest.xml b/sdksandbox/tests/unittest/SdkSandboxFrameworkTest.xml index 2858635ef4..56be0f7e29 100644 --- a/sdksandbox/tests/unittest/SdkSandboxFrameworkTest.xml +++ b/sdksandbox/tests/unittest/SdkSandboxFrameworkTest.xml @@ -17,6 +17,11 @@ <configuration description="Config for SdkSandboxFramework unit test cases"> <option name="test-tag" value="SdkSandboxFrameworkUnitTest" /> + <target_preparer class="com.android.tradefed.targetprep.DeviceSetup"> + <!-- Disable syncing to prevent overwriting flags during testing. --> + <option name="disable-device-config-sync" value="true" /> + </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> <option name="cleanup-apks" value="true"/> <option name="test-file-name" value="CodeProviderWithResources.apk"/> diff --git a/sdksandbox/tests/unittest/SdkSandboxManagerServiceTest.xml b/sdksandbox/tests/unittest/SdkSandboxManagerServiceTest.xml index 46f16a8e36..90957d0300 100644 --- a/sdksandbox/tests/unittest/SdkSandboxManagerServiceTest.xml +++ b/sdksandbox/tests/unittest/SdkSandboxManagerServiceTest.xml @@ -17,6 +17,11 @@ <configuration description="Config for SdkSandboxManagerService unit test cases"> <option name="test-tag" value="SdkSandboxManagerServiceUnitTest" /> + <target_preparer class="com.android.tradefed.targetprep.DeviceSetup"> + <!-- Disable syncing to prevent overwriting flags during testing. --> + <option name="disable-device-config-sync" value="true" /> + </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> <option name="cleanup-apks" value="true"/> <option name="test-file-name" value="SampleCodeProviderApp.apk"/> diff --git a/sdksandbox/tests/unittest/src/android/app/sdksandbox/SandboxedSdkContextUnitTest.java b/sdksandbox/tests/unittest/src/android/app/sdksandbox/SandboxedSdkContextUnitTest.java index e08c504a4c..fc835727ef 100644 --- a/sdksandbox/tests/unittest/src/android/app/sdksandbox/SandboxedSdkContextUnitTest.java +++ b/sdksandbox/tests/unittest/src/android/app/sdksandbox/SandboxedSdkContextUnitTest.java @@ -67,6 +67,7 @@ public class SandboxedSdkContextUnitTest { mSandboxedSdkContext = new SandboxedSdkContext( InstrumentationRegistry.getContext(), + getClass().getClassLoader(), CLIENT_PACKAGE_NAME, info, SDK_NAME, @@ -117,6 +118,11 @@ public class SandboxedSdkContextUnitTest { } @Test + public void testClassLoader() { + assertThat(mSandboxedSdkContext.getClassLoader()).isEqualTo(getClass().getClassLoader()); + } + + @Test public void testGetDataDir_CredentialEncrypted() throws Exception { assertThat(mSandboxedSdkContext.getDataDir().toString()).isEqualTo(SDK_CE_DATA_DIR); @@ -153,6 +159,7 @@ public class SandboxedSdkContextUnitTest { SandboxedSdkContext sandboxedSdkContext = new SandboxedSdkContext( testContext, + getClass().getClassLoader(), CLIENT_PACKAGE_NAME, info, SDK_NAME, @@ -179,6 +186,7 @@ public class SandboxedSdkContextUnitTest { SandboxedSdkContext sandboxedSdkContext = new SandboxedSdkContext( testContext, + getClass().getClassLoader(), CLIENT_PACKAGE_NAME, info, SDK_NAME, @@ -204,6 +212,7 @@ public class SandboxedSdkContextUnitTest { new SandboxedSdkContext( InstrumentationRegistry.getContext() .createCredentialProtectedStorageContext(), + getClass().getClassLoader(), CLIENT_PACKAGE_NAME, info, SDK_NAME, @@ -213,6 +222,7 @@ public class SandboxedSdkContextUnitTest { new SandboxedSdkContext( InstrumentationRegistry.getContext() .createCredentialProtectedStorageContext(), + getClass().getClassLoader(), CLIENT_PACKAGE_NAME, info, SDK_NAME, diff --git a/sdksandbox/tests/unittest/src/android/app/sdksandbox/SandboxedSdkUnitTest.java b/sdksandbox/tests/unittest/src/android/app/sdksandbox/SandboxedSdkUnitTest.java new file mode 100644 index 0000000000..d6e1f719a2 --- /dev/null +++ b/sdksandbox/tests/unittest/src/android/app/sdksandbox/SandboxedSdkUnitTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.sdksandbox; + +import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assert.assertThrows; + +import android.content.pm.SharedLibraryInfo; +import android.content.pm.VersionedPackage; +import android.os.Binder; +import android.os.Parcel; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.ArrayList; + +@RunWith(JUnit4.class) +public class SandboxedSdkUnitTest { + + public static final SharedLibraryInfo SHARED_LIBRARY_INFO = + new SharedLibraryInfo( + "testpath", + "test", + new ArrayList<>(), + "test", + 0L, + SharedLibraryInfo.TYPE_STATIC, + new VersionedPackage("test", 0L), + null, + null, + false /* isNative */); + + @Test + public void testAttachSharedLibraryInfoFailsWhenCalledAgain() { + SandboxedSdk sandboxedSdk = new SandboxedSdk(new Binder()); + sandboxedSdk.attachSharedLibraryInfo(SHARED_LIBRARY_INFO); + // Only one update should be received + assertThrows( + "SharedLibraryInfo already set", + IllegalStateException.class, + () -> sandboxedSdk.attachSharedLibraryInfo(SHARED_LIBRARY_INFO)); + } + + @Test + public void testGetInterface() { + Binder binder = new Binder(); + SandboxedSdk sandboxedSdk = new SandboxedSdk(binder); + assertThat(sandboxedSdk.getInterface()).isSameInstanceAs(binder); + } + + @Test + public void testGetSharedLibraryInfo() { + SandboxedSdk sandboxedSdk = new SandboxedSdk(new Binder()); + sandboxedSdk.attachSharedLibraryInfo(SHARED_LIBRARY_INFO); + assertThat(sandboxedSdk.getSharedLibraryInfo()).isSameInstanceAs(SHARED_LIBRARY_INFO); + } + + @Test + public void testGetSharedLibraryInfoNull() { + SandboxedSdk sandboxedSdk = new SandboxedSdk(new Binder()); + assertThrows(IllegalStateException.class, () -> sandboxedSdk.getSharedLibraryInfo()); + } + + @Test + public void testDescribeContents() { + SandboxedSdk sandboxedSdk = new SandboxedSdk(new Binder()); + int descriptor = sandboxedSdk.describeContents(); + assertThat(descriptor).isEqualTo(0); + } + + @Test + public void testWriteToParcel() { + SandboxedSdk sandboxedSdk = new SandboxedSdk(new Binder()); + + Parcel parcel = Parcel.obtain(); + sandboxedSdk.writeToParcel(parcel, 0 /* flags */); + parcel.setDataPosition(0); + SandboxedSdk fromParcel = SandboxedSdk.CREATOR.createFromParcel(parcel); + parcel.recycle(); + + assertThat(sandboxedSdk.getInterface()).isEqualTo(fromParcel.getInterface()); + } + + @Test + public void testWriteToParcelWithSharedLibraryInfo() { + SandboxedSdk sandboxedSdk = new SandboxedSdk(new Binder()); + sandboxedSdk.attachSharedLibraryInfo(SHARED_LIBRARY_INFO); + + Parcel parcel = Parcel.obtain(); + sandboxedSdk.writeToParcel(parcel, 0 /* flags */); + parcel.setDataPosition(0); + SandboxedSdk fromParcel = SandboxedSdk.CREATOR.createFromParcel(parcel); + parcel.recycle(); + + assertThat(sandboxedSdk.getInterface()).isEqualTo(fromParcel.getInterface()); + assertThat(sandboxedSdk.getSharedLibraryInfo().getName()) + .isEqualTo(fromParcel.getSharedLibraryInfo().getName()); + assertThat(sandboxedSdk.getSharedLibraryInfo().getLongVersion()) + .isEqualTo(fromParcel.getSharedLibraryInfo().getLongVersion()); + } +} diff --git a/sdksandbox/tests/unittest/src/android/app/sdksandbox/SdkSandboxControllerUnitTest.java b/sdksandbox/tests/unittest/src/android/app/sdksandbox/SdkSandboxControllerUnitTest.java deleted file mode 100644 index 7f2f470768..0000000000 --- a/sdksandbox/tests/unittest/src/android/app/sdksandbox/SdkSandboxControllerUnitTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.app.sdksandbox; - -import static com.google.common.truth.Truth.assertThat; - -import android.content.Context; - -import androidx.test.platform.app.InstrumentationRegistry; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class SdkSandboxControllerUnitTest { - private Context mContext; - - @Before - public void setup() { - mContext = InstrumentationRegistry.getInstrumentation().getContext(); - } - - @Test - public void testCreateInstance() throws Exception { - SdkSandboxController controller = new SdkSandboxController(mContext); - assertThat(controller).isNotNull(); - } - - @Test - public void testGetInstance() throws Exception { - assertThat(mContext.getSystemService(SdkSandboxController.class)).isNotNull(); - } -} diff --git a/sdksandbox/tests/unittest/src/android/app/sdksandbox/SdkSandboxLocalSingletonUnitTest.java b/sdksandbox/tests/unittest/src/android/app/sdksandbox/SdkSandboxLocalSingletonUnitTest.java new file mode 100644 index 0000000000..32ba47245e --- /dev/null +++ b/sdksandbox/tests/unittest/src/android/app/sdksandbox/SdkSandboxLocalSingletonUnitTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.sdksandbox; + +import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assert.assertThrows; + +import android.os.IBinder; +import android.os.RemoteException; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mockito; + +@RunWith(JUnit4.class) +public class SdkSandboxLocalSingletonUnitTest { + private IBinder mBinder; + + @Before + public void setup() throws RemoteException { + mBinder = Mockito.mock(IBinder.class); + Mockito.when(mBinder.getInterfaceDescriptor()).thenReturn(ISdkToServiceCallback.DESCRIPTOR); + } + + @After + public void tearDown() { + SdkSandboxLocalSingleton.destroySingleton(); + } + + @Test + public void testInitInstanceWithIncorrectType() throws RemoteException { + IBinder binder2 = Mockito.mock(IBinder.class); + Mockito.when(binder2.getInterfaceDescriptor()).thenReturn("xyz"); + assertThrows( + "IInterface not supported", + UnsupportedOperationException.class, + () -> SdkSandboxLocalSingleton.initInstance(binder2)); + } + + @Test + public void testInitInstance() { + SdkSandboxLocalSingleton.initInstance(mBinder); + SdkSandboxLocalSingleton singletonInstance = SdkSandboxLocalSingleton.getExistingInstance(); + assertThat(singletonInstance).isNotNull(); + assertThat(singletonInstance.getSdkToServiceCallback().asBinder()).isEqualTo(mBinder); + } + + @Test + public void testInitInstanceWhenAlreadyExists() { + SdkSandboxLocalSingleton.initInstance(mBinder); + + IBinder binder2 = Mockito.mock(IBinder.class); + SdkSandboxLocalSingleton.initInstance(binder2); + + // Assert that the callback was not overridden and the new instance was not created. + SdkSandboxLocalSingleton singletonInstance = SdkSandboxLocalSingleton.getExistingInstance(); + assertThat(singletonInstance).isNotNull(); + assertThat(singletonInstance.getSdkToServiceCallback().asBinder()).isEqualTo(mBinder); + } + + @Test + public void testGetInstanceReturnsSameObjectAlways() { + SdkSandboxLocalSingleton.initInstance(mBinder); + + SdkSandboxLocalSingleton singletonInstance = SdkSandboxLocalSingleton.getExistingInstance(); + assertThat(singletonInstance).isNotNull(); + assertThat(SdkSandboxLocalSingleton.getExistingInstance()) + .isSameInstanceAs(singletonInstance); + } + + @Test + public void testGetInstanceWhenItDoesNotExist() { + assertThrows( + "SdkSandboxLocalSingleton not found", + IllegalStateException.class, + SdkSandboxLocalSingleton::getExistingInstance); + } +} diff --git a/sdksandbox/tests/unittest/src/android/app/sdksandbox/SdkSandboxManagerUnitTest.java b/sdksandbox/tests/unittest/src/android/app/sdksandbox/SdkSandboxManagerUnitTest.java index d6256f5bf0..4c7583150f 100644 --- a/sdksandbox/tests/unittest/src/android/app/sdksandbox/SdkSandboxManagerUnitTest.java +++ b/sdksandbox/tests/unittest/src/android/app/sdksandbox/SdkSandboxManagerUnitTest.java @@ -32,7 +32,6 @@ import static org.junit.Assert.assertTrue; import android.app.sdksandbox.testutils.FakeOutcomeReceiver; import android.content.Context; -import android.content.pm.SharedLibraryInfo; import android.os.Binder; import android.os.Bundle; import android.os.OutcomeReceiver; @@ -152,15 +151,14 @@ public class SdkSandboxManagerUnitTest { } @Test - public void testGetLoadedSdkLibrariesInfo() throws Exception { - List<SharedLibraryInfo> sharedLibraries = List.of(); - Mockito.when(mBinder.getLoadedSdkLibrariesInfo(Mockito.anyString(), Mockito.anyLong())) - .thenReturn(sharedLibraries); + public void testGetSandboxedSdks() throws Exception { + List<SandboxedSdk> sandboxedSdks = List.of(); + Mockito.when(mBinder.getSandboxedSdks(Mockito.anyString(), Mockito.anyLong())) + .thenReturn(sandboxedSdks); - assertThat(mSdkSandboxManager.getLoadedSdkLibrariesInfo()).isEqualTo(sharedLibraries); + assertThat(mSdkSandboxManager.getSandboxedSdks()).isSameInstanceAs(sandboxedSdks); Mockito.verify(mBinder) - .getLoadedSdkLibrariesInfo( - Mockito.eq(mContext.getPackageName()), Mockito.anyLong()); + .getSandboxedSdks(Mockito.eq(mContext.getPackageName()), Mockito.anyLong()); } @Test diff --git a/sdksandbox/tests/unittest/src/android/app/sdksandbox/SharedPreferencesSyncManagerUnitTest.java b/sdksandbox/tests/unittest/src/android/app/sdksandbox/SharedPreferencesSyncManagerUnitTest.java index 65c034abb4..9dbc849f6a 100644 --- a/sdksandbox/tests/unittest/src/android/app/sdksandbox/SharedPreferencesSyncManagerUnitTest.java +++ b/sdksandbox/tests/unittest/src/android/app/sdksandbox/SharedPreferencesSyncManagerUnitTest.java @@ -37,6 +37,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.Mockito; import java.util.ArrayList; import java.util.Collections; @@ -89,6 +90,23 @@ public class SharedPreferencesSyncManagerUnitTest { final SharedPreferencesSyncManager manager2 = SharedPreferencesSyncManager.getInstance(mContext, mSdkSandboxManagerService); assertThat(manager1).isSameInstanceAs(manager2); + + Context mockContext = Mockito.mock(Context.class); + Mockito.when(mockContext.getPackageName()).thenReturn(mContext.getPackageName()); + final SharedPreferencesSyncManager manager3 = + SharedPreferencesSyncManager.getInstance(mockContext, mSdkSandboxManagerService); + assertThat(manager1).isSameInstanceAs(manager3); + } + + @Test + public void test_sharedPreferencesSyncManager_isSingletonPerPackage() throws Exception { + final SharedPreferencesSyncManager manager1 = + SharedPreferencesSyncManager.getInstance(mContext, mSdkSandboxManagerService); + + Context mockContext = Mockito.mock(Context.class); + final SharedPreferencesSyncManager manager2 = + SharedPreferencesSyncManager.getInstance(mockContext, mSdkSandboxManagerService); + assertThat(manager1).isNotSameInstanceAs(manager2); } @Test @@ -122,6 +140,18 @@ public class SharedPreferencesSyncManagerUnitTest { } @Test + public void test_removeKeys_updateSentForRemoval() throws Exception { + mSyncManager.addSharedPreferencesSyncKeys(KEYS_TO_SYNC); + + // Remove key + mSyncManager.removeSharedPreferencesSyncKeys(Set.of(KEY_TO_UPDATE)); + + final SharedPreferencesUpdate update = mSdkSandboxManagerService.getLastUpdate(); + assertThat(update.getData().keySet()).doesNotContain(Set.of(KEY_TO_UPDATE)); + assertThat(update.getKeysInUpdate()).containsExactly(KEY_WITH_TYPE_TO_UPDATE); + } + + @Test public void test_bulkSync_syncSpecifiedKeys() throws Exception { // Populate default shared preference with test data populateDefaultSharedPreference(TEST_DATA); diff --git a/sdksandbox/tests/unittest/src/android/app/sdksandbox/sdkprovider/SdkSandboxControllerUnitTest.java b/sdksandbox/tests/unittest/src/android/app/sdksandbox/sdkprovider/SdkSandboxControllerUnitTest.java new file mode 100644 index 0000000000..d07b8d4658 --- /dev/null +++ b/sdksandbox/tests/unittest/src/android/app/sdksandbox/sdkprovider/SdkSandboxControllerUnitTest.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.sdksandbox.sdkprovider; + +import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assert.assertThrows; + +import android.app.sdksandbox.ISdkToServiceCallback; +import android.app.sdksandbox.SandboxedSdk; +import android.app.sdksandbox.SandboxedSdkContext; +import android.app.sdksandbox.SdkSandboxLocalSingleton; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; +import android.os.Binder; +import android.os.RemoteException; + +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.dx.mockito.inline.extended.ExtendedMockito; +import com.android.dx.mockito.inline.extended.StaticMockitoSession; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(JUnit4.class) +public class SdkSandboxControllerUnitTest { + private static final String RESOURCES_PACKAGE = "com.android.codeproviderresources_1"; + + private Context mContext; + private SandboxedSdkContext mSandboxedSdkContext; + private SdkSandboxLocalSingleton mSdkSandboxLocalSingleton; + private StaticMockitoSession mStaticMockSession; + + @Before + public void setup() throws Exception { + mContext = InstrumentationRegistry.getInstrumentation().getContext(); + mSandboxedSdkContext = + new SandboxedSdkContext( + mContext, + getClass().getClassLoader(), + /*clientPackageName=*/ "", + new ApplicationInfo(), + /*sdkName=*/ "", + /*sdkCeDataDir=*/ null, + /*sdkDeDataDir=*/ null); + + mStaticMockSession = + ExtendedMockito.mockitoSession() + .mockStatic(SdkSandboxLocalSingleton.class) + .startMocking(); + mSdkSandboxLocalSingleton = Mockito.mock(SdkSandboxLocalSingleton.class); + // Populate mSdkSandboxLocalSingleton + ExtendedMockito.doReturn(mSdkSandboxLocalSingleton) + .when(() -> SdkSandboxLocalSingleton.getExistingInstance()); + } + + @After + public void tearDown() { + mStaticMockSession.finishMocking(); + } + + @Test + public void testCreateInstance() throws Exception { + final SdkSandboxController controller = new SdkSandboxController(mContext); + assertThat(controller).isNotNull(); + } + + @Test + public void testInitWithAnyContext() throws Exception { + SdkSandboxController controller = mContext.getSystemService(SdkSandboxController.class); + assertThat(controller).isNotNull(); + // Does not fail on initialising with same context + controller.initialize(mContext); + assertThat(controller).isNotNull(); + } + + @Test + public void testGetSandboxedSdks() throws RemoteException { + SdkSandboxController controller = mContext.getSystemService(SdkSandboxController.class); + controller.initialize(mSandboxedSdkContext); + + // Mock singleton methods + ISdkToServiceCallback serviceCallback = Mockito.mock(ISdkToServiceCallback.class); + ArrayList<SandboxedSdk> sandboxedSdksMock = new ArrayList<>(); + sandboxedSdksMock.add(new SandboxedSdk(new Binder())); + Mockito.when(serviceCallback.getSandboxedSdks(Mockito.anyString())) + .thenReturn(sandboxedSdksMock); + Mockito.when(mSdkSandboxLocalSingleton.getSdkToServiceCallback()) + .thenReturn(serviceCallback); + + List<SandboxedSdk> sandboxedSdks = controller.getSandboxedSdks(); + assertThat(sandboxedSdks).isEqualTo(sandboxedSdksMock); + } + + @Test + public void testGetSandboxedSdksFailsWithIncorrectContext() { + SdkSandboxController controller = mContext.getSystemService(SdkSandboxController.class); + + assertThrows( + "Only available from the context obtained by calling android.app.sdksandbox" + + ".SandboxedSdkProvider#getContext()", + UnsupportedOperationException.class, + () -> controller.getSandboxedSdks()); + } + + @Test + public void testGetClientSharedPreferences_onlyFromSandboxedContext() throws Exception { + final SdkSandboxController controller = new SdkSandboxController(mContext); + assertThrows( + "Only available from SandboxedSdkContext", + UnsupportedOperationException.class, + () -> controller.getClientSharedPreferences()); + } + + @Test + public void testGetClientSharedPreferences() throws Exception { + final SdkSandboxController controller = new SdkSandboxController(mContext); + controller.initialize(mSandboxedSdkContext); + + final SharedPreferences sp = controller.getClientSharedPreferences(); + // Assert same instance as a name SharedPreference on sandboxed context + final SharedPreferences spFromSandboxedContext = + mSandboxedSdkContext.getSharedPreferences( + SdkSandboxController.CLIENT_SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); + assertThat(sp).isSameInstanceAs(spFromSandboxedContext); + // Assert same instance as a name SharedPreference on original context + final SharedPreferences spFromOriginalContext = + mContext.getSharedPreferences( + SdkSandboxController.CLIENT_SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); + assertThat(sp).isSameInstanceAs(spFromOriginalContext); + } +} diff --git a/sdksandbox/tests/unittest/src/com/android/sdksandbox/SdkSandboxTest.java b/sdksandbox/tests/unittest/src/com/android/sdksandbox/SdkSandboxTest.java index 0e7701b5eb..815596ec6e 100644 --- a/sdksandbox/tests/unittest/src/com/android/sdksandbox/SdkSandboxTest.java +++ b/sdksandbox/tests/unittest/src/com/android/sdksandbox/SdkSandboxTest.java @@ -18,8 +18,11 @@ package com.android.sdksandbox; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + import android.app.sdksandbox.LoadSdkException; import android.app.sdksandbox.SandboxedSdk; +import android.app.sdksandbox.SdkSandboxLocalSingleton; import android.app.sdksandbox.SharedPreferencesKey; import android.app.sdksandbox.SharedPreferencesUpdate; import android.app.sdksandbox.testutils.StubSdkToServiceLink; @@ -30,10 +33,8 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Binder; import android.os.Bundle; -import android.os.IBinder; import android.os.Looper; import android.os.Process; -import android.preference.PreferenceManager; import android.view.SurfaceControlViewHost; import androidx.test.platform.app.InstrumentationRegistry; @@ -131,7 +132,27 @@ public class SdkSandboxTest { @After public void teardown() throws Exception { - getClientSharedPreference().edit().clear().commit(); + mService.getClientSharedPreferences().edit().clear().commit(); + } + + @Test + public void testSandboxInitialization_initializesSdkSandboxLocalSingleTon() throws Exception { + assertThrows( + IllegalStateException.class, () -> SdkSandboxLocalSingleton.getExistingInstance()); + + mService.initialize(new StubSdkToServiceLink()); + + assertThat(SdkSandboxLocalSingleton.getExistingInstance()).isNotNull(); + } + + @Test + public void testSandboxInitialization_clearsSyncedData() throws Exception { + // First write some data + mService.syncDataFromClient(TEST_UPDATE); + + mService.initialize(new StubSdkToServiceLink()); + + assertThat(mService.getClientSharedPreferences().getAll()).isEmpty(); } @Test @@ -140,7 +161,6 @@ public class SdkSandboxTest { RemoteCode mRemoteCode = new RemoteCode(latch); mService.loadSdk( CLIENT_PACKAGE_NAME, - new Binder(), mApplicationInfo, SDK_NAME, SDK_PROVIDER_CLASS, @@ -148,8 +168,7 @@ public class SdkSandboxTest { null, new Bundle(), mRemoteCode, - SANDBOX_LATENCY_INFO, - new StubSdkToServiceLink()); + SANDBOX_LATENCY_INFO); assertThat(latch.await(1, TimeUnit.MINUTES)).isTrue(); assertThat(mRemoteCode.mSuccessful).isTrue(); } @@ -160,10 +179,8 @@ public class SdkSandboxTest { RemoteCode mRemoteCode1 = new RemoteCode(latch1); CountDownLatch latch2 = new CountDownLatch(1); RemoteCode mRemoteCode2 = new RemoteCode(latch2); - IBinder duplicateToken = new Binder(); mService.loadSdk( CLIENT_PACKAGE_NAME, - duplicateToken, mApplicationInfo, SDK_NAME, SDK_PROVIDER_CLASS, @@ -171,13 +188,11 @@ public class SdkSandboxTest { null, new Bundle(), mRemoteCode1, - SANDBOX_LATENCY_INFO, - new StubSdkToServiceLink()); + SANDBOX_LATENCY_INFO); assertThat(latch1.await(1, TimeUnit.MINUTES)).isTrue(); assertThat(mRemoteCode1.mSuccessful).isTrue(); mService.loadSdk( CLIENT_PACKAGE_NAME, - duplicateToken, mApplicationInfo, SDK_NAME, SDK_PROVIDER_CLASS, @@ -185,8 +200,7 @@ public class SdkSandboxTest { null, new Bundle(), mRemoteCode2, - SANDBOX_LATENCY_INFO, - new StubSdkToServiceLink()); + SANDBOX_LATENCY_INFO); assertThat(latch2.await(1, TimeUnit.MINUTES)).isTrue(); assertThat(mRemoteCode2.mSuccessful).isFalse(); assertThat(mRemoteCode2.mErrorCode) @@ -194,49 +208,11 @@ public class SdkSandboxTest { } @Test - public void testLoadingMultiple() throws Exception { - CountDownLatch latch1 = new CountDownLatch(1); - RemoteCode mRemoteCode1 = new RemoteCode(latch1); - CountDownLatch latch2 = new CountDownLatch(1); - RemoteCode mRemoteCode2 = new RemoteCode(latch2); - StubSdkToServiceLink sdkToServiceLink = new StubSdkToServiceLink(); - mService.loadSdk( - CLIENT_PACKAGE_NAME, - new Binder(), - mApplicationInfo, - SDK_NAME, - SDK_PROVIDER_CLASS, - null, - null, - new Bundle(), - mRemoteCode1, - SANDBOX_LATENCY_INFO, - sdkToServiceLink); - mService.loadSdk( - CLIENT_PACKAGE_NAME, - new Binder(), - mApplicationInfo, - SDK_NAME, - SDK_PROVIDER_CLASS, - null, - null, - new Bundle(), - mRemoteCode2, - SANDBOX_LATENCY_INFO, - sdkToServiceLink); - assertThat(latch1.await(1, TimeUnit.MINUTES)).isTrue(); - assertThat(mRemoteCode1.mSuccessful).isTrue(); - assertThat(latch2.await(1, TimeUnit.MINUTES)).isTrue(); - assertThat(mRemoteCode2.mSuccessful).isTrue(); - } - - @Test public void testRequestSurfacePackage() throws Exception { CountDownLatch latch = new CountDownLatch(1); RemoteCode mRemoteCode = new RemoteCode(latch); mService.loadSdk( CLIENT_PACKAGE_NAME, - new Binder(), mApplicationInfo, SDK_NAME, SDK_PROVIDER_CLASS, @@ -244,8 +220,7 @@ public class SdkSandboxTest { null, new Bundle(), mRemoteCode, - SANDBOX_LATENCY_INFO, - new StubSdkToServiceLink()); + SANDBOX_LATENCY_INFO); assertThat(latch.await(1, TimeUnit.MINUTES)).isTrue(); CountDownLatch surfaceLatch = new CountDownLatch(1); @@ -271,7 +246,6 @@ public class SdkSandboxTest { RemoteCode mRemoteCode = new RemoteCode(latch); mService.loadSdk( CLIENT_PACKAGE_NAME, - new Binder(), mApplicationInfo, SDK_NAME, SDK_PROVIDER_CLASS, @@ -279,8 +253,7 @@ public class SdkSandboxTest { null, new Bundle(), mRemoteCode, - SANDBOX_LATENCY_INFO, - new StubSdkToServiceLink()); + SANDBOX_LATENCY_INFO); assertThat(latch.await(1, TimeUnit.MINUTES)).isTrue(); CountDownLatch surfaceLatch = new CountDownLatch(1); @@ -305,10 +278,6 @@ public class SdkSandboxTest { @Test public void testDump_NoSdk() { - Mockito.doNothing() - .when(mContext) - .enforceCallingPermission( - Mockito.eq("android.permission.DUMP"), Mockito.anyString()); final StringWriter stringWriter = new StringWriter(); mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]); assertThat(stringWriter.toString()).contains("mHeldSdk is empty"); @@ -316,14 +285,8 @@ public class SdkSandboxTest { @Test public void testDump_WithSdk() { - Mockito.doNothing() - .when(mContext) - .enforceCallingPermission( - Mockito.eq("android.permission.DUMP"), Mockito.anyString()); - mService.loadSdk( CLIENT_PACKAGE_NAME, - new Binder(), mApplicationInfo, SDK_NAME, SDK_PROVIDER_CLASS, @@ -331,8 +294,7 @@ public class SdkSandboxTest { null, new Bundle(), new RemoteCode(new CountDownLatch(1)), - SANDBOX_LATENCY_INFO, - new StubSdkToServiceLink()); + SANDBOX_LATENCY_INFO); final StringWriter stringWriter = new StringWriter(); mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]); @@ -363,17 +325,12 @@ public class SdkSandboxTest { assertThat(callback.isDisabled()).isFalse(); } - @Test(expected = SecurityException.class) - public void testDump_WithoutPermission() { - mService.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), new String[0]); - } - @Test public void testSyncDataFromClient_StoresInClientSharedPreference() throws Exception { mService.syncDataFromClient(TEST_UPDATE); // Verify that ClientSharedPreference contains the synced data - SharedPreferences pref = getClientSharedPreference(); + SharedPreferences pref = mService.getClientSharedPreferences(); assertThat(pref.getAll().keySet()).containsExactlyElementsIn(TEST_DATA.keySet()); assertThat(pref.getAll().values()).containsExactlyElementsIn(TEST_DATA.values()); } @@ -402,7 +359,7 @@ public class SdkSandboxTest { mService.syncDataFromClient(update); // Verify that ClientSharedPreference contains the synced data - SharedPreferences pref = getClientSharedPreference(); + SharedPreferences pref = mService.getClientSharedPreferences(); assertThat(pref.getAll().keySet()).containsExactlyElementsIn(bundle.keySet()); assertThat(pref.getString("string", "")).isEqualTo("value"); assertThat(pref.getBoolean("boolean", false)).isEqualTo(true); @@ -425,7 +382,7 @@ public class SdkSandboxTest { mService.syncDataFromClient(newUpdate); // Verify that ClientSharedPreference contains the synced data - SharedPreferences pref = getClientSharedPreference(); + SharedPreferences pref = mService.getClientSharedPreferences(); assertThat(pref.getAll().keySet()).containsExactlyElementsIn(TEST_DATA.keySet()); assertThat(pref.getString(KEY_TO_UPDATE, "")).isEqualTo("update"); } @@ -441,7 +398,7 @@ public class SdkSandboxTest { mService.syncDataFromClient(newUpdate); // Verify that ClientSharedPreference contains the synced data - SharedPreferences pref = getClientSharedPreference(); + SharedPreferences pref = mService.getClientSharedPreferences(); assertThat(pref.getAll().keySet()).doesNotContain(KEY_TO_UPDATE); } @@ -460,7 +417,6 @@ public class SdkSandboxTest { mService.loadSdk( CLIENT_PACKAGE_NAME, - new Binder(), mApplicationInfo, SDK_NAME, SDK_PROVIDER_CLASS, @@ -468,8 +424,7 @@ public class SdkSandboxTest { null, new Bundle(), mRemoteCode, - SANDBOX_LATENCY_INFO, - new StubSdkToServiceLink()); + SANDBOX_LATENCY_INFO); assertThat(latch.await(1, TimeUnit.MINUTES)).isTrue(); assertThat(mRemoteCode.mSandboxLatencyInfo.getLatencySystemServerToSandbox()) .isEqualTo( @@ -505,12 +460,9 @@ public class SdkSandboxTest { TIME_SDK_CALL_COMPLETED, TIME_SANDBOX_CALLED_SYSTEM_SERVER); - final IBinder sdkToken = new Binder(); - final CountDownLatch latch = new CountDownLatch(1); mService.loadSdk( CLIENT_PACKAGE_NAME, - sdkToken, mApplicationInfo, SDK_NAME, SDK_PROVIDER_CLASS, @@ -518,12 +470,11 @@ public class SdkSandboxTest { null, new Bundle(), new RemoteCode(latch), - SANDBOX_LATENCY_INFO, - new StubSdkToServiceLink()); + SANDBOX_LATENCY_INFO); assertThat(latch.await(1, TimeUnit.MINUTES)).isTrue(); final UnloadSdkCallbackImpl unloadSdkCallback = new UnloadSdkCallbackImpl(); - mService.unloadSdk(sdkToken, unloadSdkCallback, SANDBOX_LATENCY_INFO); + mService.unloadSdk(SDK_NAME, unloadSdkCallback, SANDBOX_LATENCY_INFO); final SandboxLatencyInfo sandboxLatencyInfo = unloadSdkCallback.getSandboxLatencyInfo(); @@ -561,7 +512,6 @@ public class SdkSandboxTest { mService.loadSdk( CLIENT_PACKAGE_NAME, - new Binder(), mApplicationInfo, SDK_NAME, SDK_PROVIDER_CLASS, @@ -569,8 +519,7 @@ public class SdkSandboxTest { null, new Bundle(), mRemoteCode, - SANDBOX_LATENCY_INFO, - new StubSdkToServiceLink()); + SANDBOX_LATENCY_INFO); assertThat(latch.await(1, TimeUnit.MINUTES)).isTrue(); CountDownLatch surfaceLatch = new CountDownLatch(1); @@ -663,10 +612,6 @@ public class SdkSandboxTest { return bundle; } - private SharedPreferences getClientSharedPreference() { - return PreferenceManager.getDefaultSharedPreferences(mContext); - } - private static class RequestSurfacePackageCallbackImpl extends IRequestSurfacePackageFromSdkCallback.Stub { private CountDownLatch mLatch; diff --git a/sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxManagerServiceUnitTest.java b/sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxManagerServiceUnitTest.java index 2316563957..c8f5db3ea1 100644 --- a/sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxManagerServiceUnitTest.java +++ b/sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxManagerServiceUnitTest.java @@ -20,6 +20,7 @@ import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREG import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__ADD_SDK_SANDBOX_LIFECYCLE_CALLBACK; import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__REMOVE_SDK_SANDBOX_LIFECYCLE_CALLBACK; +import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE; import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER; import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_SANDBOX_TO_APP; import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX; @@ -108,6 +109,7 @@ public class SdkSandboxManagerServiceUnitTest { private MockitoSession mStaticMockSession = null; private Context mSpyContext; private SdkSandboxManagerService.Injector mInjector; + private int mClientAppUid; private static final String CLIENT_PACKAGE_NAME = "com.android.client"; private static final String SDK_NAME = "com.android.codeprovider"; @@ -173,6 +175,8 @@ public class SdkSandboxManagerServiceUnitTest { mInjector = Mockito.spy(new InjectorForTest()); mService = new SdkSandboxManagerService(mSpyContext, mProvider, mInjector); + + mClientAppUid = Process.myUid(); } @After @@ -336,7 +340,6 @@ public class SdkSandboxManagerServiceUnitTest { android.Manifest.permission.ACCESS_NETWORK_STATE); } - @Test public void testLoadSdk_successOnFirstLoad_errorOnLoadAgain() throws Exception { disableNetworkPermissionChecks(); @@ -366,33 +369,51 @@ public class SdkSandboxManagerServiceUnitTest { } @Test - public void testLoadSdk_errorOnFirstLoad_canBeLoadedAgain() throws Exception { + public void testLoadSdk_firstLoadPending_errorOnLoadAgainRequest() throws Exception { disableNetworkPermissionChecks(); disableForegroundCheck(); - // Load code, but make it fail + // Request to load the SDK, but do not complete loading it { FakeLoadSdkCallbackBinder callback = new FakeLoadSdkCallbackBinder(); mService.loadSdk( TEST_PACKAGE, SDK_NAME, TIME_APP_CALLED_SYSTEM_SERVER, new Bundle(), callback); - // Assume SupplementalProcess load fails - mSdkSandboxService.sendLoadCodeError(); + } + + // Requesting to load the SDK while the first load is still pending should throw an error + { + FakeLoadSdkCallbackBinder callback = new FakeLoadSdkCallbackBinder(); + mService.loadSdk( + TEST_PACKAGE, SDK_NAME, TIME_APP_CALLED_SYSTEM_SERVER, new Bundle(), callback); + // Verify loading failed assertThat(callback.isLoadSdkSuccessful()).isFalse(); + assertThat(callback.getLoadSdkErrorCode()) + .isEqualTo(SdkSandboxManager.LOAD_SDK_ALREADY_LOADED); + assertThat(callback.getLoadSdkErrorMsg()).contains("is currently being loaded"); } + } - // Caller should be able to retry loading the code + @Test + public void testLoadSdk_errorOnFirstLoad_canBeLoadedAgain() throws Exception { + disableNetworkPermissionChecks(); + disableForegroundCheck(); + + // Load code, but make it fail { FakeLoadSdkCallbackBinder callback = new FakeLoadSdkCallbackBinder(); mService.loadSdk( TEST_PACKAGE, SDK_NAME, TIME_APP_CALLED_SYSTEM_SERVER, new Bundle(), callback); - // Assume SupplementalProcess loads successfully - mSdkSandboxService.sendLoadCodeSuccessful(); - assertThat(callback.isLoadSdkSuccessful()).isTrue(); + // Assume sdk load fails + mSdkSandboxService.sendLoadCodeError(); + assertThat(callback.isLoadSdkSuccessful()).isFalse(); } + + // Caller should be able to retry loading the code + loadSdk(SDK_NAME); } @Test - public void testLoadSdk_SandboxDiesInBetween() throws Exception { + public void testLoadSdk_sandboxDiesInBetween() throws Exception { disableNetworkPermissionChecks(); disableForegroundCheck(); @@ -415,7 +436,24 @@ public class SdkSandboxManagerServiceUnitTest { } @Test - public void testRequestSurfacePackageSdkNotLoaded() throws Exception { + public void testLoadSdk_sandboxIsInitialized() throws Exception { + loadSdk(SDK_NAME); + + // Verify that sandbox was initialized + assertThat(mSdkSandboxService.getInitializationCount()).isEqualTo(1); + } + + @Test + public void testLoadSdk_sandboxIsInitialized_onlyOnce() throws Exception { + loadSdk(SDK_NAME); + loadSdk(SDK_PROVIDER_RESOURCES_SDK_NAME); + + // Verify that sandbox was initialized + assertThat(mSdkSandboxService.getInitializationCount()).isEqualTo(1); + } + + @Test + public void testRequestSurfacePackageSdkNotLoaded_SandboxExists() throws Exception { disableNetworkPermissionChecks(); disableForegroundCheck(); @@ -428,21 +466,21 @@ public class SdkSandboxManagerServiceUnitTest { // Trying to request package with not exist SDK packageName String sdkName = "invalid"; - IllegalArgumentException thrown = - assertThrows( - IllegalArgumentException.class, - () -> - mService.requestSurfacePackage( - TEST_PACKAGE, - sdkName, - new Binder(), - 0, - 500, - 500, - TIME_APP_CALLED_SYSTEM_SERVER, - new Bundle(), - new FakeRequestSurfacePackageCallbackBinder())); - assertThat(thrown).hasMessageThat().contains("Sdk " + sdkName + " is not loaded"); + FakeRequestSurfacePackageCallbackBinder surfacePackageCallback = + new FakeRequestSurfacePackageCallbackBinder(); + mService.requestSurfacePackage( + TEST_PACKAGE, + sdkName, + new Binder(), + 0, + 500, + 500, + TIME_APP_CALLED_SYSTEM_SERVER, + new Bundle(), + surfacePackageCallback); + assertThat(surfacePackageCallback.isRequestSurfacePackageSuccessful()).isFalse(); + assertThat(surfacePackageCallback.getSurfacePackageErrorCode()) + .isEqualTo(SdkSandboxManager.REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED); } @Test @@ -465,13 +503,13 @@ public class SdkSandboxManagerServiceUnitTest { callback); assertThat(callback.isRequestSurfacePackageSuccessful()).isFalse(); assertThat(callback.getSurfacePackageErrorCode()) - .isEqualTo(SdkSandboxManager.SDK_SANDBOX_PROCESS_NOT_AVAILABLE); + .isEqualTo(SdkSandboxManager.REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED); } @Test public void testRequestSurfacePackage() throws Exception { // 1. We first need to collect a proper sdkToken by calling loadCode - loadSdk(); + loadSdk(SDK_NAME); // 2. Call request package with the retrieved sdkToken FakeRequestSurfacePackageCallbackBinder surfacePackageCallback = @@ -528,12 +566,12 @@ public class SdkSandboxManagerServiceUnitTest { requestSurfacePackageCallback); assertThat(requestSurfacePackageCallback.isRequestSurfacePackageSuccessful()).isFalse(); assertThat(requestSurfacePackageCallback.getSurfacePackageErrorCode()) - .isEqualTo(SdkSandboxManager.SDK_SANDBOX_PROCESS_NOT_AVAILABLE); + .isEqualTo(SdkSandboxManager.REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED); } @Test public void testSurfacePackageError() throws Exception { - loadSdk(); + loadSdk(SDK_NAME); // Assume SurfacePackage encounters an error. FakeRequestSurfacePackageCallbackBinder surfacePackageCallback = @@ -583,7 +621,7 @@ public class SdkSandboxManagerServiceUnitTest { assertThat(surfacePackageCallback.isRequestSurfacePackageSuccessful()).isFalse(); assertThat(surfacePackageCallback.getSurfacePackageErrorCode()) - .isEqualTo(SdkSandboxManager.SDK_SANDBOX_PROCESS_NOT_AVAILABLE); + .isEqualTo(SdkSandboxManager.REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED); } @Test @@ -595,7 +633,7 @@ public class SdkSandboxManagerServiceUnitTest { TEST_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER, lifecycleCallback); // Load SDK and start the sandbox - loadSdk(); + loadSdk(SDK_NAME); // Kill the sandbox ArgumentCaptor<IBinder.DeathRecipient> deathRecipientCaptor = @@ -612,7 +650,7 @@ public class SdkSandboxManagerServiceUnitTest { @Test public void testAddSdkSandboxProcessDeathCallback_AfterStartingSandbox() throws Exception { // Load SDK and start the sandbox - loadSdk(); + loadSdk(SDK_NAME); // Register for sandbox death event FakeSdkSandboxProcessDeathCallbackBinder lifecycleCallback = @@ -635,7 +673,7 @@ public class SdkSandboxManagerServiceUnitTest { @Test public void testMultipleAddSdkSandboxProcessDeathCallbacks() throws Exception { // Load SDK and start the sandbox - loadSdk(); + loadSdk(SDK_NAME); // Register for sandbox death event FakeSdkSandboxProcessDeathCallbackBinder lifecycleCallback1 = @@ -665,7 +703,7 @@ public class SdkSandboxManagerServiceUnitTest { @Test public void testRemoveSdkSandboxProcessDeathCallback() throws Exception { // Load SDK and start the sandbox - loadSdk(); + loadSdk(SDK_NAME); // Register for sandbox death event FakeSdkSandboxProcessDeathCallbackBinder lifecycleCallback1 = @@ -734,7 +772,14 @@ public class SdkSandboxManagerServiceUnitTest { PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES); assertThat(info).isNotNull(); SandboxedSdkContext sandboxedSdkContext = - new SandboxedSdkContext(context, CLIENT_PACKAGE_NAME, info, SDK_NAME, null, null); + new SandboxedSdkContext( + context, + getClass().getClassLoader(), + CLIENT_PACKAGE_NAME, + info, + SDK_NAME, + null, + null); Resources resources = sandboxedSdkContext.getResources(); int integerId = resources.getIdentifier("test_integer", "integer", @@ -790,7 +835,7 @@ public class SdkSandboxManagerServiceUnitTest { disableKillUid(); // First load SDK. - loadSdk(); + loadSdk(SDK_NAME); final CallingInfo callingInfo = new CallingInfo(Process.myUid(), TEST_PACKAGE); @@ -811,7 +856,7 @@ public class SdkSandboxManagerServiceUnitTest { disableKillUid(); // First load SDK. - loadSdk(); + loadSdk(SDK_NAME); final CallingInfo callingInfo = new CallingInfo(Process.myUid(), TEST_PACKAGE); @@ -879,20 +924,20 @@ public class SdkSandboxManagerServiceUnitTest { } @Test - public void testGetLoadedSdkLibrariesInfo_afterLoadSdkSuccess() throws Exception { - loadSdk(); - assertThat(mService.getLoadedSdkLibrariesInfo(TEST_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER)) + public void testGetSandboxedSdks_afterLoadSdkSuccess() throws Exception { + loadSdk(SDK_NAME); + assertThat(mService.getSandboxedSdks(TEST_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER)) .hasSize(1); assertThat( - mService.getLoadedSdkLibrariesInfo( - TEST_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER) + mService.getSandboxedSdks(TEST_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER) .get(0) + .getSharedLibraryInfo() .getName()) .isEqualTo(SDK_NAME); } @Test - public void testGetLoadedSdkLibrariesInfo_errorLoadingSdk() throws Exception { + public void testGetSandboxedSdks_errorLoadingSdk() throws Exception { disableNetworkPermissionChecks(); disableForegroundCheck(); @@ -906,7 +951,7 @@ public class SdkSandboxManagerServiceUnitTest { assertThat(callback.isLoadSdkSuccessful()).isFalse(); assertThat(callback.getLoadSdkErrorCode()) .isEqualTo(SdkSandboxManager.LOAD_SDK_INTERNAL_ERROR); - assertThat(mService.getLoadedSdkLibrariesInfo(TEST_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER)) + assertThat(mService.getSandboxedSdks(TEST_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER)) .isEmpty(); } @@ -928,28 +973,17 @@ public class SdkSandboxManagerServiceUnitTest { @Test public void testUnloadSdkThatIsNotLoaded() throws Exception { // Load SDK to bring up a sandbox - loadSdk(); - // Trying to load an SDK that is not loaded should fail. - assertThrows( - IllegalArgumentException.class, - () -> mService.unloadSdk( - TEST_PACKAGE, SDK_PROVIDER_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER)); + loadSdk(SDK_NAME); + // Trying to unload an SDK that is not loaded should do nothing - it's a no-op. + mService.unloadSdk(TEST_PACKAGE, SDK_PROVIDER_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER); } @Test public void testUnloadSdkThatIsLoaded() throws Exception { disableKillUid(); - loadSdk(); + loadSdk(SDK_NAME); - FakeLoadSdkCallbackBinder callback2 = new FakeLoadSdkCallbackBinder(); - mService.loadSdk( - TEST_PACKAGE, - SDK_PROVIDER_RESOURCES_SDK_NAME, - TIME_APP_CALLED_SYSTEM_SERVER, - new Bundle(), - callback2); - mSdkSandboxService.sendLoadCodeSuccessful(); - assertThat(callback2.isLoadSdkSuccessful()).isTrue(); + loadSdk(SDK_PROVIDER_RESOURCES_SDK_NAME); final CallingInfo callingInfo = new CallingInfo(Process.myUid(), TEST_PACKAGE); mService.unloadSdk(TEST_PACKAGE, SDK_NAME, TIME_APP_CALLED_SYSTEM_SERVER); @@ -967,10 +1001,32 @@ public class SdkSandboxManagerServiceUnitTest { } @Test + public void testUnloadSdkThatIsBeingLoaded() throws Exception { + // Ask to load SDK, but don't finish loading it + disableKillUid(); + disableNetworkPermissionChecks(); + disableForegroundCheck(); + + FakeLoadSdkCallbackBinder callback = new FakeLoadSdkCallbackBinder(); + mService.loadSdk( + TEST_PACKAGE, SDK_NAME, TIME_APP_CALLED_SYSTEM_SERVER, new Bundle(), callback); + + // Trying to unload an SDK that is being loaded should fail + assertThrows( + IllegalArgumentException.class, + () -> mService.unloadSdk(TEST_PACKAGE, SDK_NAME, TIME_APP_CALLED_SYSTEM_SERVER)); + + // After loading the SDK, unloading should not fail + mSdkSandboxService.sendLoadCodeSuccessful(); + assertThat(callback.isLoadSdkSuccessful()).isTrue(); + mService.unloadSdk(TEST_PACKAGE, SDK_NAME, TIME_APP_CALLED_SYSTEM_SERVER); + } + + @Test public void testUnloadSdkAfterKillingSandboxDoesNotThrowException() throws Exception { disableKillUid(); - loadSdk(); + loadSdk(SDK_NAME); // Kill the sandbox ArgumentCaptor<IBinder.DeathRecipient> deathRecipientCaptor = @@ -1030,7 +1086,7 @@ public class SdkSandboxManagerServiceUnitTest { callback.resetLatch(); // Now loadSdk so that sandbox is created - loadSdk(); + loadSdk(SDK_NAME); // Verify that onSandboxStart was called assertThat(callback.hasSandboxStarted()).isTrue(); @@ -1059,7 +1115,7 @@ public class SdkSandboxManagerServiceUnitTest { @Test public void testStopSdkSandbox() throws Exception { disableKillUid(); - loadSdk(); + loadSdk(SDK_NAME); Mockito.doNothing() .when(mSpyContext) @@ -1117,7 +1173,7 @@ public class SdkSandboxManagerServiceUnitTest { @Test public void testLatencyMetrics_IpcFromAppToSystemServer_LoadSdk() throws Exception { - loadSdk(); + loadSdk(SDK_NAME); ExtendedMockito.verify( () -> @@ -1128,14 +1184,14 @@ public class SdkSandboxManagerServiceUnitTest { (TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP - TIME_APP_CALLED_SYSTEM_SERVER), /*success=*/ true, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER, + mClientAppUid)); } @Test public void testLatencyMetrics_IpcFromAppToSystemServer_RequestSurfacePackage() throws Exception { - loadSdk(); + loadSdk(SDK_NAME); // 2. Call request package FakeRequestSurfacePackageCallbackBinder surfacePackageCallback = @@ -1154,37 +1210,36 @@ public class SdkSandboxManagerServiceUnitTest { () -> SdkSandboxStatsLog.write( SdkSandboxStatsLog.SANDBOX_API_CALLED, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, + SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, (int) (TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP - TIME_APP_CALLED_SYSTEM_SERVER), /*success=*/ true, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER, + mClientAppUid)); } @Test - public void testLatencyMetrics_IpcFromAppToSystemServer_GetLoadedSdkLibrariesInfo() { - mService.getLoadedSdkLibrariesInfo(TEST_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER); + public void testLatencyMetrics_IpcFromAppToSystemServer_GetSandboxedSdks() { + mService.getSandboxedSdks(TEST_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER); ExtendedMockito.verify( () -> SdkSandboxStatsLog.write( SdkSandboxStatsLog.SANDBOX_API_CALLED, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__GET_LOADED_SDK_LIBRARIES_INFO, + SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__GET_SANDBOXED_SDKS, (int) (TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP - TIME_APP_CALLED_SYSTEM_SERVER), /*success=*/ true, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER, + mClientAppUid)); } @Test public void testLatencyMetrics_IpcFromAppToSystemServer_UnloadSdk() throws Exception { disableKillUid(); - loadSdk(); + + loadSdk(SDK_NAME); mService.unloadSdk(TEST_PACKAGE, SDK_NAME, TIME_APP_CALLED_SYSTEM_SERVER); ExtendedMockito.verify( () -> @@ -1195,8 +1250,8 @@ public class SdkSandboxManagerServiceUnitTest { (TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP - TIME_APP_CALLED_SYSTEM_SERVER), /*success=*/ true, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER, + mClientAppUid)); } @Test @@ -1217,8 +1272,8 @@ public class SdkSandboxManagerServiceUnitTest { (TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP - TIME_APP_CALLED_SYSTEM_SERVER), /*success=*/ true, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER, + mClientAppUid)); } // TODO(b/242149555): Update tests to use fake for getting time series. @@ -1230,7 +1285,7 @@ public class SdkSandboxManagerServiceUnitTest { START_TIME_TO_LOAD_SANDBOX, END_TIME_TO_LOAD_SANDBOX, TIME_SYSTEM_SERVER_CALLS_SANDBOX); - loadSdk(); + loadSdk(SDK_NAME); final int timeToLoadSdk = (int) (END_TIME_TO_LOAD_SANDBOX - START_TIME_TO_LOAD_SANDBOX); @@ -1241,7 +1296,8 @@ public class SdkSandboxManagerServiceUnitTest { SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK, timeToLoadSdk, /*success=*/ true, - SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__LOAD_SANDBOX)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__LOAD_SANDBOX, + mClientAppUid)); int timeSystemServerAppToSandbox = (int) @@ -1257,12 +1313,13 @@ public class SdkSandboxManagerServiceUnitTest { timeSystemServerAppToSandbox, /*success=*/ true, SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX)); + .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, + mClientAppUid)); } @Test public void testLatencyMetrics_SystemServerSandboxToApp_LoadSdk() throws Exception { - loadSdk(); + loadSdk(SDK_NAME); ExtendedMockito.verify( () -> @@ -1271,7 +1328,8 @@ public class SdkSandboxManagerServiceUnitTest { Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK), Mockito.anyInt(), Mockito.eq(/*success=*/ true), - Mockito.eq(SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX))); + Mockito.eq(SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX), + Mockito.eq(mClientAppUid))); ExtendedMockito.verify( () -> @@ -1280,7 +1338,8 @@ public class SdkSandboxManagerServiceUnitTest { Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK), Mockito.anyInt(), Mockito.eq(/*success=*/ true), - Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX))); + Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX), + Mockito.eq(mClientAppUid))); ExtendedMockito.verify( () -> @@ -1289,7 +1348,8 @@ public class SdkSandboxManagerServiceUnitTest { Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK), Mockito.anyInt(), Mockito.eq(/*success=*/ true), - Mockito.eq(SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER))); + Mockito.eq(SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER), + Mockito.eq(mClientAppUid))); } @Test @@ -1320,7 +1380,8 @@ public class SdkSandboxManagerServiceUnitTest { (TIME_SANDBOX_RECEIVED_CALL_FROM_SYSTEM_SERVER - TIME_SYSTEM_SERVER_CALLED_SANDBOX), /*success=*/ true, - SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX)); + SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX, + mClientAppUid)); int sandboxLatency = (int) @@ -1335,7 +1396,8 @@ public class SdkSandboxManagerServiceUnitTest { SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK, sandboxLatency, /*success=*/ true, - SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX, + mClientAppUid)); ExtendedMockito.verify( () -> @@ -1344,7 +1406,8 @@ public class SdkSandboxManagerServiceUnitTest { SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK, (int) (TIME_SDK_CALL_COMPLETED - TIME_SANDBOX_CALLED_SDK), /*success=*/ true, - SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SDK)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SDK, + mClientAppUid)); ExtendedMockito.verify( () -> @@ -1355,7 +1418,8 @@ public class SdkSandboxManagerServiceUnitTest { (TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_SANDBOX - TIME_SANDBOX_CALLED_SYSTEM_SERVER), /*success=*/ true, - SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER)); + SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER, + mClientAppUid)); } @Test @@ -1363,6 +1427,7 @@ public class SdkSandboxManagerServiceUnitTest { throws Exception { disableNetworkPermissionChecks(); disableForegroundCheck(); + Mockito.when(mInjector.getCurrentTime()) .thenReturn( TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP, @@ -1400,7 +1465,8 @@ public class SdkSandboxManagerServiceUnitTest { timeSystemServerAppToSandbox, /*success=*/ false, SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX)); + .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, + mClientAppUid)); } @Test @@ -1408,6 +1474,7 @@ public class SdkSandboxManagerServiceUnitTest { throws RemoteException { disableNetworkPermissionChecks(); disableForegroundCheck(); + Mockito.when(mInjector.getCurrentTime()) .thenReturn(TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP, TIME_FAILURE_HANDLED); @@ -1425,7 +1492,8 @@ public class SdkSandboxManagerServiceUnitTest { - TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP), /*success=*/ false, SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX)); + .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, + mClientAppUid)); ExtendedMockito.verify( () -> @@ -1434,6 +1502,7 @@ public class SdkSandboxManagerServiceUnitTest { Mockito.anyInt(), Mockito.anyInt(), Mockito.anyBoolean(), + Mockito.anyInt(), Mockito.anyInt()), Mockito.times(2)); } @@ -1473,7 +1542,8 @@ public class SdkSandboxManagerServiceUnitTest { - TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP), /*success=*/ false, SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX)); + .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, + mClientAppUid)); ExtendedMockito.verify( () -> @@ -1482,6 +1552,7 @@ public class SdkSandboxManagerServiceUnitTest { Mockito.anyInt(), Mockito.anyInt(), Mockito.anyBoolean(), + Mockito.anyInt(), Mockito.anyInt()), Mockito.times(2)); } @@ -1510,7 +1581,8 @@ public class SdkSandboxManagerServiceUnitTest { SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK, (int) (TIME_FAILURE_HANDLED - START_TIME_TO_LOAD_SANDBOX), /*success=*/ false, - SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__LOAD_SANDBOX)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__LOAD_SANDBOX, + mClientAppUid)); } @Test @@ -1526,7 +1598,7 @@ public class SdkSandboxManagerServiceUnitTest { TIME_SYSTEM_SERVER_CALLED_APP, TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP, TIME_SYSTEM_SERVER_CALLED_SANDBOX); - loadSdk(); + loadSdk(SDK_NAME); // 2. Call request package FakeRequestSurfacePackageCallbackBinder surfacePackageCallback = @@ -1548,47 +1620,44 @@ public class SdkSandboxManagerServiceUnitTest { () -> SdkSandboxStatsLog.write( SdkSandboxStatsLog.SANDBOX_API_CALLED, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, + SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, (int) (TIME_SYSTEM_SERVER_CALLED_SANDBOX - TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP), /*success=*/ true, SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX)); + .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, + mClientAppUid)); ExtendedMockito.verify( () -> SdkSandboxStatsLog.write( Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED), - Mockito.eq( - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), + Mockito.eq(SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), Mockito.anyInt(), Mockito.eq(/*success=*/ true), - Mockito.eq(SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX))); + Mockito.eq(SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX), + Mockito.eq(mClientAppUid))); ExtendedMockito.verify( () -> SdkSandboxStatsLog.write( Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED), - Mockito.eq( - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), + Mockito.eq(SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), Mockito.anyInt(), Mockito.eq(/*success=*/ true), - Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX))); + Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX), + Mockito.eq(mClientAppUid))); ExtendedMockito.verify( () -> SdkSandboxStatsLog.write( Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED), - Mockito.eq( - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), + Mockito.eq(SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), Mockito.anyInt(), Mockito.eq(/*success=*/ true), - Mockito.eq(SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER))); + Mockito.eq(SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER), + Mockito.eq(mClientAppUid))); } @Test @@ -1605,7 +1674,7 @@ public class SdkSandboxManagerServiceUnitTest { TIME_SYSTEM_SERVER_CALLED_APP, TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP, TIME_SYSTEM_SERVER_CALLED_SANDBOX); - loadSdk(); + loadSdk(SDK_NAME); // 2. Call request package FakeRequestSurfacePackageCallbackBinder surfacePackageCallback = @@ -1627,80 +1696,122 @@ public class SdkSandboxManagerServiceUnitTest { () -> SdkSandboxStatsLog.write( SdkSandboxStatsLog.SANDBOX_API_CALLED, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, + SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, (int) (TIME_SYSTEM_SERVER_CALLED_SANDBOX - TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP), /*success=*/ true, SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX)); + .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, + mClientAppUid)); ExtendedMockito.verify( () -> SdkSandboxStatsLog.write( Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED), - Mockito.eq( - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), + Mockito.eq(SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), Mockito.anyInt(), Mockito.eq(/*success=*/ true), - Mockito.eq(SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX))); + Mockito.eq(SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX), + Mockito.eq(mClientAppUid))); ExtendedMockito.verify( () -> SdkSandboxStatsLog.write( Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED), - Mockito.eq( - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), + Mockito.eq(SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), Mockito.anyInt(), Mockito.eq(/*success=*/ true), - Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX))); + Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX), + Mockito.eq(mClientAppUid))); ExtendedMockito.verify( () -> SdkSandboxStatsLog.write( Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED), - Mockito.eq( - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), + Mockito.eq(SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), Mockito.anyInt(), Mockito.eq(/*success=*/ true), - Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SDK))); + Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SDK), + Mockito.eq(mClientAppUid))); ExtendedMockito.verify( () -> SdkSandboxStatsLog.write( Mockito.eq(SdkSandboxStatsLog.SANDBOX_API_CALLED), - Mockito.eq( - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), + Mockito.eq(SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE), Mockito.anyInt(), Mockito.eq(/*success=*/ true), - Mockito.eq(SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER))); + Mockito.eq(SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER), + Mockito.eq(mClientAppUid))); + } + + @Test + public void testLatencyMetrics_SystemServerSandboxToApp_RequestSurfacePackage() + throws RemoteException { + Mockito.when(mInjector.getCurrentTime()) + .thenReturn( + TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP, + START_TIME_TO_LOAD_SANDBOX, + END_TIME_TO_LOAD_SANDBOX, + TIME_SYSTEM_SERVER_CALLED_SANDBOX, + TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_SANDBOX, + TIME_SYSTEM_SERVER_CALLED_APP, + TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP, + TIME_SYSTEM_SERVER_CALLED_SANDBOX, + TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_SANDBOX, + TIME_SYSTEM_SERVER_CALLED_APP); + loadSdk(SDK_NAME); + + // 2. Call request package + FakeRequestSurfacePackageCallbackBinder surfacePackageCallback = + new FakeRequestSurfacePackageCallbackBinder(); + mService.requestSurfacePackage( + TEST_PACKAGE, + SDK_NAME, + new Binder(), + 0, + 500, + 500, + TIME_APP_CALLED_SYSTEM_SERVER, + new Bundle(), + surfacePackageCallback); + mSdkSandboxService.sendSurfacePackageReady( + new SandboxLatencyInfo(TIME_SYSTEM_SERVER_CALLED_SANDBOX)); + + ExtendedMockito.verify( + () -> + SdkSandboxStatsLog.write( + SdkSandboxStatsLog.SANDBOX_API_CALLED, + SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, + (int) + (TIME_SYSTEM_SERVER_CALLED_APP + - TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_SANDBOX), + /*success=*/ true, + SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_SANDBOX_TO_APP, + mClientAppUid)); } @Test - public void testLatencyMetrics_SystemServerAppToSandbox_GetLoadedSdkLibrariesInfo() { + public void testLatencyMetrics_SystemServerAppToSandbox_GetSandboxedSdks() { // TODO(b/242149555): Update tests to use fake for getting time series. Mockito.when(mInjector.getCurrentTime()) .thenReturn(TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP, END_TIME_IN_SYSTEM_SERVER); - mService.getLoadedSdkLibrariesInfo(TEST_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER); + mService.getSandboxedSdks(TEST_PACKAGE, TIME_APP_CALLED_SYSTEM_SERVER); ExtendedMockito.verify( () -> SdkSandboxStatsLog.write( SdkSandboxStatsLog.SANDBOX_API_CALLED, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__GET_LOADED_SDK_LIBRARIES_INFO, + SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__GET_SANDBOXED_SDKS, (int) (END_TIME_IN_SYSTEM_SERVER - TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP), /*success=*/ true, SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX)); + .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, + mClientAppUid)); } @Test @@ -1711,12 +1822,11 @@ public class SdkSandboxManagerServiceUnitTest { () -> SdkSandboxStatsLog.write( SdkSandboxStatsLog.SANDBOX_API_CALLED, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, + SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, /*latency=*/ 1, /*success=*/ true, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_APP)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_APP, + mClientAppUid)); } @Test @@ -1753,14 +1863,14 @@ public class SdkSandboxManagerServiceUnitTest { assertThat(listener.isKillSwitchEnabled()).isFalse(); listener.onPropertiesChanged( new DeviceConfig.Properties( - DeviceConfig.NAMESPACE_SDK_SANDBOX, + DeviceConfig.NAMESPACE_ADSERVICES, Map.of(PROPERTY_DISABLE_SANDBOX, "true"))); assertThat(listener.isKillSwitchEnabled()).isTrue(); listener.onPropertiesChanged( new DeviceConfig.Properties( - DeviceConfig.NAMESPACE_SDK_SANDBOX, + DeviceConfig.NAMESPACE_ADSERVICES, Map.of(PROPERTY_DISABLE_SANDBOX, "false"))); - assertThat(listener.isKillSwitchEnabled()).isTrue(); + assertThat(listener.isKillSwitchEnabled()).isFalse(); } @Test @@ -1770,13 +1880,13 @@ public class SdkSandboxManagerServiceUnitTest { mService.getSdkSandboxSettingsListener(); listener.onPropertiesChanged( new DeviceConfig.Properties( - DeviceConfig.NAMESPACE_SDK_SANDBOX, + DeviceConfig.NAMESPACE_ADSERVICES, Map.of(PROPERTY_DISABLE_SANDBOX, "false"))); mService.getSdkSandboxSettingsListener().reset(); - loadSdk(); + loadSdk(SDK_NAME); listener.onPropertiesChanged( new DeviceConfig.Properties( - DeviceConfig.NAMESPACE_SDK_SANDBOX, + DeviceConfig.NAMESPACE_ADSERVICES, Map.of(PROPERTY_DISABLE_SANDBOX, "true"))); int callingUid = Binder.getCallingUid(); final CallingInfo callingInfo = new CallingInfo(callingUid, TEST_PACKAGE); @@ -1784,15 +1894,18 @@ public class SdkSandboxManagerServiceUnitTest { } @Test - public void testLoadSdkFailsWhenSandboxDisabled() { + public void testLoadSdkFailsWhenSandboxDisabled() throws Exception { disableNetworkPermissionChecks(); disableForegroundCheck(); SdkSandboxManagerService.SdkSandboxSettingsListener listener = mService.getSdkSandboxSettingsListener(); listener.reset(); + // Sleep needed to avoid deadlock. + // TODO(b/257255118): Remove this sleep. + Thread.sleep(500); listener.onPropertiesChanged( new DeviceConfig.Properties( - DeviceConfig.NAMESPACE_SDK_SANDBOX, + DeviceConfig.NAMESPACE_ADSERVICES, Map.of(PROPERTY_DISABLE_SANDBOX, "true"))); FakeLoadSdkCallbackBinder callback = new FakeLoadSdkCallbackBinder(); mService.loadSdk( @@ -1828,14 +1941,14 @@ public class SdkSandboxManagerServiceUnitTest { () -> SdkSandboxStatsLog.write( SdkSandboxStatsLog.SANDBOX_API_CALLED, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, + SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, (int) (TIME_FAILURE_HANDLED - TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP), /*success=*/ false, SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX)); + .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, + mClientAppUid)); } @Test @@ -1857,7 +1970,7 @@ public class SdkSandboxManagerServiceUnitTest { TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_SANDBOX, TIME_SYSTEM_SERVER_CALLED_APP); - loadSdk(); + loadSdk(SDK_NAME); mService.unloadSdk(TEST_PACKAGE, SDK_NAME, TIME_APP_CALLED_SYSTEM_SERVER); ExtendedMockito.verify( () -> @@ -1868,8 +1981,8 @@ public class SdkSandboxManagerServiceUnitTest { (TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP - TIME_APP_CALLED_SYSTEM_SERVER), /*success=*/ true, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER, + mClientAppUid)); ExtendedMockito.verify( () -> @@ -1881,11 +1994,12 @@ public class SdkSandboxManagerServiceUnitTest { - TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP), /*success=*/ true, SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX)); + .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, + mClientAppUid)); } @Test - public void testLatencyMetrics_systemServer_unloadSdk_withSandboxLatencies() throws Exception { + public void testLatencyMetrics_SystemServer_UnloadSdk_WithSandboxLatencies() throws Exception { disableKillUid(); Mockito.when(mInjector.getCurrentTime()) @@ -1904,7 +2018,7 @@ public class SdkSandboxManagerServiceUnitTest { TIME_SYSTEM_SERVER_CALLED_APP, TIME_SANDBOX_CALLED_SYSTEM_SERVER); - loadSdk(); + loadSdk(SDK_NAME); mService.unloadSdk(TEST_PACKAGE, SDK_NAME, TIME_APP_CALLED_SYSTEM_SERVER); mSdkSandboxService.sendUnloadSdkSuccess(); @@ -1917,7 +2031,8 @@ public class SdkSandboxManagerServiceUnitTest { (TIME_SANDBOX_RECEIVED_CALL_FROM_SYSTEM_SERVER - TIME_SYSTEM_SERVER_CALLED_SANDBOX), /*success=*/ true, - SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX)); + SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX, + mClientAppUid)); ExtendedMockito.verify( () -> @@ -1930,7 +2045,8 @@ public class SdkSandboxManagerServiceUnitTest { - (TIME_SDK_CALL_COMPLETED - TIME_SANDBOX_CALLED_SDK)), /*success=*/ true, - SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX, + mClientAppUid)); ExtendedMockito.verify( () -> @@ -1939,7 +2055,8 @@ public class SdkSandboxManagerServiceUnitTest { SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__UNLOAD_SDK, (int) (TIME_SDK_CALL_COMPLETED - TIME_SANDBOX_CALLED_SDK), /*success=*/ true, - SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SDK)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SDK, + mClientAppUid)); ExtendedMockito.verify( () -> @@ -1950,7 +2067,8 @@ public class SdkSandboxManagerServiceUnitTest { (TIME_SANDBOX_CALLED_SYSTEM_SERVER - TIME_SANDBOX_CALLED_SYSTEM_SERVER), /*success=*/ true, - SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER)); + SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER, + mClientAppUid)); ExtendedMockito.verify( () -> @@ -1961,7 +2079,8 @@ public class SdkSandboxManagerServiceUnitTest { (TIME_SYSTEM_SERVER_CALLED_APP - TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_SANDBOX), /*success=*/ true, - SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_SANDBOX_TO_APP)); + SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_SANDBOX_TO_APP, + mClientAppUid)); } @Test @@ -1985,8 +2104,8 @@ public class SdkSandboxManagerServiceUnitTest { (TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP - TIME_APP_CALLED_SYSTEM_SERVER), /*success=*/ true, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER, + mClientAppUid)); } @Test @@ -2013,7 +2132,8 @@ public class SdkSandboxManagerServiceUnitTest { - TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP), /*success=*/ true, SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX)); + .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, + mClientAppUid)); } @Test @@ -2045,8 +2165,8 @@ public class SdkSandboxManagerServiceUnitTest { (TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP - TIME_APP_CALLED_SYSTEM_SERVER), /*success=*/ true, - SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER)); + SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER, + mClientAppUid)); } @Test @@ -2081,7 +2201,8 @@ public class SdkSandboxManagerServiceUnitTest { - TIME_SYSTEM_SERVER_RECEIVED_CALL_FROM_APP), /*success=*/ true, SdkSandboxStatsLog - .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX)); + .SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, + mClientAppUid)); } private SandboxLatencyInfo getFakedSandboxLatencies() { @@ -2096,12 +2217,12 @@ public class SdkSandboxManagerServiceUnitTest { return sandboxLatencyInfo; } - private void loadSdk() throws RemoteException { + private void loadSdk(String sdkName) throws RemoteException { disableNetworkPermissionChecks(); disableForegroundCheck(); FakeLoadSdkCallbackBinder callback = new FakeLoadSdkCallbackBinder(); mService.loadSdk( - TEST_PACKAGE, SDK_NAME, TIME_APP_CALLED_SYSTEM_SERVER, new Bundle(), callback); + TEST_PACKAGE, sdkName, TIME_APP_CALLED_SYSTEM_SERVER, new Bundle(), callback); mSdkSandboxService.sendLoadCodeSuccessful(); assertThat(callback.isLoadSdkSuccessful()).isTrue(); } @@ -2171,10 +2292,11 @@ public class SdkSandboxManagerServiceUnitTest { private ILoadSdkInSandboxCallback mLoadSdkInSandboxCallback; private final ISdkSandboxManagerToSdkSandboxCallback mManagerToSdkCallback; private IRequestSurfacePackageFromSdkCallback mRequestSurfacePackageFromSdkCallback = null; - private ISdkToServiceCallback mSdkToServiceCallback; private IUnloadSdkCallback mUnloadSdkCallback = null; private boolean mSurfacePackageRequested = false; + private int mInitializationCount = 0; + boolean mIsDisabledResponse = false; private SharedPreferencesUpdate mLastSyncUpdate = null; @@ -2184,9 +2306,13 @@ public class SdkSandboxManagerServiceUnitTest { } @Override + public void initialize(ISdkToServiceCallback sdkToServiceCallback) { + mInitializationCount++; + } + + @Override public void loadSdk( String callingPackageName, - IBinder codeToken, ApplicationInfo info, String sdkName, String sdkProviderClass, @@ -2194,15 +2320,13 @@ public class SdkSandboxManagerServiceUnitTest { String deDataDir, Bundle params, ILoadSdkInSandboxCallback callback, - SandboxLatencyInfo sandboxLatencyInfo, - ISdkToServiceCallback sdkToServiceCallback) { + SandboxLatencyInfo sandboxLatencyInfo) { mLoadSdkInSandboxCallback = callback; - mSdkToServiceCallback = sdkToServiceCallback; } @Override public void unloadSdk( - IBinder sdkToken, + String sdkName, IUnloadSdkCallback callback, SandboxLatencyInfo sandboxLatencyInfo) { mUnloadSdkCallback = callback; @@ -2232,12 +2356,11 @@ public class SdkSandboxManagerServiceUnitTest { return mLastSyncUpdate; } + int getInitializationCount() { + return mInitializationCount; + } + void sendLoadCodeSuccessful() throws RemoteException { - // Whenever loadSdk has been called successfully, the callback should have been - // instantiated. - Objects.requireNonNull( - mSdkToServiceCallback, - "mSdkToServiceCallback should have been passed when loadSdk succeeded"); mLoadSdkInSandboxCallback.onLoadSdkSuccess( new SandboxedSdk(new Binder()), mManagerToSdkCallback, diff --git a/sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxStorageManagerUnitTest.java b/sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxStorageManagerUnitTest.java index 1e5934913e..9b4252790d 100644 --- a/sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxStorageManagerUnitTest.java +++ b/sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxStorageManagerUnitTest.java @@ -29,7 +29,7 @@ import androidx.annotation.NonNull; import androidx.test.platform.app.InstrumentationRegistry; import com.android.server.pm.PackageManagerLocal; -import com.android.server.sdksandbox.SdkSandboxStorageManager.SdkDataDirInfo; +import com.android.server.sdksandbox.SdkSandboxStorageManager.StorageDirInfo; import com.android.server.sdksandbox.SdkSandboxStorageManager.SubDirectories; import org.junit.After; @@ -41,6 +41,7 @@ import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -56,6 +57,8 @@ public class SdkSandboxStorageManagerUnitTest { private static final String CLIENT_PKG_NAME = "client"; private static final String SDK_NAME = "sdk"; private static final String SDK2_NAME = "sdk2"; + private static final String STORAGE_UUID = "41217664-9172-527a-b3d5-edabb50a7d69"; + private static final int USER_ID = 0; // Use the test app's private storage as mount point for sdk storage testing private SdkSandboxStorageManager mSdkSandboxStorageManager; @@ -105,59 +108,58 @@ public class SdkSandboxStorageManagerUnitTest { @Test public void test_GetSdkDataPackageDirectory() throws Exception { - assertThat(mSdkSandboxStorageManager.getSdkDataPackageDirectory(null, 0, "foo", true)) + assertThat(mSdkSandboxStorageManager.getSdkDataPackageDirectory(null, USER_ID, "foo", true)) .isEqualTo(mTestDir + "/data/misc_ce/0/sdksandbox/foo"); // Build DE path - assertThat(mSdkSandboxStorageManager.getSdkDataPackageDirectory(null, 0, "foo", false)) + assertThat( + mSdkSandboxStorageManager.getSdkDataPackageDirectory( + null, USER_ID, "foo", false)) .isEqualTo(mTestDir + "/data/misc_de/0/sdksandbox/foo"); // Build with different package name - assertThat(mSdkSandboxStorageManager.getSdkDataPackageDirectory(null, 0, "bar", true)) + assertThat(mSdkSandboxStorageManager.getSdkDataPackageDirectory(null, USER_ID, "bar", true)) .isEqualTo(mTestDir + "/data/misc_ce/0/sdksandbox/bar"); // Build with different user assertThat(mSdkSandboxStorageManager.getSdkDataPackageDirectory(null, 10, "foo", true)) .isEqualTo(mTestDir + "/data/misc_ce/10/sdksandbox/foo"); // Build with different volume - assertThat(mSdkSandboxStorageManager.getSdkDataPackageDirectory("hello", 0, "foo", true)) + assertThat( + mSdkSandboxStorageManager.getSdkDataPackageDirectory( + "hello", USER_ID, "foo", true)) .isEqualTo(mTestDir + "/mnt/expand/hello/misc_ce/0/sdksandbox/foo"); } @Test - public void test_SdkDataDirInfo_GetterApis() throws Exception { - final SdkDataDirInfo sdkInfo = new SdkDataDirInfo("foo", "bar"); + public void test_StorageDirInfo_GetterApis() throws Exception { + final StorageDirInfo sdkInfo = new StorageDirInfo("foo", "bar"); assertThat(sdkInfo.getCeDataDir()).isEqualTo("foo"); assertThat(sdkInfo.getDeDataDir()).isEqualTo("bar"); } @Test - public void test_GetSdkDataDirInfo_NonExistingStorage() throws Exception { - // Call getSdkDataDirInfo on SdkStorageManager + public void test_getSdkStorageDirInfo_nonExistingStorage() throws Exception { + // Call getSdkStorageDirInfo on SdkStorageManager final CallingInfo callingInfo = new CallingInfo(CLIENT_UID, CLIENT_PKG_NAME); - final SdkDataDirInfo sdkInfo = - mSdkSandboxStorageManager.getSdkDataDirInfo(callingInfo, SDK_NAME); + final StorageDirInfo sdkInfo = + mSdkSandboxStorageManager.getSdkStorageDirInfo(callingInfo, SDK_NAME); assertThat(sdkInfo.getCeDataDir()).isNull(); assertThat(sdkInfo.getDeDataDir()).isNull(); } @Test - public void test_GetSdkDataDirInfo_StorageExists() throws Exception { - createSdkStorageForTest( - /*volumeUuid=*/ null, - /*userId=*/ 0, - CLIENT_PKG_NAME, - Arrays.asList(SDK_NAME), - Collections.emptyList()); + public void test_getSdkStorageDirInfo_storageExists() throws Exception { + createSdkStorageForTest(Arrays.asList(SDK_NAME), Collections.emptyList()); final ApplicationInfo info = new ApplicationInfo(); - info.storageUuid = UUID.fromString("41217664-9172-527a-b3d5-edabb50a7d69"); + info.storageUuid = UUID.fromString(STORAGE_UUID); Mockito.doReturn(info) .when(mPmMock) .getApplicationInfo(Mockito.any(String.class), Mockito.anyInt()); - // Call getSdkDataDirInfo on SdkStorageManager + // Call getSdkStorageDirInfo on SdkStorageManager final CallingInfo callingInfo = new CallingInfo(CLIENT_UID, CLIENT_PKG_NAME); - final SdkDataDirInfo sdkInfo = - mSdkSandboxStorageManager.getSdkDataDirInfo(callingInfo, SDK_NAME); + final StorageDirInfo sdkInfo = + mSdkSandboxStorageManager.getSdkStorageDirInfo(callingInfo, SDK_NAME); assertThat(sdkInfo.getCeDataDir()) .isEqualTo(mTestDir + "/data/misc_ce/0/sdksandbox/client/sdk@sdk"); @@ -166,10 +168,41 @@ public class SdkSandboxStorageManagerUnitTest { } @Test - public void test_GetMountedVolumes_NewVolumeExists() throws Exception { + public void test_getInernalStorageDirInfo_nonExistingStorage() throws Exception { + final CallingInfo callingInfo = new CallingInfo(CLIENT_UID, CLIENT_PKG_NAME); + final StorageDirInfo dirInfo = + mSdkSandboxStorageManager.getInternalStorageDirInfo(callingInfo, SDK_NAME); + + assertThat(dirInfo.getCeDataDir()).isNull(); + assertThat(dirInfo.getDeDataDir()).isNull(); + } + + @Test + public void test_getInternalStorageDirInfo_storageExists() throws Exception { + createSdkStorageForTest(Collections.emptyList(), Arrays.asList(SubDirectories.SANDBOX_DIR)); + + final ApplicationInfo info = new ApplicationInfo(); + info.storageUuid = UUID.fromString(STORAGE_UUID); + Mockito.doReturn(info) + .when(mPmMock) + .getApplicationInfo(Mockito.any(String.class), Mockito.anyInt()); + + final CallingInfo callingInfo = new CallingInfo(CLIENT_UID, CLIENT_PKG_NAME); + final StorageDirInfo internalSubDirInfo = + mSdkSandboxStorageManager.getInternalStorageDirInfo( + callingInfo, SubDirectories.SANDBOX_DIR); + + assertThat(internalSubDirInfo.getCeDataDir()) + .isEqualTo(mTestDir + "/data/misc_ce/0/sdksandbox/client/sandbox#sandbox"); + assertThat(internalSubDirInfo.getDeDataDir()) + .isEqualTo(mTestDir + "/data/misc_de/0/sdksandbox/client/sandbox#sandbox"); + } + + @Test + public void test_getMountedVolumes_newVolumeExists() throws Exception { createSdkStorageForTest( /*volumeUuid=*/ null, - /*userId=*/ 0, + USER_ID, CLIENT_PKG_NAME, Arrays.asList(SDK_NAME), Collections.emptyList()); @@ -189,7 +222,7 @@ public class SdkSandboxStorageManagerUnitTest { public void test_GetMountedVolumes_NewVolumeDoesNotExist() throws Exception { createSdkStorageForTest( /*volumeUuid=*/ null, - /*userId=*/ 0, + USER_ID, CLIENT_PKG_NAME, Arrays.asList(SDK_NAME), Collections.emptyList()); @@ -203,7 +236,7 @@ public class SdkSandboxStorageManagerUnitTest { public void test_onUserUnlocking_Instrumentation_NoSdk_PackageDirNotRemoved() throws Exception { createSdkStorageForTest( /*volumeUuid=*/ null, - /*userId=*/ 0, + USER_ID, CLIENT_PKG_NAME, Collections.emptyList(), Collections.emptyList()); @@ -216,12 +249,12 @@ public class SdkSandboxStorageManagerUnitTest { final Path ceDataPackageDirectory = Paths.get( mSdkSandboxStorageManager.getSdkDataPackageDirectory( - null, 0, CLIENT_PKG_NAME, true)); + null, USER_ID, CLIENT_PKG_NAME, true)); final Path deDataPackageDirectory = Paths.get( mSdkSandboxStorageManager.getSdkDataPackageDirectory( - null, 0, CLIENT_PKG_NAME, false)); + null, USER_ID, CLIENT_PKG_NAME, false)); assertThat(Files.exists(ceDataPackageDirectory)).isTrue(); assertThat(Files.exists(deDataPackageDirectory)).isTrue(); @@ -231,22 +264,22 @@ public class SdkSandboxStorageManagerUnitTest { public void test_onUserUnlocking_NoInstrumentation_NoSdk_PackageDirRemoved() throws Exception { createSdkStorageForTest( /*volumeUuid=*/ null, - /*userId=*/ 0, + USER_ID, CLIENT_PKG_NAME, Collections.emptyList(), Collections.emptyList()); - mSdkSandboxStorageManager.onUserUnlocking(0); + mSdkSandboxStorageManager.onUserUnlocking(USER_ID); final Path ceDataPackageDirectory = Paths.get( mSdkSandboxStorageManager.getSdkDataPackageDirectory( - null, 0, CLIENT_PKG_NAME, true)); + null, USER_ID, CLIENT_PKG_NAME, true)); final Path deDataPackageDirectory = Paths.get( mSdkSandboxStorageManager.getSdkDataPackageDirectory( - null, 0, CLIENT_PKG_NAME, false)); + null, USER_ID, CLIENT_PKG_NAME, false)); assertThat(Files.exists(ceDataPackageDirectory)).isFalse(); assertThat(Files.exists(deDataPackageDirectory)).isFalse(); @@ -254,12 +287,7 @@ public class SdkSandboxStorageManagerUnitTest { @Test public void test_SdkSubDirectories_NonExistingParentPath() throws Exception { - createSdkStorageForTest( - /*volumeUuid=*/ null, - /*userId=*/ 0, - CLIENT_PKG_NAME, - Arrays.asList(SDK_NAME), - Collections.emptyList()); + createSdkStorageForTest(Arrays.asList(SDK_NAME), Collections.emptyList()); final SubDirectories subDirs = new SubDirectories("/does/not/exist"); @@ -269,16 +297,11 @@ public class SdkSandboxStorageManagerUnitTest { @Test public void test_SdkSubDirectories_GetSdkSubDir() throws Exception { - createSdkStorageForTest( - /*volumeUuid=*/ null, - /*userId=*/ 0, - CLIENT_PKG_NAME, - Arrays.asList(SDK_NAME), - Collections.emptyList()); + createSdkStorageForTest(Arrays.asList(SDK_NAME), Collections.emptyList()); final String packageDir = mSdkSandboxStorageManager.getSdkDataPackageDirectory( - /*volumeUuid=*/ null, /*userId=*/ 0, CLIENT_PKG_NAME, /*isCeData=*/ true); + /*volumeUuid=*/ null, USER_ID, CLIENT_PKG_NAME, /*isCeData=*/ true); final SubDirectories subDirs = new SubDirectories(packageDir); @@ -294,15 +317,12 @@ public class SdkSandboxStorageManagerUnitTest { @Test public void test_SdkSubDirectories_IsValid() throws Exception { createSdkStorageForTest( - /*volumeUuid=*/ null, - /*userId=*/ 0, - CLIENT_PKG_NAME, Arrays.asList(SDK_NAME, SDK2_NAME), - Arrays.asList("shared")); + Arrays.asList(SubDirectories.SHARED_DIR, SubDirectories.SANDBOX_DIR)); final String packageDir = mSdkSandboxStorageManager.getSdkDataPackageDirectory( - /*volumeUuid=*/ null, /*userId=*/ 0, CLIENT_PKG_NAME, /*isCeData=*/ true); + /*volumeUuid=*/ null, USER_ID, CLIENT_PKG_NAME, /*isCeData=*/ true); final SubDirectories subDirs = new SubDirectories(packageDir); @@ -314,16 +334,11 @@ public class SdkSandboxStorageManagerUnitTest { @Test public void test_SdkSubDirectories_IsValid_MissingNonSdkStorage() throws Exception { // Avoid creating "shared" storage - createSdkStorageForTest( - /*volumeUuid=*/ null, - /*userId=*/ 0, - CLIENT_PKG_NAME, - Arrays.asList(SDK_NAME), - Collections.emptyList()); + createSdkStorageForTest(Arrays.asList(SDK_NAME), Collections.emptyList()); final String packageDir = mSdkSandboxStorageManager.getSdkDataPackageDirectory( - /*volumeUuid=*/ null, /*userId=*/ 0, CLIENT_PKG_NAME, /*isCeData=*/ true); + /*volumeUuid=*/ null, USER_ID, CLIENT_PKG_NAME, /*isCeData=*/ true); final SubDirectories subDirs = new SubDirectories(packageDir); @@ -332,17 +347,12 @@ public class SdkSandboxStorageManagerUnitTest { @Test public void test_SdkSubDirectories_IsValid_HasUnknownSubDir() throws Exception { - createSdkStorageForTest( - /*volumeUuid=*/ null, - /*userId=*/ 0, - CLIENT_PKG_NAME, - Arrays.asList(SDK_NAME), - Arrays.asList("shared")); + createSdkStorageForTest(Arrays.asList(SDK_NAME), Arrays.asList(SubDirectories.SHARED_DIR)); // Create a random subdir not following our format final String packageDir = mSdkSandboxStorageManager.getSdkDataPackageDirectory( - /*volumeUuid=*/ null, /*userId=*/ 0, CLIENT_PKG_NAME, /*isCeData=*/ true); + /*volumeUuid=*/ null, USER_ID, CLIENT_PKG_NAME, /*isCeData=*/ true); Path invalidSubDir = Paths.get(packageDir, "invalid"); Files.createDirectories(invalidSubDir); @@ -351,6 +361,114 @@ public class SdkSandboxStorageManagerUnitTest { assertThat(subDirs.isValid(Set.of(SDK_NAME))).isFalse(); } + @Test + public void test_SdkSubDirectories_GenerateSubDirNames_InternalOnly_NonExisting() + throws Exception { + final SubDirectories subDirs = new SubDirectories("does.not.exist"); + + final List<String> internalSubDirs = subDirs.generateSubDirNames(Collections.emptyList()); + assertThat(internalSubDirs).hasSize(SubDirectories.INTERNAL_SUBDIRS.size()); + assertThat(internalSubDirs).contains(SubDirectories.SHARED_DIR); + for (String subDir : internalSubDirs) { + if (subDir.equals(SubDirectories.SHARED_DIR)) continue; + final String[] tokens = subDir.split("#"); + assertThat(tokens).asList().hasSize(2); + assertThat(SubDirectories.INTERNAL_SUBDIRS).contains(tokens[0]); + } + } + + @Test + public void test_SdkSubDirectories_GenerateSubDirNames_InternalOnly_Existing() + throws Exception { + createSdkStorageForTest( + Collections.emptyList(), + Arrays.asList(SubDirectories.SHARED_DIR, SubDirectories.SANDBOX_DIR)); + + final String packageDir = + mSdkSandboxStorageManager.getSdkDataPackageDirectory( + /*volumeUuid=*/ null, USER_ID, CLIENT_PKG_NAME, /*isCeData=*/ true); + final SubDirectories subDirs = new SubDirectories(packageDir); + + final List<String> internalSubDirs = subDirs.generateSubDirNames(Collections.emptyList()); + final String expectedSandboxDirName = + SubDirectories.SANDBOX_DIR + "#" + SubDirectories.SANDBOX_DIR; + assertThat(internalSubDirs).containsExactly("shared", expectedSandboxDirName); + } + + @Test + public void test_SdkSubDirectories_GenerateSubDirNames_WithSdkNames() throws Exception { + createSdkStorageForTest( + Arrays.asList(SDK_NAME), + Arrays.asList(SubDirectories.SHARED_DIR, SubDirectories.SANDBOX_DIR)); + + final String packageDir = + mSdkSandboxStorageManager.getSdkDataPackageDirectory( + /*volumeUuid=*/ null, USER_ID, CLIENT_PKG_NAME, /*isCeData=*/ true); + final SubDirectories subDirs = new SubDirectories(packageDir); + + final List<String> allSubDirNames = + subDirs.generateSubDirNames(Arrays.asList(SDK_NAME, "foo")); + assertThat(allSubDirNames).hasSize(2 + SubDirectories.INTERNAL_SUBDIRS.size()); + + // Assert internal directories + final String expectedSandboxDirName = + SubDirectories.SANDBOX_DIR + "#" + SubDirectories.SANDBOX_DIR; + assertThat(allSubDirNames).containsAtLeast("shared", expectedSandboxDirName); + + // Assert per-sdk directories + assertThat(allSubDirNames).contains(SDK_NAME + "@" + SDK_NAME); + boolean foundFoo = + allSubDirNames.stream() + .anyMatch(s -> s.contains("@") && s.split("@")[0].equals("foo")); + assertThat(foundFoo).isTrue(); + } + + @Test + public void test_getSdkStorageDirInfo() throws Exception { + final List<String> sdkNames = Arrays.asList(SDK_NAME); + createSdkStorageForTest(sdkNames, new ArrayList<>()); + + final ApplicationInfo info = new ApplicationInfo(); + info.storageUuid = UUID.fromString(STORAGE_UUID); + Mockito.doReturn(info) + .when(mPmMock) + .getApplicationInfo(Mockito.any(String.class), Mockito.anyInt()); + + final CallingInfo callingInfo = new CallingInfo(CLIENT_UID, CLIENT_PKG_NAME); + + List<StorageDirInfo> sdkStorageDirInfo = + mSdkSandboxStorageManager.getSdkStorageDirInfo(callingInfo); + List<StorageDirInfo> expectedSdkStorageDirInfo = + getSdkStorageDirInfoForTest( + /*volumeUuid=*/ null, USER_ID, CLIENT_PKG_NAME, sdkNames); + + assertThat(sdkStorageDirInfo).containsExactlyElementsIn(expectedSdkStorageDirInfo); + } + + @Test + public void test_getInternalStorageDirInfo() throws Exception { + final List<String> nonSdkDirectories = + Arrays.asList(SubDirectories.SHARED_DIR, SubDirectories.SANDBOX_DIR); + createSdkStorageForTest(new ArrayList<>(), nonSdkDirectories); + + final ApplicationInfo info = new ApplicationInfo(); + info.storageUuid = UUID.fromString(STORAGE_UUID); + Mockito.doReturn(info) + .when(mPmMock) + .getApplicationInfo(Mockito.any(String.class), Mockito.anyInt()); + + final CallingInfo callingInfo = new CallingInfo(CLIENT_UID, CLIENT_PKG_NAME); + + List<StorageDirInfo> internalStorageDirInfo = + mSdkSandboxStorageManager.getInternalStorageDirInfo(callingInfo); + List<StorageDirInfo> expectedInternalStorageDirInfo = + getInternalStorageDirInfoForTest( + /*volumeUuid=*/ null, USER_ID, CLIENT_PKG_NAME, nonSdkDirectories); + + assertThat(internalStorageDirInfo) + .containsExactlyElementsIn(expectedInternalStorageDirInfo); + } + /** * A helper method for create sdk storage for test purpose. * @@ -365,24 +483,83 @@ public class SdkSandboxStorageManagerUnitTest { List<String> sdkNames, List<String> nonSdkDirectories) throws Exception { - for (int i = 0; i < 2; i++) { - final boolean isCeData = (i == 0); - final String packageDir = - mSdkSandboxStorageManager.getSdkDataPackageDirectory( - volumeUuid, userId, packageName, isCeData); - final Path packagePath = Paths.get(packageDir); - Files.createDirectories(packagePath); - for (String sdkName : sdkNames) { - final Path perSdkPath = Paths.get(packageDir, sdkName + "@" + sdkName); - Files.createDirectories(perSdkPath); - } - - for (String dir : nonSdkDirectories) { - final Path subDir = - Paths.get(packageDir, dir.equals("shared") ? dir : dir + "#" + dir); - Files.createDirectories(subDir); - } + final List<StorageDirInfo> sdkStorageInfos = + getSdkStorageDirInfoForTest(volumeUuid, userId, packageName, sdkNames); + final List<StorageDirInfo> internalStorageDirInfos = + getInternalStorageDirInfoForTest( + volumeUuid, userId, packageName, nonSdkDirectories); + + createPackagePath(volumeUuid, userId, packageName, /*isCeData=*/ true); + createPackagePath(volumeUuid, userId, packageName, /*isCeData=*/ false); + + createFilesFromList(sdkStorageInfos); + createFilesFromList(internalStorageDirInfos); + } + + private void createPackagePath( + String volumeUuid, int userId, String packageName, boolean isCeData) throws Exception { + final String packageDir = + mSdkSandboxStorageManager.getSdkDataPackageDirectory( + volumeUuid, userId, packageName, isCeData); + Files.createDirectories(Paths.get(packageDir)); + } + + private void createFilesFromList(List<StorageDirInfo> storageDirInfos) throws Exception { + final int storageDirInfosSize = storageDirInfos.size(); + + for (int i = 0; i < storageDirInfosSize; i++) { + final Path ceSdkStoragePath = Paths.get(storageDirInfos.get(i).getCeDataDir()); + Files.createDirectories(ceSdkStoragePath); + + final Path deSdkStoragePath = Paths.get(storageDirInfos.get(i).getDeDataDir()); + Files.createDirectories(deSdkStoragePath); + } + } + + private void createSdkStorageForTest(List<String> sdkNames, List<String> nonSdkDirectories) + throws Exception { + createSdkStorageForTest( + /*volumeUuid=*/ null, USER_ID, CLIENT_PKG_NAME, sdkNames, nonSdkDirectories); + } + + /** A helper method to get the storage paths of SDKs for test purpose */ + private List<StorageDirInfo> getSdkStorageDirInfoForTest( + String volumeUuid, int userId, String packageName, List<String> sdkNames) { + + final List<StorageDirInfo> sdkStorageDirInfo = new ArrayList<>(); + final String cePackageDir = + mSdkSandboxStorageManager.getSdkDataPackageDirectory( + volumeUuid, userId, packageName, /*isCeData=*/ true); + final String dePackageDir = + mSdkSandboxStorageManager.getSdkDataPackageDirectory( + volumeUuid, userId, packageName, /*isCeData=*/ false); + + for (String sdkName : sdkNames) { + String sdkCeSubDirPath = cePackageDir + "/" + sdkName + "@" + sdkName; + String sdkDeSubDirPath = dePackageDir + "/" + sdkName + "@" + sdkName; + sdkStorageDirInfo.add(new StorageDirInfo(sdkCeSubDirPath, sdkDeSubDirPath)); + } + return sdkStorageDirInfo; + } + + /** A helper method to get the internal storage paths for test purpose */ + private List<StorageDirInfo> getInternalStorageDirInfoForTest( + String volumeUuid, int userId, String packageName, List<String> nonSdkDirectories) { + final List<StorageDirInfo> internalStorageDirInfo = new ArrayList<>(); + final String cePackageDir = + mSdkSandboxStorageManager.getSdkDataPackageDirectory( + volumeUuid, userId, packageName, /*isCeData=*/ true); + final String dePackageDir = + mSdkSandboxStorageManager.getSdkDataPackageDirectory( + volumeUuid, userId, packageName, /*isCeData=*/ false); + + for (String dir : nonSdkDirectories) { + String path = dir.equals(SubDirectories.SHARED_DIR) ? dir : dir + '#' + dir; + String sdkCeSubDirPath = cePackageDir + "/" + path; + String sdkDeSubDirPath = dePackageDir + "/" + path; + internalStorageDirInfo.add(new StorageDirInfo(sdkCeSubDirPath, sdkDeSubDirPath)); } + return internalStorageDirInfo; } private static class FakeSdkSandboxManagerLocal implements SdkSandboxManagerLocal { |