Convert VcnNetworkProvider to use NetworkOffers
This change brings VcnNetworkProvider to full functionality in the new NetworkProvider paradigm, where NetworkProviders offer networks, and are notified based on NetworkOfferCallbacks. Bug: 185204197 Test: atest FrameworksVcnTests Change-Id: I88c69c0be9f6fd81839fb1595ed00341001694a5 Merged-In: I88c69c0be9f6fd81839fb1595ed00341001694a5
This commit is contained in:
@@ -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<>();
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user