diff options
Diffstat (limited to 'framework-t/src')
| -rw-r--r-- | framework-t/src/android/net/nsd/NsdManager.java | 61 |
1 files changed, 39 insertions, 22 deletions
diff --git a/framework-t/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java index 33b44c8210..f19bf4a6fb 100644 --- a/framework-t/src/android/net/nsd/NsdManager.java +++ b/framework-t/src/android/net/nsd/NsdManager.java @@ -312,9 +312,12 @@ public final class NsdManager { @Override public void onAvailable(@NonNull Network network) { final DelegatingDiscoveryListener wrappedListener = new DelegatingDiscoveryListener( - network, mBaseListener); + network, mBaseListener, mBaseExecutor); mPerNetworkListeners.put(network, wrappedListener); - discoverServices(mServiceType, mProtocolType, network, mBaseExecutor, + // Run discovery callbacks inline on the service handler thread, which is the + // same thread used by this NetworkCallback, but DelegatingDiscoveryListener will + // use the base executor to run the wrapped callbacks. + discoverServices(mServiceType, mProtocolType, network, Runnable::run, wrappedListener); } @@ -334,7 +337,8 @@ public final class NsdManager { public void start(@NonNull NetworkRequest request) { final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); cm.registerNetworkCallback(request, mNetworkCb, mHandler); - mHandler.post(() -> mBaseListener.onDiscoveryStarted(mServiceType)); + mHandler.post(() -> mBaseExecutor.execute(() -> + mBaseListener.onDiscoveryStarted(mServiceType))); } /** @@ -351,7 +355,7 @@ public final class NsdManager { final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); cm.unregisterNetworkCallback(mNetworkCb); if (mPerNetworkListeners.size() == 0) { - mBaseListener.onDiscoveryStopped(mServiceType); + mBaseExecutor.execute(() -> mBaseListener.onDiscoveryStopped(mServiceType)); return; } for (int i = 0; i < mPerNetworkListeners.size(); i++) { @@ -399,14 +403,23 @@ public final class NsdManager { } } + /** + * A listener wrapping calls to an app-provided listener, while keeping track of found + * services, so they can all be reported lost when the underlying network is lost. + * + * This should be registered to run on the service handler. + */ private class DelegatingDiscoveryListener implements DiscoveryListener { private final Network mNetwork; private final DiscoveryListener mWrapped; + private final Executor mWrappedExecutor; private final ArraySet<TrackedNsdInfo> mFoundInfo = new ArraySet<>(); - private DelegatingDiscoveryListener(Network network, DiscoveryListener listener) { + private DelegatingDiscoveryListener(Network network, DiscoveryListener listener, + Executor executor) { mNetwork = network; mWrapped = listener; + mWrappedExecutor = executor; } void notifyAllServicesLost() { @@ -415,7 +428,7 @@ public final class NsdManager { final NsdServiceInfo serviceInfo = new NsdServiceInfo( trackedInfo.mServiceName, trackedInfo.mServiceType); serviceInfo.setNetwork(mNetwork); - mWrapped.onServiceLost(serviceInfo); + mWrappedExecutor.execute(() -> mWrapped.onServiceLost(serviceInfo)); } } @@ -444,7 +457,7 @@ public final class NsdManager { // Do not report onStopDiscoveryFailed when some underlying listeners failed: // this does not mean that all listeners did, and onStopDiscoveryFailed is not // actionable anyway. Just report that discovery stopped. - mWrapped.onDiscoveryStopped(serviceType); + mWrappedExecutor.execute(() -> mWrapped.onDiscoveryStopped(serviceType)); } } @@ -452,20 +465,20 @@ public final class NsdManager { public void onDiscoveryStopped(String serviceType) { mPerNetworkListeners.remove(mNetwork); if (mStopRequested && mPerNetworkListeners.size() == 0) { - mWrapped.onDiscoveryStopped(serviceType); + mWrappedExecutor.execute(() -> mWrapped.onDiscoveryStopped(serviceType)); } } @Override public void onServiceFound(NsdServiceInfo serviceInfo) { mFoundInfo.add(new TrackedNsdInfo(serviceInfo)); - mWrapped.onServiceFound(serviceInfo); + mWrappedExecutor.execute(() -> mWrapped.onServiceFound(serviceInfo)); } @Override public void onServiceLost(NsdServiceInfo serviceInfo) { mFoundInfo.remove(new TrackedNsdInfo(serviceInfo)); - mWrapped.onServiceLost(serviceInfo); + mWrappedExecutor.execute(() -> mWrapped.onServiceLost(serviceInfo)); } } } @@ -648,8 +661,12 @@ public final class NsdManager { @Override public void handleMessage(Message message) { + // Do not use message in the executor lambdas, as it will be recycled once this method + // returns. Keep references to its content instead. final int what = message.what; + final int errorCode = message.arg1; final int key = message.arg2; + final Object obj = message.obj; final Object listener; final NsdServiceInfo ns; final Executor executor; @@ -659,7 +676,7 @@ public final class NsdManager { executor = mExecutorMap.get(key); } if (listener == null) { - Log.d(TAG, "Stale key " + message.arg2); + Log.d(TAG, "Stale key " + key); return; } if (DBG) { @@ -667,28 +684,28 @@ public final class NsdManager { } switch (what) { case DISCOVER_SERVICES_STARTED: - final String s = getNsdServiceInfoType((NsdServiceInfo) message.obj); + final String s = getNsdServiceInfoType((NsdServiceInfo) obj); executor.execute(() -> ((DiscoveryListener) listener).onDiscoveryStarted(s)); break; case DISCOVER_SERVICES_FAILED: removeListener(key); executor.execute(() -> ((DiscoveryListener) listener).onStartDiscoveryFailed( - getNsdServiceInfoType(ns), message.arg1)); + getNsdServiceInfoType(ns), errorCode)); break; case SERVICE_FOUND: executor.execute(() -> ((DiscoveryListener) listener).onServiceFound( - (NsdServiceInfo) message.obj)); + (NsdServiceInfo) obj)); break; case SERVICE_LOST: executor.execute(() -> ((DiscoveryListener) listener).onServiceLost( - (NsdServiceInfo) message.obj)); + (NsdServiceInfo) obj)); break; case STOP_DISCOVERY_FAILED: // TODO: failure to stop discovery should be internal and retried internally, as // the effect for the client is indistinguishable from STOP_DISCOVERY_SUCCEEDED removeListener(key); executor.execute(() -> ((DiscoveryListener) listener).onStopDiscoveryFailed( - getNsdServiceInfoType(ns), message.arg1)); + getNsdServiceInfoType(ns), errorCode)); break; case STOP_DISCOVERY_SUCCEEDED: removeListener(key); @@ -698,33 +715,33 @@ public final class NsdManager { case REGISTER_SERVICE_FAILED: removeListener(key); executor.execute(() -> ((RegistrationListener) listener).onRegistrationFailed( - ns, message.arg1)); + ns, errorCode)); break; case REGISTER_SERVICE_SUCCEEDED: executor.execute(() -> ((RegistrationListener) listener).onServiceRegistered( - (NsdServiceInfo) message.obj)); + (NsdServiceInfo) obj)); break; case UNREGISTER_SERVICE_FAILED: removeListener(key); executor.execute(() -> ((RegistrationListener) listener).onUnregistrationFailed( - ns, message.arg1)); + ns, errorCode)); break; case UNREGISTER_SERVICE_SUCCEEDED: // TODO: do not unregister listener until service is unregistered, or provide // alternative way for unregistering ? - removeListener(message.arg2); + removeListener(key); executor.execute(() -> ((RegistrationListener) listener).onServiceUnregistered( ns)); break; case RESOLVE_SERVICE_FAILED: removeListener(key); executor.execute(() -> ((ResolveListener) listener).onResolveFailed( - ns, message.arg1)); + ns, errorCode)); break; case RESOLVE_SERVICE_SUCCEEDED: removeListener(key); executor.execute(() -> ((ResolveListener) listener).onServiceResolved( - (NsdServiceInfo) message.obj)); + (NsdServiceInfo) obj)); break; default: Log.d(TAG, "Ignored " + message); |
