Add APIs to manage profiles in the VpnBlobStore
Add hidden apis for settings to store profiles directly into the
VpnBlobStore.
Bug: 307903113
Test: m
Change-Id: I148ceedcb2ae235d89a3dd5ffba4a8ef26b5d104
diff --git a/core/java/android/net/IVpnManager.aidl b/core/java/android/net/IVpnManager.aidl
index f302378..5149967 100644
--- a/core/java/android/net/IVpnManager.aidl
+++ b/core/java/android/net/IVpnManager.aidl
@@ -60,6 +60,12 @@
LegacyVpnInfo getLegacyVpnInfo(int userId);
boolean updateLockdownVpn();
+ /** Profile store APIs */
+ byte[] getFromVpnProfileStore(String name);
+ boolean putIntoVpnProfileStore(String name, in byte[] blob);
+ boolean removeFromVpnProfileStore(String name);
+ String[] listFromVpnProfileStore(String prefix);
+
/** General system APIs */
VpnConfig getVpnConfig(int userId);
void factoryReset();
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
index ff47f3f..c50bc56 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -717,4 +717,81 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Get the vpn profile owned by the calling uid with the given name from the vpn database.
+ *
+ * <p>Note this method should not be used for platform VPN profiles. </p>
+ *
+ * @param name The name of the profile to retrieve.
+ * @return the unstructured blob for the matching vpn profile.
+ * Returns null if no profile with a matching name was found.
+ * @hide
+ */
+ @Nullable
+ public byte[] getFromVpnProfileStore(@NonNull String name) {
+ try {
+ return mService.getFromVpnProfileStore(name);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Put the given vpn profile owned by the calling uid with the given name into the vpn database.
+ * Existing profiles with the same name will be replaced.
+ *
+ * <p>Note this method should not be used for platform VPN profiles.
+ * To update a platform VPN, use provisionVpnProfile() instead. </p>
+ *
+ * @param name The name of the profile to put.
+ * @param blob The profile.
+ * @return true if the profile was successfully added. False otherwise.
+ * @hide
+ */
+ public boolean putIntoVpnProfileStore(@NonNull String name, @NonNull byte[] blob) {
+ try {
+ return mService.putIntoVpnProfileStore(name, blob);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Removes the vpn profile owned by the calling uid with the given name from the vpn database.
+ *
+ * <p>Note this method should not be used for platform VPN profiles.
+ * To remove a platform VPN, use deleteVpnProfile() instead.</p>
+ *
+ * @param name The name of the profile to be removed.
+ * @return true if a profile was removed. False if no profile with a matching name was found.
+ * @hide
+ */
+ public boolean removeFromVpnProfileStore(@NonNull String name) {
+ try {
+ return mService.removeFromVpnProfileStore(name);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns a list of the name suffixes of the vpn profiles owned by the calling uid in the vpn
+ * database matching the given prefix, sorted in ascending order.
+ *
+ * <p>Note this method should not be used for platform VPN profiles. </p>
+ *
+ * @param prefix The prefix to match.
+ * @return an array of strings representing the name suffixes stored in the profile database
+ * matching the given prefix. The return value may be empty but never null.
+ * @hide
+ */
+ @NonNull
+ public String[] listFromVpnProfileStore(@NonNull String prefix) {
+ try {
+ return mService.listFromVpnProfileStore(prefix);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 1d1e2d9..626fa70 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -1007,6 +1007,71 @@
}
}
+ /**
+ * Get the vpn profile owned by the calling uid with the given name from the vpn database.
+ *
+ * <p>Note this method should not be used for platform VPN profiles. </p>
+ *
+ * @param name The name of the profile to retrieve.
+ * @return the unstructured blob for the matching vpn profile.
+ * Returns null if no profile with a matching name was found.
+ * @hide
+ */
+ @Override
+ @Nullable
+ public byte[] getFromVpnProfileStore(@NonNull String name) {
+ return mVpnProfileStore.get(name);
+ }
+
+ /**
+ * Put the given vpn profile owned by the calling uid with the given name into the vpn database.
+ * Existing profiles with the same name will be replaced.
+ *
+ * <p>Note this method should not be used for platform VPN profiles.
+ * To update a platform VPN, use provisionVpnProfile() instead. </p>
+ *
+ * @param name The name of the profile to put.
+ * @param blob The profile.
+ * @return true if the profile was successfully added. False otherwise.
+ * @hide
+ */
+ @Override
+ public boolean putIntoVpnProfileStore(@NonNull String name, @NonNull byte[] blob) {
+ return mVpnProfileStore.put(name, blob);
+ }
+
+ /**
+ * Removes the vpn profile owned by the calling uid with the given name from the vpn database.
+ *
+ * <p>Note this method should not be used for platform VPN profiles.
+ * To remove a platform VPN, use deleteVpnProfile() instead.</p>
+ *
+ * @param name The name of the profile to be removed.
+ * @return true if a profile was removed. False if no profile with a matching name was found.
+ * @hide
+ */
+ @Override
+ public boolean removeFromVpnProfileStore(@NonNull String name) {
+ return mVpnProfileStore.remove(name);
+ }
+
+ /**
+ * Returns a list of the name suffixes of the vpn profiles owned by the calling uid in the vpn
+ * database matching the given prefix, sorted in ascending order.
+ *
+ * <p>Note this method should not be used for platform VPN profiles. </p>
+ *
+ * @param prefix The prefix to match.
+ * @return an array of strings representing the name suffixes stored in the profile database
+ * matching the given prefix. The return value may be empty but never null.
+ * @hide
+ */
+ @Override
+ @NonNull
+ public String[] listFromVpnProfileStore(@NonNull String prefix) {
+ return mVpnProfileStore.list(prefix);
+ }
+
private void ensureRunningOnHandlerThread() {
if (mHandler.getLooper().getThread() != Thread.currentThread()) {
throw new IllegalStateException(
diff --git a/services/tests/VpnTests/java/com/android/server/VpnManagerServiceTest.java b/services/tests/VpnTests/java/com/android/server/VpnManagerServiceTest.java
index ecc70e3..8495de4 100644
--- a/services/tests/VpnTests/java/com/android/server/VpnManagerServiceTest.java
+++ b/services/tests/VpnTests/java/com/android/server/VpnManagerServiceTest.java
@@ -397,4 +397,35 @@
// Even lockdown is enabled but no Vpn is created for SECONDARY_USER.
assertNull(mService.getVpnLockdownAllowlist(SECONDARY_USER.id));
}
+
+ @Test
+ public void testGetFromVpnProfileStore() {
+ final String name = Credentials.VPN + TEST_VPN_PKG;
+ mService.getFromVpnProfileStore(name);
+ verify(mVpnProfileStore).get(name);
+ }
+
+ @Test
+ public void testPutIntoVpnProfileStore() {
+ final String name = Credentials.VPN + TEST_VPN_PKG;
+ final VpnProfile vpnProfile = new VpnProfile(TEST_VPN_PKG);
+ final byte[] encodedProfile = vpnProfile.encode();
+
+ mService.putIntoVpnProfileStore(name, encodedProfile);
+ verify(mVpnProfileStore).put(name, encodedProfile);
+ }
+
+ @Test
+ public void testRemoveFromVpnProfileStore() {
+ final String name = Credentials.VPN + TEST_VPN_PKG;
+ mService.removeFromVpnProfileStore(name);
+ verify(mVpnProfileStore).remove(name);
+ }
+
+ @Test
+ public void testListFromVpnProfileStore() {
+ final String name = Credentials.VPN + TEST_VPN_PKG;
+ mService.listFromVpnProfileStore(name);
+ verify(mVpnProfileStore).list(name);
+ }
}