1 /*
2 * Copyright (C) 2023 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.server
18
19 import android.content.pm.PackageManager.FEATURE_LEANBACK
20 import android.net.INetd
21 import android.net.LocalNetworkConfig
22 import android.net.NativeNetworkConfig
23 import android.net.NativeNetworkType
24 import android.net.NetworkCapabilities
25 import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK
26 import android.net.NetworkRequest
27 import android.net.NetworkScore
28 import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
29 import android.net.VpnManager
30 import android.os.Build
31 import androidx.test.filters.SmallTest
32 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
33 import com.android.testutils.DevSdkIgnoreRunner
34 import com.android.testutils.RecorderCallback.CallbackEntry.Available
35 import com.android.testutils.TestableNetworkCallback
36 import kotlin.test.assertFailsWith
37 import org.junit.Assert.assertEquals
38 import org.junit.Test
39 import org.junit.runner.RunWith
40 import org.junit.runners.Parameterized
41 import org.mockito.Mockito.doReturn
42 import org.mockito.Mockito.inOrder
43 import org.mockito.Mockito.never
44 import org.mockito.Mockito.timeout
45
46 private const val TIMEOUT_MS = 2_000L
47 private const val NO_CALLBACK_TIMEOUT_MS = 200L
48
keepConnectedScorenull49 private fun keepConnectedScore() =
50 FromS(NetworkScore.Builder().setKeepConnectedReason(KEEP_CONNECTED_FOR_TEST).build())
51
52 private fun defaultLnc() = FromS(LocalNetworkConfig.Builder().build())
53
54 @DevSdkIgnoreRunner.MonitorThreadLeak
55 @RunWith(DevSdkIgnoreRunner::class)
56 @SmallTest
57 @IgnoreUpTo(Build.VERSION_CODES.R)
58 class CSLocalAgentCreationTests(
59 private val sdkLevel: Int,
60 private val isTv: Boolean,
61 private val addLocalNetCapToRequest: Boolean
62 ) : CSTest() {
63 companion object {
64 @JvmStatic
65 @Parameterized.Parameters
66 fun arguments() = listOf(
67 arrayOf(VERSION_V, false /* isTv */, true /* addLocalNetCapToRequest */),
68 arrayOf(VERSION_V, false /* isTv */, false /* addLocalNetCapToRequest */),
69 arrayOf(VERSION_V, true /* isTv */, true /* addLocalNetCapToRequest */),
70 arrayOf(VERSION_V, true /* isTv */, false /* addLocalNetCapToRequest */),
71 arrayOf(VERSION_U, false /* isTv */, true /* addLocalNetCapToRequest */),
72 arrayOf(VERSION_U, false /* isTv */, false /* addLocalNetCapToRequest */),
73 arrayOf(VERSION_U, true /* isTv */, true /* addLocalNetCapToRequest */),
74 arrayOf(VERSION_U, true /* isTv */, false /* addLocalNetCapToRequest */),
75 arrayOf(VERSION_T, false /* isTv */, false /* addLocalNetCapToRequest */),
76 arrayOf(VERSION_T, true /* isTv */, false /* addLocalNetCapToRequest */),
77 )
78 }
79
80 private fun makeNativeNetworkConfigLocal(netId: Int, permission: Int) =
81 NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL_LOCAL, permission,
82 false /* secure */, VpnManager.TYPE_VPN_NONE, false /* excludeLocalRoutes */)
83
84 @Test
85 fun testLocalAgents() {
86 val netdInOrder = inOrder(netd)
87 deps.setBuildSdk(sdkLevel)
88 doReturn(isTv).`when`(packageManager).hasSystemFeature(FEATURE_LEANBACK)
89 val allNetworksCb = TestableNetworkCallback()
90 val request = NetworkRequest.Builder()
91 if (addLocalNetCapToRequest) {
92 request.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
93 }
94 cm.registerNetworkCallback(request.build(), allNetworksCb)
95 val ncTemplate = NetworkCapabilities.Builder().run {
96 addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
97 addCapability(NET_CAPABILITY_LOCAL_NETWORK)
98 }.build()
99 val localAgent = if (sdkLevel >= VERSION_V || sdkLevel == VERSION_U && isTv) {
100 Agent(nc = ncTemplate, score = keepConnectedScore(), lnc = defaultLnc())
101 } else {
102 assertFailsWith<IllegalArgumentException> { Agent(nc = ncTemplate, lnc = defaultLnc()) }
103 netdInOrder.verify(netd, never()).networkCreate(any())
104 return
105 }
106 localAgent.connect()
107 netdInOrder.verify(netd).networkCreate(
108 makeNativeNetworkConfigLocal(localAgent.network.netId, INetd.PERMISSION_NONE))
109 if (addLocalNetCapToRequest) {
110 assertEquals(localAgent.network, allNetworksCb.expect<Available>().network)
111 } else {
112 allNetworksCb.assertNoCallback(NO_CALLBACK_TIMEOUT_MS)
113 }
114 cm.unregisterNetworkCallback(allNetworksCb)
115 localAgent.disconnect()
116 netdInOrder.verify(netd, timeout(TIMEOUT_MS)).networkDestroy(localAgent.network.netId)
117 }
118
119 @Test
120 fun testBadAgents() {
121 assertFailsWith<IllegalArgumentException> {
122 Agent(nc = NetworkCapabilities.Builder()
123 .addCapability(NET_CAPABILITY_LOCAL_NETWORK)
124 .build(),
125 lnc = null)
126 }
127 assertFailsWith<IllegalArgumentException> {
128 Agent(nc = NetworkCapabilities.Builder().build(), lnc = defaultLnc())
129 }
130 }
131 }
132