Merge "Replace manual buffer handling with std::span"
diff --git a/Android.bp b/Android.bp
index 6e7c0b5..8ea035b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -76,7 +76,7 @@
         "binder/android/net/resolv/aidl/**/*.aidl",
     ],
     imports: [
-        "netd_event_listener_interface",
+        "netd_event_listener_interface-V1",
     ],
     backend: {
         java: {
diff --git a/doh.rs b/doh.rs
index ac9ab5b..c4a594f 100644
--- a/doh.rs
+++ b/doh.rs
@@ -357,7 +357,6 @@
                     }
                 }
             }
-            // TODO: clean up the expired queries.
             self.recv_rx().await?;
             self.flush_tx().await?;
             if let Ok((stream_id, buf)) = self.recv_query() {
@@ -679,6 +678,19 @@
         let _ = resp.send(Response::Error { error: QueryError::ServerNotReady });
     }
 }
+fn need_process_queries(doh_conn_map: &HashMap<u32, (ServerInfo, Option<DohConnection>)>) -> bool {
+    if doh_conn_map.is_empty() {
+        return false;
+    }
+    for (_, doh_conn) in doh_conn_map.values() {
+        if let Some(doh_conn) = doh_conn {
+            if !doh_conn.query_map.is_empty() || !doh_conn.pending_queries.is_empty() {
+                return true;
+            }
+        }
+    }
+    false
+}
 
 async fn doh_handler(
     mut cmd_rx: CmdReceiver,
@@ -703,7 +715,7 @@
                     }
                 }
                 join_all(futures).await
-            } , if !doh_conn_map.is_empty() => {},
+            }, if need_process_queries(&doh_conn_map) => {},
             Some(result) = probe_futures.next() => {
                 let runtime_clone = runtime.clone();
                 handle_probe_result(result, &mut doh_conn_map, runtime_clone, validation_fn);
@@ -1015,12 +1027,11 @@
                         response.copy_from_slice(&answer);
                         answer.len() as ssize_t
                     }
-                    Response::Error { error: QueryError::ServerNotReady } => RESULT_CAN_NOT_SEND,
-                    _ => RESULT_INTERNAL_ERROR,
+                    _ => RESULT_CAN_NOT_SEND,
                 },
                 Err(e) => {
                     error!("no result {}", e);
-                    RESULT_INTERNAL_ERROR
+                    RESULT_CAN_NOT_SEND
                 }
             },
             Err(e) => {
@@ -1029,7 +1040,7 @@
             }
         }
     } else {
-        RESULT_INTERNAL_ERROR
+        RESULT_CAN_NOT_SEND
     }
 }
 
diff --git a/res_cache.cpp b/res_cache.cpp
index 0c736a0..fe0885a 100644
--- a/res_cache.cpp
+++ b/res_cache.cpp
@@ -67,7 +67,6 @@
 
 using aidl::android::net::IDnsResolver;
 using aidl::android::net::ResolverOptionsParcel;
-using android::base::StringAppendF;
 using android::net::DnsQueryEvent;
 using android::net::DnsStats;
 using android::net::Experiments;
@@ -1122,11 +1121,9 @@
 }
 
 static void cache_dump_mru_locked(Cache* cache) {
-    std::string buf;
-
-    StringAppendF(&buf, "MRU LIST (%2d): ", cache->num_entries);
+    std::string buf = fmt::format("MRU LIST ({:2d}): ", cache->num_entries);
     for (Entry* e = cache->mru_list.mru_next; e != &cache->mru_list; e = e->mru_next) {
-        StringAppendF(&buf, " %d", e->id);
+        fmt::format_to(std::back_inserter(buf), " {}", e->id);
     }
 
     LOG(INFO) << __func__ << ": " << buf;
diff --git a/res_debug.cpp b/res_debug.cpp
index 7085c40..083f873 100644
--- a/res_debug.cpp
+++ b/res_debug.cpp
@@ -129,7 +129,7 @@
 #define RESOLV_ALLOW_VERBOSE_LOGGING 0
 #endif
 
-using android::base::StringAppendF;
+using fmt::format_to;
 
 struct res_sym {
     int number;            /* Identifying number, like T_MX */
@@ -142,30 +142,31 @@
     int buflen = 2048;
     ns_rr rr;
     std::string s;
-
+    auto out = std::back_inserter(s);
     /*
      * Print answer records.
      */
     for (;;) {
         if (ns_parserr(handle, section, rrnum, &rr)) {
-            if (errno != ENODEV) StringAppendF(&s, "ns_parserr: %s", strerror(errno));
+            if (errno != ENODEV) format_to(out, "ns_parserr: {}", strerror(errno));
+
             LOG(VERBOSE) << s;
             return;
         }
         if (rrnum == 0) {
             int opcode = ns_msg_getflag(*handle, ns_f_opcode);
-            StringAppendF(&s, ";; %s SECTION:\n", p_section(section, opcode));
+            format_to(out, ";; {} SECTION:\n", p_section(section, opcode));
         }
         if (section == ns_s_qd)
-            StringAppendF(&s, ";;\t%s, type = %s, class = %s\n", ns_rr_name(rr),
-                          p_type(ns_rr_type(rr)), p_class(ns_rr_class(rr)));
+            format_to(out, ";;\t{}, type = {}, class = {}\n", ns_rr_name(rr),
+                      p_type(ns_rr_type(rr)), p_class(ns_rr_class(rr)));
         else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) {
             size_t rdatalen;
             uint16_t optcode, optlen;
 
             rdatalen = ns_rr_rdlen(rr);
-            StringAppendF(&s, "; EDNS: version: %" PRIu32 ", udp=%u, flags=%" PRIu32 "\n",
-                          (rr.ttl >> 16) & 0xff, ns_rr_class(rr), rr.ttl & 0xffff);
+            format_to(out, "; EDNS: version: {}, udp={}, flags={}\n", (rr.ttl >> 16) & 0xff,
+                      ns_rr_class(rr), rr.ttl & 0xffff);
             const uint8_t* cp = ns_rr_rdata(rr);
             while (rdatalen <= ns_rr_rdlen(rr) && rdatalen >= 4) {
                 int i;
@@ -174,33 +175,33 @@
                 GETSHORT(optlen, cp);
 
                 if (optcode == NS_OPT_NSID) {
-                    StringAppendF(&s, "; NSID: ");
+                    format_to(out, "; NSID: ");
                     if (optlen == 0) {
-                        StringAppendF(&s, "; NSID\n");
+                        format_to(out, "; NSID\n");
                     } else {
-                        StringAppendF(&s, "; NSID: ");
+                        format_to(out, "; NSID: ");
                         for (i = 0; i < optlen; i++) {
-                            StringAppendF(&s, "%02x ", cp[i]);
+                            format_to(out, "{:02x} ", cp[i]);
                         }
-                        StringAppendF(&s, " (");
+                        format_to(out, " (");
                         for (i = 0; i < optlen; i++) {
-                            StringAppendF(&s, "%c", isprint(cp[i]) ? cp[i] : '.');
+                            format_to(out, "{} ", isprint(cp[i]) ? cp[i] : '.');
                         }
-                        StringAppendF(&s, ")\n");
+                        format_to(out, ")\n");
                     }
                 } else {
                     if (optlen == 0) {
-                        StringAppendF(&s, "; OPT=%u\n", optcode);
+                        format_to(out, "; OPT={}\n", optcode);
                     } else {
-                        StringAppendF(&s, "; OPT=%u: ", optcode);
+                        format_to(out, "; OPT={}: ", optcode);
                         for (i = 0; i < optlen; i++) {
-                            StringAppendF(&s, "%02x ", cp[i]);
+                            format_to(out, "{:02x} ", cp[i]);
                         }
-                        StringAppendF(&s, " (");
+                        format_to(out, " (");
                         for (i = 0; i < optlen; i++) {
-                            StringAppendF(&s, "%c", isprint(cp[i]) ? cp[i] : '.');
+                            format_to(out, "{}", isprint(cp[i]) ? cp[i] : '.');
                         }
-                        StringAppendF(&s, ")\n");
+                        format_to(out, ")\n");
                     }
                 }
                 rdatalen -= 4 + optlen;
@@ -215,16 +216,16 @@
                         buflen += 1024;
                         continue;
                     } else {
-                        StringAppendF(&s, "buflen over 131072");
+                        format_to(out, "buflen over 131072");
                         PLOG(VERBOSE) << s;
                         return;
                     }
                 }
-                StringAppendF(&s, "ns_sprintrr failed");
+                format_to(out, "ns_sprintrr failed");
                 PLOG(VERBOSE) << s;
                 return;
             }
-            StringAppendF(&s, ";; %s\n", buf.get());
+            format_to(out, ";; {}\n", buf.get());
         }
         rrnum++;
     }
@@ -269,22 +270,22 @@
     /*
      * Print header fields.
      */
-    std::string s;
-    StringAppendF(&s, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n", _res_opcodes[opcode],
-                  p_rcode((int)rcode), id);
-    StringAppendF(&s, ";; flags:");
-    if (ns_msg_getflag(handle, ns_f_qr)) StringAppendF(&s, " qr");
-    if (ns_msg_getflag(handle, ns_f_aa)) StringAppendF(&s, " aa");
-    if (ns_msg_getflag(handle, ns_f_tc)) StringAppendF(&s, " tc");
-    if (ns_msg_getflag(handle, ns_f_rd)) StringAppendF(&s, " rd");
-    if (ns_msg_getflag(handle, ns_f_ra)) StringAppendF(&s, " ra");
-    if (ns_msg_getflag(handle, ns_f_z)) StringAppendF(&s, " ??");
-    if (ns_msg_getflag(handle, ns_f_ad)) StringAppendF(&s, " ad");
-    if (ns_msg_getflag(handle, ns_f_cd)) StringAppendF(&s, " cd");
-    StringAppendF(&s, "; %s: %d", p_section(ns_s_qd, (int)opcode), qdcount);
-    StringAppendF(&s, ", %s: %d", p_section(ns_s_an, (int)opcode), ancount);
-    StringAppendF(&s, ", %s: %d", p_section(ns_s_ns, (int)opcode), nscount);
-    StringAppendF(&s, ", %s: %d", p_section(ns_s_ar, (int)opcode), arcount);
+    std::string s = fmt::format(";; ->>HEADER<<- opcode: {}, status: {}, id: {}\n",
+                                _res_opcodes[opcode], p_rcode((int)rcode), id);
+    auto out = std::back_inserter(s);
+    format_to(out, ";; flags:");
+    if (ns_msg_getflag(handle, ns_f_qr)) format_to(out, " qr");
+    if (ns_msg_getflag(handle, ns_f_aa)) format_to(out, " aa");
+    if (ns_msg_getflag(handle, ns_f_tc)) format_to(out, " tc");
+    if (ns_msg_getflag(handle, ns_f_rd)) format_to(out, " rd");
+    if (ns_msg_getflag(handle, ns_f_ra)) format_to(out, " ra");
+    if (ns_msg_getflag(handle, ns_f_z)) format_to(out, " ??");
+    if (ns_msg_getflag(handle, ns_f_ad)) format_to(out, " ad");
+    if (ns_msg_getflag(handle, ns_f_cd)) format_to(out, " cd");
+    format_to(out, "; {}: {}", p_section(ns_s_qd, (int)opcode), qdcount);
+    format_to(out, ", {}: {}", p_section(ns_s_an, (int)opcode), ancount);
+    format_to(out, ", {}: {}", p_section(ns_s_ns, (int)opcode), nscount);
+    format_to(out, ", {}: {}", p_section(ns_s_ar, (int)opcode), arcount);
 
     LOG(VERBOSE) << s;
 
diff --git a/tests/resolv_private_dns_test.cpp b/tests/resolv_private_dns_test.cpp
index d1d7160..a1e5274 100644
--- a/tests/resolv_private_dns_test.cpp
+++ b/tests/resolv_private_dns_test.cpp
@@ -285,7 +285,7 @@
     if (testParamHasDoh()) {
         EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 2 /* doh */));
     } else {
-        EXPECT_NO_FAILURE(expectQueries(2 /* dns */, 0 /* dot */, 0 /* doh */));
+        EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 2 /* dot */, 0 /* doh */));
     }
 
     // Stop the private DNS servers. Since we are in opportunistic mode, queries will
@@ -298,7 +298,7 @@
     if (testParamHasDoh()) {
         EXPECT_NO_FAILURE(expectQueries(2 /* dns */, 0 /* dot */, 2 /* doh */));
     } else {
-        EXPECT_NO_FAILURE(expectQueries(4 /* dns */, 0 /* dot */, 0 /* doh */));
+        EXPECT_NO_FAILURE(expectQueries(2 /* dns */, 2 /* dot */, 0 /* doh */));
     }
 }
 
@@ -357,8 +357,7 @@
 
 // Tests that DoH query fails and fallback happens.
 //   - Fallback to UDP if DoH query times out
-//   - Fallback to DoT if DoH validation is in progress.
-//   - Fallback to UDP if DoH validation has failed.
+//   - Fallback to DoT if DoH validation is in progress or has failed.
 TEST_F(PrivateDnsDohTest, QueryFailover) {
     const auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
     ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));
@@ -391,13 +390,6 @@
 
     EXPECT_EQ(dot.queries(), 2);
     EXPECT_EQ(dns.queries().size(), 0U);
-    waitForDohValidationTimeout();
-    flushCache();
-
-    // Expect that this query fall back to UDP.
-    EXPECT_NO_FAILURE(sendQueryAndCheckResult());
-    EXPECT_EQ(dot.queries(), 2);
-    EXPECT_EQ(dns.queries().size(), 2U);
 }
 
 // Tests that the DnsResolver prioritizes IPv6 DoH servers over IPv4 DoH servers.