Merge "Unicast state of existing ethernet interfaces when registering new Ethernet Listener." am: baa5442dd9

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2076404

Change-Id: I40e3391eb550780c3346cfd70514412d311d74a4
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Treehugger Robot 2022-04-28 13:11:48 +00:00 • committed by Automerger Merge Worker
commit 3da1befe74
2 changed files with 55 additions and 64 deletions

View file

@ -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<ListenerInfo<InterfaceStateListener>> mIfaceListeners =
new ArrayList<>();
private final ArrayMap<InterfaceStateListener, IEthernetServiceListener>
mIfaceServiceListeners = new ArrayMap<>();
@GuardedBy("mListenerLock")
private final ArrayList<ListenerInfo<IntConsumer>> mEthernetStateListeners =
new ArrayList<>();
private final ArrayMap<IntConsumer, IEthernetServiceListener> 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<IntConsumer> 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<InterfaceStateListener> 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<T> {
@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<InterfaceStateListener>(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<IntConsumer>(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));
}
}

View file

@ -75,7 +75,7 @@ class EthernetManagerTest {
private val em by lazy { EthernetManagerShimImpl.newInstance(context) }
private val createdIfaces = ArrayList<EthernetTestInterface>()
private val addedListeners = ArrayList<InterfaceStateListener>()
private val addedListeners = ArrayList<EthernetStateListener>()
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