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);  |