Clean up gPrivateDnsConfiguration

Use singleton to get an instance of PrivateDnsConfiguration.
The lifetime of the instance is almost aligned with the
DnsResolver service.

Bug: 130686826
Test: cd packages/modules/DnsResolver && atest
Change-Id: Id71f90c7d0508eacd1b20db42408a78d9ea1e03a
diff --git a/DnsProxyListener.cpp b/DnsProxyListener.cpp
index a177913..df5d873 100644
--- a/DnsProxyListener.cpp
+++ b/DnsProxyListener.cpp
@@ -116,7 +116,7 @@
 }
 
 bool queryingViaTls(unsigned dns_netid) {
-    const auto privateDnsStatus = gPrivateDnsConfiguration.getStatus(dns_netid);
+    const auto privateDnsStatus = PrivateDnsConfiguration::getInstance().getStatus(dns_netid);
     switch (privateDnsStatus.mode) {
         case PrivateDnsMode::OPPORTUNISTIC:
             return !privateDnsStatus.validatedServers().empty();
@@ -294,7 +294,7 @@
 // Note: Even if it returns PDM_OFF, it doesn't mean there's no DoT stats in the message
 // because Private DNS mode can change at any time.
 PrivateDnsModes getPrivateDnsModeForMetrics(uint32_t netId) {
-    switch (gPrivateDnsConfiguration.getStatus(netId).mode) {
+    switch (PrivateDnsConfiguration::getInstance().getStatus(netId).mode) {
         case PrivateDnsMode::OFF:
             // It can also be due to netId not found.
             return PrivateDnsModes::PDM_OFF;
diff --git a/PrivateDnsConfiguration.cpp b/PrivateDnsConfiguration.cpp
index 182a5ac..7d9e82a 100644
--- a/PrivateDnsConfiguration.cpp
+++ b/PrivateDnsConfiguration.cpp
@@ -350,7 +350,5 @@
     return (iter == tracker.end()) || (iter->second == Validation::fail);
 }
 
-PrivateDnsConfiguration gPrivateDnsConfiguration;
-
 }  // namespace net
 }  // namespace android
diff --git a/PrivateDnsConfiguration.h b/PrivateDnsConfiguration.h
index b66859c..31fb546 100644
--- a/PrivateDnsConfiguration.h
+++ b/PrivateDnsConfiguration.h
@@ -52,6 +52,12 @@
 
 class PrivateDnsConfiguration {
   public:
+    // The only instance of PrivateDnsConfiguration.
+    static PrivateDnsConfiguration& getInstance() {
+        static PrivateDnsConfiguration instance;
+        return instance;
+    }
+
     int set(int32_t netId, uint32_t mark, const std::vector<std::string>& servers,
             const std::string& name, const std::string& caCert) EXCLUDES(mPrivateDnsLock);
 
@@ -63,6 +69,8 @@
     typedef std::map<DnsTlsServer, Validation, AddressComparator> PrivateDnsTracker;
     typedef std::set<DnsTlsServer, AddressComparator> ThreadTracker;
 
+    PrivateDnsConfiguration() = default;
+
     void validatePrivateDnsProvider(const DnsTlsServer& server, PrivateDnsTracker& tracker,
                                     unsigned netId, uint32_t mark) REQUIRES(mPrivateDnsLock);
 
@@ -85,7 +93,5 @@
     std::map<unsigned, ThreadTracker> mPrivateDnsValidateThreads GUARDED_BY(mPrivateDnsLock);
 };
 
-extern PrivateDnsConfiguration gPrivateDnsConfiguration;
-
 }  // namespace net
 }  // namespace android
diff --git a/ResolverController.cpp b/ResolverController.cpp
index be0b989..6a10326 100644
--- a/ResolverController.cpp
+++ b/ResolverController.cpp
@@ -184,7 +184,7 @@
 
     resolv_delete_cache_for_net(netId);
     mDns64Configuration.stopPrefixDiscovery(netId);
-    gPrivateDnsConfiguration.clear(netId);
+    PrivateDnsConfiguration::getInstance().clear(netId);
 }
 
 int ResolverController::createNetworkCache(unsigned netId) {
@@ -215,9 +215,9 @@
     // through a different network. For example, on a VPN with no DNS servers (Do53), if the VPN
     // applies to UID 0, dns_mark is assigned for default network rathan the VPN. (note that it's
     // possible that a VPN doesn't have any DNS servers but DoT servers in DNS strict mode)
-    const int err =
-            gPrivateDnsConfiguration.set(resolverParams.netId, netcontext.app_mark, tlsServers,
-                                         resolverParams.tlsName, resolverParams.caCertificate);
+    const int err = PrivateDnsConfiguration::getInstance().set(
+            resolverParams.netId, netcontext.app_mark, tlsServers, resolverParams.tlsName,
+            resolverParams.caCertificate);
 
     if (err != 0) {
         return err;
@@ -254,7 +254,7 @@
     // Serialize the information for binder.
     ResolverStats::encodeAll(res_stats, stats);
 
-    const auto privateDnsStatus = gPrivateDnsConfiguration.getStatus(netId);
+    const auto privateDnsStatus = PrivateDnsConfiguration::getInstance().getStatus(netId);
     for (const auto& pair : privateDnsStatus.serversMap) {
         tlsServers->push_back(addrToString(&pair.first.ss));
     }
@@ -347,7 +347,7 @@
         }
 
         mDns64Configuration.dump(dw, netId);
-        const auto privateDnsStatus = gPrivateDnsConfiguration.getStatus(netId);
+        const auto privateDnsStatus = PrivateDnsConfiguration::getInstance().getStatus(netId);
         dw.println("Private DNS mode: %s", getPrivateDnsModeString(privateDnsStatus.mode));
         if (privateDnsStatus.serversMap.size() == 0) {
             dw.println("No Private DNS servers configured");
diff --git a/res_send.cpp b/res_send.cpp
index fe38994..5d93112 100644
--- a/res_send.cpp
+++ b/res_send.cpp
@@ -125,7 +125,6 @@
 using android::net::DnsQueryEvent;
 using android::net::DnsTlsDispatcher;
 using android::net::DnsTlsTransport;
-using android::net::gPrivateDnsConfiguration;
 using android::net::IpVersion;
 using android::net::IV_IPV4;
 using android::net::IV_IPV6;
@@ -135,6 +134,7 @@
 using android::net::NS_T_INVALID;
 using android::net::NsRcode;
 using android::net::NsType;
+using android::net::PrivateDnsConfiguration;
 using android::net::PrivateDnsMode;
 using android::net::PrivateDnsModes;
 using android::net::PrivateDnsStatus;
@@ -1209,7 +1209,8 @@
     int resplen = 0;
     const unsigned netId = statp->netid;
 
-    PrivateDnsStatus privateDnsStatus = gPrivateDnsConfiguration.getStatus(netId);
+    auto& privateDnsConfiguration = PrivateDnsConfiguration::getInstance();
+    PrivateDnsStatus privateDnsStatus = privateDnsConfiguration.getStatus(netId);
     statp->event->set_private_dns_modes(convertEnumType(privateDnsStatus.mode));
 
     if (privateDnsStatus.mode == PrivateDnsMode::OFF) {
@@ -1238,8 +1239,8 @@
                 std::this_thread::sleep_for(std::chrono::milliseconds(100));
                 // Calling getStatus() to merely check if there's any validated server seems
                 // wasteful. Consider adding a new method in PrivateDnsConfiguration for speed ups.
-                if (!gPrivateDnsConfiguration.getStatus(netId).validatedServers().empty()) {
-                    privateDnsStatus = gPrivateDnsConfiguration.getStatus(netId);
+                if (!privateDnsConfiguration.getStatus(netId).validatedServers().empty()) {
+                    privateDnsStatus = privateDnsConfiguration.getStatus(netId);
                     break;
                 }
             }
diff --git a/tests/resolv_gold_test.cpp b/tests/resolv_gold_test.cpp
index 2179ce2..e8df5f6 100644
--- a/tests/resolv_gold_test.cpp
+++ b/tests/resolv_gold_test.cpp
@@ -85,7 +85,7 @@
 
     void TearDown() override {
         // Clear TLS configuration for test
-        gPrivateDnsConfiguration.clear(TEST_NETID);
+        privateDnsConfiguration.clear(TEST_NETID);
         // Delete cache for test
         resolv_delete_cache_for_net(TEST_NETID);
     }
@@ -106,8 +106,8 @@
         fwmark.explicitlySelected = true;
         fwmark.protectedFromVpn = true;
         fwmark.permission = PERMISSION_SYSTEM;
-        ASSERT_EQ(gPrivateDnsConfiguration.set(TEST_NETID, fwmark.intValue, tlsServers, tlsHostname,
-                                               caCert),
+        ASSERT_EQ(privateDnsConfiguration.set(TEST_NETID, fwmark.intValue, tlsServers, tlsHostname,
+                                              caCert),
                   0);
         ASSERT_EQ(resolv_set_nameservers(TEST_NETID, servers, domains, kParams), 0);
     }
@@ -129,7 +129,7 @@
         android::base::Timer t;
         while (t.duration() < timeoutMs) {
             const auto& validatedServers =
-                    gPrivateDnsConfiguration.getStatus(TEST_NETID).validatedServers();
+                    privateDnsConfiguration.getStatus(TEST_NETID).validatedServers();
             for (const auto& server : validatedServers) {
                 if (serverAddr == ToString(&server.ss)) return true;
             }
@@ -273,6 +273,10 @@
             // packages/modules/DnsResolver/DnsProxyListener.cpp.
             .flags = NET_CONTEXT_FLAG_USE_DNS_OVER_TLS | NET_CONTEXT_FLAG_USE_EDNS,
     };
+
+  private:
+    // Only one instance is created and used across tests.
+    PrivateDnsConfiguration& privateDnsConfiguration = PrivateDnsConfiguration::getInstance();
 };
 class ResolvGetAddrInfo : public TestBase {};