Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e98c9815 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Convert VcnNetworkProvider to use NetworkOffers"

parents e6510baf 705021aa
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -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<>();
+1 −2
Original line number Diff line number Diff line
@@ -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(),
+87 −6
Original line number Diff line number Diff line
@@ -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);
        }
    }
}
+46 −5
Original line number Diff line number Diff line
@@ -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) {