From 4d662c5bde103ccbc01c27207e16d7c69452eb63 Mon Sep 17 00:00:00 2001 From: Nikhil Nayunigari Date: Wed, 15 Jan 2025 22:20:26 +0000 Subject: [PATCH] Adding EthernetInterfaceTracker to support EthernetSettings This class is part of the middleware and will be used to be notified when an EthernetInterface is added or removed. Flag: com.android.settings.connectivity.ethernet_settings Test: atest SettingsRoboTests: com.android.settings.network.EthernetInterfaceTrackerTest Change-Id: If3a1f4d7a96b301cd47ffbea55864bcc780cd1e0 --- .../ethernet/EthernetInterfaceTracker.kt | 75 ++++++++++++++++++ .../ethernet/EthernetInterfaceTrackerTest.kt | 79 +++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 src/com/android/settings/network/ethernet/EthernetInterfaceTracker.kt create mode 100644 tests/robotests/src/com/android/settings/network/ethernet/EthernetInterfaceTrackerTest.kt diff --git a/src/com/android/settings/network/ethernet/EthernetInterfaceTracker.kt b/src/com/android/settings/network/ethernet/EthernetInterfaceTracker.kt new file mode 100644 index 00000000000..ef2ea122dd4 --- /dev/null +++ b/src/com/android/settings/network/ethernet/EthernetInterfaceTracker.kt @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.network.ethernet + +import android.content.Context +import android.net.EthernetManager +import android.net.IpConfiguration +import androidx.core.content.ContextCompat +import java.util.concurrent.Executor + +class EthernetInterfaceTracker(private val context: Context) : + EthernetManager.InterfaceStateListener { + interface EthernetInterfaceListListener { + fun onInterfaceListChanged() + } + + private val ethernetManager = + context.getSystemService(Context.ETHERNET_SERVICE) as EthernetManager + private val TAG = "EthernetInterfaceTracker" + + // Maps ethernet interface identifier to EthernetInterface object + private val ethernetInterfaces = mutableMapOf() + private val interfaceListeners = mutableListOf() + private val mExecutor = ContextCompat.getMainExecutor(context) + + init { + ethernetManager.addInterfaceStateListener(mExecutor, this) + } + + fun getInterface(id: String): EthernetInterface? { + return ethernetInterfaces.get(id) + } + + fun getAvailableInterfaces(): Collection { + return ethernetInterfaces.values + } + + fun registerInterfaceListener(listener: EthernetInterfaceListListener) { + interfaceListeners.add(listener) + } + + fun unregisterInterfaceListener(listener: EthernetInterfaceListListener) { + interfaceListeners.remove(listener) + } + + override fun onInterfaceStateChanged(id: String, state: Int, role: Int, cfg: IpConfiguration?) { + var interfacesChanged = false + if (!ethernetInterfaces.contains(id) && state != EthernetManager.STATE_ABSENT) { + ethernetInterfaces.put(id, EthernetInterface(context, id)) + interfacesChanged = true + } else if (ethernetInterfaces.contains(id) && state == EthernetManager.STATE_ABSENT) { + ethernetInterfaces.remove(id) + interfacesChanged = true + } + if (interfacesChanged) { + for (listener in interfaceListeners) { + listener.onInterfaceListChanged() + } + } + } +} diff --git a/tests/robotests/src/com/android/settings/network/ethernet/EthernetInterfaceTrackerTest.kt b/tests/robotests/src/com/android/settings/network/ethernet/EthernetInterfaceTrackerTest.kt new file mode 100644 index 00000000000..369eb1a5515 --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/ethernet/EthernetInterfaceTrackerTest.kt @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.network.ethernet + +import android.content.Context +import android.content.ContextWrapper +import android.net.EthernetManager +import android.net.IpConfiguration +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.mock + +@RunWith(AndroidJUnit4::class) +class EthernetInterfaceTrackerTest { + private val mockEthernetManager = mock() + + private val context: Context = + object : ContextWrapper(ApplicationProvider.getApplicationContext()) { + override fun getSystemService(name: String): Any? = + when (name) { + Context.ETHERNET_SERVICE -> mockEthernetManager + else -> super.getSystemService(name) + } + } + + private val ethernetInterfaceTracker = EthernetInterfaceTracker(context) + + @Test + fun getInterface_shouldReturnEmpty() { + assertNull(ethernetInterfaceTracker.getInterface("id0")) + } + + @Test + fun getAvailableInterfaces_shouldReturnEmpty() { + assertEquals(ethernetInterfaceTracker.getAvailableInterfaces().size, 0) + } + + @Test + fun interfacesChanged_shouldUpdateInterfaces() { + ethernetInterfaceTracker.onInterfaceStateChanged( + "id0", + EthernetManager.STATE_LINK_DOWN, + EthernetManager.ROLE_NONE, + IpConfiguration(), + ) + + assertNotNull(ethernetInterfaceTracker.getInterface("id0")) + assertEquals(ethernetInterfaceTracker.getAvailableInterfaces().size, 1) + + ethernetInterfaceTracker.onInterfaceStateChanged( + "id0", + EthernetManager.STATE_ABSENT, + EthernetManager.ROLE_NONE, + IpConfiguration(), + ) + + assertNull(ethernetInterfaceTracker.getInterface("id0")) + assertEquals(ethernetInterfaceTracker.getAvailableInterfaces().size, 0) + } +}