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

Commit 0acd4caf authored by Benedict Wong's avatar Benedict Wong
Browse files

Add NetworkProvider to VcnManagementService

This change adds a skeleton VcnNetworkProvider, and registers it with
ConnectivityService upon system startup.

Bug: 163431879
Test: FrameworksVcnTests passing
Change-Id: I7720db1cea805cbdca052a2e37cb2d754189ea05
parent 4b140e2b
Loading
Loading
Loading
Loading
+49 −2
Original line number Diff line number Diff line
@@ -20,10 +20,18 @@ import static java.util.Objects.requireNonNull;

import android.annotation.NonNull;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkProvider;
import android.net.NetworkRequest;
import android.net.vcn.IVcnManagementService;
import android.net.vcn.VcnConfig;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.ParcelUuid;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;

/**
 * VcnManagementService manages Virtual Carrier Network profiles and lifecycles.
 *
@@ -88,9 +96,16 @@ public class VcnManagementService extends IVcnManagementService.Stub {
    @NonNull private final Context mContext;
    @NonNull private final Dependencies mDeps;

    private VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) {
    @NonNull private final Looper mLooper;
    @NonNull private final VcnNetworkProvider mNetworkProvider;

    @VisibleForTesting(visibility = Visibility.PRIVATE)
    VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) {
        mContext = requireNonNull(context, "Missing context");
        mDeps = requireNonNull(deps, "Missing dependencies");

        mLooper = mDeps.getLooper();
        mNetworkProvider = new VcnNetworkProvider(mContext, mLooper);
    }

    // Package-visibility for SystemServer to create instances.
@@ -98,11 +113,31 @@ public class VcnManagementService extends IVcnManagementService.Stub {
        return new VcnManagementService(context, new Dependencies());
    }

    private static class Dependencies {}
    /** External dependencies used by VcnManagementService, for injection in tests */
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    public static class Dependencies {
        private HandlerThread mHandlerThread;

        /** Retrieves a looper for the VcnManagementService */
        public Looper getLooper() {
            if (mHandlerThread == null) {
                synchronized (this) {
                    if (mHandlerThread == null) {
                        mHandlerThread = new HandlerThread(TAG);
                        mHandlerThread.start();
                    }
                }
            }
            return mHandlerThread.getLooper();
        }
    }

    /** Notifies the VcnManagementService that external dependencies can be set up. */
    public void systemReady() {
        // TODO: Retrieve existing profiles from KeyStore

        mContext.getSystemService(ConnectivityManager.class)
                .registerNetworkProvider(mNetworkProvider);
    }

    /**
@@ -129,4 +164,16 @@ public class VcnManagementService extends IVcnManagementService.Stub {

        // TODO: Clear VCN configuration, trigger teardown as necessary
    }

    @VisibleForTesting(visibility = Visibility.PRIVATE)
    class VcnNetworkProvider extends NetworkProvider {
        VcnNetworkProvider(@NonNull Context context, @NonNull Looper looper) {
            super(context, looper, VcnNetworkProvider.class.getSimpleName());
        }

        @Override
        public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {
            // TODO: Handle network requests - Ensure VCN started, and start appropriate tunnels.
        }
    }
}
+62 −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;

import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import android.content.Context;
import android.net.ConnectivityManager;
import android.os.test.TestLooper;

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

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

/** Tests for {@link VcnManagementService}. */
@RunWith(AndroidJUnit4.class)
@SmallTest
public class VcnManagementServiceTest {
    private final Context mMockContext = mock(Context.class);
    private final VcnManagementService.Dependencies mMockDeps =
            mock(VcnManagementService.Dependencies.class);
    private final TestLooper mTestLooper = new TestLooper();
    private final ConnectivityManager mConnMgr = mock(ConnectivityManager.class);
    private final VcnManagementService mVcnMgmtSvc;

    public VcnManagementServiceTest() {
        doReturn(Context.CONNECTIVITY_SERVICE)
                .when(mMockContext)
                .getSystemServiceName(ConnectivityManager.class);
        doReturn(mConnMgr).when(mMockContext).getSystemService(Context.CONNECTIVITY_SERVICE);

        doReturn(mTestLooper.getLooper()).when(mMockDeps).getLooper();
        mVcnMgmtSvc = new VcnManagementService(mMockContext, mMockDeps);
    }

    @Test
    public void testSystemReady() throws Exception {
        mVcnMgmtSvc.systemReady();

        verify(mConnMgr)
                .registerNetworkProvider(any(VcnManagementService.VcnNetworkProvider.class));
    }
}