diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt index 05d0beb2ea..30e0015a1c 100644 --- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt +++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt @@ -17,7 +17,9 @@ package android.net.cts import android.Manifest.permission.MANAGE_TEST_NETWORKS import android.Manifest.permission.NETWORK_SETTINGS +import android.net.InetAddresses import android.net.IpConfiguration +import android.net.MacAddress import android.net.TestNetworkInterface import android.net.TestNetworkManager import android.platform.test.annotations.AppModeFull @@ -32,6 +34,7 @@ import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.Test +import android.content.Context import org.junit.runner.RunWith import kotlin.test.assertNull import kotlin.test.fail @@ -46,10 +49,15 @@ import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_LINK_UP import com.android.networkstack.apishim.common.EthernetManagerShim.ROLE_CLIENT import com.android.networkstack.apishim.common.EthernetManagerShim.ROLE_NONE import com.android.networkstack.apishim.EthernetManagerShimImpl +import com.android.testutils.RouterAdvertisementResponder +import com.android.testutils.TapPacketReader +import com.android.testutils.waitForIdle +import java.net.Inet6Address import java.util.concurrent.Executor import kotlin.test.assertFalse import kotlin.test.assertEquals import kotlin.test.assertTrue +import java.net.NetworkInterface private const val TIMEOUT_MS = 1000L private const val NO_CALLBACK_TIMEOUT_MS = 200L @@ -66,9 +74,40 @@ class EthernetManagerTest { private val context by lazy { InstrumentationRegistry.getInstrumentation().context } private val em by lazy { EthernetManagerShimImpl.newInstance(context) } - private val createdIfaces = ArrayList() + private val createdIfaces = ArrayList() private val addedListeners = ArrayList() + private class EthernetTestInterface( + context: Context, + private val handler: Handler + ) { + private val tapInterface: TestNetworkInterface + private val packetReader: TapPacketReader + private val raResponder: RouterAdvertisementResponder + val interfaceName get() = tapInterface.interfaceName + + init { + tapInterface = runAsShell(MANAGE_TEST_NETWORKS) { + val tnm = context.getSystemService(TestNetworkManager::class.java) + tnm.createTapInterface(false /* bringUp */) + } + val mtu = NetworkInterface.getByName(tapInterface.interfaceName).getMTU() + packetReader = TapPacketReader(handler, tapInterface.fileDescriptor.fileDescriptor, mtu) + raResponder = RouterAdvertisementResponder(packetReader) + raResponder.addRouterEntry(MacAddress.fromString("01:23:45:67:89:ab"), + InetAddresses.parseNumericAddress("fe80::abcd") as Inet6Address) + + packetReader.startAsyncForTest() + raResponder.start() + } + + fun destroy() { + raResponder.stop() + handler.post({ packetReader.stop() }) + handler.waitForIdle(TIMEOUT_MS) + } + } + private open class EthernetStateListener private constructor( private val history: ArrayTrackRecord ) : InterfaceStateListener, @@ -101,7 +140,7 @@ class EthernetManagerTest { return event as T } - fun expectCallback(iface: TestNetworkInterface, state: Int, role: Int) { + fun expectCallback(iface: EthernetTestInterface, state: Int, role: Int) { expectCallback(InterfaceStateChanged(iface.interfaceName, state, role, if (state != STATE_ABSENT) DEFAULT_IP_CONFIGURATION else null)) } @@ -125,7 +164,7 @@ class EthernetManagerTest { fun tearDown() { setIncludeTestInterfaces(false) for (iface in createdIfaces) { - if (iface.fileDescriptor.fileDescriptor.valid()) iface.fileDescriptor.close() + iface.destroy() } for (listener in addedListeners) { em.removeInterfaceStateListener(listener) @@ -137,11 +176,8 @@ class EthernetManagerTest { addedListeners.add(listener) } - private fun createInterface(): TestNetworkInterface { - return runAsShell(MANAGE_TEST_NETWORKS) { - val tnm = context.getSystemService(TestNetworkManager::class.java) - tnm.createTapInterface(false /* bringUp */).also { createdIfaces.add(it) } - } + private fun createInterface(): EthernetTestInterface { + return EthernetTestInterface(context, Handler(Looper.getMainLooper())) } private fun setIncludeTestInterfaces(value: Boolean) { @@ -150,8 +186,8 @@ class EthernetManagerTest { } } - private fun removeInterface(iface: TestNetworkInterface) { - iface.fileDescriptor.close() + private fun removeInterface(iface: EthernetTestInterface) { + iface.destroy() createdIfaces.remove(iface) } @@ -193,15 +229,15 @@ class EthernetManagerTest { val iface2 = createInterface() var ifaces = em.getInterfaceList() assertTrue(ifaces.size > 0) - assertTrue(ifaces.contains(iface1.getInterfaceName())) - assertTrue(ifaces.contains(iface2.getInterfaceName())) + assertTrue(ifaces.contains(iface1.interfaceName)) + assertTrue(ifaces.contains(iface2.interfaceName)) // Remove one existing test interface and check the return list doesn't contain the // removed interface name. removeInterface(iface1) ifaces = em.getInterfaceList() - assertFalse(ifaces.contains(iface1.getInterfaceName())) - assertTrue(ifaces.contains(iface2.getInterfaceName())) + assertFalse(ifaces.contains(iface1.interfaceName)) + assertTrue(ifaces.contains(iface2.interfaceName)) removeInterface(iface2) }