Run IpClientLinkObserver on Binder thread

This restores previous behavior, where callbacks would not be called on
the IpClient handler thread.

Test: atest FrameworksNetTests NetworkStackTests
Test: flashed, WiFi works
Bug: 123062477
Change-Id: I3015566b0922d76ac7cf70579a1de3e033bf7b4a
This commit is contained in:
Remi NGUYEN VAN
2019-01-29 16:46:48 +09:00
parent 31d7447e04
commit 1bbed8a3b8
3 changed files with 32 additions and 6 deletions

View File

@@ -543,7 +543,7 @@ public class IpClient extends StateMachine {
}
private void startStateMachineUpdaters() {
mObserverRegistry.registerObserver(mLinkObserver, getHandler());
mObserverRegistry.registerObserverForNonblockingCallback(mLinkObserver);
}
private void stopStateMachineUpdaters() {

View File

@@ -24,8 +24,10 @@ import android.net.LinkAddress;
import android.net.RouteInfo;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -35,6 +37,7 @@ import java.util.concurrent.ConcurrentHashMap;
* all INetworkManagementEventObserver objects that have registered with it.
*/
public class NetworkObserverRegistry extends INetdUnsolicitedEventListener.Stub {
private static final String TAG = NetworkObserverRegistry.class.getSimpleName();
/**
* Constructs a new NetworkObserverRegistry.
@@ -53,7 +56,7 @@ public class NetworkObserverRegistry extends INetdUnsolicitedEventListener.Stub
netd.registerUnsolicitedEventListener(this);
}
private final ConcurrentHashMap<NetworkObserver, Handler> mObservers =
private final ConcurrentHashMap<NetworkObserver, Optional<Handler>> mObservers =
new ConcurrentHashMap<>();
/**
@@ -61,7 +64,20 @@ public class NetworkObserverRegistry extends INetdUnsolicitedEventListener.Stub
* This method may be called on any thread.
*/
public void registerObserver(@NonNull NetworkObserver observer, @NonNull Handler handler) {
mObservers.put(observer, handler);
if (handler == null) {
throw new IllegalArgumentException("handler must be non-null");
}
mObservers.put(observer, Optional.of(handler));
}
/**
* Registers the specified observer, and start sending callbacks to it.
*
* <p>This method must only be called with callbacks that are nonblocking, such as callbacks
* that only send a message to a StateMachine.
*/
public void registerObserverForNonblockingCallback(@NonNull NetworkObserver observer) {
mObservers.put(observer, Optional.empty());
}
/**
@@ -80,9 +96,19 @@ public class NetworkObserverRegistry extends INetdUnsolicitedEventListener.Stub
private void invokeForAllObservers(@NonNull final NetworkObserverEventCallback callback) {
// ConcurrentHashMap#entrySet is weakly consistent: observers that were in the map before
// creation will be processed, those added during traversal may or may not.
for (Map.Entry<NetworkObserver, Handler> entry : mObservers.entrySet()) {
for (Map.Entry<NetworkObserver, Optional<Handler>> entry : mObservers.entrySet()) {
final NetworkObserver observer = entry.getKey();
entry.getValue().post(() -> callback.sendCallback(observer));
final Optional<Handler> handler = entry.getValue();
if (handler.isPresent()) {
handler.get().post(() -> callback.sendCallback(observer));
return;
}
try {
callback.sendCallback(observer);
} catch (RuntimeException e) {
Log.e(TAG, "Error sending callback to observer", e);
}
}
}

View File

@@ -129,7 +129,7 @@ public class IpClientTest {
verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(ifname, false);
verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(ifname);
ArgumentCaptor<NetworkObserver> arg = ArgumentCaptor.forClass(NetworkObserver.class);
verify(mObserverRegistry, times(1)).registerObserver(arg.capture(), any());
verify(mObserverRegistry, times(1)).registerObserverForNonblockingCallback(arg.capture());
mObserver = arg.getValue();
reset(mObserverRegistry);
reset(mNetd);