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