diff options
Diffstat (limited to 'tests/vcn/java/com/android/server/VcnManagementServiceTest.java')
-rw-r--r-- | tests/vcn/java/com/android/server/VcnManagementServiceTest.java | 206 |
1 files changed, 201 insertions, 5 deletions
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index c91fdbffd760..1cc953239fed 100644 --- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java +++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java @@ -16,42 +16,123 @@ package com.android.server; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import android.content.Context; import android.net.ConnectivityManager; +import android.net.vcn.VcnConfig; +import android.net.vcn.VcnConfigTest; +import android.os.ParcelUuid; +import android.os.PersistableBundle; +import android.os.Process; +import android.os.UserHandle; import android.os.test.TestLooper; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.server.vcn.util.PersistableBundleUtils; + import org.junit.Test; import org.junit.runner.RunWith; +import java.io.FileNotFoundException; +import java.util.Collections; +import java.util.Map; +import java.util.UUID; + /** Tests for {@link VcnManagementService}. */ @RunWith(AndroidJUnit4.class) @SmallTest public class VcnManagementServiceTest { + private static final ParcelUuid TEST_UUID_1 = new ParcelUuid(new UUID(0, 0)); + private static final ParcelUuid TEST_UUID_2 = new ParcelUuid(new UUID(1, 1)); + private static final VcnConfig TEST_VCN_CONFIG = VcnConfigTest.buildTestConfig(); + private static final Map<ParcelUuid, VcnConfig> TEST_VCN_CONFIG_MAP = + Collections.unmodifiableMap(Collections.singletonMap(TEST_UUID_1, TEST_VCN_CONFIG)); + + private static final SubscriptionInfo TEST_SUBSCRIPTION_INFO = + new SubscriptionInfo( + 1 /* id */, + "" /* iccId */, + 0 /* simSlotIndex */, + "Carrier" /* displayName */, + "Carrier" /* carrierName */, + 0 /* nameSource */, + 255 /* iconTint */, + "12345" /* number */, + 0 /* roaming */, + null /* icon */, + "0" /* mcc */, + "0" /* mnc */, + "0" /* countryIso */, + false /* isEmbedded */, + null /* nativeAccessRules */, + null /* cardString */, + false /* isOpportunistic */, + TEST_UUID_1.toString() /* groupUUID */, + 0 /* carrierId */, + 0 /* profileClass */); + private final Context mMockContext = mock(Context.class); private final VcnManagementService.Dependencies mMockDeps = mock(VcnManagementService.Dependencies.class); private final TestLooper mTestLooper = new TestLooper(); private final ConnectivityManager mConnMgr = mock(ConnectivityManager.class); + private final TelephonyManager mTelMgr = mock(TelephonyManager.class); + private final SubscriptionManager mSubMgr = mock(SubscriptionManager.class); private final VcnManagementService mVcnMgmtSvc; + private final PersistableBundleUtils.LockingReadWriteHelper mConfigReadWriteHelper = + mock(PersistableBundleUtils.LockingReadWriteHelper.class); - public VcnManagementServiceTest() { - doReturn(Context.CONNECTIVITY_SERVICE) - .when(mMockContext) - .getSystemServiceName(ConnectivityManager.class); - doReturn(mConnMgr).when(mMockContext).getSystemService(Context.CONNECTIVITY_SERVICE); + public VcnManagementServiceTest() throws Exception { + setupSystemService(mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class); + setupSystemService(mTelMgr, Context.TELEPHONY_SERVICE, TelephonyManager.class); + setupSystemService( + mSubMgr, Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class); doReturn(mTestLooper.getLooper()).when(mMockDeps).getLooper(); + doReturn(Process.FIRST_APPLICATION_UID).when(mMockDeps).getBinderCallingUid(); + doReturn(mConfigReadWriteHelper) + .when(mMockDeps) + .newPersistableBundleLockingReadWriteHelper(any()); + + final PersistableBundle bundle = + PersistableBundleUtils.fromMap( + TEST_VCN_CONFIG_MAP, + PersistableBundleUtils::fromParcelUuid, + VcnConfig::toPersistableBundle); + doReturn(bundle).when(mConfigReadWriteHelper).readFromDisk(); + + setupMockedCarrierPrivilege(true); mVcnMgmtSvc = new VcnManagementService(mMockContext, mMockDeps); } + private void setupSystemService(Object service, String name, Class<?> serviceClass) { + doReturn(name).when(mMockContext).getSystemServiceName(serviceClass); + doReturn(service).when(mMockContext).getSystemService(name); + } + + private void setupMockedCarrierPrivilege(boolean isPrivileged) { + doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO)) + .when(mSubMgr) + .getSubscriptionsInGroup(any()); + doReturn(isPrivileged) + .when(mTelMgr) + .hasCarrierPrivileges(eq(TEST_SUBSCRIPTION_INFO.getSubscriptionId())); + } + @Test public void testSystemReady() throws Exception { mVcnMgmtSvc.systemReady(); @@ -59,4 +140,119 @@ public class VcnManagementServiceTest { verify(mConnMgr) .registerNetworkProvider(any(VcnManagementService.VcnNetworkProvider.class)); } + + @Test + public void testNonSystemServerRealConfigFileAccessPermission() throws Exception { + // Attempt to build a real instance of the dependencies, and verify we cannot write to the + // file. + VcnManagementService.Dependencies deps = new VcnManagementService.Dependencies(); + PersistableBundleUtils.LockingReadWriteHelper configReadWriteHelper = + deps.newPersistableBundleLockingReadWriteHelper( + VcnManagementService.VCN_CONFIG_FILE); + + // Even tests should not be able to read/write configs from disk; SELinux policies restrict + // it to only the system server. + // Reading config should always return null since the file "does not exist", and writing + // should throw an IOException. + assertNull(configReadWriteHelper.readFromDisk()); + + try { + configReadWriteHelper.writeToDisk(new PersistableBundle()); + fail("Expected IOException due to SELinux policy"); + } catch (FileNotFoundException expected) { + } + } + + @Test + public void testLoadVcnConfigsOnStartup() throws Exception { + mTestLooper.dispatchAll(); + + assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs()); + verify(mConfigReadWriteHelper).readFromDisk(); + } + + @Test + public void testSetVcnConfigRequiresNonSystemServer() throws Exception { + doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid(); + + try { + mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, VcnConfigTest.buildTestConfig()); + fail("Expected IllegalStateException exception for system server"); + } catch (IllegalStateException expected) { + } + } + + @Test + public void testSetVcnConfigRequiresSystemUser() throws Exception { + doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, Process.FIRST_APPLICATION_UID)) + .when(mMockDeps) + .getBinderCallingUid(); + + try { + mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, VcnConfigTest.buildTestConfig()); + fail("Expected security exception for non system user"); + } catch (SecurityException expected) { + } + } + + @Test + public void testSetVcnConfigRequiresCarrierPrivileges() throws Exception { + setupMockedCarrierPrivilege(false); + + try { + mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, VcnConfigTest.buildTestConfig()); + fail("Expected security exception for missing carrier privileges"); + } catch (SecurityException expected) { + } + } + + @Test + public void testSetVcnConfig() throws Exception { + // Use a different UUID to simulate a new VCN config. + mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG); + assertEquals(TEST_VCN_CONFIG, mVcnMgmtSvc.getConfigs().get(TEST_UUID_2)); + verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); + } + + @Test + public void testClearVcnConfigRequiresNonSystemServer() throws Exception { + doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid(); + + try { + mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1); + fail("Expected IllegalStateException exception for system server"); + } catch (IllegalStateException expected) { + } + } + + @Test + public void testClearVcnConfigRequiresSystemUser() throws Exception { + doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, Process.FIRST_APPLICATION_UID)) + .when(mMockDeps) + .getBinderCallingUid(); + + try { + mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1); + fail("Expected security exception for non system user"); + } catch (SecurityException expected) { + } + } + + @Test + public void testClearVcnConfigRequiresCarrierPrivileges() throws Exception { + setupMockedCarrierPrivilege(false); + + try { + mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1); + fail("Expected security exception for missing carrier privileges"); + } catch (SecurityException expected) { + } + } + + @Test + public void testClearVcnConfig() throws Exception { + mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1); + assertTrue(mVcnMgmtSvc.getConfigs().isEmpty()); + verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); + } } |