Merge "Convert VcnNetworkProvider to use NetworkOffers"

This commit is contained in:
Treehugger Robot
2021-06-16 19:48:58 +00:00
committed by Gerrit Code Review
4 changed files with 140 additions and 14 deletions

View File

@@ -83,7 +83,12 @@ public final class VcnGatewayConnectionConfig {
@VisibleForTesting(visibility = Visibility.PRIVATE)
static final int MIN_MTU_V6 = 1280;
private static final Set<Integer> ALLOWED_CAPABILITIES;
/**
* The set of allowed capabilities for exposed capabilities.
*
* @hide
*/
public static final Set<Integer> ALLOWED_CAPABILITIES;
static {
Set<Integer> allowedCaps = new ArraySet<>();

View File

@@ -372,8 +372,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
/** Notifies the VcnManagementService that external dependencies can be set up. */
public void systemReady() {
mContext.getSystemService(ConnectivityManager.class)
.registerNetworkProvider(mNetworkProvider);
mNetworkProvider.register();
mContext.getSystemService(ConnectivityManager.class)
.registerNetworkCallback(
new NetworkRequest.Builder().clearCapabilities().build(),

View File

@@ -16,12 +16,24 @@
package com.android.server.vcn;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static com.android.server.VcnManagementService.VDBG;
import android.annotation.NonNull;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkProvider;
import android.net.NetworkRequest;
import android.net.NetworkScore;
import android.net.vcn.VcnGatewayConnectionConfig;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
import android.util.ArraySet;
import android.util.Slog;
@@ -30,7 +42,9 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
import com.android.internal.util.IndentingPrintWriter;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
/**
* VCN Network Provider routes NetworkRequests to listeners to bring up tunnels as needed.
@@ -45,6 +59,10 @@ public class VcnNetworkProvider extends NetworkProvider {
private final Set<NetworkRequestListener> mListeners = new ArraySet<>();
private final Context mContext;
private final Handler mHandler;
private final Dependencies mDeps;
/**
* Cache of NetworkRequest(s).
*
@@ -52,8 +70,59 @@ public class VcnNetworkProvider extends NetworkProvider {
*/
private final Set<NetworkRequest> mRequests = new ArraySet<>();
public VcnNetworkProvider(Context context, Looper looper) {
super(context, looper, VcnNetworkProvider.class.getSimpleName());
public VcnNetworkProvider(@NonNull Context context, @NonNull Looper looper) {
this(context, looper, new Dependencies());
}
@VisibleForTesting(visibility = Visibility.PRIVATE)
public VcnNetworkProvider(
@NonNull Context context, @NonNull Looper looper, @NonNull Dependencies dependencies) {
super(
Objects.requireNonNull(context, "Missing context"),
Objects.requireNonNull(looper, "Missing looper"),
TAG);
mContext = context;
mHandler = new Handler(looper);
mDeps = Objects.requireNonNull(dependencies, "Missing dependencies");
}
/** Registers this VcnNetworkProvider and a generic network offer with ConnectivityService. */
public void register() {
mContext.getSystemService(ConnectivityManager.class).registerNetworkProvider(this);
mDeps.registerNetworkOffer(
this,
Vcn.getNetworkScore(), // score filter
buildCapabilityFilter(),
new HandlerExecutor(mHandler),
new NetworkOfferCallback() {
@Override
public void onNetworkNeeded(@NonNull NetworkRequest request) {
handleNetworkRequested(request);
}
@Override
public void onNetworkUnneeded(@NonNull NetworkRequest request) {
handleNetworkRequestWithdrawn(request);
}
});
}
/** Builds the filter for NetworkRequests that can be served by the VcnNetworkProvider. */
private NetworkCapabilities buildCapabilityFilter() {
final NetworkCapabilities.Builder builder =
new NetworkCapabilities.Builder()
.addTransportType(TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_TRUSTED)
.addCapability(NET_CAPABILITY_NOT_RESTRICTED)
.addCapability(NET_CAPABILITY_NOT_VPN)
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
for (int cap : VcnGatewayConnectionConfig.ALLOWED_CAPABILITIES) {
builder.addCapability(cap);
}
return builder.build();
}
/**
@@ -88,8 +157,7 @@ public class VcnNetworkProvider extends NetworkProvider {
listener.onNetworkRequested(request);
}
@Override
public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {
private void handleNetworkRequested(@NonNull NetworkRequest request) {
if (VDBG) {
Slog.v(TAG, "Network requested: Request = " + request);
}
@@ -103,8 +171,7 @@ public class VcnNetworkProvider extends NetworkProvider {
}
}
@Override
public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {
private void handleNetworkRequestWithdrawn(@NonNull NetworkRequest request) {
if (VDBG) {
Slog.v(TAG, "Network request withdrawn: Request = " + request);
}
@@ -144,4 +211,18 @@ public class VcnNetworkProvider extends NetworkProvider {
pw.decreaseIndent();
}
/** Proxy class for dependencies used for testing. */
@VisibleForTesting(visibility = Visibility.PRIVATE)
public static class Dependencies {
/** Registers a given network offer for the given provider. */
public void registerNetworkOffer(
@NonNull VcnNetworkProvider provider,
@NonNull NetworkScore score,
@NonNull NetworkCapabilities capabilitiesFilter,
@NonNull Executor executor,
@NonNull NetworkOfferCallback callback) {
provider.registerNetworkOffer(score, capabilitiesFilter, executor, callback);
}
}
}

View File

@@ -16,12 +16,18 @@
package com.android.server.vcn;
import static android.net.NetworkProvider.NetworkOfferCallback;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.annotation.NonNull;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkRequest;
import android.os.test.TestLooper;
@@ -33,6 +39,7 @@ import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import java.util.ArrayList;
import java.util.List;
@@ -47,6 +54,8 @@ public class VcnNetworkProviderTest {
@NonNull private final Context mContext;
@NonNull private final TestLooper mTestLooper;
@NonNull private VcnNetworkProvider.Dependencies mDeps;
@NonNull private ConnectivityManager mConnMgr;
@NonNull private VcnNetworkProvider mVcnNetworkProvider;
@NonNull private NetworkRequestListener mListener;
@@ -57,16 +66,47 @@ public class VcnNetworkProviderTest {
@Before
public void setUp() throws Exception {
mVcnNetworkProvider = new VcnNetworkProvider(mContext, mTestLooper.getLooper());
mDeps = mock(VcnNetworkProvider.Dependencies.class);
mConnMgr = mock(ConnectivityManager.class);
VcnTestUtils.setupSystemService(
mContext, mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
mVcnNetworkProvider = new VcnNetworkProvider(mContext, mTestLooper.getLooper(), mDeps);
mListener = mock(NetworkRequestListener.class);
}
private NetworkOfferCallback verifyRegisterAndGetOfferCallback() throws Exception {
mVcnNetworkProvider.register();
final ArgumentCaptor<NetworkOfferCallback> cbCaptor =
ArgumentCaptor.forClass(NetworkOfferCallback.class);
verify(mConnMgr).registerNetworkProvider(eq(mVcnNetworkProvider));
verify(mDeps)
.registerNetworkOffer(
eq(mVcnNetworkProvider),
argThat(
score ->
score.getLegacyInt()
== Vcn.getNetworkScore().getLegacyInt()),
any(),
any(),
cbCaptor.capture());
return cbCaptor.getValue();
}
@Test
public void testRegister() throws Exception {
verifyRegisterAndGetOfferCallback();
}
@Test
public void testRequestsPassedToRegisteredListeners() throws Exception {
mVcnNetworkProvider.registerListener(mListener);
final NetworkRequest request = mock(NetworkRequest.class);
mVcnNetworkProvider.onNetworkRequested(request, TEST_SCORE_UNSATISFIED, TEST_PROVIDER_ID);
verifyRegisterAndGetOfferCallback().onNetworkNeeded(request);
verify(mListener).onNetworkRequested(request);
}
@@ -76,13 +116,14 @@ public class VcnNetworkProviderTest {
mVcnNetworkProvider.unregisterListener(mListener);
final NetworkRequest request = mock(NetworkRequest.class);
mVcnNetworkProvider.onNetworkRequested(request, TEST_SCORE_UNSATISFIED, TEST_PROVIDER_ID);
verifyRegisterAndGetOfferCallback().onNetworkNeeded(request);
verifyNoMoreInteractions(mListener);
}
@Test
public void testCachedRequestsPassedOnRegister() throws Exception {
final List<NetworkRequest> requests = new ArrayList<>();
final NetworkOfferCallback offerCb = verifyRegisterAndGetOfferCallback();
for (int i = 0; i < 10; i++) {
// Build unique network requests; in this case, iterate down the capabilities as a way
@@ -91,12 +132,12 @@ public class VcnNetworkProviderTest {
new NetworkRequest.Builder().clearCapabilities().addCapability(i).build();
requests.add(request);
mVcnNetworkProvider.onNetworkRequested(request, i, i + 1);
offerCb.onNetworkNeeded(request);
}
// Remove one, and verify that it is never sent to the listeners.
final NetworkRequest removed = requests.remove(0);
mVcnNetworkProvider.onNetworkRequestWithdrawn(removed);
offerCb.onNetworkUnneeded(removed);
mVcnNetworkProvider.registerListener(mListener);
for (NetworkRequest request : requests) {