Implementation of control flags in asynchronous DNS query API

Flags definitions are in multinetwork.h

Test: built, flashed, booted
      system/netd/tests/runtests.sh passes

Change-Id: Iab1983b783d1470bc1cf23489abbef7a2d88e860
diff --git a/resolv/res_send.cpp b/resolv/res_send.cpp
index a8b2aeb..21017ac 100644
--- a/resolv/res_send.cpp
+++ b/resolv/res_send.cpp
@@ -388,7 +388,8 @@
     return (1);
 }
 
-int res_nsend(res_state statp, const u_char* buf, int buflen, u_char* ans, int anssiz, int* rcode) {
+int res_nsend(res_state statp, const u_char* buf, int buflen, u_char* ans, int anssiz, int* rcode,
+              uint32_t flags) {
     int gotsomewhere, terrno, v_circuit, resplen, n;
     ResolvCacheStatus cache_status = RESOLV_CACHE_UNSUPPORTED;
 
@@ -404,7 +405,7 @@
     terrno = ETIMEDOUT;
 
     int anslen = 0;
-    cache_status = _resolv_cache_lookup(statp->netid, buf, buflen, ans, anssiz, &anslen);
+    cache_status = _resolv_cache_lookup(statp->netid, buf, buflen, ans, anssiz, &anslen, flags);
 
     if (cache_status == RESOLV_CACHE_FOUND) {
         return anslen;
@@ -417,7 +418,7 @@
         // We have no nameservers configured, so there's no point trying.
         // Tell the cache the query failed, or any retries and anyone else asking the same
         // question will block for PENDING_REQUEST_TIMEOUT seconds instead of failing fast.
-        _resolv_cache_query_failed(statp->netid, buf, buflen);
+        _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
 
         // TODO: Remove errno once callers stop using it
         errno = ESRCH;
@@ -507,7 +508,9 @@
     /*
      * Send request, RETRY times, or until successful.
      */
-    for (int attempt = 0; attempt < statp->retry; ++attempt) {
+    int retryTimes = (flags & ANDROID_RESOLV_NO_RETRY) ? 1 : statp->retry;
+
+    for (int attempt = 0; attempt < retryTimes; ++attempt) {
         struct res_stats stats[MAXNS];
         struct __res_params params;
         int revision_id = resolv_cache_get_resolver_stats(statp->netid, &params, stats);
@@ -539,7 +542,7 @@
                     return resplen;
                 }
                 if (!fallback) {
-                    _resolv_cache_query_failed(statp->netid, buf, buflen);
+                    _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
                     res_nclose(statp);
                     return -terrno;
                 }
@@ -554,7 +557,8 @@
 
             if (v_circuit) {
                 /* Use VC; at most one attempt per server. */
-                attempt = statp->retry;
+                bool shouldRecordStats = (attempt == 0);
+                attempt = retryTimes;
 
                 n = send_vc(statp, &params, buf, buflen, ans, anssiz, &terrno, ns, &now, rcode,
                             &delay);
@@ -564,7 +568,7 @@
                  * queries that deterministically fail (e.g., a name that always returns
                  * SERVFAIL or times out) do not unduly affect the stats.
                  */
-                if (attempt == 0) {
+                if (shouldRecordStats) {
                     res_sample sample;
                     _res_stats_set_sample(&sample, now, *rcode, delay);
                     _resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, ns, &sample,
@@ -574,7 +578,7 @@
                 VLOG << "used send_vc " << n;
 
                 if (n < 0) {
-                    _resolv_cache_query_failed(statp->netid, buf, buflen);
+                    _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
                     res_nclose(statp);
                     return -terrno;
                 };
@@ -598,7 +602,7 @@
                 VLOG << "used send_dg " << n;
 
                 if (n < 0) {
-                    _resolv_cache_query_failed(statp->netid, buf, buflen);
+                    _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
                     res_nclose(statp);
                     return -terrno;
                 };
@@ -645,7 +649,7 @@
     } else {
         errno = terrno;
     }
-    _resolv_cache_query_failed(statp->netid, buf, buflen);
+    _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
 
     return -terrno;
 }
@@ -1314,11 +1318,11 @@
     }
 }
 
-int resolv_res_nsend(const android_net_context* netContext, const u_char* msg, int msgLen,
-                     u_char* ans, int ansLen, int* rcode) {
+int resolv_res_nsend(const android_net_context* netContext, const uint8_t* msg, int msgLen,
+                     uint8_t* ans, int ansLen, int* rcode, uint32_t flags) {
     res_state res = res_get_state();
     res_setnetcontext(res, netContext);
     _resolv_populate_res_for_net(res);
     *rcode = NOERROR;
-    return res_nsend(res, msg, msgLen, ans, ansLen, rcode);
-}
+    return res_nsend(res, msg, msgLen, ans, ansLen, rcode, flags);
+}
\ No newline at end of file