1 /*
<lambda>null2  * Copyright (C) 2022 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 package android.net.cts
17 
18 import android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS
19 import android.Manifest.permission.MANAGE_TEST_NETWORKS
20 import android.Manifest.permission.NETWORK_SETTINGS
21 import android.content.Context
22 import android.net.ConnectivityManager
23 import android.net.EthernetManager
24 import android.net.EthernetManager.ETHERNET_STATE_DISABLED
25 import android.net.EthernetManager.ETHERNET_STATE_ENABLED
26 import android.net.EthernetManager.InterfaceStateListener
27 import android.net.EthernetManager.ROLE_CLIENT
28 import android.net.EthernetManager.ROLE_NONE
29 import android.net.EthernetManager.ROLE_SERVER
30 import android.net.EthernetManager.STATE_ABSENT
31 import android.net.EthernetManager.STATE_LINK_DOWN
32 import android.net.EthernetManager.STATE_LINK_UP
33 import android.net.EthernetManager.TetheredInterfaceCallback
34 import android.net.EthernetManager.TetheredInterfaceRequest
35 import android.net.EthernetNetworkManagementException
36 import android.net.EthernetNetworkSpecifier
37 import android.net.EthernetNetworkUpdateRequest
38 import android.net.InetAddresses
39 import android.net.IpConfiguration
40 import android.net.LinkAddress
41 import android.net.MacAddress
42 import android.net.Network
43 import android.net.NetworkCapabilities
44 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED
45 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED
46 import android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED
47 import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
48 import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
49 import android.net.NetworkCapabilities.TRANSPORT_TEST
50 import android.net.NetworkRequest
51 import android.net.StaticIpConfiguration
52 import android.net.TestNetworkInterface
53 import android.net.TestNetworkManager
54 import android.net.cts.EthernetManagerTest.EthernetStateListener.CallbackEntry.EthernetStateChanged
55 import android.net.cts.EthernetManagerTest.EthernetStateListener.CallbackEntry.InterfaceStateChanged
56 import android.os.Build
57 import android.os.Handler
58 import android.os.Looper
59 import android.os.OutcomeReceiver
60 import android.os.Process
61 import android.os.SystemProperties
62 import android.platform.test.annotations.AppModeFull
63 import androidx.test.platform.app.InstrumentationRegistry
64 import com.android.net.module.util.ArrayTrackRecord
65 import com.android.net.module.util.TrackRecord
66 import com.android.testutils.ConnectivityModuleTest
67 import com.android.testutils.DevSdkIgnoreRule
68 import com.android.testutils.DevSdkIgnoreRunner
69 import com.android.testutils.DeviceInfoUtils.isKernelVersionAtLeast
70 import com.android.testutils.RecorderCallback.CallbackEntry.Available
71 import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
72 import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
73 import com.android.testutils.RecorderCallback.CallbackEntry.Lost
74 import com.android.testutils.RouterAdvertisementResponder
75 import com.android.testutils.PollPacketReader
76 import com.android.testutils.TestableNetworkCallback
77 import com.android.testutils.assertThrows
78 import com.android.testutils.runAsShell
79 import com.android.testutils.waitForIdle
80 import java.io.IOException
81 import java.net.Inet6Address
82 import java.net.Socket
83 import java.util.Random
84 import java.util.concurrent.CompletableFuture
85 import java.util.concurrent.ExecutionException
86 import java.util.concurrent.TimeUnit
87 import java.util.concurrent.TimeoutException
88 import java.util.function.IntConsumer
89 import kotlin.test.assertEquals
90 import kotlin.test.assertFailsWith
91 import kotlin.test.assertFalse
92 import kotlin.test.assertNotNull
93 import kotlin.test.assertNull
94 import kotlin.test.assertTrue
95 import org.junit.After
96 import org.junit.Assume.assumeFalse
97 import org.junit.Assume.assumeTrue
98 import org.junit.Before
99 import org.junit.Test
100 import org.junit.runner.RunWith
101 
102 private const val TAG = "EthernetManagerTest"
103 // This timeout does not affect the test duration for passing tests. It needs to be long enough to
104 // account for RS delay (and potentially the first retry interval (4s)). There have been failures
105 // where the interface did not gain provisioning within the allotted timeout.
106 private const val TIMEOUT_MS = 10_000L
107 // Timeout used to confirm no callbacks matching given criteria are received. Must be long enough to
108 // process all callbacks including ip provisioning when using the updateConfiguration API.
109 // Note that increasing this timeout increases the test duration.
110 private const val NO_CALLBACK_TIMEOUT_MS = 500L
111 
112 private val DEFAULT_IP_CONFIGURATION = IpConfiguration(IpConfiguration.IpAssignment.DHCP,
113         IpConfiguration.ProxySettings.NONE, null, null)
114 private val ETH_REQUEST: NetworkRequest = NetworkRequest.Builder()
115         .addTransportType(TRANSPORT_TEST)
116         .addTransportType(TRANSPORT_ETHERNET)
117         .removeCapability(NET_CAPABILITY_TRUSTED)
118         .build()
119 private val TEST_CAPS = NetworkCapabilities.Builder(ETH_REQUEST.networkCapabilities)
120         .addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
121         .addCapability(NET_CAPABILITY_NOT_CONGESTED)
122         .build()
123 private val STATIC_IP_CONFIGURATION = IpConfiguration.Builder()
124         .setStaticIpConfiguration(StaticIpConfiguration.Builder()
125                 .setIpAddress(LinkAddress("192.0.2.1/30")).build())
126         .build()
127 
128 @AppModeFull(reason = "Instant apps can't access EthernetManager")
129 // EthernetManager is not updatable before T, so tests do not need to be backwards compatible.
130 @RunWith(DevSdkIgnoreRunner::class)
131 // This test depends on behavior introduced post-T as part of connectivity module updates
132 @ConnectivityModuleTest
133 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
134 class EthernetManagerTest {
135 
136     private val context by lazy { InstrumentationRegistry.getInstrumentation().context }
137     private val em by lazy { context.getSystemService(EthernetManager::class.java)!! }
138     private val cm by lazy { context.getSystemService(ConnectivityManager::class.java)!! }
139     private val handler by lazy { Handler(Looper.getMainLooper()) }
140 
141     private val ifaceListener = EthernetStateListener()
142     private val createdIfaces = ArrayList<EthernetTestInterface>()
143     private val addedListeners = ArrayList<EthernetStateListener>()
144     private val registeredCallbacks = ArrayList<TestableNetworkCallback>()
145 
146     private var tetheredInterfaceRequest: TetheredInterfaceRequest? = null
147 
148     private var ethernetEnabled = true
149 
150     private class EthernetTestInterface(
151         context: Context,
152         private val handler: Handler,
153         hasCarrier: Boolean
154     ) {
155         private val tapInterface: TestNetworkInterface
156         private val packetReader: PollPacketReader
157         private val raResponder: RouterAdvertisementResponder
158         private val tnm: TestNetworkManager
159         val name get() = tapInterface.interfaceName
160         val onLinkPrefix get() = raResponder.prefix
161 
162         init {
163             tnm = runAsShell(MANAGE_TEST_NETWORKS) {
164                 context.getSystemService(TestNetworkManager::class.java)!!
165             }
166             tapInterface = runAsShell(MANAGE_TEST_NETWORKS) {
167                 // Configuring a tun/tap interface always enables the carrier. If hasCarrier is
168                 // false, it is subsequently disabled. This means that the interface may briefly get
169                 // link. With IPv6 provisioning delays (RS delay and DAD) disabled, this can cause
170                 // tests that expect no network to come up when hasCarrier is false to become flaky.
171                 tnm.createTapInterface(hasCarrier, false /* bringUp */)
172             }
173             val mtu = tapInterface.mtu
174             packetReader = PollPacketReader(
175                     handler,
176                     tapInterface.fileDescriptor.fileDescriptor,
177                     mtu
178             )
179             raResponder = RouterAdvertisementResponder(packetReader)
180             val iidString = "fe80::${Integer.toHexString(Random().nextInt(65536))}"
181             val linklocal = InetAddresses.parseNumericAddress(iidString) as Inet6Address
182             raResponder.addRouterEntry(MacAddress.fromString("01:23:45:67:89:ab"), linklocal)
183 
184             packetReader.startAsyncForTest()
185             raResponder.start()
186         }
187 
188         // WARNING: this function requires kernel support. Call assumeChangingCarrierSupported() at
189         // the top of your test.
190         fun setCarrierEnabled(enabled: Boolean) {
191             runAsShell(MANAGE_TEST_NETWORKS) {
192                 tnm.setCarrierEnabled(tapInterface, enabled)
193             }
194         }
195 
196         fun destroy() {
197             raResponder.stop()
198             handler.post({ packetReader.stop() })
199             handler.waitForIdle(TIMEOUT_MS)
200         }
201     }
202 
203     private open class EthernetStateListener private constructor(
204         private val history: ArrayTrackRecord<CallbackEntry>
205     ) : InterfaceStateListener, IntConsumer,
206                 TrackRecord<EthernetStateListener.CallbackEntry> by history {
207         constructor() : this(ArrayTrackRecord())
208 
209         val events = history.newReadHead()
210 
211         sealed class CallbackEntry {
212             data class InterfaceStateChanged(
213                 val iface: String,
214                 val state: Int,
215                 val role: Int,
216                 val configuration: IpConfiguration?
217             ) : CallbackEntry() {
218                 override fun toString(): String {
219                     val stateString = when (state) {
220                         STATE_ABSENT -> "STATE_ABSENT"
221                         STATE_LINK_UP -> "STATE_LINK_UP"
222                         STATE_LINK_DOWN -> "STATE_LINK_DOWN"
223                         else -> state.toString()
224                     }
225                     val roleString = when (role) {
226                         ROLE_NONE -> "ROLE_NONE"
227                         ROLE_CLIENT -> "ROLE_CLIENT"
228                         ROLE_SERVER -> "ROLE_SERVER"
229                         else -> role.toString()
230                     }
231                     return ("InterfaceStateChanged(iface=$iface, state=$stateString, " +
232                             "role=$roleString, ipConfig=$configuration)")
233                 }
234             }
235 
236             data class EthernetStateChanged(val state: Int) : CallbackEntry() {
237                 override fun toString(): String {
238                     val stateString = when (state) {
239                         ETHERNET_STATE_ENABLED -> "ETHERNET_STATE_ENABLED"
240                         ETHERNET_STATE_DISABLED -> "ETHERNET_STATE_DISABLED"
241                         else -> state.toString()
242                     }
243                     return "EthernetStateChanged(state=$stateString)"
244                 }
245             }
246         }
247 
248         override fun onInterfaceStateChanged(
249             iface: String,
250             state: Int,
251             role: Int,
252             cfg: IpConfiguration?
253         ) {
254             add(InterfaceStateChanged(iface, state, role, cfg))
255         }
256 
257         override fun accept(state: Int) {
258             add(EthernetStateChanged(state))
259         }
260 
261         fun <T : CallbackEntry> expectCallback(expected: T): T {
262             val event = events.poll(TIMEOUT_MS)
263             assertEquals(expected, event)
264             return event as T
265         }
266 
267         fun expectCallback(iface: EthernetTestInterface, state: Int, role: Int) {
268             expectCallback(createChangeEvent(iface.name, state, role))
269         }
270 
271         fun expectCallback(state: Int) {
272             expectCallback(EthernetStateChanged(state))
273         }
274 
275         private fun createChangeEvent(iface: String, state: Int, role: Int) =
276                 InterfaceStateChanged(iface, state, role,
277                         if (state != STATE_ABSENT) DEFAULT_IP_CONFIGURATION else null)
278 
279         fun eventuallyExpect(expected: CallbackEntry) {
280             val cb = events.poll(TIMEOUT_MS) { it == expected }
281             assertNotNull(cb, "Never received expected $expected. Received: ${events.backtrace()}")
282         }
283 
284         fun eventuallyExpect(iface: EthernetTestInterface, state: Int, role: Int) {
285             eventuallyExpect(createChangeEvent(iface.name, state, role))
286         }
287 
288         fun eventuallyExpect(state: Int) {
289             eventuallyExpect(EthernetStateChanged(state))
290         }
291 
292         fun assertNoCallback() {
293             val cb = events.poll(NO_CALLBACK_TIMEOUT_MS)
294             assertNull(cb, "Expected no callback but got $cb")
295         }
296     }
297 
298     private class TetheredInterfaceListener : TetheredInterfaceCallback {
299         private val available = CompletableFuture<String>()
300 
301         override fun onAvailable(iface: String) {
302             available.complete(iface)
303         }
304 
305         override fun onUnavailable() {
306             available.completeExceptionally(IllegalStateException("onUnavailable was called"))
307         }
308 
309         fun expectOnAvailable(timeout: Long = TIMEOUT_MS): String {
310             return available.get(timeout, TimeUnit.MILLISECONDS)
311         }
312     }
313 
314     private class EthernetOutcomeReceiver :
315         OutcomeReceiver<String, EthernetNetworkManagementException> {
316         private val result = CompletableFuture<String>()
317 
318         override fun onResult(iface: String) {
319             assertFalse(result.isDone())
320             result.complete(iface)
321         }
322 
323         override fun onError(e: EthernetNetworkManagementException) {
324             assertFalse(result.isDone())
325             result.completeExceptionally(e)
326         }
327 
328         fun expectResult(expected: String) {
329             assertEquals(expected, result.get(TIMEOUT_MS, TimeUnit.MILLISECONDS))
330         }
331 
332         fun expectError() {
333             // Assert that the future fails with EthernetNetworkManagementException from the
334             // completeExceptionally() call inside onUnavailable.
335             assertFailsWith(EthernetNetworkManagementException::class) {
336                 try {
337                     result.get()
338                 } catch (e: ExecutionException) {
339                     throw e.cause!!
340                 }
341             }
342         }
343     }
344 
345     private fun isEthernetSupported(): Boolean {
346         return context.getSystemService(EthernetManager::class.java) != null
347     }
348 
349     @Before
350     fun setUp() {
351         assumeTrue(isEthernetSupported())
352         setIncludeTestInterfaces(true)
353         addInterfaceStateListener(ifaceListener)
354         // Handler.post() events may get processed after native fd events, so it is possible that
355         // RTM_NEWLINK (from a subsequent createInterface() call) arrives before the interface state
356         // listener is registered. This affects the callbacks and breaks the tests.
357         // setEthernetEnabled() will always wait on a callback, so it is used as a barrier to ensure
358         // proper listener registration before proceeding.
359         setEthernetEnabled(true)
360     }
361 
362     @After
363     fun tearDown() {
364         if (!isEthernetSupported()) return
365         // Reenable ethernet, so ABSENT callbacks are received.
366         setEthernetEnabled(true)
367 
368         for (iface in createdIfaces) {
369             iface.destroy()
370             ifaceListener.eventuallyExpect(iface, STATE_ABSENT, ROLE_NONE)
371         }
372 
373         // After test interfaces are removed, disable tracking.
374         setIncludeTestInterfaces(false)
375 
376         for (listener in addedListeners) {
377             // Even if a given listener was not registered as both an interface and ethernet state
378             // listener, calling remove is safe.
379             em.removeInterfaceStateListener(listener)
380             em.removeEthernetStateListener(listener)
381         }
382         registeredCallbacks.forEach { cm.unregisterNetworkCallback(it) }
383         releaseTetheredInterface()
384         // Force releaseTetheredInterface() to be processed before starting the next test by calling
385         // setEthernetEnabled(true) which always waits on a callback.
386         setEthernetEnabled(true)
387     }
388 
389     // Setting the carrier up / down relies on TUNSETCARRIER which was added in kernel version 5.0.
390     private fun assumeChangingCarrierSupported() {
391         assumeTrue(isKernelVersionAtLeast("5.0.0"))
392     }
393 
394     // Configuring a tap interface without carrier relies on IFF_NO_CARRIER
395     // which was added in kernel version 6.0.
396     private fun assumeCreateInterfaceWithoutCarrierSupported() {
397         assumeTrue(isKernelVersionAtLeast("6.0.0"))
398     }
399 
400     private fun isAdbOverEthernet(): Boolean {
401         // If no ethernet interface is available, adb is not connected over ethernet.
402         if (em.getInterfaceList().isEmpty()) return false
403 
404         // cuttlefish is special and does not connect adb over ethernet.
405         if (SystemProperties.get("ro.product.board", "") == "cutf") return false
406 
407         // Check if adb is connected over the network.
408         return (SystemProperties.getInt("persist.adb.tcp.port", -1) > -1 ||
409                 SystemProperties.getInt("service.adb.tcp.port", -1) > -1)
410     }
411 
412     private fun addInterfaceStateListener(listener: EthernetStateListener) {
413         em.addInterfaceStateListener(handler::post, listener)
414         addedListeners.add(listener)
415     }
416 
417     private fun addEthernetStateListener(listener: EthernetStateListener) {
418         em.addEthernetStateListener(handler::post, listener)
419         addedListeners.add(listener)
420     }
421 
422     // WARNING: setting hasCarrier to false requires kernel support. Call
423     // assumeCreateInterfaceWithoutCarrierSupported() at the top of your test.
424     private fun createInterface(hasCarrier: Boolean = true): EthernetTestInterface {
425         val iface = EthernetTestInterface(
426             context,
427             handler,
428             hasCarrier
429         ).also { createdIfaces.add(it) }
430 
431         // when an interface comes up, we should always see a down cb before an up cb.
432         ifaceListener.eventuallyExpect(iface, STATE_LINK_DOWN, ROLE_CLIENT)
433         if (hasCarrier && ethernetEnabled) {
434             ifaceListener.expectCallback(iface, STATE_LINK_UP, ROLE_CLIENT)
435         }
436         return iface
437     }
438 
439     private fun setIncludeTestInterfaces(value: Boolean) {
440         runAsShell(NETWORK_SETTINGS) {
441             em.setIncludeTestInterfaces(value)
442         }
443     }
444 
445     private fun removeInterface(iface: EthernetTestInterface) {
446         iface.destroy()
447         createdIfaces.remove(iface)
448         ifaceListener.eventuallyExpect(iface, STATE_ABSENT, ROLE_NONE)
449     }
450 
451     private fun requestNetwork(request: NetworkRequest): TestableNetworkCallback {
452         return TestableNetworkCallback(
453                 timeoutMs = TIMEOUT_MS,
454                 noCallbackTimeoutMs = NO_CALLBACK_TIMEOUT_MS).also {
455             cm.requestNetwork(request, it)
456             registeredCallbacks.add(it)
457         }
458     }
459 
460     private fun registerNetworkListener(request: NetworkRequest): TestableNetworkCallback {
461         return TestableNetworkCallback(
462                 timeoutMs = TIMEOUT_MS,
463                 noCallbackTimeoutMs = NO_CALLBACK_TIMEOUT_MS).also {
464             cm.registerNetworkCallback(request, it)
465             registeredCallbacks.add(it)
466         }
467     }
468 
469     private fun requestTetheredInterface() = TetheredInterfaceListener().also {
470         tetheredInterfaceRequest = runAsShell(NETWORK_SETTINGS) {
471             em.requestTetheredInterface(handler::post, it)
472         }
473     }
474 
475     private fun releaseTetheredInterface() {
476         runAsShell(NETWORK_SETTINGS) {
477             tetheredInterfaceRequest?.release()
478             tetheredInterfaceRequest = null
479         }
480     }
481 
482     private fun releaseRequest(cb: TestableNetworkCallback) {
483         cm.unregisterNetworkCallback(cb)
484         registeredCallbacks.remove(cb)
485     }
486 
487     private fun disableInterface(iface: EthernetTestInterface) = EthernetOutcomeReceiver().also {
488         runAsShell(MANAGE_TEST_NETWORKS) {
489             em.disableInterface(iface.name, handler::post, it)
490         }
491     }
492 
493     private fun enableInterface(iface: EthernetTestInterface) = EthernetOutcomeReceiver().also {
494         runAsShell(MANAGE_TEST_NETWORKS) {
495             em.enableInterface(iface.name, handler::post, it)
496         }
497     }
498 
499     private fun updateConfiguration(
500         iface: EthernetTestInterface,
501         ipConfig: IpConfiguration? = null,
502         capabilities: NetworkCapabilities? = null
503     ) = EthernetOutcomeReceiver().also {
504         runAsShell(MANAGE_TEST_NETWORKS) {
505             em.updateConfiguration(
506                 iface.name,
507                 EthernetNetworkUpdateRequest.Builder()
508                     .setIpConfiguration(ipConfig)
509                     .setNetworkCapabilities(capabilities).build(),
510                 handler::post,
511                 it)
512         }
513     }
514 
515     // WARNING: check that isAdbOverEthernet() is false before calling setEthernetEnabled(false).
516     private fun setEthernetEnabled(enabled: Boolean) {
517         runAsShell(NETWORK_SETTINGS) { em.setEthernetEnabled(enabled) }
518 
519         ethernetEnabled = enabled
520         val listener = EthernetStateListener()
521         addEthernetStateListener(listener)
522         listener.eventuallyExpect(if (enabled) ETHERNET_STATE_ENABLED else ETHERNET_STATE_DISABLED)
523     }
524 
525     // NetworkRequest.Builder does not create a copy of the passed NetworkRequest, so in order to
526     // keep ETH_REQUEST as it is, a defensive copy is created here.
527     private fun NetworkRequest.copyWithEthernetSpecifier(ifaceName: String) =
528         NetworkRequest.Builder(NetworkRequest(ETH_REQUEST))
529             .setNetworkSpecifier(EthernetNetworkSpecifier(ifaceName)).build()
530 
531     // b/233534110: eventuallyExpect<Lost>() does not advance ReadHead, use
532     // eventuallyExpect(Lost::class) instead.
533     private fun TestableNetworkCallback.eventuallyExpectLost(n: Network? = null) =
534         eventuallyExpect(Lost::class) { n?.equals(it.network) ?: true }
535 
536     private fun TestableNetworkCallback.assertNeverLost(n: Network? = null) =
537         assertNoCallback { it is Lost && (n?.equals(it.network) ?: true) }
538 
539     private fun TestableNetworkCallback.assertNeverAvailable(n: Network? = null) =
540         assertNoCallback { it is Available && (n?.equals(it.network) ?: true) }
541 
542     private fun TestableNetworkCallback.expectCapabilitiesWithInterfaceName(name: String) =
543         expect<CapabilitiesChanged> { it.caps.networkSpecifier == EthernetNetworkSpecifier(name) }
544 
545     private fun TestableNetworkCallback.eventuallyExpectCapabilities(nc: NetworkCapabilities) {
546         // b/233534110: eventuallyExpect<CapabilitiesChanged>() does not advance ReadHead.
547         eventuallyExpect(CapabilitiesChanged::class) {
548             // CS may mix in additional capabilities, so NetworkCapabilities#equals cannot be used.
549             // Check if all expected capabilities are present instead.
550             it is CapabilitiesChanged && nc.capabilities.all { c -> it.caps.hasCapability(c) }
551         }
552     }
553 
554     private fun TestableNetworkCallback.eventuallyExpectLpForStaticConfig(
555         config: StaticIpConfiguration
556     ) {
557         // b/233534110: eventuallyExpect<LinkPropertiesChanged>() does not advance ReadHead.
558         eventuallyExpect(LinkPropertiesChanged::class) {
559             it is LinkPropertiesChanged && it.lp.linkAddresses.any { la ->
560                 la.isSameAddressAs(config.ipAddress)
561             }
562         }
563     }
564 
565     @Test
566     fun testCallbacks() {
567         // Only run this test when no non-restricted / physical interfaces are present.
568         // This test ensures that interface state listeners function properly, so the assumption
569         // check is explicitly *not* using an interface state listener.
570         // Since restricted interfaces cannot be used for tethering,
571         // assumeNoInterfaceForTetheringAvailable() is an okay proxy.
572         assumeNoInterfaceForTetheringAvailable()
573 
574         // If an interface exists when the callback is registered, it is reported on registration.
575         val iface = createInterface()
576         val listener1 = EthernetStateListener()
577         addInterfaceStateListener(listener1)
578         listener1.expectCallback(iface, STATE_LINK_UP, ROLE_CLIENT)
579 
580         // If an interface appears, existing callbacks see it.
581         val iface2 = createInterface()
582         listener1.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT)
583         listener1.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
584 
585         // Register a new listener, it should see state of all existing interfaces immediately.
586         val listener2 = EthernetStateListener()
587         addInterfaceStateListener(listener2)
588         listener2.expectCallback(iface, STATE_LINK_UP, ROLE_CLIENT)
589         listener2.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
590 
591         // Removing interfaces first sends link down, then STATE_ABSENT/ROLE_NONE.
592         removeInterface(iface)
593         for (listener in listOf(listener1, listener2)) {
594             listener.expectCallback(iface, STATE_LINK_DOWN, ROLE_CLIENT)
595             listener.expectCallback(iface, STATE_ABSENT, ROLE_NONE)
596         }
597 
598         removeInterface(iface2)
599         for (listener in listOf(listener1, listener2)) {
600             listener.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT)
601             listener.expectCallback(iface2, STATE_ABSENT, ROLE_NONE)
602             listener.assertNoCallback()
603         }
604     }
605 
606     private fun assumeNoInterfaceForTetheringAvailable() {
607         // Interfaces that have configured NetworkCapabilities will never be used for tethering,
608         // see aosp/2123900.
609         try {
610             // assumeException does not exist.
611             requestTetheredInterface().expectOnAvailable(NO_CALLBACK_TIMEOUT_MS)
612             // interface used for tethering is available, throw an assumption error.
613             assumeTrue(false)
614         } catch (e: TimeoutException) {
615             // do nothing -- the TimeoutException indicates that no interface is available for
616             // tethering.
617             releaseTetheredInterface()
618             // Force releaseTetheredInterface() to be processed before proceeding by calling
619             // setEthernetEnabled(true) which always waits on a callback.
620             setEthernetEnabled(true)
621         }
622     }
623 
624     @Test
625     fun testCallbacks_forServerModeInterfaces() {
626         // do not run this test if an interface that can be used for tethering already exists.
627         assumeNoInterfaceForTetheringAvailable()
628 
629         val iface = createInterface()
630         requestTetheredInterface().expectOnAvailable()
631 
632         val listener = EthernetStateListener()
633         addInterfaceStateListener(listener)
634         // TODO(b/295146844): do not report IpConfiguration for server mode interfaces.
635         listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_SERVER)
636 
637         releaseTetheredInterface()
638         listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_CLIENT)
639 
640         requestTetheredInterface().expectOnAvailable()
641         // This should be changed to expectCallback, once b/236895792 is fixed.
642         listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_SERVER)
643 
644         releaseTetheredInterface()
645         listener.expectCallback(iface, STATE_LINK_UP, ROLE_CLIENT)
646     }
647 
648     @Test
649     fun testCallbacks_afterRemovingServerModeInterface() {
650         // do not run this test if an interface that can be used for tethering already exists.
651         assumeNoInterfaceForTetheringAvailable()
652 
653         val iface = createInterface()
654         requestTetheredInterface().expectOnAvailable()
655         removeInterface(iface)
656 
657         val listener = EthernetStateListener()
658         addInterfaceStateListener(listener)
659         listener.assertNoCallback()
660     }
661 
662     @Test
663     fun testGetInterfaceList() {
664         // Create two test interfaces and check the return list contains the interface names.
665         val iface1 = createInterface()
666         val iface2 = createInterface()
667         var ifaces = em.getInterfaceList()
668         assertTrue(ifaces.size > 0)
669         assertTrue(ifaces.contains(iface1.name))
670         assertTrue(ifaces.contains(iface2.name))
671 
672         // Remove one existing test interface and check the return list doesn't contain the
673         // removed interface name.
674         removeInterface(iface1)
675         ifaces = em.getInterfaceList()
676         assertFalse(ifaces.contains(iface1.name))
677         assertTrue(ifaces.contains(iface2.name))
678 
679         removeInterface(iface2)
680     }
681 
682     @Test
683     fun testNetworkRequest_withSingleExistingInterface() {
684         createInterface()
685 
686         // install a listener which will later be used to verify the Lost callback
687         val listenerCb = registerNetworkListener(ETH_REQUEST)
688         // assert the network is only brought up by a request.
689         listenerCb.assertNeverAvailable()
690 
691         val cb = requestNetwork(ETH_REQUEST)
692         val network = cb.expect<Available>().network
693 
694         cb.assertNeverLost()
695         releaseRequest(cb)
696         listenerCb.eventuallyExpectLost(network)
697     }
698 
699     @Test
700     fun testNetworkRequest_beforeSingleInterfaceIsUp() {
701         val cb = requestNetwork(ETH_REQUEST)
702 
703         // bring up interface after network has been requested.
704         // Note: there is no guarantee that the NetworkRequest has been processed before the
705         // interface is actually created. That being said, it takes a few seconds between calling
706         // createInterface and the interface actually being properly registered with the ethernet
707         // module, so it is extremely unlikely that the CS handler thread has not run until then.
708         val iface = createInterface()
709         val network = cb.expect<Available>().network
710 
711         // remove interface before network request has been removed
712         cb.assertNeverLost()
713         removeInterface(iface)
714         cb.eventuallyExpectLost()
715     }
716 
717     @Test
718     fun testNetworkRequest_withMultipleInterfaces() {
719         val iface1 = createInterface()
720         val iface2 = createInterface()
721 
722         val cb = requestNetwork(ETH_REQUEST.copyWithEthernetSpecifier(iface2.name))
723 
724         cb.expect<Available>()
725         cb.expectCapabilitiesWithInterfaceName(iface2.name)
726 
727         removeInterface(iface1)
728         cb.assertNeverLost()
729         removeInterface(iface2)
730         cb.eventuallyExpectLost()
731     }
732 
733     @Test
734     fun testNetworkRequest_withInterfaceBeingReplaced() {
735         val iface1 = createInterface()
736 
737         val cb = requestNetwork(ETH_REQUEST)
738         val network = cb.expect<Available>().network
739 
740         // create another network and verify the request sticks to the current network
741         val iface2 = createInterface()
742         cb.assertNeverLost()
743 
744         // remove iface1 and verify the request brings up iface2
745         removeInterface(iface1)
746         cb.eventuallyExpectLost(network)
747         cb.expect<Available>()
748     }
749 
750     @Test
751     fun testNetworkRequest_withMultipleInterfacesAndRequests() {
752         val iface1 = createInterface()
753         val iface2 = createInterface()
754 
755         val cb1 = requestNetwork(ETH_REQUEST.copyWithEthernetSpecifier(iface1.name))
756         val cb2 = requestNetwork(ETH_REQUEST.copyWithEthernetSpecifier(iface2.name))
757         val cb3 = requestNetwork(ETH_REQUEST)
758 
759         cb1.expect<Available>()
760         cb1.expectCapabilitiesWithInterfaceName(iface1.name)
761         cb2.expect<Available>()
762         cb2.expectCapabilitiesWithInterfaceName(iface2.name)
763         // this request can be matched by either network.
764         cb3.expect<Available>()
765 
766         cb1.assertNeverLost()
767         cb2.assertNeverLost()
768         cb3.assertNeverLost()
769     }
770 
771     @Test
772     fun testNetworkRequest_ensureProperRefcounting() {
773         // create first request before interface is up / exists; create another request after it has
774         // been created; release one of them and check that the network stays up.
775         val listener = registerNetworkListener(ETH_REQUEST)
776         val cb1 = requestNetwork(ETH_REQUEST)
777 
778         val iface = createInterface()
779         val network = cb1.expect<Available>().network
780 
781         val cb2 = requestNetwork(ETH_REQUEST)
782         cb2.expect<Available>()
783 
784         // release the first request; this used to trigger b/197548738
785         releaseRequest(cb1)
786 
787         cb2.assertNeverLost()
788         releaseRequest(cb2)
789         listener.eventuallyExpectLost(network)
790     }
791 
792     @Test
793     fun testNetworkRequest_forInterfaceWhileTogglingCarrier() {
794         assumeCreateInterfaceWithoutCarrierSupported()
795         assumeChangingCarrierSupported()
796 
797         val iface = createInterface(false /* hasCarrier */)
798 
799         val cb = requestNetwork(ETH_REQUEST)
800         cb.assertNeverAvailable()
801 
802         iface.setCarrierEnabled(true)
803         cb.expect<Available>()
804 
805         iface.setCarrierEnabled(false)
806         cb.eventuallyExpectLost()
807     }
808 
809     // TODO: move to MTS
810     @Test
811     fun testNetworkRequest_linkPropertiesUpdate() {
812         val iface = createInterface()
813         val cb = requestNetwork(ETH_REQUEST)
814         // b/233534110: eventuallyExpect<LinkPropertiesChanged>() does not advance ReadHead
815         cb.eventuallyExpect(LinkPropertiesChanged::class) {
816             it is LinkPropertiesChanged && it.lp.addresses.any {
817                 address -> iface.onLinkPrefix.contains(address)
818             }
819         }
820     }
821 
822     @Test
823     fun testRemoveInterface_whileInServerMode() {
824         assumeNoInterfaceForTetheringAvailable()
825 
826         val listener = EthernetStateListener()
827         addInterfaceStateListener(listener)
828 
829         val iface = createInterface()
830         val ifaceName = requestTetheredInterface().expectOnAvailable()
831 
832         assertEquals(iface.name, ifaceName)
833         listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_SERVER)
834 
835         removeInterface(iface)
836 
837         // Note: removeInterface already verifies that a STATE_ABSENT, ROLE_NONE callback is
838         // received, but it can't hurt to explicitly check for it.
839         listener.expectCallback(iface, STATE_ABSENT, ROLE_NONE)
840         releaseTetheredInterface()
841         listener.assertNoCallback()
842     }
843 
844     @Test
845     fun testEnableDisableInterface_withActiveRequest() {
846         val iface = createInterface()
847         val cb = requestNetwork(ETH_REQUEST)
848         cb.expect<Available>()
849         cb.assertNeverLost()
850 
851         disableInterface(iface).expectResult(iface.name)
852         cb.eventuallyExpectLost()
853 
854         enableInterface(iface).expectResult(iface.name)
855         cb.expect<Available>()
856     }
857 
858     @Test
859     fun testEnableDisableInterface_withoutStateChange() {
860         val iface = createInterface()
861         // Interface is already enabled, so enableInterface() should return success
862         enableInterface(iface).expectResult(iface.name)
863 
864         disableInterface(iface).expectResult(iface.name)
865         // Interface is already disabled, so disableInterface() should return success.
866         disableInterface(iface).expectResult(iface.name)
867     }
868 
869     @Test
870     fun testEnableDisableInterface_withMissingInterface() {
871         val iface = createInterface()
872         removeInterface(iface)
873         // Interface does not exist, enable/disableInterface() should both return an error.
874         enableInterface(iface).expectError()
875         disableInterface(iface).expectError()
876     }
877 
878     @Test
879     fun testEnableDisableInterface_callbacks() {
880         val iface = createInterface()
881         val listener = EthernetStateListener()
882         addInterfaceStateListener(listener)
883         // Uses eventuallyExpect to account for interfaces that could already exist on device
884         listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_CLIENT)
885 
886         disableInterface(iface).expectResult(iface.name)
887         listener.eventuallyExpect(iface, STATE_LINK_DOWN, ROLE_CLIENT)
888 
889         enableInterface(iface).expectResult(iface.name)
890         listener.expectCallback(iface, STATE_LINK_UP, ROLE_CLIENT)
891 
892         disableInterface(iface).expectResult(iface.name)
893         listener.expectCallback(iface, STATE_LINK_DOWN, ROLE_CLIENT)
894     }
895 
896     @Test
897     fun testEnableDisableInterface_disableEnableEthernet() {
898         val iface = createInterface()
899         val listener = EthernetStateListener()
900         addInterfaceStateListener(listener)
901         listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_CLIENT)
902 
903         // When ethernet is disabled, interface should be down and enable/disableInterface()
904         // should not bring the interfaces up.
905         setEthernetEnabled(false)
906         listener.eventuallyExpect(iface, STATE_LINK_DOWN, ROLE_CLIENT)
907         enableInterface(iface).expectError()
908         disableInterface(iface).expectError()
909         listener.assertNoCallback()
910 
911         // When ethernet is enabled, enable/disableInterface() should succeed.
912         setEthernetEnabled(true)
913         listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_CLIENT)
914         disableInterface(iface).expectResult(iface.name)
915         listener.eventuallyExpect(iface, STATE_LINK_DOWN, ROLE_CLIENT)
916         enableInterface(iface).expectResult(iface.name)
917         listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_CLIENT)
918     }
919 
920     @Test
921     fun testUpdateConfiguration_forBothIpConfigAndCapabilities() {
922         val iface = createInterface()
923         val cb = requestNetwork(ETH_REQUEST.copyWithEthernetSpecifier(iface.name))
924         cb.expect<Available>()
925 
926         updateConfiguration(iface, STATIC_IP_CONFIGURATION, TEST_CAPS).expectResult(iface.name)
927         cb.eventuallyExpectCapabilities(TEST_CAPS)
928         cb.eventuallyExpectLpForStaticConfig(STATIC_IP_CONFIGURATION.staticIpConfiguration)
929     }
930 
931     @Test
932     fun testUpdateConfiguration_forOnlyIpConfig() {
933         val iface = createInterface()
934         val cb = requestNetwork(ETH_REQUEST.copyWithEthernetSpecifier(iface.name))
935         cb.expect<Available>()
936 
937         updateConfiguration(iface, STATIC_IP_CONFIGURATION).expectResult(iface.name)
938         cb.eventuallyExpectLpForStaticConfig(STATIC_IP_CONFIGURATION.staticIpConfiguration)
939     }
940 
941     @Test
942     fun testUpdateConfiguration_forOnlyCapabilities() {
943         val iface = createInterface()
944         val cb = requestNetwork(ETH_REQUEST.copyWithEthernetSpecifier(iface.name))
945         cb.expect<Available>()
946 
947         updateConfiguration(iface, capabilities = TEST_CAPS).expectResult(iface.name)
948         cb.eventuallyExpectCapabilities(TEST_CAPS)
949     }
950 
951     @Test
952     fun testUpdateConfiguration_forAllowedUids() {
953         // Configure a restricted network.
954         val iface = createInterface()
955         val request = NetworkRequest.Builder(ETH_REQUEST.copyWithEthernetSpecifier(iface.name))
956                 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED).build()
957         updateConfiguration(iface, capabilities = request.networkCapabilities)
958                 .expectResult(iface.name)
959 
960         // Request the restricted network as the shell with CONNECTIVITY_USE_RESTRICTED_NETWORKS.
961         val cb = runAsShell(CONNECTIVITY_USE_RESTRICTED_NETWORKS) { requestNetwork(request) }
962         val network = cb.expect<Available>().network
963         cb.assertNeverLost(network)
964 
965         // The network is restricted therefore binding to it when available will fail.
966         Socket().use { socket ->
967             assertThrows(IOException::class.java, { network.bindSocket(socket) })
968         }
969 
970         // Add the test process UID to the allowed UIDs for the network and ultimately bind again.
971         val allowedUids = setOf(Process.myUid())
972         val nc = NetworkCapabilities.Builder(request.networkCapabilities)
973                 .setAllowedUids(allowedUids).build()
974         updateConfiguration(iface, capabilities = nc).expectResult(iface.name)
975 
976         // UpdateConfiguration() currently does a restart on the ethernet interface therefore lost
977         // will be expected first before available, as part of the restart.
978         cb.expect<Lost>(network)
979         val updatedNetwork = cb.expect<Available>().network
980         // With the test process UID allowed, binding to a restricted network should be successful.
981         Socket().use { socket -> updatedNetwork.bindSocket(socket) }
982 
983         // Reset capabilities to not-restricted, otherwise tearDown won't see the interface callback
984         // as ifaceListener does not have the restricted permission.
985         // TODO: Find a better way to do this when there are more tests around restricted
986         // interfaces.
987         updateConfiguration(iface, capabilities = TEST_CAPS).expectResult(iface.name)
988     }
989 
990     // TODO: consider only having this test in MTS as it makes use of the fact that
991     // setEthernetEnabled(false) untracks all interfaces. This behavior is an implementation detail
992     // and may change in the future.
993     @Test
994     fun testUpdateConfiguration_onUntrackedInterface() {
995         assumeFalse(isAdbOverEthernet())
996         val iface = createInterface()
997         setEthernetEnabled(false)
998 
999         // Updating the IpConfiguration and NetworkCapabilities on absent interfaces is a supported
1000         // use case.
1001         updateConfiguration(iface, STATIC_IP_CONFIGURATION, TEST_CAPS).expectResult(iface.name)
1002 
1003         setEthernetEnabled(true)
1004         val cb = requestNetwork(ETH_REQUEST)
1005         cb.expect<Available>()
1006         cb.eventuallyExpectCapabilities(TEST_CAPS)
1007         cb.eventuallyExpectLpForStaticConfig(STATIC_IP_CONFIGURATION.staticIpConfiguration)
1008     }
1009 
1010     @Test
1011     fun testUpdateConfiguration_withLinkDown() {
1012         assumeChangingCarrierSupported()
1013         // createInterface without carrier is racy, so create it and then remove carrier.
1014         val iface = createInterface()
1015         val cb = requestNetwork(ETH_REQUEST)
1016         cb.expect<Available>()
1017 
1018         iface.setCarrierEnabled(false)
1019         cb.eventuallyExpectLost()
1020 
1021         updateConfiguration(iface, STATIC_IP_CONFIGURATION, TEST_CAPS).expectResult(iface.name)
1022         cb.assertNoCallback()
1023 
1024         iface.setCarrierEnabled(true)
1025         cb.eventuallyExpectCapabilities(TEST_CAPS)
1026         cb.eventuallyExpectLpForStaticConfig(STATIC_IP_CONFIGURATION.staticIpConfiguration)
1027     }
1028 
1029     @Test
1030     fun testAddInterface_disableEnableEthernet() {
1031         val listener = EthernetStateListener()
1032         addInterfaceStateListener(listener)
1033 
1034         // When ethernet is disabled, newly added interfaces should not be brought up.
1035         setEthernetEnabled(false)
1036         val iface = createInterface(/* hasCarrier */ true)
1037         listener.eventuallyExpect(iface, STATE_LINK_DOWN, ROLE_CLIENT)
1038 
1039         // When ethernet is re-enabled after interface is added, it will be brought up.
1040         setEthernetEnabled(true)
1041         listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_CLIENT)
1042     }
1043 
1044 
1045     @Test
1046     fun testRemoveInterface_disableEnableEthernet() {
1047         // Set up 2 interfaces for testing
1048         val iface1 = createInterface()
1049         val listener = EthernetStateListener()
1050         addInterfaceStateListener(listener)
1051         listener.eventuallyExpect(iface1, STATE_LINK_UP, ROLE_CLIENT)
1052         val iface2 = createInterface()
1053         listener.eventuallyExpect(iface2, STATE_LINK_UP, ROLE_CLIENT)
1054 
1055         // Removing interfaces when ethernet is enabled will first send link down, then
1056         // STATE_ABSENT/ROLE_NONE.
1057         removeInterface(iface1)
1058         listener.expectCallback(iface1, STATE_LINK_DOWN, ROLE_CLIENT)
1059         listener.expectCallback(iface1, STATE_ABSENT, ROLE_NONE)
1060 
1061         // Removing interfaces after ethernet is disabled will first send link down when ethernet is
1062         // disabled, then STATE_ABSENT/ROLE_NONE when interface is removed.
1063         setEthernetEnabled(false)
1064         listener.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT)
1065         removeInterface(iface2)
1066         listener.expectCallback(iface2, STATE_ABSENT, ROLE_NONE)
1067     }
1068 
1069     @Test
1070     fun testSetTetheringInterfaceMode_disableEnableEthernet() {
1071         val listener = EthernetStateListener()
1072         addInterfaceStateListener(listener)
1073 
1074         val iface = createInterface()
1075         requestTetheredInterface().expectOnAvailable()
1076         listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_SERVER)
1077 
1078         // (b/234743836): Currently the state of server mode interfaces always returns true due to
1079         // that interface state for server mode interfaces is not tracked properly.
1080         // So we do not get any state change when disabling ethernet.
1081         setEthernetEnabled(false)
1082         listener.assertNoCallback()
1083 
1084         // When ethernet is disabled, change interface mode will not bring the interface up.
1085         releaseTetheredInterface()
1086         listener.eventuallyExpect(iface, STATE_LINK_DOWN, ROLE_CLIENT)
1087 
1088         // When ethernet is re-enabled, interface will be brought up.
1089         setEthernetEnabled(true)
1090         listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_CLIENT)
1091     }
1092 }
1093