1 /* 2 * Copyright (C) 2021 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.FEATURE_QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER 22 import android.net.InetAddresses.parseNumericAddress 23 import android.net.KeepalivePacketData 24 import android.net.LinkAddress 25 import android.net.LinkProperties 26 import android.net.NetworkAgent 27 import android.net.NetworkAgentConfig 28 import android.net.NetworkCapabilities 29 import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED 30 import android.net.NetworkCapabilities.TRANSPORT_TEST 31 import android.net.NetworkProvider 32 import android.net.NetworkRequest 33 import android.net.NetworkScore 34 import android.net.QosFilter 35 import android.net.Uri 36 import android.os.Looper 37 import android.system.ErrnoException 38 import android.system.Os 39 import android.system.OsConstants 40 import android.system.OsConstants.EADDRNOTAVAIL 41 import android.system.OsConstants.ENETUNREACH 42 import android.system.OsConstants.ENONET 43 import android.system.OsConstants.IPPROTO_UDP 44 import android.system.OsConstants.SOCK_DGRAM 45 import com.android.modules.utils.build.SdkLevel.isAtLeastS 46 import com.android.net.module.util.ArrayTrackRecord 47 import com.android.testutils.CompatUtil.makeTestNetworkSpecifier 48 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnAddKeepalivePacketFilter 49 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnAutomaticReconnectDisabled 50 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnBandwidthUpdateRequested 51 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnDscpPolicyStatusUpdated 52 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkCreated 53 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkDestroyed 54 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkUnwanted 55 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnRegisterQosCallback 56 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnRemoveKeepalivePacketFilter 57 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnSaveAcceptUnvalidated 58 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnSignalStrengthThresholdsUpdated 59 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnStartSocketKeepalive 60 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnStopSocketKeepalive 61 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnUnregisterQosCallback 62 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnValidationStatus 63 import java.net.NetworkInterface 64 import java.net.SocketException 65 import java.time.Duration 66 import kotlin.test.assertEquals 67 import kotlin.test.assertNotNull 68 import kotlin.test.assertNull 69 import kotlin.test.assertTrue 70 import kotlin.test.fail 71 import org.junit.Assert.assertArrayEquals 72 73 // Any legal score (0~99) for the test network would do, as it is going to be kept up by the 74 // requests filed by the test and should never match normal internet requests. 70 is the default 75 // score of Ethernet networks, it's as good a value as any other. 76 // Note that this can't use NetworkScore.Builder() because this test must be able to 77 // run on R, which doesn't know this class. 78 private const val TEST_NETWORK_SCORE = 70 79 80 private class Provider(context: Context, looper: Looper) : 81 NetworkProvider(context, looper, "NetworkAgentTest NetworkProvider") 82 83 private val enabledFeatures = mutableMapOf<Long, Boolean>() 84 85 public open class TestableNetworkAgent( 86 context: Context, 87 looper: Looper, 88 val nc: NetworkCapabilities, 89 val lp: LinkProperties, 90 conf: NetworkAgentConfig 91 ) : NetworkAgent(context, looper, TestableNetworkAgent::class.java.simpleName /* tag */, 92 nc, lp, TEST_NETWORK_SCORE, conf, Provider(context, looper)) { 93 isFeatureEnablednull94 override fun isFeatureEnabled(context: Context, feature: Long): Boolean { 95 when (val it = enabledFeatures.get(feature)) { 96 null -> { 97 val cm = context.getSystemService(ConnectivityManager::class.java) 98 val res = cm.isFeatureEnabled(feature) 99 enabledFeatures[feature] = res 100 return res 101 } 102 else -> return it 103 } 104 } 105 106 companion object { setFeatureEnablednull107 fun setFeatureEnabled(flag: Long, enabled: Boolean) = enabledFeatures.set(flag, enabled) 108 109 /** 110 * Convenience method to create a [NetworkRequest] matching [TestableNetworkAgent]s from 111 * [createOnInterface]. 112 */ 113 fun makeNetworkRequestForInterface(ifaceName: String) = NetworkRequest.Builder() 114 .removeCapability(NET_CAPABILITY_TRUSTED) 115 .addTransportType(TRANSPORT_TEST) 116 .setNetworkSpecifier(makeTestNetworkSpecifier(ifaceName)) 117 .build() 118 119 /** 120 * Convenience method to initialize a [TestableNetworkAgent] on a given interface. 121 * 122 * This waits for link-local addresses to be setup and ensures LinkProperties are updated 123 * with the addresses. 124 */ 125 fun createOnInterface( 126 context: Context, 127 looper: Looper, 128 ifaceName: String, 129 timeoutMs: Long 130 ): TestableNetworkAgent { 131 val lp = LinkProperties().apply { 132 interfaceName = ifaceName 133 } 134 val agent = TestableNetworkAgent( 135 context, 136 looper, 137 NetworkCapabilities().apply { 138 removeCapability(NET_CAPABILITY_TRUSTED) 139 addTransportType(TRANSPORT_TEST) 140 setNetworkSpecifier(makeTestNetworkSpecifier(ifaceName)) 141 }, 142 lp, 143 NetworkAgentConfig.Builder().build() 144 ) 145 val network = agent.register() 146 agent.markConnected() 147 if (isAtLeastS()) { 148 // OnNetworkCreated was added in S 149 agent.eventuallyExpect<OnNetworkCreated>() 150 } 151 152 // Wait until the link-local address can be used. Address flags are not available 153 // without elevated permissions, so check that bindSocket works. 154 assertEventuallyTrue("No usable v6 address after $timeoutMs ms", timeoutMs) { 155 // To avoid race condition between socket connection succeeding and interface 156 // returning a non-empty address list. Verify that interface returns a non-empty 157 // list, before trying the socket connection. 158 if (NetworkInterface.getByName(ifaceName).interfaceAddresses.isEmpty()) { 159 return@assertEventuallyTrue false 160 } 161 162 val sock = Os.socket(OsConstants.AF_INET6, SOCK_DGRAM, IPPROTO_UDP) 163 tryTest { 164 network.bindSocket(sock) 165 Os.connect(sock, parseNumericAddress("ff02::fb%$ifaceName"), 12345) 166 true 167 }.catch<ErrnoException> { 168 if (it.errno != ENETUNREACH && it.errno != EADDRNOTAVAIL) { 169 throw it 170 } 171 false 172 }.catch<SocketException> { 173 // OnNetworkCreated does not exist on R, so a SocketException caused by ENONET 174 // may be seen before the network is created 175 if (isAtLeastS()) throw it 176 val cause = it.cause as? ErrnoException ?: throw it 177 if (cause.errno != ENONET) { 178 throw it 179 } 180 false 181 } cleanup { 182 Os.close(sock) 183 } 184 } 185 186 agent.lp.setLinkAddresses(NetworkInterface.getByName(ifaceName).interfaceAddresses.map { 187 LinkAddress(it.address, it.networkPrefixLength.toInt()) 188 }) 189 agent.sendLinkProperties(agent.lp) 190 return agent 191 } 192 } 193 194 val DEFAULT_TIMEOUT_MS = 5000L 195 196 val history = ArrayTrackRecord<CallbackEntry>().newReadHead() 197 198 sealed class CallbackEntry { 199 object OnBandwidthUpdateRequested : CallbackEntry() 200 object OnNetworkUnwanted : CallbackEntry() 201 data class OnAddKeepalivePacketFilter( 202 val slot: Int, 203 val packet: KeepalivePacketData 204 ) : CallbackEntry() 205 data class OnRemoveKeepalivePacketFilter(val slot: Int) : CallbackEntry() 206 data class OnStartSocketKeepalive( 207 val slot: Int, 208 val interval: Int, 209 val packet: KeepalivePacketData 210 ) : CallbackEntry() 211 data class OnStopSocketKeepalive(val slot: Int) : CallbackEntry() 212 data class OnSaveAcceptUnvalidated(val accept: Boolean) : CallbackEntry() 213 object OnAutomaticReconnectDisabled : CallbackEntry() 214 data class OnValidationStatus(val status: Int, val uri: Uri?) : CallbackEntry() 215 data class OnSignalStrengthThresholdsUpdated(val thresholds: IntArray) : CallbackEntry() 216 object OnNetworkCreated : CallbackEntry() 217 object OnNetworkDestroyed : CallbackEntry() 218 data class OnDscpPolicyStatusUpdated(val policyId: Int, val status: Int) : CallbackEntry() 219 data class OnRegisterQosCallback( 220 val callbackId: Int, 221 val filter: QosFilter 222 ) : CallbackEntry() 223 data class OnUnregisterQosCallback(val callbackId: Int) : CallbackEntry() 224 } 225 onBandwidthUpdateRequestednull226 override fun onBandwidthUpdateRequested() { 227 history.add(OnBandwidthUpdateRequested) 228 } 229 onNetworkUnwantednull230 override fun onNetworkUnwanted() { 231 history.add(OnNetworkUnwanted) 232 } 233 onAddKeepalivePacketFilternull234 override fun onAddKeepalivePacketFilter(slot: Int, packet: KeepalivePacketData) { 235 history.add(OnAddKeepalivePacketFilter(slot, packet)) 236 } 237 onRemoveKeepalivePacketFilternull238 override fun onRemoveKeepalivePacketFilter(slot: Int) { 239 history.add(OnRemoveKeepalivePacketFilter(slot)) 240 } 241 onStartSocketKeepalivenull242 override fun onStartSocketKeepalive( 243 slot: Int, 244 interval: Duration, 245 packet: KeepalivePacketData 246 ) { 247 history.add(OnStartSocketKeepalive(slot, interval.seconds.toInt(), packet)) 248 } 249 onStopSocketKeepalivenull250 override fun onStopSocketKeepalive(slot: Int) { 251 history.add(OnStopSocketKeepalive(slot)) 252 } 253 onSaveAcceptUnvalidatednull254 override fun onSaveAcceptUnvalidated(accept: Boolean) { 255 history.add(OnSaveAcceptUnvalidated(accept)) 256 } 257 onAutomaticReconnectDisablednull258 override fun onAutomaticReconnectDisabled() { 259 history.add(OnAutomaticReconnectDisabled) 260 } 261 onSignalStrengthThresholdsUpdatednull262 override fun onSignalStrengthThresholdsUpdated(thresholds: IntArray) { 263 history.add(OnSignalStrengthThresholdsUpdated(thresholds)) 264 } 265 expectSignalStrengthsnull266 fun expectSignalStrengths(thresholds: IntArray? = intArrayOf()) { 267 expectCallback<OnSignalStrengthThresholdsUpdated>().let { 268 assertArrayEquals(thresholds, it.thresholds) 269 } 270 } 271 onQosCallbackRegisterednull272 override fun onQosCallbackRegistered(qosCallbackId: Int, filter: QosFilter) { 273 history.add(OnRegisterQosCallback(qosCallbackId, filter)) 274 } 275 onQosCallbackUnregisterednull276 override fun onQosCallbackUnregistered(qosCallbackId: Int) { 277 history.add(OnUnregisterQosCallback(qosCallbackId)) 278 } 279 onValidationStatusnull280 override fun onValidationStatus(status: Int, uri: Uri?) { 281 history.add(OnValidationStatus(status, uri)) 282 } 283 onNetworkCreatednull284 override fun onNetworkCreated() { 285 history.add(OnNetworkCreated) 286 } 287 onNetworkDestroyednull288 override fun onNetworkDestroyed() { 289 history.add(OnNetworkDestroyed) 290 } 291 onDscpPolicyStatusUpdatednull292 override fun onDscpPolicyStatusUpdated(policyId: Int, status: Int) { 293 history.add(OnDscpPolicyStatusUpdated(policyId, status)) 294 } 295 296 // Expects the initial validation event that always occurs immediately after registering 297 // a NetworkAgent whose network does not require validation (which test networks do 298 // not, since they lack the INTERNET capability). It always contains the default argument 299 // for the URI. <lambda>null300 fun expectValidationBypassedStatus() = expectCallback<OnValidationStatus>().let { 301 assertEquals(it.status, VALID_NETWORK) 302 // The returned Uri is parsed from the empty string, which means it's an 303 // instance of the (private) Uri.StringUri. There are no real good ways 304 // to check this, the least bad is to just convert it to a string and 305 // make sure it's empty. 306 assertEquals("", it.uri.toString()) 307 } 308 expectCallbacknull309 inline fun <reified T : CallbackEntry> expectCallback(): T { 310 val foundCallback = history.poll(DEFAULT_TIMEOUT_MS) 311 assertTrue(foundCallback is T, "Expected ${T::class} but found $foundCallback") 312 return foundCallback 313 } 314 expectCallbacknull315 inline fun <reified T : CallbackEntry> expectCallback(valid: (T) -> Boolean) { 316 val foundCallback = history.poll(DEFAULT_TIMEOUT_MS) 317 assertTrue(foundCallback is T, "Expected ${T::class} but found $foundCallback") 318 assertTrue(valid(foundCallback), "Unexpected callback : $foundCallback") 319 } 320 eventuallyExpectnull321 inline fun <reified T : CallbackEntry> eventuallyExpect() = 322 history.poll(DEFAULT_TIMEOUT_MS) { it is T }.also { 323 assertNotNull(it, "Callback ${T::class} not received") 324 } as T 325 assertNoCallbacknull326 fun assertNoCallback() { 327 assertTrue(waitForIdle(DEFAULT_TIMEOUT_MS), 328 "Handler didn't became idle after ${DEFAULT_TIMEOUT_MS}ms") 329 assertNull(history.peek()) 330 } 331 } 332