Merge "Allow VPN network agent to exclude local traffic" am: a7b3d00968

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1927018

Change-Id: Ie569c72d63ce866b08bd6ccb18f7b0ef1437f6d3
This commit is contained in:
Chiachang Wang
2021-12-28 07:57:44 +00:00
committed by Automerger Merge Worker
3 changed files with 62 additions and 6 deletions

View File

@@ -232,6 +232,20 @@ public final class NetworkAgentConfig implements Parcelable {
return mLegacyExtraInfo; return mLegacyExtraInfo;
} }
/**
* If the {@link Network} is a VPN, whether the local traffic is exempted from the VPN.
* @hide
*/
public boolean excludeLocalRouteVpn = false;
/**
* @return whether local traffic is excluded from the VPN network.
* @hide
*/
public boolean getExcludeLocalRouteVpn() {
return excludeLocalRouteVpn;
}
/** @hide */ /** @hide */
public NetworkAgentConfig() { public NetworkAgentConfig() {
} }
@@ -251,6 +265,7 @@ public final class NetworkAgentConfig implements Parcelable {
legacySubType = nac.legacySubType; legacySubType = nac.legacySubType;
legacySubTypeName = nac.legacySubTypeName; legacySubTypeName = nac.legacySubTypeName;
mLegacyExtraInfo = nac.mLegacyExtraInfo; mLegacyExtraInfo = nac.mLegacyExtraInfo;
excludeLocalRouteVpn = nac.excludeLocalRouteVpn;
} }
} }
@@ -406,6 +421,17 @@ public final class NetworkAgentConfig implements Parcelable {
return this; return this;
} }
/**
* Sets whether the local traffic is exempted from VPN.
*
* @return this builder, to facilitate chaining.
* @hide TODO(184750836): Unhide once the implementation is completed.
*/
public Builder setExcludeLocalRoutesVpn(boolean excludeLocalRoutes) {
mConfig.excludeLocalRouteVpn = excludeLocalRoutes;
return this;
}
/** /**
* Returns the constructed {@link NetworkAgentConfig} object. * Returns the constructed {@link NetworkAgentConfig} object.
*/ */
@@ -429,14 +455,15 @@ public final class NetworkAgentConfig implements Parcelable {
&& legacyType == that.legacyType && legacyType == that.legacyType
&& Objects.equals(subscriberId, that.subscriberId) && Objects.equals(subscriberId, that.subscriberId)
&& Objects.equals(legacyTypeName, that.legacyTypeName) && Objects.equals(legacyTypeName, that.legacyTypeName)
&& Objects.equals(mLegacyExtraInfo, that.mLegacyExtraInfo); && Objects.equals(mLegacyExtraInfo, that.mLegacyExtraInfo)
&& excludeLocalRouteVpn == that.excludeLocalRouteVpn;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated, return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated,
acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId, acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId,
skip464xlat, legacyType, legacyTypeName, mLegacyExtraInfo); skip464xlat, legacyType, legacyTypeName, mLegacyExtraInfo, excludeLocalRouteVpn);
} }
@Override @Override
@@ -453,6 +480,7 @@ public final class NetworkAgentConfig implements Parcelable {
+ ", hasShownBroken = " + hasShownBroken + ", hasShownBroken = " + hasShownBroken
+ ", legacyTypeName = '" + legacyTypeName + '\'' + ", legacyTypeName = '" + legacyTypeName + '\''
+ ", legacyExtraInfo = '" + mLegacyExtraInfo + '\'' + ", legacyExtraInfo = '" + mLegacyExtraInfo + '\''
+ ", excludeLocalRouteVpn = '" + excludeLocalRouteVpn + '\''
+ "}"; + "}";
} }
@@ -475,6 +503,7 @@ public final class NetworkAgentConfig implements Parcelable {
out.writeInt(legacySubType); out.writeInt(legacySubType);
out.writeString(legacySubTypeName); out.writeString(legacySubTypeName);
out.writeString(mLegacyExtraInfo); out.writeString(mLegacyExtraInfo);
out.writeInt(excludeLocalRouteVpn ? 1 : 0);
} }
public static final @NonNull Creator<NetworkAgentConfig> CREATOR = public static final @NonNull Creator<NetworkAgentConfig> CREATOR =
@@ -494,6 +523,7 @@ public final class NetworkAgentConfig implements Parcelable {
networkAgentConfig.legacySubType = in.readInt(); networkAgentConfig.legacySubType = in.readInt();
networkAgentConfig.legacySubTypeName = in.readString(); networkAgentConfig.legacySubTypeName = in.readString();
networkAgentConfig.mLegacyExtraInfo = in.readString(); networkAgentConfig.mLegacyExtraInfo = in.readString();
networkAgentConfig.excludeLocalRouteVpn = in.readInt() != 0;
return networkAgentConfig; return networkAgentConfig;
} }

View File

@@ -48,9 +48,16 @@ class NetworkAgentConfigTest {
setBypassableVpn(true) setBypassableVpn(true)
} }
}.build() }.build()
// This test can be run as unit test against the latest system image, as CTS to verify
// an Android release that is as recent as the test, or as MTS to verify the
// Connectivity module. In the first two cases NetworkAgentConfig will be as recent
// as the test. In the last case, starting from S NetworkAgentConfig is updated as part
// of Connectivity, so it is also as recent as the test. For MTS on Q and R,
// NetworkAgentConfig is not updatable, so it may have a different number of fields.
if (isAtLeastS()) { if (isAtLeastS()) {
// From S, the config will have 12 items // When this test is run on S+, NetworkAgentConfig is as recent as the test,
assertParcelSane(config, 12) // so this should be the most recent known number of fields.
assertParcelSane(config, 13)
} else { } else {
// For R or below, the config will have 10 items // For R or below, the config will have 10 items
assertParcelSane(config, 10) assertParcelSane(config, 10)

View File

@@ -16,6 +16,7 @@
package com.android.internal.net; package com.android.internal.net;
import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
import static com.android.testutils.ParcelUtils.assertParcelSane; import static com.android.testutils.ParcelUtils.assertParcelSane;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@@ -48,6 +49,7 @@ public class VpnProfileTest {
private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23; private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23;
private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24; private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24;
private static final int ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE = 25;
@Test @Test
public void testDefaults() throws Exception { public void testDefaults() throws Exception {
@@ -126,8 +128,13 @@ public class VpnProfileTest {
@Test @Test
public void testParcelUnparcel() { public void testParcelUnparcel() {
if (isAtLeastT()) {
// excludeLocalRoutes is added in T.
assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 24);
} else {
assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23); assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23);
} }
}
@Test @Test
public void testEncodeDecode() { public void testEncodeDecode() {
@@ -166,7 +173,8 @@ public class VpnProfileTest {
final String tooFewValues = final String tooFewValues =
getEncodedDecodedIkev2ProfileMissingValues( getEncodedDecodedIkev2ProfileMissingValues(
ENCODED_INDEX_AUTH_PARAMS_INLINE, ENCODED_INDEX_AUTH_PARAMS_INLINE,
ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */); ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS,
ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE /* missingIndices */);
assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes())); assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()));
} }
@@ -182,6 +190,17 @@ public class VpnProfileTest {
assertFalse(decoded.isRestrictedToTestNetworks); assertFalse(decoded.isRestrictedToTestNetworks);
} }
@Test
public void testEncodeDecodeMissingExcludeLocalRoutes() {
final String tooFewValues =
getEncodedDecodedIkev2ProfileMissingValues(
ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE /* missingIndices */);
// Verify decoding without isRestrictedToTestNetworks defaults to false
final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
assertFalse(decoded.excludeLocalRoutes);
}
@Test @Test
public void testEncodeDecodeLoginsNotSaved() { public void testEncodeDecodeLoginsNotSaved() {
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY); final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);