[mdns] fix race conditions in MdnsAdvertiser
There is a race condition in MdnsAdvertiser when removing the last
service:
1. When the last service is removed, it will call the destroyNow()
to tear down the interface advertiser and schedule a onDestroyed()
callback for MdnsAdvetiser to do further cleanup
2. If another serivce is registered after removing the last service but
before onDestroyed() is invoked, then onAdvertiserDestroyed() will
return false and the InterfaceAdvertiserRequest is kept in the map in
MdnsAdvertiser. This is because the newly registered service is in
the mPendingRestionstrations.
3. The problem is that InterfaceAdvertiserRequest now have no
InterfaceAdvertiser (because the only advertiser has already
destroyed) and cause the newly registered service can't be
advertised.
It needs to schedule onDestroyed() on the handler thread because we
can't do modify-during-iteration, but this introduces the race condition
here.
The fix in this commit changes to not destroy the InterfaceAdvertiser
immediately when the last service is removed but destroy when there are
no pending registrations in the InterfaceAdvertiserRequest.
Test: atest --iterations 100 CtsNetTestCases:android.net.cts.NsdManagerTest#testRegisterService_registerImmediatelyAfterUnregister_serviceFound
Change-Id: I6b6f01e6ddf103d16a8b0296af000dc8262ea65b
5 files changed