Add ShadowVpnManager to Robolectric.
PiperOrigin-RevId: 526856997
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowVpnManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowVpnManagerTest.java
new file mode 100644
index 0000000..dbf7250
--- /dev/null
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowVpnManagerTest.java
@@ -0,0 +1,95 @@
+package org.robolectric.shadows;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.content.Intent;
+import android.net.Ikev2VpnProfile;
+import android.net.VpnManager;
+import android.net.VpnProfileState;
+import android.os.Build.VERSION_CODES;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(AndroidJUnit4.class)
+@Config(minSdk = VERSION_CODES.R)
+public class ShadowVpnManagerTest {
+ private VpnManager vpnManager;
+ private ShadowVpnManager shadowVpnManager;
+
+ @Before
+ public void setUp() throws Exception {
+ vpnManager = ApplicationProvider.getApplicationContext().getSystemService(VpnManager.class);
+ shadowVpnManager = shadowOf(vpnManager);
+ }
+
+ @Test
+ public void provisionVpnProfile() {
+ Intent intent = new Intent("foo");
+ shadowVpnManager.setProvisionVpnProfileResult(intent);
+
+ assertThat(
+ vpnManager.provisionVpnProfile(
+ new Ikev2VpnProfile.Builder("server", "local.identity")
+ .setAuthPsk(new byte[0])
+ .build()))
+ .isSameInstanceAs(intent);
+
+ if (RuntimeEnvironment.getApiLevel() >= VERSION_CODES.TIRAMISU) {
+ VpnProfileState state = vpnManager.getProvisionedVpnProfileState();
+ assertThat(state.getState()).isEqualTo(VpnProfileState.STATE_DISCONNECTED);
+ assertThat(state.getSessionId()).isNull();
+ }
+ }
+
+ @Test
+ public void deleteVpnProfile() {
+ vpnManager.provisionVpnProfile(
+ new Ikev2VpnProfile.Builder("server", "local.identity").setAuthPsk(new byte[0]).build());
+ vpnManager.deleteProvisionedVpnProfile();
+ }
+
+ @Test
+ @Config(minSdk = VERSION_CODES.TIRAMISU)
+ public void deleteVpnProfile_tiramisu() {
+ vpnManager.provisionVpnProfile(
+ new Ikev2VpnProfile.Builder("server", "local.identity").setAuthPsk(new byte[0]).build());
+ assertThat(vpnManager.getProvisionedVpnProfileState()).isNotNull();
+
+ vpnManager.deleteProvisionedVpnProfile();
+ assertThat(vpnManager.getProvisionedVpnProfileState()).isNull();
+ }
+
+ @Test
+ public void startAndStopVpnProfile() {
+ vpnManager.provisionVpnProfile(
+ new Ikev2VpnProfile.Builder("server", "local.identity").setAuthPsk(new byte[0]).build());
+ vpnManager.startProvisionedVpnProfile();
+ vpnManager.stopProvisionedVpnProfile();
+ }
+
+ @Test
+ @Config(minSdk = VERSION_CODES.TIRAMISU)
+ public void startAndStopVpnProfile_tiramisu() {
+ vpnManager.provisionVpnProfile(
+ new Ikev2VpnProfile.Builder("server", "local.identity").setAuthPsk(new byte[0]).build());
+ String sessionKey = vpnManager.startProvisionedVpnProfileSession();
+ VpnProfileState state = vpnManager.getProvisionedVpnProfileState();
+ assertThat(state.getState()).isEqualTo(VpnProfileState.STATE_CONNECTED);
+ assertThat(state.getSessionId()).isEqualTo(sessionKey);
+ assertThat(state.isAlwaysOn()).isFalse();
+ assertThat(state.isLockdownEnabled()).isFalse();
+
+ vpnManager.stopProvisionedVpnProfile();
+ state = vpnManager.getProvisionedVpnProfileState();
+ assertThat(state.getState()).isEqualTo(VpnProfileState.STATE_DISCONNECTED);
+ assertThat(state.getSessionId()).isNull();
+ assertThat(state.isAlwaysOn()).isFalse();
+ assertThat(state.isLockdownEnabled()).isFalse();
+ }
+}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowServiceManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowServiceManager.java
index 15d5971..17b4ba1 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowServiceManager.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowServiceManager.java
@@ -59,6 +59,7 @@
import android.net.INetworkPolicyManager;
import android.net.INetworkScoreService;
import android.net.ITetheringConnector;
+import android.net.IVpnManager;
import android.net.nsd.INsdManager;
import android.net.vcn.IVcnManagementService;
import android.net.wifi.IWifiManager;
@@ -209,6 +210,7 @@
addBinderService(Context.VCN_MANAGEMENT_SERVICE, IVcnManagementService.class);
addBinderService(Context.TRANSLATION_MANAGER_SERVICE, ITranslationManager.class);
addBinderService(Context.SENSOR_PRIVACY_SERVICE, ISensorPrivacyManager.class);
+ addBinderService(Context.VPN_MANAGEMENT_SERVICE, IVpnManager.class);
}
if (RuntimeEnvironment.getApiLevel() >= TIRAMISU) {
addBinderService(Context.AMBIENT_CONTEXT_SERVICE, IAmbientContextManager.class);
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowVpnManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowVpnManager.java
new file mode 100644
index 0000000..99f807b
--- /dev/null
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowVpnManager.java
@@ -0,0 +1,67 @@
+package org.robolectric.shadows;
+
+import android.content.Intent;
+import android.net.PlatformVpnProfile;
+import android.net.VpnManager;
+import android.net.VpnProfileState;
+import android.os.Build.VERSION_CODES;
+import java.util.UUID;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+/** Shadow for {@link VpnManager}. */
+@Implements(value = VpnManager.class, minSdk = VERSION_CODES.R)
+public class ShadowVpnManager {
+
+ private VpnProfileState vpnProfileState;
+ private Intent provisionVpnProfileIntent;
+
+ @Implementation
+ protected void deleteProvisionedVpnProfile() {
+ vpnProfileState = null;
+ }
+
+ @Implementation(minSdk = VERSION_CODES.TIRAMISU)
+ protected VpnProfileState getProvisionedVpnProfileState() {
+ return vpnProfileState;
+ }
+
+ /**
+ * @see #setProvisionVpnProfileResult(Intent).
+ */
+ @Implementation
+ protected Intent provisionVpnProfile(PlatformVpnProfile profile) {
+ if (RuntimeEnvironment.getApiLevel() >= VERSION_CODES.TIRAMISU) {
+ vpnProfileState = new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, null, false, false);
+ }
+ return provisionVpnProfileIntent;
+ }
+
+ /** Sets the return value of #provisionVpnProfile(PlatformVpnProfile). */
+ public void setProvisionVpnProfileResult(Intent intent) {
+ provisionVpnProfileIntent = intent;
+ }
+
+ @Implementation
+ protected void startProvisionedVpnProfile() {
+ startProvisionedVpnProfileSession();
+ }
+
+ @Implementation(minSdk = VERSION_CODES.TIRAMISU)
+ protected String startProvisionedVpnProfileSession() {
+ String sessionKey = UUID.randomUUID().toString();
+ if (RuntimeEnvironment.getApiLevel() >= VERSION_CODES.TIRAMISU) {
+ vpnProfileState =
+ new VpnProfileState(VpnProfileState.STATE_CONNECTED, sessionKey, false, false);
+ }
+ return sessionKey;
+ }
+
+ @Implementation
+ protected void stopProvisionedVpnProfile() {
+ if (RuntimeEnvironment.getApiLevel() >= VERSION_CODES.TIRAMISU) {
+ vpnProfileState = new VpnProfileState(VpnProfileState.STATE_DISCONNECTED, null, false, false);
+ }
+ }
+}