Merge changes I64b56575,I40553a7b
* changes:
Expose API for retrieval of subscription groups with VCN configured
Add support for retrieval of configured VCNs by carrier privilege
diff --git a/core/api/current.txt b/core/api/current.txt
index 1230c3a..5bc749f 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -25725,6 +25725,7 @@
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 5b79f73..e16f6b1 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.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 344b20c..9d1c1ff 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -38,6 +38,7 @@
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 @@
}
}
+ /**
+ * 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 6eb6a0e..723507b 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -614,6 +614,34 @@
});
}
+ /**
+ * 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 9a66343..545448d 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -96,6 +96,7 @@
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 @@
}
@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);