Add private DNS validation thread tracker

The behavior is that the different dns changed in 10ms every 3-5s,
and this dns vibrate will be set by DnsResolver. In ResolverController,
will start one thread for validate each dns server. If dns server removed,
and the trace of dns server will be erased too, but dns validate thread
not destory immediately.
So for this scene will start new thread for dns vibrate in 10ms,
and many thread will cause OOM.

Test:
We verified this solution in that special user environment and merged it
at end of Feb 2019.
We didn't get any regression issue report so far (Sep 2019)

Bug: 139782337

Change-Id: I88431d77f575ccffa5af7c596a915f223e515027
diff --git a/PrivateDnsConfiguration.cpp b/PrivateDnsConfiguration.cpp
index f59e64e..a9fb7ed 100644
--- a/PrivateDnsConfiguration.cpp
+++ b/PrivateDnsConfiguration.cpp
@@ -97,6 +97,7 @@
         mPrivateDnsModes[netId] = PrivateDnsMode::OFF;
         mPrivateDnsTransports.erase(netId);
         resolv_stats_set_servers_for_dot(netId, {});
+        mPrivateDnsValidateThreads.erase(netId);
         return 0;
     }
 
@@ -155,6 +156,7 @@
     std::lock_guard guard(mPrivateDnsLock);
     mPrivateDnsModes.erase(netId);
     mPrivateDnsTransports.erase(netId);
+    mPrivateDnsValidateThreads.erase(netId);
 }
 
 void PrivateDnsConfiguration::validatePrivateDnsProvider(const DnsTlsServer& server,
@@ -163,6 +165,10 @@
     tracker[server] = Validation::in_process;
     LOG(DEBUG) << "Server " << addrToString(&server.ss) << " marked as in_process on netId "
                << netId << ". Tracker now has size " << tracker.size();
+    // This judge must be after "tracker[server] = Validation::in_process;"
+    if (!needValidateThread(server, netId)) {
+        return;
+    }
 
     // Note that capturing |server| and |netId| in this lambda create copies.
     std::thread validate_thread([this, server, netId, mark] {
@@ -205,6 +211,7 @@
                 break;
             }
         }
+        this->cleanValidateThreadTracker(server, netId);
     });
     validate_thread.detach();
 }
@@ -279,6 +286,50 @@
     return reevaluationStatus;
 }
 
+bool PrivateDnsConfiguration::needValidateThread(const DnsTlsServer& server, unsigned netId)
+        REQUIRES(mPrivateDnsLock) {
+    // Create the thread tracker if it was not present
+    auto threadPair = mPrivateDnsValidateThreads.find(netId);
+    if (threadPair == mPrivateDnsValidateThreads.end()) {
+        // No thread tracker yet for this netId.
+        bool added;
+        std::tie(threadPair, added) = mPrivateDnsValidateThreads.emplace(netId, ThreadTracker());
+        if (!added) {
+            LOG(ERROR) << "Memory error while needValidateThread for netId " << netId;
+            return true;
+        }
+    }
+    auto& threadTracker = threadPair->second;
+    if (threadTracker.count(server)) {
+        LOG(DEBUG) << "Server " << addrToString(&(server.ss))
+                   << " validate thread is already running. Thread tracker now has size "
+                   << threadTracker.size();
+        return false;
+    } else {
+        threadTracker.insert(server);
+        LOG(DEBUG) << "Server " << addrToString(&(server.ss))
+                   << " validate thread is not running. Thread tracker now has size "
+                   << threadTracker.size();
+        return true;
+    }
+}
+
+void PrivateDnsConfiguration::cleanValidateThreadTracker(const DnsTlsServer& server,
+                                                         unsigned netId) {
+    std::lock_guard<std::mutex> guard(mPrivateDnsLock);
+    LOG(DEBUG) << "cleanValidateThreadTracker Server " << addrToString(&(server.ss))
+               << " validate thread is stopped.";
+
+    auto threadPair = mPrivateDnsValidateThreads.find(netId);
+    if (threadPair != mPrivateDnsValidateThreads.end()) {
+        auto& threadTracker = threadPair->second;
+        threadTracker.erase(server);
+        LOG(DEBUG) << "Server " << addrToString(&(server.ss))
+                   << " validate thread is stopped. Thread tracker now has size "
+                   << threadTracker.size();
+    }
+}
+
 // Start validation for newly added servers as well as any servers that have
 // landed in Validation::fail state. Note that servers that have failed
 // multiple validation attempts but for which there is still a validating