Replace Handler with Executor for async DNS API

Bug: 124882626
Test: built, flashed, booted
      atest DnsResolverTest DnsPacketTest

Change-Id: Ie1dc27643d4767f2a8a39da755edf388a00962d5
diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java
index f248958..93b8cf8 100644
--- a/core/java/android/net/DnsResolver.java
+++ b/core/java/android/net/DnsResolver.java
@@ -22,11 +22,11 @@
 import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
 import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.os.Handler;
-import android.os.MessageQueue;
+import android.os.Looper;
 import android.system.ErrnoException;
 import android.util.Log;
 
@@ -37,6 +37,7 @@
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * Dns resolver class for asynchronous dns querying
@@ -182,20 +183,19 @@
     }
 
     /**
-     * Pass in a blob and corresponding flags, get an answer back asynchronously
-     * through {@link AnswerCallback}.
+     * Send a raw DNS query.
+     * The answer will be provided asynchronously through the provided {@link AnswerCallback}.
      *
      * @param network {@link Network} specifying which network for querying.
      *         {@code null} for query on default network.
      * @param query blob message
      * @param flags flags as a combination of the FLAGS_* constants
-     * @param handler {@link Handler} to specify the thread
-     *         upon which the {@link AnswerCallback} will be invoked.
+     * @param executor The {@link Executor} that the callback should be executed on.
      * @param callback an {@link AnswerCallback} which will be called to notify the caller
      *         of the result of dns query.
      */
     public <T> void query(@Nullable Network network, @NonNull byte[] query, @QueryFlag int flags,
-            @NonNull Handler handler, @NonNull AnswerCallback<T> callback) {
+            @NonNull @CallbackExecutor Executor executor, @NonNull AnswerCallback<T> callback) {
         final FileDescriptor queryfd;
         try {
             queryfd = resNetworkSend((network != null
@@ -205,12 +205,12 @@
             return;
         }
 
-        registerFDListener(handler.getLooper().getQueue(), queryfd, callback);
+        registerFDListener(executor, queryfd, callback);
     }
 
     /**
-     * Pass in a domain name and corresponding setting, get an answer back asynchronously
-     * through {@link AnswerCallback}.
+     * Send a DNS query with the specified name, class and query type.
+     * The answer will be provided asynchronously through the provided {@link AnswerCallback}.
      *
      * @param network {@link Network} specifying which network for querying.
      *         {@code null} for query on default network.
@@ -218,14 +218,13 @@
      * @param nsClass dns class as one of the CLASS_* constants
      * @param nsType dns resource record (RR) type as one of the TYPE_* constants
      * @param flags flags as a combination of the FLAGS_* constants
-     * @param handler {@link Handler} to specify the thread
-     *         upon which the {@link AnswerCallback} will be invoked.
+     * @param executor The {@link Executor} that the callback should be executed on.
      * @param callback an {@link AnswerCallback} which will be called to notify the caller
      *         of the result of dns query.
      */
     public <T> void query(@Nullable Network network, @NonNull String domain,
             @QueryClass int nsClass, @QueryType int nsType, @QueryFlag int flags,
-            @NonNull Handler handler, @NonNull AnswerCallback<T> callback) {
+            @NonNull @CallbackExecutor Executor executor, @NonNull AnswerCallback<T> callback) {
         final FileDescriptor queryfd;
         try {
             queryfd = resNetworkQuery((network != null
@@ -234,33 +233,32 @@
             callback.onQueryException(e);
             return;
         }
-        registerFDListener(handler.getLooper().getQueue(), queryfd, callback);
+        registerFDListener(executor, queryfd, callback);
     }
 
-    private <T> void registerFDListener(@NonNull MessageQueue queue,
+    private <T> void registerFDListener(@NonNull Executor executor,
             @NonNull FileDescriptor queryfd, @NonNull AnswerCallback<T> answerCallback) {
-        queue.addOnFileDescriptorEventListener(
+        Looper.getMainLooper().getQueue().addOnFileDescriptorEventListener(
                 queryfd,
                 FD_EVENTS,
                 (fd, events) -> {
-                    byte[] answerbuf = null;
-                    try {
-                    // TODO: Implement result function in Java side instead of using JNI
-                    //       Because JNI method close fd prior than unregistering fd on
-                    //       event listener.
-                        answerbuf = resNetworkResult(fd);
-                    } catch (ErrnoException e) {
-                        Log.e(TAG, "resNetworkResult:" + e.toString());
-                        answerCallback.onQueryException(e);
-                        return 0;
-                    }
+                    executor.execute(() -> {
+                        byte[] answerbuf = null;
+                        try {
+                            answerbuf = resNetworkResult(fd);
+                        } catch (ErrnoException e) {
+                            Log.e(TAG, "resNetworkResult:" + e.toString());
+                            answerCallback.onQueryException(e);
+                            return;
+                        }
 
-                    try {
-                        answerCallback.onAnswer(answerCallback.parser.parse(answerbuf));
-                    } catch (ParseException e) {
-                        answerCallback.onParseException(e);
-                    }
-
+                        try {
+                            answerCallback.onAnswer(
+                                    answerCallback.parser.parse(answerbuf));
+                        } catch (ParseException e) {
+                            answerCallback.onParseException(e);
+                        }
+                    });
                     // Unregister this fd listener
                     return 0;
                 });