diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index 2b76dd935f..886d19499c 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -32,13 +32,13 @@ import android.content.pm.PackageManager; import android.os.Build; import android.os.OutcomeReceiver; import android.os.RemoteException; +import android.util.ArrayMap; import com.android.internal.annotations.GuardedBy; import com.android.modules.utils.BackgroundThread; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; @@ -56,37 +56,12 @@ public class EthernetManager { private final IEthernetManager mService; @GuardedBy("mListenerLock") - private final ArrayList> mIfaceListeners = - new ArrayList<>(); + private final ArrayMap + mIfaceServiceListeners = new ArrayMap<>(); @GuardedBy("mListenerLock") - private final ArrayList> mEthernetStateListeners = - new ArrayList<>(); + private final ArrayMap mStateServiceListeners = + new ArrayMap<>(); final Object mListenerLock = new Object(); - private final IEthernetServiceListener.Stub mServiceListener = - new IEthernetServiceListener.Stub() { - @Override - public void onEthernetStateChanged(int state) { - synchronized (mListenerLock) { - for (ListenerInfo li : mEthernetStateListeners) { - li.executor.execute(() -> { - li.listener.accept(state); - }); - } - } - } - - @Override - public void onInterfaceStateChanged(String iface, int state, int role, - IpConfiguration configuration) { - synchronized (mListenerLock) { - for (ListenerInfo li : mIfaceListeners) { - li.executor.execute(() -> - li.listener.onInterfaceStateChanged(iface, state, role, - configuration)); - } - } - } - }; /** * Indicates that Ethernet is disabled. @@ -104,18 +79,6 @@ public class EthernetManager { @SystemApi(client = MODULE_LIBRARIES) public static final int ETHERNET_STATE_ENABLED = 1; - private static class ListenerInfo { - @NonNull - public final Executor executor; - @NonNull - public final T listener; - - private ListenerInfo(@NonNull Executor executor, @NonNull T listener) { - this.executor = executor; - this.listener = listener; - } - } - /** * The interface is absent. * @hide @@ -323,18 +286,28 @@ public class EthernetManager { if (listener == null || executor == null) { throw new NullPointerException("listener and executor must not be null"); } + + final IEthernetServiceListener.Stub serviceListener = new IEthernetServiceListener.Stub() { + @Override + public void onEthernetStateChanged(int state) {} + + @Override + public void onInterfaceStateChanged(String iface, int state, int role, + IpConfiguration configuration) { + executor.execute(() -> + listener.onInterfaceStateChanged(iface, state, role, configuration)); + } + }; synchronized (mListenerLock) { - maybeAddServiceListener(); - mIfaceListeners.add(new ListenerInfo(executor, listener)); + addServiceListener(serviceListener); + mIfaceServiceListeners.put(listener, serviceListener); } } @GuardedBy("mListenerLock") - private void maybeAddServiceListener() { - if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return; - + private void addServiceListener(@NonNull final IEthernetServiceListener listener) { try { - mService.addListener(mServiceListener); + mService.addListener(listener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -364,17 +337,16 @@ public class EthernetManager { public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) { Objects.requireNonNull(listener); synchronized (mListenerLock) { - mIfaceListeners.removeIf(l -> l.listener == listener); - maybeRemoveServiceListener(); + maybeRemoveServiceListener(mIfaceServiceListeners.remove(listener)); } } @GuardedBy("mListenerLock") - private void maybeRemoveServiceListener() { - if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return; + private void maybeRemoveServiceListener(@Nullable final IEthernetServiceListener listener) { + if (listener == null) return; try { - mService.removeListener(mServiceListener); + mService.removeListener(listener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -687,9 +659,19 @@ public class EthernetManager { @NonNull IntConsumer listener) { Objects.requireNonNull(executor); Objects.requireNonNull(listener); + final IEthernetServiceListener.Stub serviceListener = new IEthernetServiceListener.Stub() { + @Override + public void onEthernetStateChanged(int state) { + executor.execute(() -> listener.accept(state)); + } + + @Override + public void onInterfaceStateChanged(String iface, int state, int role, + IpConfiguration configuration) {} + }; synchronized (mListenerLock) { - maybeAddServiceListener(); - mEthernetStateListeners.add(new ListenerInfo(executor, listener)); + addServiceListener(serviceListener); + mStateServiceListeners.put(listener, serviceListener); } } @@ -705,8 +687,7 @@ public class EthernetManager { public void removeEthernetStateListener(@NonNull IntConsumer listener) { Objects.requireNonNull(listener); synchronized (mListenerLock) { - mEthernetStateListeners.removeIf(l -> l.listener == listener); - maybeRemoveServiceListener(); + maybeRemoveServiceListener(mStateServiceListeners.remove(listener)); } } diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt index f7a2421b45..04434e545c 100644 --- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt +++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt @@ -75,7 +75,7 @@ class EthernetManagerTest { private val em by lazy { EthernetManagerShimImpl.newInstance(context) } private val createdIfaces = ArrayList() - private val addedListeners = ArrayList() + private val addedListeners = ArrayList() private class EthernetTestInterface( context: Context, @@ -171,7 +171,7 @@ class EthernetManagerTest { } } - private fun addInterfaceStateListener(executor: Executor, listener: InterfaceStateListener) { + private fun addInterfaceStateListener(executor: Executor, listener: EthernetStateListener) { em.addInterfaceStateListener(executor, listener) addedListeners.add(listener) } @@ -212,15 +212,25 @@ class EthernetManagerTest { listener.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT) listener.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT) + // Register a new listener, it should see state of all existing interfaces immediately. + val listener2 = EthernetStateListener() + addInterfaceStateListener(executor, listener2) + listener2.expectCallback(iface, STATE_LINK_UP, ROLE_CLIENT) + listener2.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT) + // Removing interfaces first sends link down, then STATE_ABSENT/ROLE_NONE. removeInterface(iface) - listener.expectCallback(iface, STATE_LINK_DOWN, ROLE_CLIENT) - listener.expectCallback(iface, STATE_ABSENT, ROLE_NONE) + for (listener in addedListeners) { + listener.expectCallback(iface, STATE_LINK_DOWN, ROLE_CLIENT) + listener.expectCallback(iface, STATE_ABSENT, ROLE_NONE) + } removeInterface(iface2) - listener.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT) - listener.expectCallback(iface2, STATE_ABSENT, ROLE_NONE) - listener.assertNoCallback() + for (listener in addedListeners) { + listener.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT) + listener.expectCallback(iface2, STATE_ABSENT, ROLE_NONE) + listener.assertNoCallback() + } } @Test