Loading core/java/android/net/vcn/VcnGatewayConnectionConfig.java +6 −1 Original line number Diff line number Diff line Loading @@ -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<>(); Loading services/core/java/com/android/server/VcnManagementService.java +1 −2 Original line number Diff line number Diff line Loading @@ -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(), Loading services/core/java/com/android/server/vcn/VcnNetworkProvider.java +87 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading @@ -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). * Loading @@ -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(); } /** Loading Loading @@ -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); } Loading @@ -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); } Loading Loading @@ -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); } } } tests/vcn/java/com/android/server/vcn/VcnNetworkProviderTest.java +46 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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); } Loading @@ -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 Loading @@ -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) { Loading Loading
core/java/android/net/vcn/VcnGatewayConnectionConfig.java +6 −1 Original line number Diff line number Diff line Loading @@ -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<>(); Loading
services/core/java/com/android/server/VcnManagementService.java +1 −2 Original line number Diff line number Diff line Loading @@ -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(), Loading
services/core/java/com/android/server/vcn/VcnNetworkProvider.java +87 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading @@ -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). * Loading @@ -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(); } /** Loading Loading @@ -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); } Loading @@ -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); } Loading Loading @@ -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); } } }
tests/vcn/java/com/android/server/vcn/VcnNetworkProviderTest.java +46 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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); } Loading @@ -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 Loading @@ -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) { Loading