From 6e8c1d6da72fb4358f033ef86ff57e312bd58dc0 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 20 Apr 2021 15:09:43 -0700 Subject: [PATCH] Add support for retrieval of configured VCNs by carrier privilege This change adds support for retrieval of a list of subscription groups that have a VCN configured. Bug: 184612525 Test: atest FrameworksVcnTests Change-Id: I40553a7bb45d9b1f948c7d0a791f1b22a422d55c --- .../net/vcn/IVcnManagementService.aidl | 3 ++ core/java/android/net/vcn/VcnManager.java | 19 ++++++++++ .../android/server/VcnManagementService.java | 28 ++++++++++++++ .../server/VcnManagementServiceTest.java | 38 +++++++++++++++++++ 4 files changed, 88 insertions(+) diff --git a/core/java/android/net/vcn/IVcnManagementService.aidl b/core/java/android/net/vcn/IVcnManagementService.aidl index 5b79f7311b6d6..e16f6b1677506 100644 --- a/core/java/android/net/vcn/IVcnManagementService.aidl +++ b/core/java/android/net/vcn/IVcnManagementService.aidl @@ -24,12 +24,15 @@ import android.net.vcn.VcnConfig; import android.net.vcn.VcnUnderlyingNetworkPolicy; import android.os.ParcelUuid; +import java.util.List; + /** * @hide */ interface IVcnManagementService { void setVcnConfig(in ParcelUuid subscriptionGroup, in VcnConfig config, in String opPkgName); void clearVcnConfig(in ParcelUuid subscriptionGroup, in String opPkgName); + List getConfiguredSubscriptionGroups(in String opPkgName); void addVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener); void removeVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener); diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java index 344b20c036a0c..1cd4ff0a5c260 100644 --- a/core/java/android/net/vcn/VcnManager.java +++ b/core/java/android/net/vcn/VcnManager.java @@ -38,6 +38,7 @@ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; @@ -162,6 +163,24 @@ public class VcnManager { } } + /** + * Retrieves the list of Subscription Groups for which a VCN Configuration has been set. + * + *

The returned list will include only subscription groups for which the carrier app is + * privileged, and which have an associated {@link VcnConfig}. + * + * @throws SecurityException if the caller is not running as the primary user + * @hide + */ + @NonNull + public List getConfiguredSubscriptionGroups() { + try { + return mService.getConfiguredSubscriptionGroups(mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + // TODO(b/180537630): remove all VcnUnderlyingNetworkPolicyListener refs once Telephony is using // the new VcnNetworkPolicyChangeListener API /** diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java index 9c10658e7c0e9..e1db241a6dfbb 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -614,6 +614,34 @@ public class VcnManagementService extends IVcnManagementService.Stub { }); } + /** + * Retrieves the list of subscription groups with configured VcnConfigs + * + *

Limited to subscription groups for which the caller is carrier privileged. + * + *

Implements the IVcnManagementService Binder interface. + */ + @Override + @NonNull + public List getConfiguredSubscriptionGroups(@NonNull String opPkgName) { + requireNonNull(opPkgName, "opPkgName was null"); + + mContext.getSystemService(AppOpsManager.class) + .checkPackage(mDeps.getBinderCallingUid(), opPkgName); + enforcePrimaryUser(); + + final List result = new ArrayList<>(); + synchronized (mLock) { + for (ParcelUuid subGrp : mConfigs.keySet()) { + if (mLastSnapshot.packageHasPermissionsForSubscriptionGroup(subGrp, opPkgName)) { + result.add(subGrp); + } + } + } + + return result; + } + @GuardedBy("mLock") private void writeConfigsToDiskLocked() { try { diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index bbc9bb600f6d9..38d2bb1c954a2 100644 --- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java +++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java @@ -96,6 +96,7 @@ import org.mockito.ArgumentCaptor; import java.io.FileNotFoundException; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -616,6 +617,43 @@ public class VcnManagementServiceTest { verify(vcnInstance).teardownAsynchronously(); } + @Test + public void testGetConfiguredSubscriptionGroupsRequiresSystemUser() throws Exception { + doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, TEST_UID)) + .when(mMockDeps) + .getBinderCallingUid(); + + try { + mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME); + fail("Expected security exception for non system user"); + } catch (SecurityException expected) { + } + } + + @Test + public void testGetConfiguredSubscriptionGroupsMismatchedPackages() throws Exception { + final String badPackage = "IncorrectPackage"; + doThrow(new SecurityException()).when(mAppOpsMgr).checkPackage(TEST_UID, badPackage); + + try { + mVcnMgmtSvc.getConfiguredSubscriptionGroups(badPackage); + fail("Expected security exception due to mismatched packages"); + } catch (SecurityException expected) { + } + } + + @Test + public void testGetConfiguredSubscriptionGroups() throws Exception { + mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); + + // Assert that if both UUID 1 and 2 are provisioned, the caller only gets ones that they are + // privileged for. + triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1)); + final List subGrps = + mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME); + assertEquals(Collections.singletonList(TEST_UUID_1), subGrps); + } + @Test public void testAddVcnUnderlyingNetworkPolicyListener() throws Exception { mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);