1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.testutils
18
19 import android.content.Context
20 import android.net.ConnectivityManager
21 import android.net.ConnectivityManager.NetworkCallback
22 import android.net.LinkAddress
23 import android.net.Network
24 import android.net.NetworkCapabilities
25 import android.net.NetworkRequest
26 import android.net.StringNetworkSpecifier
27 import android.net.TestNetworkInterface
28 import android.net.TestNetworkManager
29 import android.os.Binder
30 import java.util.concurrent.CompletableFuture
31 import java.util.concurrent.TimeUnit
32
33 /**
34 * Create a test network based on a TUN interface.
35 *
36 * This method will block until the test network is available. Requires
37 * [android.Manifest.permission.CHANGE_NETWORK_STATE] and
38 * [android.Manifest.permission.MANAGE_TEST_NETWORKS].
39 */
initTestNetworknull40 fun initTestNetwork(context: Context, interfaceAddr: LinkAddress, setupTimeoutMs: Long = 10_000L):
41 TestNetworkTracker {
42 val tnm = context.getSystemService(TestNetworkManager::class.java)
43 val iface = tnm.createTunInterface(arrayOf(interfaceAddr))
44 return TestNetworkTracker(context, iface, tnm, setupTimeoutMs)
45 }
46
47 /**
48 * Utility class to create and track test networks.
49 *
50 * This class is not thread-safe.
51 */
52 class TestNetworkTracker internal constructor(
53 val context: Context,
54 val iface: TestNetworkInterface,
55 tnm: TestNetworkManager,
56 setupTimeoutMs: Long
57 ) {
58 private val cm = context.getSystemService(ConnectivityManager::class.java)
59 private val binder = Binder()
60
61 private val networkCallback: NetworkCallback
62 val network: Network
63
64 init {
65 val networkFuture = CompletableFuture<Network>()
66 val networkRequest = NetworkRequest.Builder()
67 .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
68 // Test networks do not have NOT_VPN or TRUSTED capabilities by default
69 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
70 .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
71 .setNetworkSpecifier(StringNetworkSpecifier(iface.interfaceName))
72 .build()
73 networkCallback = object : NetworkCallback() {
onAvailablenull74 override fun onAvailable(network: Network) {
75 networkFuture.complete(network)
76 }
77 }
78 cm.requestNetwork(networkRequest, networkCallback)
79
80 try {
81 tnm.setupTestNetwork(iface.interfaceName, binder)
82 network = networkFuture.get(setupTimeoutMs, TimeUnit.MILLISECONDS)
83 } catch (e: Throwable) {
84 teardown()
85 throw e
86 }
87 }
88
teardownnull89 fun teardown() {
90 cm.unregisterNetworkCallback(networkCallback)
91 }
92 }