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

Commit 73940447 authored by Benedict Wong's avatar Benedict Wong
Browse files

Add utility methods for creation of NetInfo, NetCaps, and LinkProps

This change adds basic utility methods to create network info, network
capabilities and link properties

Bug: 165827287
Test: atest FrameworksVcnTests
Change-Id: I915e0c4e9ca989344b9a4785e200381db0b94fb8
parent aef81edb
Loading
Loading
Loading
Loading
+171 −1
Original line number Diff line number Diff line
@@ -16,30 +16,57 @@

package com.android.server.vcn;

import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;

import static com.android.server.VcnManagementService.VDBG;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.ConnectivityManager;
import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.IpSecManager;
import android.net.IpSecManager.IpSecTunnelInterface;
import android.net.IpSecManager.ResourceUnavailableException;
import android.net.IpSecTransform;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.RouteInfo;
import android.net.annotations.PolicyDirection;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.ChildSessionConfiguration;
import android.net.ipsec.ike.ChildSessionParams;
import android.net.ipsec.ike.IkeSession;
import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.IkeSessionConfiguration;
import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.exceptions.IkeException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.net.vcn.VcnGatewayConnectionConfig;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Message;
import android.os.ParcelUuid;
import android.telephony.TelephonyManager;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@@ -628,12 +655,155 @@ public class VcnGatewayConnection extends StateMachine {
        protected void processStateMsg(Message msg) {}
    }

    private static class Dependencies {
    // TODO: Remove this when migrating to new NetworkAgent API
    private static NetworkInfo buildNetworkInfo(boolean isConnected) {
        NetworkInfo info =
                new NetworkInfo(
                        ConnectivityManager.TYPE_MOBILE,
                        TelephonyManager.NETWORK_TYPE_UNKNOWN,
                        "MOBILE",
                        "VCN");
        info.setDetailedState(
                isConnected ? DetailedState.CONNECTED : DetailedState.DISCONNECTED, null, null);

        return info;
    }

    @VisibleForTesting(visibility = Visibility.PRIVATE)
    static NetworkCapabilities buildNetworkCapabilities(
            @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig) {
        final NetworkCapabilities caps = new NetworkCapabilities();

        caps.addTransportType(TRANSPORT_CELLULAR);
        caps.addCapability(NET_CAPABILITY_NOT_CONGESTED);
        caps.addCapability(NET_CAPABILITY_NOT_SUSPENDED);

        // Add exposed capabilities
        for (int cap : gatewayConnectionConfig.getAllExposedCapabilities()) {
            caps.addCapability(cap);
        }

        return caps;
    }

    private static LinkProperties buildConnectedLinkProperties(
            @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig,
            @NonNull IpSecTunnelInterface tunnelIface,
            @NonNull ChildSessionConfiguration childConfig) {
        final LinkProperties lp = new LinkProperties();

        lp.setInterfaceName(tunnelIface.getInterfaceName());
        for (LinkAddress addr : childConfig.getInternalAddresses()) {
            lp.addLinkAddress(addr);
        }
        for (InetAddress addr : childConfig.getInternalDnsServers()) {
            lp.addDnsServer(addr);
        }

        lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
        lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));

        lp.setMtu(gatewayConnectionConfig.getMaxMtu());

        return lp;
    }

    private class IkeSessionCallbackImpl implements IkeSessionCallback {
        private final int mToken;

        IkeSessionCallbackImpl(int token) {
            mToken = token;
        }

        @Override
        public void onOpened(@NonNull IkeSessionConfiguration ikeSessionConfig) {
            Slog.v(TAG, "IkeOpened for token " + mToken);
            // Nothing to do here.
        }

        @Override
        public void onClosed() {
            Slog.v(TAG, "IkeClosed for token " + mToken);
            sessionClosed(mToken, null);
        }

        @Override
        public void onClosedExceptionally(@NonNull IkeException exception) {
            Slog.v(TAG, "IkeClosedExceptionally for token " + mToken, exception);
            sessionClosed(mToken, exception);
        }

        @Override
        public void onError(@NonNull IkeProtocolException exception) {
            Slog.v(TAG, "IkeError for token " + mToken, exception);
            // Non-fatal, log and continue.
        }
    }

    private class ChildSessionCallbackImpl implements ChildSessionCallback {
        private final int mToken;

        ChildSessionCallbackImpl(int token) {
            mToken = token;
        }

        @Override
        public void onOpened(@NonNull ChildSessionConfiguration childConfig) {
            Slog.v(TAG, "ChildOpened for token " + mToken);
            childOpened(mToken, childConfig);
        }

        @Override
        public void onClosed() {
            Slog.v(TAG, "ChildClosed for token " + mToken);
            sessionLost(mToken, null);
        }

        @Override
        public void onClosedExceptionally(@NonNull IkeException exception) {
            Slog.v(TAG, "ChildClosedExceptionally for token " + mToken, exception);
            sessionLost(mToken, exception);
        }

        @Override
        public void onIpSecTransformCreated(@NonNull IpSecTransform transform, int direction) {
            Slog.v(TAG, "ChildTransformCreated; Direction: " + direction + "; token " + mToken);
            childTransformCreated(mToken, transform, direction);
        }

        @Override
        public void onIpSecTransformDeleted(@NonNull IpSecTransform transform, int direction) {
            // Nothing to be done; no references to the IpSecTransform are held, and this transform
            // will be closed by the IKE library.
            Slog.v(TAG, "ChildTransformDeleted; Direction: " + direction + "; for token " + mToken);
        }
    }

    /** External dependencies used by VcnGatewayConnection, for injection in tests. */
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    public static class Dependencies {
        /** Builds a new UnderlyingNetworkTracker. */
        public UnderlyingNetworkTracker newUnderlyingNetworkTracker(
                VcnContext vcnContext,
                ParcelUuid subscriptionGroup,
                UnderlyingNetworkTrackerCallback callback) {
            return new UnderlyingNetworkTracker(vcnContext, subscriptionGroup, callback);
        }

        /** Builds a new IkeSession. */
        public IkeSession newIkeSession(
                VcnContext vcnContext,
                IkeSessionParams ikeSessionParams,
                ChildSessionParams childSessionParams,
                IkeSessionCallback ikeSessionCallback,
                ChildSessionCallback childSessionCallback) {
            return new IkeSession(
                    vcnContext.getContext(),
                    ikeSessionParams,
                    childSessionParams,
                    new HandlerExecutor(new Handler(vcnContext.getLooper())),
                    ikeSessionCallback,
                    childSessionCallback);
        }
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ android_test {
        "services.core",
    ],
    libs: [
        "android.net.ipsec.ike.stubs.module_lib",
        "android.test.runner",
        "android.test.base",
        "android.test.mock",
+7 −6
Original line number Diff line number Diff line
@@ -33,12 +33,13 @@ import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class VcnGatewayConnectionConfigTest {
    private static final int[] EXPOSED_CAPS =
    // Public for use in VcnGatewayConnectionTest
    public static final int[] EXPOSED_CAPS =
            new int[] {
                NetworkCapabilities.NET_CAPABILITY_INTERNET, NetworkCapabilities.NET_CAPABILITY_MMS
            };
    private static final int[] UNDERLYING_CAPS = new int[] {NetworkCapabilities.NET_CAPABILITY_DUN};
    private static final long[] RETRY_INTERVALS_MS =
    public static final int[] UNDERLYING_CAPS = new int[] {NetworkCapabilities.NET_CAPABILITY_DUN};
    public static final long[] RETRY_INTERVALS_MS =
            new long[] {
                TimeUnit.SECONDS.toMillis(5),
                TimeUnit.SECONDS.toMillis(30),
@@ -47,10 +48,10 @@ public class VcnGatewayConnectionConfigTest {
                TimeUnit.MINUTES.toMillis(15),
                TimeUnit.MINUTES.toMillis(30)
            };
    private static final int MAX_MTU = 1360;
    public static final int MAX_MTU = 1360;

    // Package protected for use in VcnConfigTest
    static VcnGatewayConnectionConfig buildTestConfig() {
    // Public for use in VcnGatewayConnectionTest
    public static VcnGatewayConnectionConfig buildTestConfig() {
        final VcnGatewayConnectionConfig.Builder builder =
                new VcnGatewayConnectionConfig.Builder()
                        .setRetryInterval(RETRY_INTERVALS_MS)
+82 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.vcn;

import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;

import android.annotation.NonNull;
import android.content.Context;
import android.net.NetworkCapabilities;
import android.net.vcn.VcnGatewayConnectionConfigTest;
import android.os.ParcelUuid;
import android.os.test.TestLooper;
import android.telephony.SubscriptionInfo;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/** Tests for TelephonySubscriptionTracker */
@RunWith(AndroidJUnit4.class)
@SmallTest
public class VcnGatewayConnectionTest {
    private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID());
    private static final int TEST_SIM_SLOT_INDEX = 1;
    private static final int TEST_SUBSCRIPTION_ID_1 = 2;
    private static final SubscriptionInfo TEST_SUBINFO_1 = mock(SubscriptionInfo.class);
    private static final int TEST_SUBSCRIPTION_ID_2 = 3;
    private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class);
    private static final Map<Integer, ParcelUuid> TEST_SUBID_TO_GROUP_MAP;

    static {
        final Map<Integer, ParcelUuid> subIdToGroupMap = new HashMap<>();
        subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_PARCEL_UUID);
        subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_PARCEL_UUID);
        TEST_SUBID_TO_GROUP_MAP = Collections.unmodifiableMap(subIdToGroupMap);
    }

    @NonNull private final Context mContext;
    @NonNull private final TestLooper mTestLooper;
    @NonNull private final VcnNetworkProvider mVcnNetworkProvider;
    @NonNull private final VcnGatewayConnection.Dependencies mDeps;

    public VcnGatewayConnectionTest() {
        mContext = mock(Context.class);
        mTestLooper = new TestLooper();
        mVcnNetworkProvider = mock(VcnNetworkProvider.class);
        mDeps = mock(VcnGatewayConnection.Dependencies.class);
    }

    @Test
    public void testBuildNetworkCapabilities() throws Exception {
        final NetworkCapabilities caps =
                VcnGatewayConnection.buildNetworkCapabilities(
                        VcnGatewayConnectionConfigTest.buildTestConfig());

        for (int exposedCapability : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) {
            assertTrue(caps.hasCapability(exposedCapability));
        }
    }
}