From b5244fbceb18de98df509a60fa36239ad8a56553 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 8 Mar 2021 11:31:59 -0800 Subject: [PATCH 1/4] Remove usage of hidden Connectivity APIs This removes one use of NetworkRequest.requestId, and the usage of the NetCapability intdef Bug: 170598012 Test: atest FrameworksVcnTests Change-Id: I6b688b008721bc9f5cb1435f2e7096277a12dc45 --- .../java/com/android/server/vcn/UnderlyingNetworkTracker.java | 3 +-- services/core/java/com/android/server/vcn/Vcn.java | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java index b2db9f5af07ec..754065920bcff 100644 --- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java +++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java @@ -23,7 +23,6 @@ import android.net.ConnectivityManager.NetworkCallback; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; -import android.net.NetworkCapabilities.NetCapability; import android.net.NetworkRequest; import android.net.TelephonyNetworkSpecifier; import android.os.Handler; @@ -133,7 +132,7 @@ public class UnderlyingNetworkTracker { private NetworkRequest.Builder getNetworkRequestBase() { NetworkRequest.Builder requestBase = new NetworkRequest.Builder(); - for (@NetCapability int capability : mRequiredUnderlyingNetworkCapabilities) { + for (int capability : mRequiredUnderlyingNetworkCapabilities) { requestBase.addCapability(capability); } diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java index 9d39c67d27fbc..e83fe802e17f6 100644 --- a/services/core/java/com/android/server/vcn/Vcn.java +++ b/services/core/java/com/android/server/vcn/Vcn.java @@ -291,9 +291,7 @@ public class Vcn extends Handler { for (VcnGatewayConnectionConfig gatewayConnectionConfig : mConfig.getGatewayConnectionConfigs()) { if (isRequestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) { - Slog.v( - getLogTag(), - "Bringing up new VcnGatewayConnection for request " + request.requestId); + Slog.v(getLogTag(), "Bringing up new VcnGatewayConnection for request " + request); final VcnGatewayConnection vcnGatewayConnection = mDeps.newVcnGatewayConnection( From 033a4308cedac48e4598e5ec843012c591a0feed Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 8 Mar 2021 11:36:46 -0800 Subject: [PATCH 2/4] Override network and use config IKE session This change ensures the IKE configs are used with the correct network Bug: 163604823 Test: FrameworksVcnTests Change-Id: Ieb2a9b202204577f6e6969ef30245baed6382aa6 --- .../server/vcn/VcnGatewayConnection.java | 23 ++++++++++++------- ...cnGatewayConnectionConnectedStateTest.java | 2 +- ...nGatewayConnectionConnectingStateTest.java | 10 +++++++- ...tewayConnectionDisconnectingStateTest.java | 3 ++- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index 6bc9978a0731f..803191e43e324 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -59,6 +59,7 @@ import android.net.ipsec.ike.exceptions.AuthenticationFailedException; import android.net.ipsec.ike.exceptions.IkeException; import android.net.ipsec.ike.exceptions.IkeInternalException; import android.net.ipsec.ike.exceptions.IkeProtocolException; +import android.net.vcn.VcnControlPlaneIkeConfig; import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnTransportInfo; import android.net.wifi.WifiInfo; @@ -1348,7 +1349,7 @@ public class VcnGatewayConnection extends StateMachine { mIkeSession = null; } - mIkeSession = buildIkeSession(); + mIkeSession = buildIkeSession(mUnderlying.network); } @Override @@ -1939,23 +1940,29 @@ public class VcnGatewayConnection extends StateMachine { new EventDisconnectRequestedInfo(reason, shouldQuit)); } - private IkeSessionParams buildIkeParams() { - // TODO: Implement this once IkeSessionParams is persisted - return null; + private IkeSessionParams buildIkeParams(@NonNull Network network) { + final VcnControlPlaneIkeConfig controlPlaneConfig = + (VcnControlPlaneIkeConfig) mConnectionConfig.getControlPlaneConfig(); + final IkeSessionParams.Builder builder = + new IkeSessionParams.Builder(controlPlaneConfig.getIkeSessionParams()); + builder.setConfiguredNetwork(network); + + return builder.build(); } private ChildSessionParams buildChildParams() { - // TODO: Implement this once IkeSessionParams is persisted - return null; + final VcnControlPlaneIkeConfig controlPlaneConfig = + (VcnControlPlaneIkeConfig) mConnectionConfig.getControlPlaneConfig(); + return controlPlaneConfig.getChildSessionParams(); } @VisibleForTesting(visibility = Visibility.PRIVATE) - VcnIkeSession buildIkeSession() { + VcnIkeSession buildIkeSession(@NonNull Network network) { final int token = ++mCurrentToken; return mDeps.newIkeSession( mVcnContext, - buildIkeParams(), + buildIkeParams(network), buildChildParams(), new IkeSessionCallbackImpl(token), new VcnChildSessionCallback(token)); diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index 69b2fb135a8df..bfa869edf06e2 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -73,7 +73,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection mGatewayConnection.setUnderlyingNetwork(TEST_UNDERLYING_NETWORK_RECORD_1); - mIkeSession = mGatewayConnection.buildIkeSession(); + mIkeSession = mGatewayConnection.buildIkeSession(TEST_UNDERLYING_NETWORK_RECORD_1.network); mGatewayConnection.setIkeSession(mIkeSession); mGatewayConnection.transitionTo(mGatewayConnection.mConnectedState); diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java index d07d2cf4f1bbb..7afa4494ee8b4 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java @@ -25,12 +25,15 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import android.net.ipsec.ike.IkeSessionParams; + import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; /** Tests for VcnGatewayConnection.ConnectingState */ @RunWith(AndroidJUnit4.class) @@ -51,7 +54,12 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio @Test public void testEnterStateCreatesNewIkeSession() throws Exception { - verify(mDeps).newIkeSession(any(), any(), any(), any(), any()); + final ArgumentCaptor paramsCaptor = + ArgumentCaptor.forClass(IkeSessionParams.class); + verify(mDeps).newIkeSession(any(), paramsCaptor.capture(), any(), any(), any()); + assertEquals( + TEST_UNDERLYING_NETWORK_RECORD_1.network, + paramsCaptor.getValue().getConfiguredNetwork()); } @Test diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java index 661e03af4f840..99feffdebc8e3 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java @@ -38,7 +38,8 @@ public class VcnGatewayConnectionDisconnectingStateTest extends VcnGatewayConnec public void setUp() throws Exception { super.setUp(); - mGatewayConnection.setIkeSession(mGatewayConnection.buildIkeSession()); + mGatewayConnection.setIkeSession( + mGatewayConnection.buildIkeSession(TEST_UNDERLYING_NETWORK_RECORD_2.network)); // ensure that mGatewayConnection has an underlying Network before entering // DisconnectingState From dc1efbb3b21c179a607c94d1dded31d73aed4cb4 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 8 Mar 2021 15:26:58 -0800 Subject: [PATCH 3/4] Allow underlying cell without unwanted NOT_VCN_MANAGED capability This change updates the UnderlyingNetworkTracker to rely on the TelephonyNetworkSpecifier for selecting underlying networks. This ensures that there is always a cellular NetworkRequest filed for Cellular to bring up an underlying Network. Bug: 182211364 Test: FrameworksVcnTests Change-Id: I826711bb671440054c2090793315a5f1d57596c0 --- .../server/vcn/UnderlyingNetworkTracker.java | 50 +++++++++++++++---- .../vcn/UnderlyingNetworkTrackerTest.java | 26 ++++++---- 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java index 754065920bcff..8dcc547508ec2 100644 --- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java +++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java @@ -114,33 +114,61 @@ public class UnderlyingNetworkTracker { getWifiNetworkRequest(), mHandler, mWifiBringupCallback); updateSubIdsAndCellularRequests(); - // register Network-selection request used to decide selected underlying Network + // Register Network-selection request used to decide selected underlying Network. All + // underlying networks must be VCN managed in order to be used. mConnectivityManager.requestBackgroundNetwork( - getNetworkRequestBase().build(), mHandler, mRouteSelectionCallback); + getBaseNetworkRequest(true /* requireVcnManaged */).build(), + mHandler, + mRouteSelectionCallback); } private NetworkRequest getWifiNetworkRequest() { - return getNetworkRequestBase().addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build(); + // Request exclusively VCN managed networks to ensure that we only ever keep carrier wifi + // alive. + return getBaseNetworkRequest(true /* requireVcnManaged */) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .build(); } private NetworkRequest getCellNetworkRequestForSubId(int subId) { - return getNetworkRequestBase() + // Do not request NOT_VCN_MANAGED to ensure that the TelephonyNetworkFactory has a + // fulfillable request to bring up underlying cellular Networks even if the VCN is already + // connected. + return getBaseNetworkRequest(false /* requireVcnManaged */) .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .setNetworkSpecifier(new TelephonyNetworkSpecifier(subId)) .build(); } - private NetworkRequest.Builder getNetworkRequestBase() { - NetworkRequest.Builder requestBase = new NetworkRequest.Builder(); + /** + * Builds and returns a NetworkRequest builder common to all Underlying Network requests + * + *

A NetworkRequest may either (1) Require the presence of a capability by using + * addCapability(), (2) require the absence of a capability using unwanted capabilities, or (3) + * allow any state. Underlying networks are never desired to have the NOT_VCN_MANAGED + * capability, and only cases (2) and (3) are used. + * + * @param requireVcnManaged whether the underlying network is required to be VCN managed to + * match this request. If {@code true}, the NOT_VCN_MANAGED capability will be set as + * unwanted. Else, the NOT_VCN_MANAGED capability will be removed, and any state is + * acceptable. + */ + private NetworkRequest.Builder getBaseNetworkRequest(boolean requireVcnManaged) { + NetworkRequest.Builder requestBase = + new NetworkRequest.Builder() + .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + for (int capability : mRequiredUnderlyingNetworkCapabilities) { requestBase.addCapability(capability); } - return requestBase - .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) - .addUnwantedCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + if (requireVcnManaged) { + requestBase.addUnwantedCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + } + + return requestBase; } /** diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java index 1d459a3475267..1ef1a61f17ea6 100644 --- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java +++ b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java @@ -194,29 +194,35 @@ public class UnderlyingNetworkTrackerTest { } private NetworkRequest getWifiRequest() { - return getExpectedRequestBase() + return getExpectedRequestBase(true) .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .build(); } private NetworkRequest getCellRequestForSubId(int subId) { - return getExpectedRequestBase() + return getExpectedRequestBase(false) .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .setNetworkSpecifier(new TelephonyNetworkSpecifier(subId)) .build(); } private NetworkRequest getRouteSelectionRequest() { - return getExpectedRequestBase().build(); + return getExpectedRequestBase(true).build(); } - private NetworkRequest.Builder getExpectedRequestBase() { - return new NetworkRequest.Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) - .addUnwantedCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + private NetworkRequest.Builder getExpectedRequestBase(boolean requireVcnManaged) { + final NetworkRequest.Builder builder = + new NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) + .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + + if (requireVcnManaged) { + builder.addUnwantedCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + } + + return builder; } @Test From de1f0c3edbe8f1f051f5ecdcb3f70297e3221b41 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 8 Mar 2021 16:08:41 -0800 Subject: [PATCH 4/4] Declare VCN exposed networks as NOT_VCN_MANAGED This change marks VCN-exposed networks as generic use, NOT_VCN_MANAGED networks. This is the result of changes to the default NetworkCapability set, where NOT_VCN_MANAGED was removed from the default capabilities. Bug: 182212201 Test: atest FrameworksVcnTests Change-Id: Iad296830201d7317537fac6bea53c79d4e41cae3 --- .../core/java/com/android/server/vcn/VcnGatewayConnection.java | 2 ++ .../java/com/android/server/vcn/VcnGatewayConnectionTest.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index 803191e43e324..55b1808a0dd3c 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -20,6 +20,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR; @@ -1727,6 +1728,7 @@ public class VcnGatewayConnection extends StateMachine { final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); builder.addTransportType(TRANSPORT_CELLULAR); + builder.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); builder.addCapability(NET_CAPABILITY_NOT_CONGESTED); builder.addCapability(NET_CAPABILITY_NOT_SUSPENDED); diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java index 748c7924685d9..d08af9dd33708 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java @@ -18,6 +18,7 @@ package com.android.server.vcn; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; @@ -87,6 +88,7 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase { private void verifyBuildNetworkCapabilitiesCommon(int transportType) { final NetworkCapabilities underlyingCaps = new NetworkCapabilities(); underlyingCaps.addTransportType(transportType); + underlyingCaps.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); underlyingCaps.addCapability(NET_CAPABILITY_NOT_METERED); underlyingCaps.addCapability(NET_CAPABILITY_NOT_ROAMING);