diff options
| -rw-r--r-- | core/api/current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/net/vcn/IVcnManagementService.aidl | 3 | ||||
| -rw-r--r-- | core/java/android/net/vcn/VcnManager.java | 18 | ||||
| -rw-r--r-- | services/core/java/com/android/server/VcnManagementService.java | 28 | ||||
| -rw-r--r-- | tests/vcn/java/com/android/server/VcnManagementServiceTest.java | 38 |
5 files changed, 88 insertions, 0 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 1230c3afb0b4..5bc749f2356c 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -25725,6 +25725,7 @@ package android.net.vcn { public class VcnManager { method @RequiresPermission("carrier privileges") public void clearVcnConfig(@NonNull android.os.ParcelUuid) throws java.io.IOException; + method @NonNull public java.util.List<android.os.ParcelUuid> getConfiguredSubscriptionGroups(); method public void registerVcnStatusCallback(@NonNull android.os.ParcelUuid, @NonNull java.util.concurrent.Executor, @NonNull android.net.vcn.VcnManager.VcnStatusCallback); method @RequiresPermission("carrier privileges") public void setVcnConfig(@NonNull android.os.ParcelUuid, @NonNull android.net.vcn.VcnConfig) throws java.io.IOException; method public void unregisterVcnStatusCallback(@NonNull android.net.vcn.VcnManager.VcnStatusCallback); diff --git a/core/java/android/net/vcn/IVcnManagementService.aidl b/core/java/android/net/vcn/IVcnManagementService.aidl index 5b79f7311b6d..e16f6b167750 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<ParcelUuid> 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 344b20c036a0..9d1c1ff898e7 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,23 @@ public class VcnManager { } } + /** + * Retrieves the list of Subscription Groups for which a VCN Configuration has been set. + * + * <p>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 + */ + @NonNull + public List<ParcelUuid> 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 6eb6a0ed7b1c..723507b877ff 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 + * + * <p>Limited to subscription groups for which the caller is carrier privileged. + * + * <p>Implements the IVcnManagementService Binder interface. + */ + @Override + @NonNull + public List<ParcelUuid> getConfiguredSubscriptionGroups(@NonNull String opPkgName) { + requireNonNull(opPkgName, "opPkgName was null"); + + mContext.getSystemService(AppOpsManager.class) + .checkPackage(mDeps.getBinderCallingUid(), opPkgName); + enforcePrimaryUser(); + + final List<ParcelUuid> 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 9a663436f983..545448db1973 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; @@ -617,6 +618,43 @@ public class VcnManagementServiceTest { } @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<ParcelUuid> subGrps = + mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME); + assertEquals(Collections.singletonList(TEST_UUID_1), subGrps); + } + + @Test public void testAddVcnUnderlyingNetworkPolicyListener() throws Exception { mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); |