Merge "Do not block for HandlerThread start" into main
This commit is contained in:
commit
b68837ea09
1 changed files with 88 additions and 29 deletions
|
|
@ -16,18 +16,19 @@
|
|||
|
||||
package com.android.server.connectivity.mdns;
|
||||
|
||||
import static com.android.server.connectivity.mdns.util.MdnsUtils.ensureRunningOnHandlerThread;
|
||||
|
||||
import android.Manifest.permission;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.GuardedBy;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils;
|
||||
|
|
@ -36,6 +37,7 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* This class keeps tracking the set of registered {@link MdnsServiceBrowserListener} instances, and
|
||||
|
|
@ -50,11 +52,12 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
|||
@NonNull private final SharedLog sharedLog;
|
||||
|
||||
@NonNull private final PerSocketServiceTypeClients perSocketServiceTypeClients;
|
||||
@NonNull private final Handler handler;
|
||||
@Nullable private final HandlerThread handlerThread;
|
||||
@NonNull private final MdnsServiceCache serviceCache;
|
||||
@NonNull private final DiscoveryExecutor discoveryExecutor;
|
||||
@NonNull private final MdnsFeatureFlags mdnsFeatureFlags;
|
||||
|
||||
// Only accessed on the handler thread, set to non-null right after initializing the handler
|
||||
private MdnsServiceCache serviceCache;
|
||||
|
||||
private static class PerSocketServiceTypeClients {
|
||||
private final ArrayMap<Pair<String, SocketKey>, MdnsServiceTypeClient> clients =
|
||||
new ArrayMap<>();
|
||||
|
|
@ -125,33 +128,87 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
|||
this.sharedLog = sharedLog;
|
||||
this.perSocketServiceTypeClients = new PerSocketServiceTypeClients();
|
||||
this.mdnsFeatureFlags = mdnsFeatureFlags;
|
||||
if (socketClient.getLooper() != null) {
|
||||
this.handlerThread = null;
|
||||
this.handler = new Handler(socketClient.getLooper());
|
||||
this.serviceCache = new MdnsServiceCache(socketClient.getLooper(), mdnsFeatureFlags);
|
||||
} else {
|
||||
this.handlerThread = new HandlerThread(MdnsDiscoveryManager.class.getSimpleName());
|
||||
this.handlerThread.start();
|
||||
this.handler = new Handler(handlerThread.getLooper());
|
||||
this.serviceCache = new MdnsServiceCache(handlerThread.getLooper(), mdnsFeatureFlags);
|
||||
}
|
||||
this.discoveryExecutor = new DiscoveryExecutor(socketClient.getLooper());
|
||||
|
||||
// The very first posted task is to initialize the service cache, so it will be always
|
||||
// set in other tasks running on the handler
|
||||
discoveryExecutor.execute(() ->
|
||||
serviceCache = new MdnsServiceCache(Looper.myLooper(), mdnsFeatureFlags));
|
||||
}
|
||||
|
||||
private void checkAndRunOnHandlerThread(@NonNull Runnable function) {
|
||||
if (this.handlerThread == null) {
|
||||
function.run();
|
||||
} else {
|
||||
private static class DiscoveryExecutor implements Executor {
|
||||
private final HandlerThread handlerThread;
|
||||
|
||||
@GuardedBy("pendingTasks")
|
||||
@Nullable private Handler handler;
|
||||
@GuardedBy("pendingTasks")
|
||||
@NonNull private final ArrayList<Runnable> pendingTasks = new ArrayList<>();
|
||||
|
||||
DiscoveryExecutor(@Nullable Looper defaultLooper) {
|
||||
if (defaultLooper != null) {
|
||||
this.handlerThread = null;
|
||||
synchronized (pendingTasks) {
|
||||
this.handler = new Handler(defaultLooper);
|
||||
}
|
||||
} else {
|
||||
this.handlerThread = new HandlerThread(MdnsDiscoveryManager.class.getSimpleName()) {
|
||||
@Override
|
||||
protected void onLooperPrepared() {
|
||||
synchronized (pendingTasks) {
|
||||
handler = new Handler(getLooper());
|
||||
for (Runnable pendingTask : pendingTasks) {
|
||||
handler.post(pendingTask);
|
||||
}
|
||||
pendingTasks.clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
this.handlerThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void checkAndRunOnHandlerThread(@NonNull Runnable function) {
|
||||
if (this.handlerThread == null) {
|
||||
// Callers are expected to already be running on the handler when a defaultLooper
|
||||
// was provided
|
||||
function.run();
|
||||
} else {
|
||||
execute(function);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable function) {
|
||||
final Handler handler;
|
||||
synchronized (pendingTasks) {
|
||||
if (this.handler == null) {
|
||||
pendingTasks.add(function);
|
||||
return;
|
||||
} else {
|
||||
handler = this.handler;
|
||||
}
|
||||
}
|
||||
handler.post(function);
|
||||
}
|
||||
|
||||
void shutDown() {
|
||||
if (this.handlerThread != null) {
|
||||
this.handlerThread.quitSafely();
|
||||
}
|
||||
}
|
||||
|
||||
void ensureRunningOnHandlerThread() {
|
||||
synchronized (pendingTasks) {
|
||||
MdnsUtils.ensureRunningOnHandlerThread(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the cleanup of the MdnsDiscoveryManager
|
||||
*/
|
||||
public void shutDown() {
|
||||
if (this.handlerThread != null) {
|
||||
this.handlerThread.quitSafely();
|
||||
}
|
||||
discoveryExecutor.shutDown();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -169,7 +226,7 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
|||
@NonNull MdnsServiceBrowserListener listener,
|
||||
@NonNull MdnsSearchOptions searchOptions) {
|
||||
sharedLog.i("Registering listener for serviceType: " + serviceType);
|
||||
checkAndRunOnHandlerThread(() ->
|
||||
discoveryExecutor.checkAndRunOnHandlerThread(() ->
|
||||
handleRegisterListener(serviceType, listener, searchOptions));
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +248,7 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
|||
new MdnsSocketClientBase.SocketCreationCallback() {
|
||||
@Override
|
||||
public void onSocketCreated(@NonNull SocketKey socketKey) {
|
||||
ensureRunningOnHandlerThread(handler);
|
||||
discoveryExecutor.ensureRunningOnHandlerThread();
|
||||
// All listeners of the same service types shares the same
|
||||
// MdnsServiceTypeClient.
|
||||
MdnsServiceTypeClient serviceTypeClient =
|
||||
|
|
@ -206,7 +263,7 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
|||
|
||||
@Override
|
||||
public void onSocketDestroyed(@NonNull SocketKey socketKey) {
|
||||
ensureRunningOnHandlerThread(handler);
|
||||
discoveryExecutor.ensureRunningOnHandlerThread();
|
||||
final MdnsServiceTypeClient serviceTypeClient =
|
||||
perSocketServiceTypeClients.get(serviceType, socketKey);
|
||||
if (serviceTypeClient == null) return;
|
||||
|
|
@ -229,7 +286,8 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
|||
public void unregisterListener(
|
||||
@NonNull String serviceType, @NonNull MdnsServiceBrowserListener listener) {
|
||||
sharedLog.i("Unregistering listener for serviceType:" + serviceType);
|
||||
checkAndRunOnHandlerThread(() -> handleUnregisterListener(serviceType, listener));
|
||||
discoveryExecutor.checkAndRunOnHandlerThread(() ->
|
||||
handleUnregisterListener(serviceType, listener));
|
||||
}
|
||||
|
||||
private void handleUnregisterListener(
|
||||
|
|
@ -260,7 +318,7 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
|||
|
||||
@Override
|
||||
public void onResponseReceived(@NonNull MdnsPacket packet, @NonNull SocketKey socketKey) {
|
||||
checkAndRunOnHandlerThread(() ->
|
||||
discoveryExecutor.checkAndRunOnHandlerThread(() ->
|
||||
handleOnResponseReceived(packet, socketKey));
|
||||
}
|
||||
|
||||
|
|
@ -282,7 +340,7 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
|||
@Override
|
||||
public void onFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode,
|
||||
@NonNull SocketKey socketKey) {
|
||||
checkAndRunOnHandlerThread(() ->
|
||||
discoveryExecutor.checkAndRunOnHandlerThread(() ->
|
||||
handleOnFailedToParseMdnsResponse(receivedPacketNumber, errorCode, socketKey));
|
||||
}
|
||||
|
||||
|
|
@ -296,12 +354,13 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
|||
@VisibleForTesting
|
||||
MdnsServiceTypeClient createServiceTypeClient(@NonNull String serviceType,
|
||||
@NonNull SocketKey socketKey) {
|
||||
discoveryExecutor.ensureRunningOnHandlerThread();
|
||||
sharedLog.log("createServiceTypeClient for type:" + serviceType + " " + socketKey);
|
||||
final String tag = serviceType + "-" + socketKey.getNetwork()
|
||||
+ "/" + socketKey.getInterfaceIndex();
|
||||
return new MdnsServiceTypeClient(
|
||||
serviceType, socketClient,
|
||||
executorProvider.newServiceTypeClientSchedulerExecutor(), socketKey,
|
||||
sharedLog.forSubComponent(tag), handler.getLooper(), serviceCache);
|
||||
sharedLog.forSubComponent(tag), Looper.myLooper(), serviceCache);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue