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

Commit 65995498 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Convert VcnNetworkProvider to use NetworkOffers" am: e98c9815

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1673238

Change-Id: I8a6ea3d190caf2717b200227e7b16d9fde3f78f8
parents 0d21e173 e98c9815
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) {