Merge changes Icb59b15d,I6fc6a266,I5cc340e5,I94db52a8 am: b79dcb24d0

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1700309

Change-Id: I76cc66f33740b519441658d0d1d631882cf4e126
This commit is contained in:
Treehugger Robot
2021-05-12 16:36:51 +00:00
committed by Automerger Merge Worker
10 changed files with 202 additions and 19 deletions

View File

@@ -52,12 +52,17 @@ public final class VcnConfig implements Parcelable {
private static final String GATEWAY_CONNECTION_CONFIGS_KEY = "mGatewayConnectionConfigs"; private static final String GATEWAY_CONNECTION_CONFIGS_KEY = "mGatewayConnectionConfigs";
@NonNull private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs; @NonNull private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs;
private static final String IS_TEST_MODE_PROFILE_KEY = "mIsTestModeProfile";
private final boolean mIsTestModeProfile;
private VcnConfig( private VcnConfig(
@NonNull String packageName, @NonNull String packageName,
@NonNull Set<VcnGatewayConnectionConfig> gatewayConnectionConfigs) { @NonNull Set<VcnGatewayConnectionConfig> gatewayConnectionConfigs,
boolean isTestModeProfile) {
mPackageName = packageName; mPackageName = packageName;
mGatewayConnectionConfigs = mGatewayConnectionConfigs =
Collections.unmodifiableSet(new ArraySet<>(gatewayConnectionConfigs)); Collections.unmodifiableSet(new ArraySet<>(gatewayConnectionConfigs));
mIsTestModeProfile = isTestModeProfile;
validate(); validate();
} }
@@ -77,6 +82,7 @@ public final class VcnConfig implements Parcelable {
new ArraySet<>( new ArraySet<>(
PersistableBundleUtils.toList( PersistableBundleUtils.toList(
gatewayConnectionConfigsBundle, VcnGatewayConnectionConfig::new)); gatewayConnectionConfigsBundle, VcnGatewayConnectionConfig::new));
mIsTestModeProfile = in.getBoolean(IS_TEST_MODE_PROFILE_KEY);
validate(); validate();
} }
@@ -103,6 +109,15 @@ public final class VcnConfig implements Parcelable {
return Collections.unmodifiableSet(mGatewayConnectionConfigs); return Collections.unmodifiableSet(mGatewayConnectionConfigs);
} }
/**
* Returns whether or not this VcnConfig is restricted to test networks.
*
* @hide
*/
public boolean isTestModeProfile() {
return mIsTestModeProfile;
}
/** /**
* Serializes this object to a PersistableBundle. * Serializes this object to a PersistableBundle.
* *
@@ -119,13 +134,14 @@ public final class VcnConfig implements Parcelable {
new ArrayList<>(mGatewayConnectionConfigs), new ArrayList<>(mGatewayConnectionConfigs),
VcnGatewayConnectionConfig::toPersistableBundle); VcnGatewayConnectionConfig::toPersistableBundle);
result.putPersistableBundle(GATEWAY_CONNECTION_CONFIGS_KEY, gatewayConnectionConfigsBundle); result.putPersistableBundle(GATEWAY_CONNECTION_CONFIGS_KEY, gatewayConnectionConfigsBundle);
result.putBoolean(IS_TEST_MODE_PROFILE_KEY, mIsTestModeProfile);
return result; return result;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(mPackageName, mGatewayConnectionConfigs); return Objects.hash(mPackageName, mGatewayConnectionConfigs, mIsTestModeProfile);
} }
@Override @Override
@@ -136,7 +152,8 @@ public final class VcnConfig implements Parcelable {
final VcnConfig rhs = (VcnConfig) other; final VcnConfig rhs = (VcnConfig) other;
return mPackageName.equals(rhs.mPackageName) return mPackageName.equals(rhs.mPackageName)
&& mGatewayConnectionConfigs.equals(rhs.mGatewayConnectionConfigs); && mGatewayConnectionConfigs.equals(rhs.mGatewayConnectionConfigs)
&& mIsTestModeProfile == rhs.mIsTestModeProfile;
} }
// Parcelable methods // Parcelable methods
@@ -172,6 +189,8 @@ public final class VcnConfig implements Parcelable {
@NonNull @NonNull
private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs = new ArraySet<>(); private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs = new ArraySet<>();
private boolean mIsTestModeProfile = false;
public Builder(@NonNull Context context) { public Builder(@NonNull Context context) {
Objects.requireNonNull(context, "context was null"); Objects.requireNonNull(context, "context was null");
@@ -206,6 +225,22 @@ public final class VcnConfig implements Parcelable {
return this; return this;
} }
/**
* Restricts this VcnConfig to matching with test networks (only).
*
* <p>This method is for testing only, and must not be used by apps. Calling {@link
* VcnManager#setVcnConfig(ParcelUuid, VcnConfig)} with a VcnConfig where test-network usage
* is enabled will require the MANAGE_TEST_NETWORKS permission.
*
* @return this {@link Builder} instance, for chaining
* @hide
*/
@NonNull
public Builder setIsTestModeProfile() {
mIsTestModeProfile = true;
return this;
}
/** /**
* Builds and validates the VcnConfig. * Builds and validates the VcnConfig.
* *
@@ -213,7 +248,7 @@ public final class VcnConfig implements Parcelable {
*/ */
@NonNull @NonNull
public VcnConfig build() { public VcnConfig build() {
return new VcnConfig(mPackageName, mGatewayConnectionConfigs); return new VcnConfig(mPackageName, mGatewayConnectionConfigs, mIsTestModeProfile);
} }
} }
} }

View File

@@ -15,6 +15,8 @@
*/ */
package android.net.vcn; package android.net.vcn;
import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
import static com.android.internal.annotations.VisibleForTesting.Visibility; import static com.android.internal.annotations.VisibleForTesting.Visibility;
import android.annotation.IntDef; import android.annotation.IntDef;
@@ -433,6 +435,8 @@ public final class VcnGatewayConnectionConfig {
* distinguish between VcnGatewayConnectionConfigs configured on a single {@link * distinguish between VcnGatewayConnectionConfigs configured on a single {@link
* VcnConfig}. This will be used as the identifier in VcnStatusCallback invocations. * VcnConfig}. This will be used as the identifier in VcnStatusCallback invocations.
* @param tunnelConnectionParams the IKE tunnel connection configuration * @param tunnelConnectionParams the IKE tunnel connection configuration
* @throws IllegalArgumentException if the provided IkeTunnelConnectionParams is not
* configured to support MOBIKE
* @see IkeTunnelConnectionParams * @see IkeTunnelConnectionParams
* @see VcnManager.VcnStatusCallback#onGatewayConnectionError * @see VcnManager.VcnStatusCallback#onGatewayConnectionError
*/ */
@@ -441,6 +445,10 @@ public final class VcnGatewayConnectionConfig {
@NonNull IkeTunnelConnectionParams tunnelConnectionParams) { @NonNull IkeTunnelConnectionParams tunnelConnectionParams) {
Objects.requireNonNull(gatewayConnectionName, "gatewayConnectionName was null"); Objects.requireNonNull(gatewayConnectionName, "gatewayConnectionName was null");
Objects.requireNonNull(tunnelConnectionParams, "tunnelConnectionParams was null"); Objects.requireNonNull(tunnelConnectionParams, "tunnelConnectionParams was null");
if (!tunnelConnectionParams.getIkeSessionParams().hasIkeOption(IKE_OPTION_MOBIKE)) {
throw new IllegalArgumentException(
"MOBIKE must be configured for the provided IkeSessionParams");
}
mGatewayConnectionName = gatewayConnectionName; mGatewayConnectionName = gatewayConnectionName;
mTunnelConnectionParams = tunnelConnectionParams; mTunnelConnectionParams = tunnelConnectionParams;

View File

@@ -167,7 +167,6 @@ public class VcnManagementService extends IVcnManagementService.Stub {
@NonNull private final VcnNetworkProvider mNetworkProvider; @NonNull private final VcnNetworkProvider mNetworkProvider;
@NonNull private final TelephonySubscriptionTrackerCallback mTelephonySubscriptionTrackerCb; @NonNull private final TelephonySubscriptionTrackerCallback mTelephonySubscriptionTrackerCb;
@NonNull private final TelephonySubscriptionTracker mTelephonySubscriptionTracker; @NonNull private final TelephonySubscriptionTracker mTelephonySubscriptionTracker;
@NonNull private final VcnContext mVcnContext;
@NonNull private final BroadcastReceiver mPkgChangeReceiver; @NonNull private final BroadcastReceiver mPkgChangeReceiver;
@NonNull @NonNull
@@ -212,7 +211,6 @@ public class VcnManagementService extends IVcnManagementService.Stub {
mContext, mLooper, mTelephonySubscriptionTrackerCb); mContext, mLooper, mTelephonySubscriptionTrackerCb);
mConfigDiskRwHelper = mDeps.newPersistableBundleLockingReadWriteHelper(VCN_CONFIG_FILE); mConfigDiskRwHelper = mDeps.newPersistableBundleLockingReadWriteHelper(VCN_CONFIG_FILE);
mVcnContext = mDeps.newVcnContext(mContext, mLooper, mNetworkProvider);
mPkgChangeReceiver = new BroadcastReceiver() { mPkgChangeReceiver = new BroadcastReceiver() {
@Override @Override
@@ -336,8 +334,9 @@ public class VcnManagementService extends IVcnManagementService.Stub {
public VcnContext newVcnContext( public VcnContext newVcnContext(
@NonNull Context context, @NonNull Context context,
@NonNull Looper looper, @NonNull Looper looper,
@NonNull VcnNetworkProvider vcnNetworkProvider) { @NonNull VcnNetworkProvider vcnNetworkProvider,
return new VcnContext(context, looper, vcnNetworkProvider); boolean getIsInTestMode) {
return new VcnContext(context, looper, vcnNetworkProvider, getIsInTestMode);
} }
/** Creates a new Vcn instance using the provided configuration */ /** Creates a new Vcn instance using the provided configuration */
@@ -421,6 +420,14 @@ public class VcnManagementService extends IVcnManagementService.Stub {
"Carrier privilege required for subscription group to set VCN Config"); "Carrier privilege required for subscription group to set VCN Config");
} }
private void enforceManageTestNetworksForTestMode(@NonNull VcnConfig vcnConfig) {
if (vcnConfig.isTestModeProfile()) {
mContext.enforceCallingPermission(
android.Manifest.permission.MANAGE_TEST_NETWORKS,
"Test-mode require the MANAGE_TEST_NETWORKS permission");
}
}
private class VcnSubscriptionTrackerCallback implements TelephonySubscriptionTrackerCallback { private class VcnSubscriptionTrackerCallback implements TelephonySubscriptionTrackerCallback {
/** /**
* Handles subscription group changes, as notified by {@link TelephonySubscriptionTracker} * Handles subscription group changes, as notified by {@link TelephonySubscriptionTracker}
@@ -544,8 +551,11 @@ public class VcnManagementService extends IVcnManagementService.Stub {
final VcnCallbackImpl vcnCallback = new VcnCallbackImpl(subscriptionGroup); final VcnCallbackImpl vcnCallback = new VcnCallbackImpl(subscriptionGroup);
final VcnContext vcnContext =
mDeps.newVcnContext(
mContext, mLooper, mNetworkProvider, config.isTestModeProfile());
final Vcn newInstance = final Vcn newInstance =
mDeps.newVcn(mVcnContext, subscriptionGroup, config, mLastSnapshot, vcnCallback); mDeps.newVcn(vcnContext, subscriptionGroup, config, mLastSnapshot, vcnCallback);
mVcns.put(subscriptionGroup, newInstance); mVcns.put(subscriptionGroup, newInstance);
// Now that a new VCN has started, notify all registered listeners to refresh their // Now that a new VCN has started, notify all registered listeners to refresh their
@@ -589,6 +599,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
mContext.getSystemService(AppOpsManager.class) mContext.getSystemService(AppOpsManager.class)
.checkPackage(mDeps.getBinderCallingUid(), config.getProvisioningPackageName()); .checkPackage(mDeps.getBinderCallingUid(), config.getProvisioningPackageName());
enforceManageTestNetworksForTestMode(config);
enforceCallingUserAndCarrierPrivilege(subscriptionGroup, opPkgName); enforceCallingUserAndCarrierPrivilege(subscriptionGroup, opPkgName);
Binder.withCleanCallingIdentity(() -> { Binder.withCleanCallingIdentity(() -> {

View File

@@ -158,8 +158,15 @@ public class UnderlyingNetworkTracker {
* carrier owned networks may be selected, as the request specifies only subIds in the VCN's * carrier owned networks may be selected, as the request specifies only subIds in the VCN's
* subscription group, while the VCN networks are excluded by virtue of not having subIds set on * subscription group, while the VCN networks are excluded by virtue of not having subIds set on
* the VCN-exposed networks. * the VCN-exposed networks.
*
* <p>If the VCN that this UnderlyingNetworkTracker belongs to is in test-mode, this will return
* a NetworkRequest that only matches Test Networks.
*/ */
private NetworkRequest getRouteSelectionRequest() { private NetworkRequest getRouteSelectionRequest() {
if (mVcnContext.isInTestMode()) {
return getTestNetworkRequest(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup));
}
return getBaseNetworkRequestBuilder() return getBaseNetworkRequestBuilder()
.setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) .setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
.build(); .build();
@@ -210,6 +217,16 @@ public class UnderlyingNetworkTracker {
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
} }
/** Builds and returns a NetworkRequest for the given subIds to match Test Networks. */
private NetworkRequest getTestNetworkRequest(@NonNull Set<Integer> subIds) {
return getBaseNetworkRequestBuilder()
.addTransportType(NetworkCapabilities.TRANSPORT_TEST)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.setSubscriptionIds(subIds)
.build();
}
/** /**
* Update this UnderlyingNetworkTracker's TelephonySubscriptionSnapshot. * Update this UnderlyingNetworkTracker's TelephonySubscriptionSnapshot.
* *

View File

@@ -31,14 +31,17 @@ public class VcnContext {
@NonNull private final Context mContext; @NonNull private final Context mContext;
@NonNull private final Looper mLooper; @NonNull private final Looper mLooper;
@NonNull private final VcnNetworkProvider mVcnNetworkProvider; @NonNull private final VcnNetworkProvider mVcnNetworkProvider;
private final boolean mIsInTestMode;
public VcnContext( public VcnContext(
@NonNull Context context, @NonNull Context context,
@NonNull Looper looper, @NonNull Looper looper,
@NonNull VcnNetworkProvider vcnNetworkProvider) { @NonNull VcnNetworkProvider vcnNetworkProvider,
boolean isInTestMode) {
mContext = Objects.requireNonNull(context, "Missing context"); mContext = Objects.requireNonNull(context, "Missing context");
mLooper = Objects.requireNonNull(looper, "Missing looper"); mLooper = Objects.requireNonNull(looper, "Missing looper");
mVcnNetworkProvider = Objects.requireNonNull(vcnNetworkProvider, "Missing networkProvider"); mVcnNetworkProvider = Objects.requireNonNull(vcnNetworkProvider, "Missing networkProvider");
mIsInTestMode = isInTestMode;
} }
@NonNull @NonNull
@@ -56,6 +59,10 @@ public class VcnContext {
return mVcnNetworkProvider; return mVcnNetworkProvider;
} }
public boolean isInTestMode() {
return mIsInTestMode;
}
/** /**
* Verifies that the caller is running on the VcnContext Thread. * Verifies that the caller is running on the VcnContext Thread.
* *

View File

@@ -16,13 +16,17 @@
package android.net.vcn; package android.net.vcn;
import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.IkeTunnelConnectionParams; import android.net.ipsec.ike.IkeTunnelConnectionParams;
import android.net.vcn.persistablebundleutils.IkeSessionParamsUtilsTest;
import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtilsTest; import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtilsTest;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -119,6 +123,21 @@ public class VcnGatewayConnectionConfigTest {
} }
} }
@Test
public void testBuilderRequiresMobikeEnabled() {
try {
final IkeSessionParams ikeParams =
IkeSessionParamsUtilsTest.createBuilderMinimum()
.removeIkeOption(IKE_OPTION_MOBIKE)
.build();
final IkeTunnelConnectionParams tunnelParams =
TunnelConnectionParamsUtilsTest.buildTestParams(ikeParams);
new VcnGatewayConnectionConfig.Builder(GATEWAY_CONNECTION_NAME_PREFIX, tunnelParams);
fail("Expected exception due to MOBIKE not enabled");
} catch (IllegalArgumentException e) {
}
}
@Test @Test
public void testBuilderRequiresNonEmptyExposedCaps() { public void testBuilderRequiresNonEmptyExposedCaps() {
try { try {

View File

@@ -52,8 +52,8 @@ import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest
public class IkeSessionParamsUtilsTest { public class IkeSessionParamsUtilsTest {
// Package private for use in EncryptedTunnelParamsUtilsTest // Public for use in VcnGatewayConnectionConfigTest, EncryptedTunnelParamsUtilsTest
static IkeSessionParams.Builder createBuilderMinimum() { public static IkeSessionParams.Builder createBuilderMinimum() {
final InetAddress serverAddress = InetAddresses.parseNumericAddress("192.0.2.100"); final InetAddress serverAddress = InetAddresses.parseNumericAddress("192.0.2.100");
// TODO: b/185941731 Make sure all valid IKE_OPTIONS are added and validated. // TODO: b/185941731 Make sure all valid IKE_OPTIONS are added and validated.
@@ -63,6 +63,7 @@ public class IkeSessionParamsUtilsTest {
.setLocalIdentification(new IkeFqdnIdentification("client.test.android.net")) .setLocalIdentification(new IkeFqdnIdentification("client.test.android.net"))
.setRemoteIdentification(new IkeFqdnIdentification("server.test.android.net")) .setRemoteIdentification(new IkeFqdnIdentification("server.test.android.net"))
.addIkeOption(IkeSessionParams.IKE_OPTION_FORCE_PORT_4500) .addIkeOption(IkeSessionParams.IKE_OPTION_FORCE_PORT_4500)
.addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE)
.setAuthPsk("psk".getBytes()); .setAuthPsk("psk".getBytes());
} }

View File

@@ -18,6 +18,7 @@ package android.net.vcn.persistablebundleutils;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.IkeTunnelConnectionParams; import android.net.ipsec.ike.IkeTunnelConnectionParams;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -31,9 +32,13 @@ import org.junit.runner.RunWith;
public class TunnelConnectionParamsUtilsTest { public class TunnelConnectionParamsUtilsTest {
// Public for use in VcnGatewayConnectionConfigTest // Public for use in VcnGatewayConnectionConfigTest
public static IkeTunnelConnectionParams buildTestParams() { public static IkeTunnelConnectionParams buildTestParams() {
return buildTestParams(IkeSessionParamsUtilsTest.createBuilderMinimum().build());
}
// Public for use in VcnGatewayConnectionConfigTest
public static IkeTunnelConnectionParams buildTestParams(IkeSessionParams params) {
return new IkeTunnelConnectionParams( return new IkeTunnelConnectionParams(
IkeSessionParamsUtilsTest.createBuilderMinimum().build(), params, TunnelModeChildSessionParamsUtilsTest.createBuilderMinimum().build());
TunnelModeChildSessionParamsUtilsTest.createBuilderMinimum().build());
} }
@Test @Test

View File

@@ -37,6 +37,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.CALLS_REAL_METHODS;
@@ -66,6 +67,7 @@ import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig; import android.net.vcn.VcnConfig;
import android.net.vcn.VcnConfigTest; import android.net.vcn.VcnConfigTest;
import android.net.vcn.VcnGatewayConnectionConfigTest;
import android.net.vcn.VcnManager; import android.net.vcn.VcnManager;
import android.net.vcn.VcnUnderlyingNetworkPolicy; import android.net.vcn.VcnUnderlyingNetworkPolicy;
import android.os.IBinder; import android.os.IBinder;
@@ -197,7 +199,8 @@ public class VcnManagementServiceTest {
.newVcnContext( .newVcnContext(
eq(mMockContext), eq(mMockContext),
eq(mTestLooper.getLooper()), eq(mTestLooper.getLooper()),
any(VcnNetworkProvider.class)); any(VcnNetworkProvider.class),
anyBoolean());
doReturn(mSubscriptionTracker) doReturn(mSubscriptionTracker)
.when(mMockDeps) .when(mMockDeps)
.newTelephonySubscriptionTracker( .newTelephonySubscriptionTracker(
@@ -370,6 +373,12 @@ public class VcnManagementServiceTest {
public void testTelephonyNetworkTrackerCallbackStartsInstances() throws Exception { public void testTelephonyNetworkTrackerCallbackStartsInstances() throws Exception {
TelephonySubscriptionSnapshot snapshot = TelephonySubscriptionSnapshot snapshot =
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1)); triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
verify(mMockDeps)
.newVcnContext(
eq(mMockContext),
eq(mTestLooper.getLooper()),
any(VcnNetworkProvider.class),
anyBoolean());
verify(mMockDeps) verify(mMockDeps)
.newVcn(eq(mVcnContext), eq(TEST_UUID_1), eq(TEST_VCN_CONFIG), eq(snapshot), any()); .newVcn(eq(mVcnContext), eq(TEST_UUID_1), eq(TEST_VCN_CONFIG), eq(snapshot), any());
} }
@@ -527,6 +536,28 @@ public class VcnManagementServiceTest {
verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
} }
@Test
public void testSetVcnConfigTestModeRequiresPermission() throws Exception {
doThrow(new SecurityException("Requires MANAGE_TEST_NETWORKS"))
.when(mMockContext)
.enforceCallingPermission(
eq(android.Manifest.permission.MANAGE_TEST_NETWORKS), any());
final VcnConfig vcnConfig =
new VcnConfig.Builder(mMockContext)
.addGatewayConnectionConfig(
VcnGatewayConnectionConfigTest.buildTestConfig())
.setIsTestModeProfile()
.build();
try {
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, vcnConfig, TEST_PACKAGE_NAME);
fail("Expected exception due to using test-mode without permission");
} catch (SecurityException e) {
verify(mMockPolicyListener, never()).onPolicyChanged();
}
}
@Test @Test
public void testSetVcnConfigNotifiesStatusCallback() throws Exception { public void testSetVcnConfigNotifiesStatusCallback() throws Exception {
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_2)); triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_2));

View File

@@ -26,6 +26,7 @@ import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.eq; import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -112,8 +113,14 @@ public class UnderlyingNetworkTrackerTest {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mTestLooper = new TestLooper(); mTestLooper = new TestLooper();
mVcnContext = spy(new VcnContext(mContext, mTestLooper.getLooper(), mVcnNetworkProvider)); mVcnContext =
doNothing().when(mVcnContext).ensureRunningOnLooperThread(); spy(
new VcnContext(
mContext,
mTestLooper.getLooper(),
mVcnNetworkProvider,
false /* isInTestMode */));
resetVcnContext();
setupSystemService( setupSystemService(
mContext, mContext,
@@ -132,6 +139,11 @@ public class UnderlyingNetworkTrackerTest {
mNetworkTrackerCb); mNetworkTrackerCb);
} }
private void resetVcnContext() {
reset(mVcnContext);
doNothing().when(mVcnContext).ensureRunningOnLooperThread();
}
private static LinkProperties getLinkPropertiesWithName(String iface) { private static LinkProperties getLinkPropertiesWithName(String iface) {
LinkProperties linkProperties = new LinkProperties(); LinkProperties linkProperties = new LinkProperties();
linkProperties.setInterfaceName(iface); linkProperties.setInterfaceName(iface);
@@ -149,7 +161,29 @@ public class UnderlyingNetworkTrackerTest {
verifyNetworkRequestsRegistered(INITIAL_SUB_IDS); verifyNetworkRequestsRegistered(INITIAL_SUB_IDS);
} }
@Test
public void testNetworkCallbacksRegisteredOnStartupForTestMode() {
resetVcnContext();
when(mVcnContext.isInTestMode()).thenReturn(true);
reset(mConnectivityManager);
mUnderlyingNetworkTracker =
new UnderlyingNetworkTracker(
mVcnContext,
SUB_GROUP,
mSubscriptionSnapshot,
Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET),
mNetworkTrackerCb);
verifyNetworkRequestsRegistered(INITIAL_SUB_IDS, true /* expectTestMode */);
}
private void verifyNetworkRequestsRegistered(Set<Integer> expectedSubIds) { private void verifyNetworkRequestsRegistered(Set<Integer> expectedSubIds) {
verifyNetworkRequestsRegistered(expectedSubIds, false /* expectTestMode */);
}
private void verifyNetworkRequestsRegistered(
Set<Integer> expectedSubIds, boolean expectTestMode) {
verify(mConnectivityManager) verify(mConnectivityManager)
.requestBackgroundNetwork( .requestBackgroundNetwork(
eq(getWifiRequest(expectedSubIds)), eq(getWifiRequest(expectedSubIds)),
@@ -162,10 +196,16 @@ public class UnderlyingNetworkTrackerTest {
any(NetworkBringupCallback.class), any()); any(NetworkBringupCallback.class), any());
} }
final NetworkRequest expectedRouteSelectionRequest =
expectTestMode
? getTestNetworkRequest(expectedSubIds)
: getRouteSelectionRequest(expectedSubIds);
verify(mConnectivityManager) verify(mConnectivityManager)
.requestBackgroundNetwork( .requestBackgroundNetwork(
eq(getRouteSelectionRequest(expectedSubIds)), eq(expectedRouteSelectionRequest),
any(RouteSelectionCallback.class), any()); any(RouteSelectionCallback.class),
any());
} }
@Test @Test
@@ -204,6 +244,15 @@ public class UnderlyingNetworkTrackerTest {
return getExpectedRequestBase().setSubscriptionIds(netCapsSubIds).build(); return getExpectedRequestBase().setSubscriptionIds(netCapsSubIds).build();
} }
private NetworkRequest getTestNetworkRequest(Set<Integer> netCapsSubIds) {
return getExpectedRequestBase()
.addTransportType(NetworkCapabilities.TRANSPORT_TEST)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.setSubscriptionIds(netCapsSubIds)
.build();
}
private NetworkRequest.Builder getExpectedRequestBase() { private NetworkRequest.Builder getExpectedRequestBase() {
final NetworkRequest.Builder builder = final NetworkRequest.Builder builder =
new NetworkRequest.Builder() new NetworkRequest.Builder()