Replace Handler with Executor for async DNS API

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

Change-Id: Ie1dc27643d4767f2a8a39da755edf388a00962d5
This commit is contained in:
Luke Huang
2019-03-07 19:01:26 +08:00
parent 6d72b2c073
commit dfd2e4da29

View File

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