I'm attempting to perform service discovery on my company's proprietary hardware device which hosts its own WiFi network and advertises a bonjour service over that network. When I'm connected to that WiFi network, I'm using NSD to discover that service and resolve it.
The code is pretty simple and generally works great and quickly. Except I'm having a fairly recurring issue (~5 out of 10 attempts) so far localized to my Samsung S8+. Cannot reproduce on a S6 or Pixel XL so far.
The issue is that DiscoveryListener never does anything beyond onDiscoveryStarted(), it just runs forever. If I kill the app and start over, sometimes it works sometimes it continues to hang.
It's like there's a blocked thread or something, but there is no useful info in the logs (that I can find) and nothing I have yet found to latch on to as something I can do to recover from this.
I have added a timeout that will stop the listener after 30 seconds, but generally when I retry after that it still doesn't work.
The service discovery process is wrapped in a LiveData, which starts it upon active.
const val SERVICE_TYPE_FOO = "_foo._tcp."
private val serviceDiscoveryListener = ServiceDiscoveryListener()
override fun onActive() {
super.onActive()
stopRunnable = StopDiscoveryRunnable()
nsdManager.discoverServices(
SERVICE_TYPE_FOO,
NsdManager.PROTOCOL_DNS_SD,
serviceDiscoveryListener
)
handler.postDelayed(stopRunnable, SERVICE_DISCOVERY_TIMEOUT_MS)
}
private lateinit var stopRunnable: Runnable
private inner class StopDiscoveryRunnable : Runnable {
override fun run() {
try {
nsdManager.stopServiceDiscovery(serviceDiscoveryListener)
Timber.w("service discovery timed out")
postValue(ServiceDiscoveryState.Error)
} catch (e: Throwable) {
// no-op
}
}
}
The listeners are very simple...
private inner class ServiceDiscoveryListener : NsdManager.DiscoveryListener {
override fun onServiceFound(serviceInfo: NsdServiceInfo?) {
if (serviceInfo != null) {
if (serviceInfo.serviceName.isNotEmpty() &&
serviceInfo.serviceName.containsFoo()
) {
nsdManager.resolveService(serviceInfo, ResolveListener())
handler.removeCallbacks(stopRunnable)
}
}
}
override fun onStopDiscoveryFailed(serviceType: String?, errorCode: Int) {
Timber.d("stop discovery failed")
nsdManager.stopServiceDiscovery(this)
postValue(ServiceDiscoveryState.Error)
}
override fun onStartDiscoveryFailed(serviceType: String?, errorCode: Int) {
Timber.d("start discovery failed")
nsdManager.stopServiceDiscovery(this)
postValue(ServiceDiscoveryState.Error)
}
override fun onDiscoveryStarted(serviceType: String?) {
Timber.d("discovery started")
}
override fun onDiscoveryStopped(serviceType: String?) {
Timber.d("discovery stopped")
}
override fun onServiceLost(serviceInfo: NsdServiceInfo?) {
Timber.d("discovery service lost")
postValue(ServiceDiscoveryState.Error)
}
}
private inner class ResolveListener : NsdManager.ResolveListener {
override fun onResolveFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) {
Timber.d("resolve failed. errorCode = $errorCode")
if (errorCode != NsdManager.FAILURE_ALREADY_ACTIVE) {
Timber.d("not already active, so error")
postValue(ServiceDiscoveryState.Error)
} else {
Timber.d("already active")
}
}
override fun onServiceResolved(serviceInfo: NsdServiceInfo?) {
if (serviceInfo != null) {
Timber.d("resolved service: ${serviceInfo.serviceName} host: ${serviceInfo.host}:${serviceInfo.port} type: ${serviceInfo.serviceType}")
postValue(ServiceDiscoveryState.FooService(serviceInfo))
}
}
}
I have not been able to find much of value in the logs, although I did see this one message when things were not working. Attempts to search for answers about this have not been fruitful.
04-26 13:50:14.541 953-1218/? W//system/bin/netd: dnssd_clientstub DNSServiceProcessResult called with invalid DNSServiceRef 0x72bb818000 FFFFFFFF DDDDDDDD
What other information can I provide?
I've reproduced the hang using Andriy Druk's bonjour Service Browser sample code on my S8+, which doesn't even use NSD... so it seems that perhaps the problem is in the core mDNS code and not specific to Google's NSD implementation?
Is there some system software or bloatware on the S8+ that may be interfering with my use of NSD or mDNS - thread blocking or something?