Merge "Restrict access to dangerous methods to <= P" into qt-dev
diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java
index 06c32c6..68826cb 100644
--- a/core/java/android/net/DnsResolver.java
+++ b/core/java/android/net/DnsResolver.java
@@ -93,6 +93,23 @@
     public static final int FLAG_NO_CACHE_STORE = 1 << 1;
     public static final int FLAG_NO_CACHE_LOOKUP = 1 << 2;
 
+    @IntDef(prefix = { "ERROR_" }, value = {
+            ERROR_PARSE,
+            ERROR_SYSTEM
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface DnsError {}
+    /**
+     * Indicates that there was an error parsing the response the query.
+     * The cause of this error is available via getCause() and is a ParseException.
+     */
+    public static final int ERROR_PARSE = 0;
+    /**
+     * Indicates that there was an error sending the query.
+     * The cause of this error is available via getCause() and is an ErrnoException.
+     */
+    public static final int ERROR_SYSTEM = 1;
+
     private static final int NETID_UNSET = 0;
 
     private static final DnsResolver sInstance = new DnsResolver();
@@ -107,97 +124,57 @@
     private DnsResolver() {}
 
     /**
-     * Answer parser for parsing raw answers
+     * Base interface for answer callbacks
      *
-     * @param <T> The type of the parsed answer
+     * @param <T> The type of the answer
      */
-    public interface AnswerParser<T> {
-        /**
-         * Creates a <T> answer by parsing the given raw answer.
-         *
-         * @param rawAnswer the raw answer to be parsed
-         * @return a parsed <T> answer
-         * @throws ParseException if parsing failed
-         */
-        @NonNull T parse(@NonNull byte[] rawAnswer) throws ParseException;
-    }
-
-    /**
-     * Base class for answer callbacks
-     *
-     * @param <T> The type of the parsed answer
-     */
-    public abstract static class AnswerCallback<T> {
-        /** @hide */
-        public final AnswerParser<T> parser;
-
-        public AnswerCallback(@NonNull AnswerParser<T> parser) {
-            this.parser = parser;
-        };
-
+    public interface Callback<T> {
         /**
          * Success response to
-         * {@link android.net.DnsResolver#query query()}.
+         * {@link android.net.DnsResolver#query query()} or
+         * {@link android.net.DnsResolver#rawQuery rawQuery()}.
          *
          * Invoked when the answer to a query was successfully parsed.
          *
-         * @param answer parsed answer to the query.
+         * @param answer <T> answer to the query.
+         * @param rcode The response code in the DNS response.
          *
          * {@see android.net.DnsResolver#query query()}
          */
-        public abstract void onAnswer(@NonNull T answer);
-
+        void onAnswer(@NonNull T answer, int rcode);
         /**
          * Error response to
-         * {@link android.net.DnsResolver#query query()}.
+         * {@link android.net.DnsResolver#query query()} or
+         * {@link android.net.DnsResolver#rawQuery rawQuery()}.
          *
          * Invoked when there is no valid answer to
          * {@link android.net.DnsResolver#query query()}
+         * {@link android.net.DnsResolver#rawQuery rawQuery()}.
          *
-         * @param exception a {@link ParseException} object with additional
+         * @param error a {@link DnsException} object with additional
          *    detail regarding the failure
          */
-        public abstract void onParseException(@NonNull ParseException exception);
-
-        /**
-         * Error response to
-         * {@link android.net.DnsResolver#query query()}.
-         *
-         * Invoked if an error happens when
-         * issuing the DNS query or receiving the result.
-         * {@link android.net.DnsResolver#query query()}
-         *
-         * @param exception an {@link ErrnoException} object with additional detail
-         *    regarding the failure
-         */
-        public abstract void onQueryException(@NonNull ErrnoException exception);
+        void onError(@NonNull DnsException error);
     }
 
     /**
-     * Callback for receiving raw answers
+     * Class to represent DNS error
      */
-    public abstract static class RawAnswerCallback extends AnswerCallback<byte[]> {
-        public RawAnswerCallback() {
-            super(rawAnswer -> rawAnswer);
-        }
-    }
+    public static class DnsException extends Exception {
+       /**
+        * DNS error code as one of the ERROR_* constants
+        */
+        @DnsError public final int code;
 
-    /**
-     * Callback for receiving parsed {@link InetAddress} answers
-     *
-     * Note that if the answer does not contain any IP addresses,
-     * onAnswer will be called with an empty list.
-     */
-    public abstract static class InetAddressAnswerCallback
-            extends AnswerCallback<List<InetAddress>> {
-        public InetAddressAnswerCallback() {
-            super(rawAnswer -> new DnsAddressAnswer(rawAnswer).getAddresses());
+        DnsException(@DnsError int code, @Nullable Throwable cause) {
+            super(cause);
+            this.code = code;
         }
     }
 
     /**
      * Send a raw DNS query.
-     * The answer will be provided asynchronously through the provided {@link AnswerCallback}.
+     * The answer will be provided asynchronously through the provided {@link Callback}.
      *
      * @param network {@link Network} specifying which network to query on.
      *         {@code null} for query on default network.
@@ -206,13 +183,13 @@
      * @param executor The {@link Executor} that the callback should be executed on.
      * @param cancellationSignal used by the caller to signal if the query should be
      *    cancelled. May be {@code null}.
-     * @param callback an {@link AnswerCallback} which will be called to notify the caller
+     * @param callback a {@link Callback} 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,
+    public void rawQuery(@Nullable Network network, @NonNull byte[] query, @QueryFlag int flags,
             @NonNull @CallbackExecutor Executor executor,
             @Nullable CancellationSignal cancellationSignal,
-            @NonNull AnswerCallback<T> callback) {
+            @NonNull Callback<? super byte[]> callback) {
         if (cancellationSignal != null && cancellationSignal.isCanceled()) {
             return;
         }
@@ -220,11 +197,9 @@
         final FileDescriptor queryfd;
         try {
             queryfd = resNetworkSend((network != null
-                ? network.netId : NETID_UNSET), query, query.length, flags);
+                ? network.getNetIdForResolv() : NETID_UNSET), query, query.length, flags);
         } catch (ErrnoException e) {
-            executor.execute(() -> {
-                callback.onQueryException(e);
-            });
+            executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
             return;
         }
 
@@ -237,7 +212,7 @@
 
     /**
      * Send a DNS query with the specified name, class and query type.
-     * The answer will be provided asynchronously through the provided {@link AnswerCallback}.
+     * The answer will be provided asynchronously through the provided {@link Callback}.
      *
      * @param network {@link Network} specifying which network to query on.
      *         {@code null} for query on default network.
@@ -248,14 +223,14 @@
      * @param executor The {@link Executor} that the callback should be executed on.
      * @param cancellationSignal used by the caller to signal if the query should be
      *    cancelled. May be {@code null}.
-     * @param callback an {@link AnswerCallback} which will be called to notify the caller
+     * @param callback a {@link Callback} which will be called to notify the caller
      *    of the result of dns query.
      */
-    public <T> void query(@Nullable Network network, @NonNull String domain,
+    public void rawQuery(@Nullable Network network, @NonNull String domain,
             @QueryClass int nsClass, @QueryType int nsType, @QueryFlag int flags,
             @NonNull @CallbackExecutor Executor executor,
             @Nullable CancellationSignal cancellationSignal,
-            @NonNull AnswerCallback<T> callback) {
+            @NonNull Callback<? super byte[]> callback) {
         if (cancellationSignal != null && cancellationSignal.isCanceled()) {
             return;
         }
@@ -263,11 +238,9 @@
         final FileDescriptor queryfd;
         try {
             queryfd = resNetworkQuery((network != null
-                    ? network.netId : NETID_UNSET), domain, nsClass, nsType, flags);
+                    ? network.getNetIdForResolv() : NETID_UNSET), domain, nsClass, nsType, flags);
         } catch (ErrnoException e) {
-            executor.execute(() -> {
-                callback.onQueryException(e);
-            });
+            executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
             return;
         }
         synchronized (lock)  {
@@ -277,27 +250,28 @@
         }
     }
 
-    private class InetAddressAnswerAccumulator extends InetAddressAnswerCallback {
+    private class InetAddressAnswerAccumulator implements Callback<byte[]> {
         private final List<InetAddress> mAllAnswers;
-        private ParseException mParseException;
-        private ErrnoException mErrnoException;
-        private final InetAddressAnswerCallback mUserCallback;
+        private int mRcode;
+        private DnsException mDnsException;
+        private final Callback<? super List<InetAddress>> mUserCallback;
         private final int mTargetAnswerCount;
         private int mReceivedAnswerCount = 0;
 
-        InetAddressAnswerAccumulator(int size, @NonNull InetAddressAnswerCallback callback) {
+        InetAddressAnswerAccumulator(int size,
+                @NonNull Callback<? super List<InetAddress>> callback) {
             mTargetAnswerCount = size;
             mAllAnswers = new ArrayList<>();
             mUserCallback = callback;
         }
 
-        private boolean maybeReportException() {
-            if (mErrnoException != null) {
-                mUserCallback.onQueryException(mErrnoException);
+        private boolean maybeReportError() {
+            if (mRcode != 0) {
+                mUserCallback.onAnswer(mAllAnswers, mRcode);
                 return true;
             }
-            if (mParseException != null) {
-                mUserCallback.onParseException(mParseException);
+            if (mDnsException != null) {
+                mUserCallback.onError(mDnsException);
                 return true;
             }
             return false;
@@ -305,34 +279,43 @@
 
         private void maybeReportAnswer() {
             if (++mReceivedAnswerCount != mTargetAnswerCount) return;
-            if (mAllAnswers.isEmpty() && maybeReportException()) return;
+            if (mAllAnswers.isEmpty() && maybeReportError()) return;
             // TODO: Do RFC6724 sort.
-            mUserCallback.onAnswer(mAllAnswers);
+            mUserCallback.onAnswer(mAllAnswers, mRcode);
         }
 
         @Override
-        public void onAnswer(@NonNull List<InetAddress> answer) {
-            mAllAnswers.addAll(answer);
+        public void onAnswer(@NonNull byte[] answer, int rcode) {
+            // If at least one query succeeded, return an rcode of 0.
+            // Otherwise, arbitrarily return the first rcode received.
+            if (mReceivedAnswerCount == 0 || rcode == 0) {
+                mRcode = rcode;
+            }
+            try {
+                mAllAnswers.addAll(new DnsAddressAnswer(answer).getAddresses());
+            } catch (ParseException e) {
+                mDnsException = new DnsException(ERROR_PARSE, e);
+            }
             maybeReportAnswer();
         }
 
         @Override
-        public void onParseException(@NonNull ParseException e) {
-            mParseException = e;
-            maybeReportAnswer();
-        }
-
-        @Override
-        public void onQueryException(@NonNull ErrnoException e) {
-            mErrnoException = e;
+        public void onError(@NonNull DnsException error) {
+            mDnsException = error;
             maybeReportAnswer();
         }
     }
 
     /**
-     * Send a DNS query with the specified name, get back a set of InetAddresses asynchronously.
-     * The answer will be provided asynchronously through the provided
-     * {@link InetAddressAnswerCallback}.
+     * Send a DNS query with the specified name on a network with both IPv4 and IPv6,
+     * get back a set of InetAddresses asynchronously.
+     *
+     * This method will examine the connection ability on given network, and query IPv4
+     * and IPv6 if connection is available.
+     *
+     * If at least one query succeeded with valid answer, rcode will be 0
+     *
+     * The answer will be provided asynchronously through the provided {@link Callback}.
      *
      * @param network {@link Network} specifying which network to query on.
      *         {@code null} for query on default network.
@@ -341,13 +324,13 @@
      * @param executor The {@link Executor} that the callback should be executed on.
      * @param cancellationSignal used by the caller to signal if the query should be
      *    cancelled. May be {@code null}.
-     * @param callback an {@link InetAddressAnswerCallback} which will be called to notify the
+     * @param callback a {@link Callback} which will be called to notify the
      *    caller of the result of dns query.
      */
     public void query(@Nullable Network network, @NonNull String domain, @QueryFlag int flags,
             @NonNull @CallbackExecutor Executor executor,
             @Nullable CancellationSignal cancellationSignal,
-            @NonNull InetAddressAnswerCallback callback) {
+            @NonNull Callback<? super List<InetAddress>> callback) {
         if (cancellationSignal != null && cancellationSignal.isCanceled()) {
             return;
         }
@@ -363,11 +346,10 @@
         if (queryIpv6) {
             try {
                 v6fd = resNetworkQuery((network != null
-                        ? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_AAAA, flags);
+                        ? network.getNetIdForResolv() : NETID_UNSET),
+                        domain, CLASS_IN, TYPE_AAAA, flags);
             } catch (ErrnoException e) {
-                executor.execute(() -> {
-                    callback.onQueryException(e);
-                });
+                executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
                 return;
             }
             queryCount++;
@@ -377,17 +359,18 @@
         // Avoiding gateways drop packets if queries are sent too close together
         try {
             Thread.sleep(SLEEP_TIME_MS);
-        } catch (InterruptedException ex) { }
+        } catch (InterruptedException ex) {
+            Thread.currentThread().interrupt();
+        }
 
         if (queryIpv4) {
             try {
                 v4fd = resNetworkQuery((network != null
-                        ? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_A, flags);
+                        ? network.getNetIdForResolv() : NETID_UNSET),
+                        domain, CLASS_IN, TYPE_A, flags);
             } catch (ErrnoException e) {
                 if (queryIpv6) resNetworkCancel(v6fd);  // Closes fd, marks it invalid.
-                executor.execute(() -> {
-                    callback.onQueryException(e);
-                });
+                executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
                 return;
             }
             queryCount++;
@@ -413,34 +396,89 @@
         }
     }
 
-    private <T> void registerFDListener(@NonNull Executor executor,
-            @NonNull FileDescriptor queryfd, @NonNull AnswerCallback<T> answerCallback,
+    /**
+     * Send a DNS query with the specified name and query type, get back a set of
+     * InetAddresses asynchronously.
+     *
+     * The answer will be provided asynchronously through the provided {@link Callback}.
+     *
+     * @param network {@link Network} specifying which network to query on.
+     *         {@code null} for query on default network.
+     * @param domain domain name to query
+     * @param nsType dns resource record (RR) type as one of the TYPE_* constants
+     * @param flags flags as a combination of the FLAGS_* constants
+     * @param executor The {@link Executor} that the callback should be executed on.
+     * @param cancellationSignal used by the caller to signal if the query should be
+     *    cancelled. May be {@code null}.
+     * @param callback a {@link Callback} which will be called to notify the caller
+     *    of the result of dns query.
+     */
+    public void query(@Nullable Network network, @NonNull String domain,
+            @QueryType int nsType, @QueryFlag int flags,
+            @NonNull @CallbackExecutor Executor executor,
+            @Nullable CancellationSignal cancellationSignal,
+            @NonNull Callback<? super List<InetAddress>> callback) {
+        if (cancellationSignal != null && cancellationSignal.isCanceled()) {
+            return;
+        }
+        final Object lock = new Object();
+        final FileDescriptor queryfd;
+        try {
+            queryfd = resNetworkQuery((network != null
+                    ? network.getNetIdForResolv() : NETID_UNSET), domain, CLASS_IN, nsType, flags);
+        } catch (ErrnoException e) {
+            executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
+            return;
+        }
+        final InetAddressAnswerAccumulator accumulator =
+                new InetAddressAnswerAccumulator(1, callback);
+        synchronized (lock)  {
+            registerFDListener(executor, queryfd, accumulator, cancellationSignal, lock);
+            if (cancellationSignal == null) return;
+            addCancellationSignal(cancellationSignal, queryfd, lock);
+        }
+    }
+
+    /**
+     * Class to retrieve DNS response
+     *
+     * @hide
+     */
+    public static final class DnsResponse {
+        public final @NonNull byte[] answerbuf;
+        public final int rcode;
+        public DnsResponse(@NonNull byte[] answerbuf, int rcode) {
+            this.answerbuf = answerbuf;
+            this.rcode = rcode;
+        }
+    }
+
+    private void registerFDListener(@NonNull Executor executor,
+            @NonNull FileDescriptor queryfd, @NonNull Callback<? super byte[]> answerCallback,
             @Nullable CancellationSignal cancellationSignal, @NonNull Object lock) {
         Looper.getMainLooper().getQueue().addOnFileDescriptorEventListener(
                 queryfd,
                 FD_EVENTS,
                 (fd, events) -> {
                     executor.execute(() -> {
+                        DnsResponse resp = null;
+                        ErrnoException exception = null;
                         synchronized (lock) {
                             if (cancellationSignal != null && cancellationSignal.isCanceled()) {
                                 return;
                             }
-                            byte[] answerbuf = null;
                             try {
-                                answerbuf = resNetworkResult(fd);  // Closes fd, marks it invalid.
+                                resp = resNetworkResult(fd);  // Closes fd, marks it invalid.
                             } 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);
+                                exception = e;
                             }
                         }
+                        if (exception != null) {
+                            answerCallback.onError(new DnsException(ERROR_SYSTEM, exception));
+                            return;
+                        }
+                        answerCallback.onAnswer(resp.answerbuf, resp.rcode);
                     });
                     // Unregister this fd listener
                     return 0;
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index db87c97..c06a132 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -145,9 +145,10 @@
     /**
      * DNS resolver series jni method.
      * Read a result for the query associated with the {@code fd}.
-     * @return a byte array containing blob answer
+     * @return DnsResponse containing blob answer and rcode
      */
-    public static native byte[] resNetworkResult(FileDescriptor fd) throws ErrnoException;
+    public static native DnsResolver.DnsResponse resNetworkResult(FileDescriptor fd)
+            throws ErrnoException;
 
     /**
      * DNS resolver series jni method.
diff --git a/core/java/android/net/TestNetworkInterface.java b/core/java/android/net/TestNetworkInterface.java
index 30e68f5..8455083 100644
--- a/core/java/android/net/TestNetworkInterface.java
+++ b/core/java/android/net/TestNetworkInterface.java
@@ -27,8 +27,6 @@
  */
 @TestApi
 public final class TestNetworkInterface implements Parcelable {
-    private static final String TAG = "TestNetworkInterface";
-
     private final ParcelFileDescriptor mFileDescriptor;
     private final String mInterfaceName;
 
diff --git a/core/java/android/net/TestNetworkManager.java b/core/java/android/net/TestNetworkManager.java
index cd58e66..e274005 100644
--- a/core/java/android/net/TestNetworkManager.java
+++ b/core/java/android/net/TestNetworkManager.java
@@ -17,7 +17,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.TestApi;
-import android.content.Context;
 import android.os.IBinder;
 import android.os.RemoteException;
 
@@ -33,11 +32,9 @@
     @NonNull private static final String TAG = TestNetworkManager.class.getSimpleName();
 
     @NonNull private final ITestNetworkManager mService;
-    @NonNull private final Context mContext;
 
     /** @hide */
-    public TestNetworkManager(@NonNull Context context, @NonNull ITestNetworkManager service) {
-        mContext = Preconditions.checkNotNull(context, "missing Context");
+    public TestNetworkManager(@NonNull ITestNetworkManager service) {
         mService = Preconditions.checkNotNull(service, "missing ITestNetworkManager");
     }
 
@@ -88,4 +85,21 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Create a tap interface for testing purposes
+     *
+     * @return A ParcelFileDescriptor of the underlying TAP interface. Close this to tear down the
+     *     TAP interface.
+     * @hide
+     */
+    @TestApi
+    public TestNetworkInterface createTapInterface() {
+        try {
+            return mService.createTapInterface();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
 }
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index dd754f3..28c59db 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -270,7 +270,7 @@
     return jniCreateFileDescriptor(env, fd);
 }
 
-static jbyteArray android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz, jobject javaFd) {
+static jobject android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz, jobject javaFd) {
     int fd = jniGetFDFromFileDescriptor(env, javaFd);
     int rcode;
     std::vector<uint8_t> buf(MAXPACKETSIZE, 0);
@@ -291,7 +291,10 @@
                 reinterpret_cast<jbyte*>(buf.data()));
     }
 
-    return answer;
+    jclass class_DnsResponse = env->FindClass("android/net/DnsResolver$DnsResponse");
+    jmethodID ctor = env->GetMethodID(class_DnsResponse, "<init>", "([BI)V");
+
+    return env->NewObject(class_DnsResponse, ctor, answer, rcode);
 }
 
 static void android_net_utils_resNetworkCancel(JNIEnv *env, jobject thiz, jobject javaFd) {
@@ -354,7 +357,7 @@
     { "setupRaSocket", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_setupRaSocket },
     { "resNetworkSend", "(I[BII)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkSend },
     { "resNetworkQuery", "(ILjava/lang/String;III)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkQuery },
-    { "resNetworkResult", "(Ljava/io/FileDescriptor;)[B", (void*) android_net_utils_resNetworkResult },
+    { "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult },
     { "resNetworkCancel", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_resNetworkCancel },
 };
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 6405254..e4c39cc 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -108,7 +108,6 @@
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.NetworkEvent;
 import android.net.netlink.InetDiagMessage;
-import android.net.shared.NetworkMonitorUtils;
 import android.net.shared.PrivateDnsConfig;
 import android.net.util.MultinetworkPolicyTracker;
 import android.net.util.NetdService;
@@ -133,6 +132,7 @@
 import android.os.ShellCallback;
 import android.os.ShellCommand;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -237,6 +237,16 @@
 
     private static final boolean LOGD_BLOCKED_NETWORKINFO = true;
 
+    /**
+     * Default URL to use for {@link #getCaptivePortalServerUrl()}. This should not be changed
+     * by OEMs for configuration purposes, as this value is overridden by
+     * Settings.Global.CAPTIVE_PORTAL_HTTP_URL.
+     * R.string.config_networkCaptivePortalServerUrl should be overridden instead for this purpose
+     * (preferably via runtime resource overlays).
+     */
+    private static final String DEFAULT_CAPTIVE_PORTAL_HTTP_URL =
+            "http://connectivitycheck.gstatic.com/generate_204";
+
     // TODO: create better separation between radio types and network types
 
     // how long to wait before switching back to a radio's default network
@@ -1628,8 +1638,11 @@
      */
     private boolean disallowedBecauseSystemCaller() {
         // TODO: start throwing a SecurityException when GnssLocationProvider stops calling
-        // requestRouteToHost.
-        if (isSystem(Binder.getCallingUid())) {
+        // requestRouteToHost. In Q, GnssLocationProvider is changed to not call requestRouteToHost
+        // for devices launched with Q and above. However, existing devices upgrading to Q and
+        // above must continued to be supported for few more releases.
+        if (isSystem(Binder.getCallingUid()) && SystemProperties.getInt(
+                "ro.product.first_api_level", 0) > Build.VERSION_CODES.P) {
             log("This method exists only for app backwards compatibility"
                     + " and must not be called by system services.");
             return true;
@@ -1767,11 +1780,8 @@
             // caller type. Need to re-factor NetdEventListenerService to allow multiple
             // NetworkMonitor registrants.
             if (nai != null && nai.satisfies(mDefaultRequest)) {
-                try {
-                    nai.networkMonitor().notifyDnsResponse(returnCode);
-                } catch (RemoteException e) {
-                    e.rethrowFromSystemServer();
-                }
+                Binder.withCleanCallingIdentity(() ->
+                        nai.networkMonitor().notifyDnsResponse(returnCode));
             }
         }
 
@@ -6542,7 +6552,7 @@
                         uid, newRules, metered, mRestrictBackground);
             }
             if (oldBlocked == newBlocked) {
-                return;
+                continue;
             }
             final int arg = encodeBool(newBlocked);
             for (int i = 0; i < nai.numNetworkRequests(); i++) {
@@ -6700,9 +6710,20 @@
     @Override
     public String getCaptivePortalServerUrl() {
         enforceConnectivityInternalPermission();
-        final String defaultUrl = mContext.getResources().getString(
-                R.string.config_networkDefaultCaptivePortalServerUrl);
-        return NetworkMonitorUtils.getCaptivePortalServerHttpUrl(mContext, defaultUrl);
+        String settingUrl = mContext.getResources().getString(
+                R.string.config_networkCaptivePortalServerUrl);
+
+        if (!TextUtils.isEmpty(settingUrl)) {
+            return settingUrl;
+        }
+
+        settingUrl = Settings.Global.getString(mContext.getContentResolver(),
+                Settings.Global.CAPTIVE_PORTAL_HTTP_URL);
+        if (!TextUtils.isEmpty(settingUrl)) {
+            return settingUrl;
+        }
+
+        return DEFAULT_CAPTIVE_PORTAL_HTTP_URL;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index e64ab78..40bf7bc 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -60,6 +60,7 @@
     @NonNull private static final String TAG = TestNetworkService.class.getSimpleName();
     @NonNull private static final String TEST_NETWORK_TYPE = "TEST_NETWORK";
     @NonNull private static final String TEST_TUN_PREFIX = "testtun";
+    @NonNull private static final String TEST_TAP_PREFIX = "testtap";
     @NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger();
 
     @NonNull private final Context mContext;
@@ -70,7 +71,7 @@
     @NonNull private final Handler mHandler;
 
     // Native method stubs
-    private static native int jniCreateTun(@NonNull String iface);
+    private static native int jniCreateTunTap(boolean isTun, @NonNull String iface);
 
     @VisibleForTesting
     protected TestNetworkService(
@@ -85,23 +86,23 @@
     }
 
     /**
-     * Create a TUN interface with the given interface name and link addresses
+     * Create a TUN or TAP interface with the given interface name and link addresses
      *
-     * <p>This method will return the FileDescriptor to the TUN interface. Close it to tear down the
-     * TUN interface.
+     * <p>This method will return the FileDescriptor to the interface. Close it to tear down the
+     * interface.
      */
-    @Override
-    public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
+    private TestNetworkInterface createInterface(boolean isTun, LinkAddress[] linkAddrs) {
         enforceTestNetworkPermissions(mContext);
 
         checkNotNull(linkAddrs, "missing linkAddrs");
 
-        String iface = TEST_TUN_PREFIX + sTestTunIndex.getAndIncrement();
+        String ifacePrefix = isTun ? TEST_TUN_PREFIX : TEST_TAP_PREFIX;
+        String iface = ifacePrefix + sTestTunIndex.getAndIncrement();
         return Binder.withCleanCallingIdentity(
                 () -> {
                     try {
                         ParcelFileDescriptor tunIntf =
-                                ParcelFileDescriptor.adoptFd(jniCreateTun(iface));
+                                ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
                         for (LinkAddress addr : linkAddrs) {
                             mNetd.interfaceAddAddress(
                                     iface,
@@ -116,6 +117,28 @@
                 });
     }
 
+    /**
+     * Create a TUN interface with the given interface name and link addresses
+     *
+     * <p>This method will return the FileDescriptor to the TUN interface. Close it to tear down the
+     * TUN interface.
+     */
+    @Override
+    public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
+        return createInterface(true, linkAddrs);
+    }
+
+    /**
+     * Create a TAP interface with the given interface name
+     *
+     * <p>This method will return the FileDescriptor to the TAP interface. Close it to tear down the
+     * TAP interface.
+     */
+    @Override
+    public TestNetworkInterface createTapInterface() {
+        return createInterface(false, new LinkAddress[0]);
+    }
+
     // Tracker for TestNetworkAgents
     @GuardedBy("mTestNetworkTracker")
     @NonNull
@@ -310,7 +333,7 @@
     public void teardownTestNetwork(int netId) {
         enforceTestNetworkPermissions(mContext);
 
-        TestNetworkAgent agent;
+        final TestNetworkAgent agent;
         synchronized (mTestNetworkTracker) {
             agent = mTestNetworkTracker.get(netId);
         }
@@ -325,14 +348,10 @@
         agent.teardown();
     }
 
-    // STOPSHIP: Change this back to android.Manifest.permission.MANAGE_TEST_NETWORKS
-    private static final String PERMISSION_NAME = "dummy";
+    private static final String PERMISSION_NAME =
+            android.Manifest.permission.MANAGE_TEST_NETWORKS;
 
     public static void enforceTestNetworkPermissions(@NonNull Context context) {
-        // STOPSHIP: Re-enable these checks. Disabled until adoptShellPermissionIdentity() can be
-        //           called from CTS test code.
-        if (false) {
-            context.enforceCallingOrSelfPermission(PERMISSION_NAME, "TestNetworkService");
-        }
+        context.enforceCallingOrSelfPermission(PERMISSION_NAME, "TestNetworkService");
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
index 948c690..a1a8e35 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
@@ -33,6 +33,7 @@
 import android.util.Pair;
 
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.TrafficStatsConstants;
 
 import libcore.io.IoUtils;
 
@@ -381,7 +382,8 @@
         protected void setupSocket(
                 int sockType, int protocol, long writeTimeout, long readTimeout, int dstPort)
                 throws ErrnoException, IOException {
-            final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
+            final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+                    TrafficStatsConstants.TAG_SYSTEM_PROBE);
             try {
                 mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol);
             } finally {
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index da1360d..b694602 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -469,7 +469,10 @@
      */
     @VisibleForTesting
     void sendPackagePermissionsToNetd(SparseIntArray netdPermissionsAppIds) {
-
+        if (mNetd == null) {
+            Log.e(TAG, "Failed to get the netd service");
+            return;
+        }
         ArrayList<Integer> allPermissionAppIds = new ArrayList<>();
         ArrayList<Integer> internetPermissionAppIds = new ArrayList<>();
         ArrayList<Integer> updateStatsPermissionAppIds = new ArrayList<>();
diff --git a/services/core/jni/com_android_server_TestNetworkService.cpp b/services/core/jni/com_android_server_TestNetworkService.cpp
index b90ff23..36a6fde 100644
--- a/services/core/jni/com_android_server_TestNetworkService.cpp
+++ b/services/core/jni/com_android_server_TestNetworkService.cpp
@@ -54,12 +54,12 @@
     jniThrowException(env, "java/lang/IllegalStateException", msg.c_str());
 }
 
-static int createTunInterface(JNIEnv* env, const char* iface) {
+static int createTunTapInterface(JNIEnv* env, bool isTun, const char* iface) {
     base::unique_fd tun(open("/dev/tun", O_RDWR | O_NONBLOCK));
     ifreq ifr{};
 
     // Allocate interface.
-    ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+    ifr.ifr_flags = (isTun ? IFF_TUN : IFF_TAP) | IFF_NO_PI;
     strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
     if (ioctl(tun.get(), TUNSETIFF, &ifr)) {
         throwException(env, errno, "allocating", ifr.ifr_name);
@@ -80,23 +80,23 @@
 
 //------------------------------------------------------------------------------
 
-static jint create(JNIEnv* env, jobject /* thiz */, jstring jIface) {
+static jint create(JNIEnv* env, jobject /* thiz */, jboolean isTun, jstring jIface) {
     ScopedUtfChars iface(env, jIface);
     if (!iface.c_str()) {
         jniThrowNullPointerException(env, "iface");
         return -1;
     }
 
-    int tun = createTunInterface(env, iface.c_str());
+    int tun = createTunTapInterface(env, isTun, iface.c_str());
 
-    // Any exceptions will be thrown from the createTunInterface call
+    // Any exceptions will be thrown from the createTunTapInterface call
     return tun;
 }
 
 //------------------------------------------------------------------------------
 
 static const JNINativeMethod gMethods[] = {
-    {"jniCreateTun", "(Ljava/lang/String;)I", (void*)create},
+    {"jniCreateTunTap", "(ZLjava/lang/String;)I", (void*)create},
 };
 
 int register_android_server_TestNetworkService(JNIEnv* env) {
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index 70b4089..c8ef82e 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -4,6 +4,7 @@
 java_defaults {
     name: "FrameworksNetTests-jni-defaults",
     static_libs: [
+        "FrameworksNetCommonTests",
         "frameworks-base-testutils",
         "framework-protos",
         "androidx.test.rules",
diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp
new file mode 100644
index 0000000..0a1ac75
--- /dev/null
+++ b/tests/net/common/Android.bp
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Tests in this folder are included both in unit tests and CTS.
+// They must be fast and stable, and exercise public or test APIs.
+java_library {
+    name: "FrameworksNetCommonTests",
+    srcs: ["java/**/*.java"],
+    static_libs: [
+        "androidx.test.rules",
+        "junit",
+    ],
+    libs: [
+        "android.test.base.stubs",
+    ],
+}
\ No newline at end of file
diff --git a/tests/net/java/android/net/IpPrefixTest.java b/tests/net/common/java/android/net/IpPrefixTest.java
similarity index 84%
rename from tests/net/java/android/net/IpPrefixTest.java
rename to tests/net/common/java/android/net/IpPrefixTest.java
index abf019a..719960d 100644
--- a/tests/net/java/android/net/IpPrefixTest.java
+++ b/tests/net/common/java/android/net/IpPrefixTest.java
@@ -39,7 +39,7 @@
 @SmallTest
 public class IpPrefixTest {
 
-    private static InetAddress Address(String addr) {
+    private static InetAddress address(String addr) {
         return InetAddress.parseNumericAddress(addr);
     }
 
@@ -58,59 +58,59 @@
         try {
             p = new IpPrefix((byte[]) null, 9);
             fail("Expected NullPointerException: null byte array");
-        } catch(RuntimeException expected) {}
+        } catch (RuntimeException expected) { }
 
         try {
             p = new IpPrefix((InetAddress) null, 10);
             fail("Expected NullPointerException: null InetAddress");
-        } catch(RuntimeException expected) {}
+        } catch (RuntimeException expected) { }
 
         try {
             p = new IpPrefix((String) null);
             fail("Expected NullPointerException: null String");
-        } catch(RuntimeException expected) {}
+        } catch (RuntimeException expected) { }
 
 
         try {
             byte[] b2 = {1, 2, 3, 4, 5};
             p = new IpPrefix(b2, 29);
             fail("Expected IllegalArgumentException: invalid array length");
-        } catch(IllegalArgumentException expected) {}
+        } catch (IllegalArgumentException expected) { }
 
         try {
             p = new IpPrefix("1.2.3.4");
             fail("Expected IllegalArgumentException: no prefix length");
-        } catch(IllegalArgumentException expected) {}
+        } catch (IllegalArgumentException expected) { }
 
         try {
             p = new IpPrefix("1.2.3.4/");
             fail("Expected IllegalArgumentException: empty prefix length");
-        } catch(IllegalArgumentException expected) {}
+        } catch (IllegalArgumentException expected) { }
 
         try {
             p = new IpPrefix("foo/32");
             fail("Expected IllegalArgumentException: invalid address");
-        } catch(IllegalArgumentException expected) {}
+        } catch (IllegalArgumentException expected) { }
 
         try {
             p = new IpPrefix("1/32");
             fail("Expected IllegalArgumentException: deprecated IPv4 format");
-        } catch(IllegalArgumentException expected) {}
+        } catch (IllegalArgumentException expected) { }
 
         try {
             p = new IpPrefix("1.2.3.256/32");
             fail("Expected IllegalArgumentException: invalid IPv4 address");
-        } catch(IllegalArgumentException expected) {}
+        } catch (IllegalArgumentException expected) { }
 
         try {
             p = new IpPrefix("foo/32");
             fail("Expected IllegalArgumentException: non-address");
-        } catch(IllegalArgumentException expected) {}
+        } catch (IllegalArgumentException expected) { }
 
         try {
             p = new IpPrefix("f00:::/32");
             fail("Expected IllegalArgumentException: invalid IPv6 address");
-        } catch(IllegalArgumentException expected) {}
+        } catch (IllegalArgumentException expected) { }
     }
 
     @Test
@@ -132,17 +132,17 @@
         try {
             p = new IpPrefix(IPV4_BYTES, 33);
             fail("Expected IllegalArgumentException: invalid prefix length");
-        } catch(RuntimeException expected) {}
+        } catch (RuntimeException expected) { }
 
         try {
             p = new IpPrefix(IPV4_BYTES, 128);
             fail("Expected IllegalArgumentException: invalid prefix length");
-        } catch(RuntimeException expected) {}
+        } catch (RuntimeException expected) { }
 
         try {
             p = new IpPrefix(IPV4_BYTES, -1);
             fail("Expected IllegalArgumentException: negative prefix length");
-        } catch(RuntimeException expected) {}
+        } catch (RuntimeException expected) { }
 
         p = new IpPrefix(IPV6_BYTES, 128);
         assertEquals("2001:db8:dead:beef:f00::a0/128", p.toString());
@@ -162,12 +162,12 @@
         try {
             p = new IpPrefix(IPV6_BYTES, -1);
             fail("Expected IllegalArgumentException: negative prefix length");
-        } catch(RuntimeException expected) {}
+        } catch (RuntimeException expected) { }
 
         try {
             p = new IpPrefix(IPV6_BYTES, 129);
             fail("Expected IllegalArgumentException: negative prefix length");
-        } catch(RuntimeException expected) {}
+        } catch (RuntimeException expected) { }
 
     }
 
@@ -226,28 +226,28 @@
     @Test
     public void testContainsInetAddress() {
         IpPrefix p = new IpPrefix("2001:db8:f00::ace:d00d/127");
-        assertTrue(p.contains(Address("2001:db8:f00::ace:d00c")));
-        assertTrue(p.contains(Address("2001:db8:f00::ace:d00d")));
-        assertFalse(p.contains(Address("2001:db8:f00::ace:d00e")));
-        assertFalse(p.contains(Address("2001:db8:f00::bad:d00d")));
-        assertFalse(p.contains(Address("2001:4868:4860::8888")));
-        assertFalse(p.contains(Address("8.8.8.8")));
+        assertTrue(p.contains(address("2001:db8:f00::ace:d00c")));
+        assertTrue(p.contains(address("2001:db8:f00::ace:d00d")));
+        assertFalse(p.contains(address("2001:db8:f00::ace:d00e")));
+        assertFalse(p.contains(address("2001:db8:f00::bad:d00d")));
+        assertFalse(p.contains(address("2001:4868:4860::8888")));
+        assertFalse(p.contains(address("8.8.8.8")));
 
         p = new IpPrefix("192.0.2.0/23");
-        assertTrue(p.contains(Address("192.0.2.43")));
-        assertTrue(p.contains(Address("192.0.3.21")));
-        assertFalse(p.contains(Address("192.0.0.21")));
-        assertFalse(p.contains(Address("8.8.8.8")));
-        assertFalse(p.contains(Address("2001:4868:4860::8888")));
+        assertTrue(p.contains(address("192.0.2.43")));
+        assertTrue(p.contains(address("192.0.3.21")));
+        assertFalse(p.contains(address("192.0.0.21")));
+        assertFalse(p.contains(address("8.8.8.8")));
+        assertFalse(p.contains(address("2001:4868:4860::8888")));
 
         IpPrefix ipv6Default = new IpPrefix("::/0");
-        assertTrue(ipv6Default.contains(Address("2001:db8::f00")));
-        assertFalse(ipv6Default.contains(Address("192.0.2.1")));
+        assertTrue(ipv6Default.contains(address("2001:db8::f00")));
+        assertFalse(ipv6Default.contains(address("192.0.2.1")));
 
         IpPrefix ipv4Default = new IpPrefix("0.0.0.0/0");
-        assertTrue(ipv4Default.contains(Address("255.255.255.255")));
-        assertTrue(ipv4Default.contains(Address("192.0.2.1")));
-        assertFalse(ipv4Default.contains(Address("2001:db8::f00")));
+        assertTrue(ipv4Default.contains(address("255.255.255.255")));
+        assertTrue(ipv4Default.contains(address("192.0.2.1")));
+        assertFalse(ipv4Default.contains(address("2001:db8::f00")));
     }
 
     @Test
@@ -315,10 +315,10 @@
                 p = new IpPrefix(b, random.nextInt(129));
             }
             if (p.equals(oldP)) {
-              assertEquals(p.hashCode(), oldP.hashCode());
+                assertEquals(p.hashCode(), oldP.hashCode());
             }
             if (p.hashCode() != oldP.hashCode()) {
-              assertNotEquals(p, oldP);
+                assertNotEquals(p, oldP);
             }
         }
     }
@@ -332,9 +332,9 @@
             new IpPrefix("0.0.0.0/0"),
         };
         for (int i = 0; i < prefixes.length; i++) {
-          for (int j = i + 1; j < prefixes.length; j++) {
-            assertNotEquals(prefixes[i].hashCode(), prefixes[j].hashCode());
-          }
+            for (int j = i + 1; j < prefixes.length; j++) {
+                assertNotEquals(prefixes[i].hashCode(), prefixes[j].hashCode());
+            }
         }
     }
 
@@ -371,8 +371,8 @@
     }
 
     public void assertParcelingIsLossless(IpPrefix p) {
-      IpPrefix p2 = passThroughParcel(p);
-      assertEquals(p, p2);
+        IpPrefix p2 = passThroughParcel(p);
+        assertEquals(p, p2);
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java
index 68ff777..22a2c94 100644
--- a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyObject;
 import static org.mockito.Matchers.eq;
@@ -134,11 +135,11 @@
         IBinder binderMock = mock(IBinder.class);
         doThrow(new RemoteException()).when(binderMock).linkToDeath(anyObject(), anyInt());
 
-        RefcountedResource<IResource> refcountedResource = getTestRefcountedResource(binderMock);
-
-        // Verify that cleanup is performed (Spy limitations prevent verification of method calls
-        // for binder death scenario; check refcount to determine if cleanup was performed.)
-        assertEquals(-1, refcountedResource.mRefCount);
+        try {
+            getTestRefcountedResource(binderMock);
+            fail("Expected exception to propogate when binder fails to link to death");
+        } catch (RuntimeException expected) {
+        }
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java
index b5c3e92..4a35015 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -156,10 +156,21 @@
 
     @Test
     public void testOpenAndCloseUdpEncapsulationSocket() throws Exception {
-        int localport = findUnusedPort();
+        int localport = -1;
+        IpSecUdpEncapResponse udpEncapResp = null;
 
-        IpSecUdpEncapResponse udpEncapResp =
-                mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+        for (int i = 0; i < IpSecService.MAX_PORT_BIND_ATTEMPTS; i++) {
+            localport = findUnusedPort();
+
+            udpEncapResp = mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+            assertNotNull(udpEncapResp);
+            if (udpEncapResp.status == IpSecManager.Status.OK) {
+                break;
+            }
+
+            // Else retry to reduce possibility for port-bind failures.
+        }
+
         assertNotNull(udpEncapResp);
         assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
         assertEquals(localport, udpEncapResp.port);
@@ -204,12 +215,11 @@
 
     @Test
     public void testOpenUdpEncapsulationSocketAfterClose() throws Exception {
-        int localport = findUnusedPort();
         IpSecUdpEncapResponse udpEncapResp =
-                mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+                mIpSecService.openUdpEncapsulationSocket(0, new Binder());
         assertNotNull(udpEncapResp);
         assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
-        assertEquals(localport, udpEncapResp.port);
+        int localport = udpEncapResp.port;
 
         mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId);
         udpEncapResp.fileDescriptor.close();
@@ -226,12 +236,11 @@
      */
     @Test
     public void testUdpEncapPortNotReleased() throws Exception {
-        int localport = findUnusedPort();
         IpSecUdpEncapResponse udpEncapResp =
-                mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+                mIpSecService.openUdpEncapsulationSocket(0, new Binder());
         assertNotNull(udpEncapResp);
         assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
-        assertEquals(localport, udpEncapResp.port);
+        int localport = udpEncapResp.port;
 
         udpEncapResp.fileDescriptor.close();
 
@@ -273,14 +282,11 @@
 
     @Test
     public void testOpenUdpEncapsulationSocketTwice() throws Exception {
-        int localport = findUnusedPort();
-
         IpSecUdpEncapResponse udpEncapResp =
-                mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+                mIpSecService.openUdpEncapsulationSocket(0, new Binder());
         assertNotNull(udpEncapResp);
         assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
-        assertEquals(localport, udpEncapResp.port);
-        mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+        int localport = udpEncapResp.port;
 
         IpSecUdpEncapResponse testUdpEncapResp =
                 mIpSecService.openUdpEncapsulationSocket(localport, new Binder());