Merge "Add test for increment operation count on non-default network"
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1e96872..540ea5c 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3152,9 +3152,9 @@
     }
 
     /**
-     * Set sign in error notification to visible or in visible
+     * Set sign in error notification to visible or invisible
      *
-     * {@hide}
+     * @hide
      * @deprecated Doesn't properly deal with multiple connected networks of the same type.
      */
     @Deprecated
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index fb01283..95a2f2e 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -31,6 +31,7 @@
 import android.net.ProxyInfo;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.INetworkActivityListener;
 import android.os.Messenger;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
@@ -233,4 +234,10 @@
                 in PersistableBundle extras);
 
     void systemReady();
+
+    void registerNetworkActivityListener(in INetworkActivityListener l);
+
+    void unregisterNetworkActivityListener(in INetworkActivityListener l);
+
+    boolean isDefaultNetworkActive();
 }
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 0941e7d..486e2d7 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -20,12 +20,13 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.net.util.LinkPropertiesUtils;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
 
+import com.android.net.module.util.LinkPropertiesUtils;
+
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java
index 178183d..c7116b4 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -20,13 +20,13 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.net.util.MacAddressUtils;
 import android.net.wifi.WifiInfo;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import com.android.internal.util.Preconditions;
+import com.android.net.module.util.MacAddressUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index d84ee2a..b5962c5 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -16,14 +16,9 @@
 
 package android.net;
 
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-
-import android.annotation.NonNull;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.system.ErrnoException;
-import android.system.Os;
 import android.util.Log;
 import android.util.Pair;
 
@@ -155,14 +150,6 @@
     public static native Network getDnsNetwork() throws ErrnoException;
 
     /**
-     * Allow/Disallow creating AF_INET/AF_INET6 sockets and DNS lookups for current process.
-     *
-     * @param allowNetworking whether to allow or disallow creating AF_INET/AF_INET6 sockets
-     *                        and DNS lookups.
-     */
-    public static native void setAllowNetworkingForProcess(boolean allowNetworking);
-
-    /**
      * Get the tcp repair window associated with the {@code fd}.
      *
      * @param fd the tcp socket's {@link FileDescriptor}.
@@ -437,60 +424,4 @@
         return routedIPCount;
     }
 
-    private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET, AF_INET6};
-
-    /**
-     * Returns true if the hostname is weakly validated.
-     * @param hostname Name of host to validate.
-     * @return True if it's a valid-ish hostname.
-     *
-     * @hide
-     */
-    public static boolean isWeaklyValidatedHostname(@NonNull String hostname) {
-        // TODO(b/34953048): Use a validation method that permits more accurate,
-        // but still inexpensive, checking of likely valid DNS hostnames.
-        final String weakHostnameRegex = "^[a-zA-Z0-9_.-]+$";
-        if (!hostname.matches(weakHostnameRegex)) {
-            return false;
-        }
-
-        for (int address_family : ADDRESS_FAMILIES) {
-            if (Os.inet_pton(address_family, hostname) != null) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Safely multiple a value by a rational.
-     * <p>
-     * Internally it uses integer-based math whenever possible, but switches
-     * over to double-based math if values would overflow.
-     * @hide
-     */
-    public static long multiplySafeByRational(long value, long num, long den) {
-        if (den == 0) {
-            throw new ArithmeticException("Invalid Denominator");
-        }
-        long x = value;
-        long y = num;
-
-        // Logic shamelessly borrowed from Math.multiplyExact()
-        long r = x * y;
-        long ax = Math.abs(x);
-        long ay = Math.abs(y);
-        if (((ax | ay) >>> 31 != 0)) {
-            // Some bits greater than 2^31 that might cause overflow
-            // Check the result using the divide operator
-            // and check for the special case of Long.MIN_VALUE * -1
-            if (((y != 0) && (r / y != x)) ||
-                    (x == Long.MIN_VALUE && y == -1)) {
-                // Use double math to avoid overflowing
-                return (long) (((double) num / den) * value);
-            }
-        }
-        return r / den;
-    }
 }
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 6166a75..94f849f 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -21,11 +21,12 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.net.util.NetUtils;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.net.module.util.NetUtils;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.net.Inet4Address;
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 8d4c4e5..2155246 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008, The Android Open Source Project
+ * Copyright 2020, 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.
@@ -28,7 +28,6 @@
 #include <netinet/udp.h>
 
 #include <DnsProxydProtocol.h> // NETID_USE_LOCAL_NAMESERVERS
-#include <android_runtime/AndroidRuntime.h>
 #include <cutils/properties.h>
 #include <nativehelper/JNIPlatformHelp.h>
 #include <nativehelper/ScopedLocalRef.h>
@@ -226,11 +225,6 @@
             class_Network, ctor, dnsNetId & ~NETID_USE_LOCAL_NAMESERVERS, privateDnsBypass);
 }
 
-static void android_net_utils_setAllowNetworkingForProcess(JNIEnv *env, jobject thiz,
-                                                           jboolean hasConnectivity) {
-    setAllowNetworkingForProcess(hasConnectivity == JNI_TRUE);
-}
-
 static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) {
     if (javaFd == NULL) {
         jniThrowNullPointerException(env, NULL);
@@ -288,7 +282,6 @@
     { "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult },
     { "resNetworkCancel", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_resNetworkCancel },
     { "getDnsNetwork", "()Landroid/net/Network;", (void*) android_net_utils_getDnsNetwork },
-    { "setAllowNetworkingForProcess", "(Z)V", (void *)android_net_utils_setAllowNetworkingForProcess },
 };
 // clang-format on
 
diff --git a/service/Android.bp b/service/Android.bp
new file mode 100644
index 0000000..a26f715
--- /dev/null
+++ b/service/Android.bp
@@ -0,0 +1,79 @@
+//
+// Copyright (C) 2020 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.
+//
+
+cc_defaults {
+    name: "libservice-connectivity-defaults",
+    // TODO: build against the NDK (sdk_version: "30" for example)
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-parameter",
+        "-Wthread-safety",
+    ],
+    srcs: [
+        "jni/com_android_server_TestNetworkService.cpp",
+        "jni/com_android_server_connectivity_Vpn.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libnativehelper",
+        // TODO: remove dependency on ifc_[add/del]_address by having Java code to add/delete
+        // addresses, and remove dependency on libnetutils.
+        "libnetutils",
+    ],
+}
+
+cc_library_shared {
+    name: "libservice-connectivity",
+    defaults: ["libservice-connectivity-defaults"],
+    srcs: [
+        "jni/onload.cpp",
+    ],
+    apex_available: [
+        // TODO: move this library to the tethering APEX and remove libservice-connectivity-static
+        // "com.android.tethering",
+    ],
+}
+
+// Static library linked into libservices.core until libservice-connectivity can be loaded from
+// the tethering APEX instead.
+cc_library_static {
+    name: "libservice-connectivity-static",
+    defaults: ["libservice-connectivity-defaults"],
+}
+
+java_library {
+    name: "service-connectivity",
+    srcs: [
+        ":connectivity-service-srcs",
+    ],
+    installable: true,
+    jarjar_rules: "jarjar-rules.txt",
+    libs: [
+        "android.net.ipsec.ike",
+        "services.core",
+        "services.net",
+        "unsupportedappusage",
+    ],
+    static_libs: [
+        "net-utils-device-common",
+        "net-utils-framework-common",
+    ],
+    apex_available: [
+        "//apex_available:platform",
+    ],
+}
diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt
new file mode 100644
index 0000000..ef53ebb
--- /dev/null
+++ b/service/jarjar-rules.txt
@@ -0,0 +1 @@
+rule com.android.net.module.util.** com.android.connectivity.util.@1
\ No newline at end of file
diff --git a/services/core/jni/com_android_server_TestNetworkService.cpp b/service/jni/com_android_server_TestNetworkService.cpp
similarity index 100%
rename from services/core/jni/com_android_server_TestNetworkService.cpp
rename to service/jni/com_android_server_TestNetworkService.cpp
diff --git a/service/jni/com_android_server_connectivity_Vpn.cpp b/service/jni/com_android_server_connectivity_Vpn.cpp
new file mode 100644
index 0000000..ea5e718
--- /dev/null
+++ b/service/jni/com_android_server_connectivity_Vpn.cpp
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#define LOG_NDEBUG 0
+
+#define LOG_TAG "VpnJni"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/route.h>
+#include <linux/ipv6_route.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <log/log.h>
+#include <android/log.h>
+
+#include "netutils/ifc.h"
+
+#include "jni.h"
+#include <nativehelper/JNIHelp.h>
+
+namespace android
+{
+
+static int inet4 = -1;
+static int inet6 = -1;
+
+static inline in_addr_t *as_in_addr(sockaddr *sa) {
+    return &((sockaddr_in *)sa)->sin_addr.s_addr;
+}
+
+//------------------------------------------------------------------------------
+
+#define SYSTEM_ERROR (-1)
+#define BAD_ARGUMENT (-2)
+
+static int create_interface(int mtu)
+{
+    int tun = open("/dev/tun", O_RDWR | O_NONBLOCK | O_CLOEXEC);
+
+    ifreq ifr4;
+    memset(&ifr4, 0, sizeof(ifr4));
+
+    // Allocate interface.
+    ifr4.ifr_flags = IFF_TUN | IFF_NO_PI;
+    if (ioctl(tun, TUNSETIFF, &ifr4)) {
+        ALOGE("Cannot allocate TUN: %s", strerror(errno));
+        goto error;
+    }
+
+    // Activate interface.
+    ifr4.ifr_flags = IFF_UP;
+    if (ioctl(inet4, SIOCSIFFLAGS, &ifr4)) {
+        ALOGE("Cannot activate %s: %s", ifr4.ifr_name, strerror(errno));
+        goto error;
+    }
+
+    // Set MTU if it is specified.
+    ifr4.ifr_mtu = mtu;
+    if (mtu > 0 && ioctl(inet4, SIOCSIFMTU, &ifr4)) {
+        ALOGE("Cannot set MTU on %s: %s", ifr4.ifr_name, strerror(errno));
+        goto error;
+    }
+
+    return tun;
+
+error:
+    close(tun);
+    return SYSTEM_ERROR;
+}
+
+static int get_interface_name(char *name, int tun)
+{
+    ifreq ifr4;
+    if (ioctl(tun, TUNGETIFF, &ifr4)) {
+        ALOGE("Cannot get interface name: %s", strerror(errno));
+        return SYSTEM_ERROR;
+    }
+    strncpy(name, ifr4.ifr_name, IFNAMSIZ);
+    return 0;
+}
+
+static int get_interface_index(const char *name)
+{
+    ifreq ifr4;
+    strncpy(ifr4.ifr_name, name, IFNAMSIZ);
+    if (ioctl(inet4, SIOGIFINDEX, &ifr4)) {
+        ALOGE("Cannot get index of %s: %s", name, strerror(errno));
+        return SYSTEM_ERROR;
+    }
+    return ifr4.ifr_ifindex;
+}
+
+static int set_addresses(const char *name, const char *addresses)
+{
+    int index = get_interface_index(name);
+    if (index < 0) {
+        return index;
+    }
+
+    ifreq ifr4;
+    memset(&ifr4, 0, sizeof(ifr4));
+    strncpy(ifr4.ifr_name, name, IFNAMSIZ);
+    ifr4.ifr_addr.sa_family = AF_INET;
+    ifr4.ifr_netmask.sa_family = AF_INET;
+
+    in6_ifreq ifr6;
+    memset(&ifr6, 0, sizeof(ifr6));
+    ifr6.ifr6_ifindex = index;
+
+    char address[65];
+    int prefix;
+    int chars;
+    int count = 0;
+
+    while (sscanf(addresses, " %64[^/]/%d %n", address, &prefix, &chars) == 2) {
+        addresses += chars;
+
+        if (strchr(address, ':')) {
+            // Add an IPv6 address.
+            if (inet_pton(AF_INET6, address, &ifr6.ifr6_addr) != 1 ||
+                    prefix < 0 || prefix > 128) {
+                count = BAD_ARGUMENT;
+                break;
+            }
+
+            ifr6.ifr6_prefixlen = prefix;
+            if (ioctl(inet6, SIOCSIFADDR, &ifr6)) {
+                count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
+                break;
+            }
+        } else {
+            // Add an IPv4 address.
+            if (inet_pton(AF_INET, address, as_in_addr(&ifr4.ifr_addr)) != 1 ||
+                    prefix < 0 || prefix > 32) {
+                count = BAD_ARGUMENT;
+                break;
+            }
+
+            if (count) {
+                snprintf(ifr4.ifr_name, sizeof(ifr4.ifr_name), "%s:%d", name, count);
+            }
+            if (ioctl(inet4, SIOCSIFADDR, &ifr4)) {
+                count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
+                break;
+            }
+
+            in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0;
+            *as_in_addr(&ifr4.ifr_netmask) = htonl(mask);
+            if (ioctl(inet4, SIOCSIFNETMASK, &ifr4)) {
+                count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
+                break;
+            }
+        }
+        ALOGD("Address added on %s: %s/%d", name, address, prefix);
+        ++count;
+    }
+
+    if (count == BAD_ARGUMENT) {
+        ALOGE("Invalid address: %s/%d", address, prefix);
+    } else if (count == SYSTEM_ERROR) {
+        ALOGE("Cannot add address: %s/%d: %s", address, prefix, strerror(errno));
+    } else if (*addresses) {
+        ALOGE("Invalid address: %s", addresses);
+        count = BAD_ARGUMENT;
+    }
+
+    return count;
+}
+
+static int reset_interface(const char *name)
+{
+    ifreq ifr4;
+    strncpy(ifr4.ifr_name, name, IFNAMSIZ);
+    ifr4.ifr_flags = 0;
+
+    if (ioctl(inet4, SIOCSIFFLAGS, &ifr4) && errno != ENODEV) {
+        ALOGE("Cannot reset %s: %s", name, strerror(errno));
+        return SYSTEM_ERROR;
+    }
+    return 0;
+}
+
+static int check_interface(const char *name)
+{
+    ifreq ifr4;
+    strncpy(ifr4.ifr_name, name, IFNAMSIZ);
+    ifr4.ifr_flags = 0;
+
+    if (ioctl(inet4, SIOCGIFFLAGS, &ifr4) && errno != ENODEV) {
+        ALOGE("Cannot check %s: %s", name, strerror(errno));
+    }
+    return ifr4.ifr_flags;
+}
+
+static bool modifyAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddress,
+                          jint jPrefixLength, bool add)
+{
+    int error = SYSTEM_ERROR;
+    const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
+    const char *address = jAddress ? env->GetStringUTFChars(jAddress, NULL) : NULL;
+
+    if (!name) {
+        jniThrowNullPointerException(env, "name");
+    } else if (!address) {
+        jniThrowNullPointerException(env, "address");
+    } else {
+        if (add) {
+            if ((error = ifc_add_address(name, address, jPrefixLength)) != 0) {
+                ALOGE("Cannot add address %s/%d on interface %s (%s)", address, jPrefixLength, name,
+                      strerror(-error));
+            }
+        } else {
+            if ((error = ifc_del_address(name, address, jPrefixLength)) != 0) {
+                ALOGE("Cannot del address %s/%d on interface %s (%s)", address, jPrefixLength, name,
+                      strerror(-error));
+            }
+        }
+    }
+
+    if (name) {
+        env->ReleaseStringUTFChars(jName, name);
+    }
+    if (address) {
+        env->ReleaseStringUTFChars(jAddress, address);
+    }
+    return !error;
+}
+
+//------------------------------------------------------------------------------
+
+static void throwException(JNIEnv *env, int error, const char *message)
+{
+    if (error == SYSTEM_ERROR) {
+        jniThrowException(env, "java/lang/IllegalStateException", message);
+    } else {
+        jniThrowException(env, "java/lang/IllegalArgumentException", message);
+    }
+}
+
+static jint create(JNIEnv *env, jobject /* thiz */, jint mtu)
+{
+    int tun = create_interface(mtu);
+    if (tun < 0) {
+        throwException(env, tun, "Cannot create interface");
+        return -1;
+    }
+    return tun;
+}
+
+static jstring getName(JNIEnv *env, jobject /* thiz */, jint tun)
+{
+    char name[IFNAMSIZ];
+    if (get_interface_name(name, tun) < 0) {
+        throwException(env, SYSTEM_ERROR, "Cannot get interface name");
+        return NULL;
+    }
+    return env->NewStringUTF(name);
+}
+
+static jint setAddresses(JNIEnv *env, jobject /* thiz */, jstring jName,
+        jstring jAddresses)
+{
+    const char *name = NULL;
+    const char *addresses = NULL;
+    int count = -1;
+
+    name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
+    if (!name) {
+        jniThrowNullPointerException(env, "name");
+        goto error;
+    }
+    addresses = jAddresses ? env->GetStringUTFChars(jAddresses, NULL) : NULL;
+    if (!addresses) {
+        jniThrowNullPointerException(env, "addresses");
+        goto error;
+    }
+    count = set_addresses(name, addresses);
+    if (count < 0) {
+        throwException(env, count, "Cannot set address");
+        count = -1;
+    }
+
+error:
+    if (name) {
+        env->ReleaseStringUTFChars(jName, name);
+    }
+    if (addresses) {
+        env->ReleaseStringUTFChars(jAddresses, addresses);
+    }
+    return count;
+}
+
+static void reset(JNIEnv *env, jobject /* thiz */, jstring jName)
+{
+    const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
+    if (!name) {
+        jniThrowNullPointerException(env, "name");
+        return;
+    }
+    if (reset_interface(name) < 0) {
+        throwException(env, SYSTEM_ERROR, "Cannot reset interface");
+    }
+    env->ReleaseStringUTFChars(jName, name);
+}
+
+static jint check(JNIEnv *env, jobject /* thiz */, jstring jName)
+{
+    const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
+    if (!name) {
+        jniThrowNullPointerException(env, "name");
+        return 0;
+    }
+    int flags = check_interface(name);
+    env->ReleaseStringUTFChars(jName, name);
+    return flags;
+}
+
+static bool addAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddress,
+                       jint jPrefixLength)
+{
+    return modifyAddress(env, thiz, jName, jAddress, jPrefixLength, true);
+}
+
+static bool delAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddress,
+                       jint jPrefixLength)
+{
+    return modifyAddress(env, thiz, jName, jAddress, jPrefixLength, false);
+}
+
+//------------------------------------------------------------------------------
+
+static const JNINativeMethod gMethods[] = {
+    {"jniCreate", "(I)I", (void *)create},
+    {"jniGetName", "(I)Ljava/lang/String;", (void *)getName},
+    {"jniSetAddresses", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setAddresses},
+    {"jniReset", "(Ljava/lang/String;)V", (void *)reset},
+    {"jniCheck", "(Ljava/lang/String;)I", (void *)check},
+    {"jniAddAddress", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)addAddress},
+    {"jniDelAddress", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)delAddress},
+};
+
+int register_android_server_connectivity_Vpn(JNIEnv *env)
+{
+    if (inet4 == -1) {
+        inet4 = socket(AF_INET, SOCK_DGRAM, 0);
+    }
+    if (inet6 == -1) {
+        inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
+    }
+    return jniRegisterNativeMethods(env, "com/android/server/connectivity/Vpn",
+            gMethods, NELEM(gMethods));
+}
+
+};
diff --git a/service/jni/onload.cpp b/service/jni/onload.cpp
new file mode 100644
index 0000000..3afcb0e
--- /dev/null
+++ b/service/jni/onload.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include <nativehelper/JNIHelp.h>
+#include <log/log.h>
+
+namespace android {
+
+int register_android_server_connectivity_Vpn(JNIEnv* env);
+int register_android_server_TestNetworkService(JNIEnv* env);
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
+    JNIEnv *env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        ALOGE("GetEnv failed");
+        return JNI_ERR;
+    }
+
+    if (register_android_server_connectivity_Vpn(env) < 0
+        || register_android_server_TestNetworkService(env) < 0) {
+        return JNI_ERR;
+    }
+
+    return JNI_VERSION_1_6;
+}
+
+};
\ No newline at end of file
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 184f1bf..fe116d9 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -136,8 +136,6 @@
 import android.net.metrics.NetworkEvent;
 import android.net.netlink.InetDiagMessage;
 import android.net.shared.PrivateDnsConfig;
-import android.net.util.LinkPropertiesUtils.CompareOrUpdateResult;
-import android.net.util.LinkPropertiesUtils.CompareResult;
 import android.net.util.MultinetworkPolicyTracker;
 import android.net.util.NetdService;
 import android.os.Binder;
@@ -146,6 +144,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.INetworkActivityListener;
 import android.os.INetworkManagementService;
 import android.os.Looper;
 import android.os.Message;
@@ -191,6 +190,8 @@
 import com.android.internal.util.MessageUtils;
 import com.android.internal.util.XmlUtils;
 import com.android.modules.utils.BasicShellCommandHandler;
+import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
+import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.connectivity.AutodestructReference;
 import com.android.server.connectivity.DataConnectionStats;
@@ -200,7 +201,6 @@
 import com.android.server.connectivity.KeepaliveTracker;
 import com.android.server.connectivity.LingerMonitor;
 import com.android.server.connectivity.MockableSystemProperties;
-import com.android.server.connectivity.MultipathPolicyTracker;
 import com.android.server.connectivity.NetworkAgentInfo;
 import com.android.server.connectivity.NetworkDiagnostics;
 import com.android.server.connectivity.NetworkNotificationManager;
@@ -441,11 +441,6 @@
     private static final int EVENT_EXPIRE_NET_TRANSITION_WAKELOCK = 24;
 
     /**
-     * Used internally to indicate the system is ready.
-     */
-    private static final int EVENT_SYSTEM_READY = 25;
-
-    /**
      * used to add a network request with a pending intent
      * obj = NetworkRequestInfo
      */
@@ -660,9 +655,6 @@
     final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
 
     @VisibleForTesting
-    final MultipathPolicyTracker mMultipathPolicyTracker;
-
-    @VisibleForTesting
     final Map<IBinder, ConnectivityDiagnosticsCallbackInfo> mConnectivityDiagnosticsCallbacks =
             new HashMap<>();
 
@@ -1166,8 +1158,6 @@
                 mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
         mMultinetworkPolicyTracker.start();
 
-        mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler);
-
         mDnsManager = new DnsManager(mContext, mDnsResolver);
         registerPrivateDnsSettingsCallbacks();
     }
@@ -1380,8 +1370,11 @@
             return;
         }
         final String action = blocked ? "BLOCKED" : "UNBLOCKED";
+        final NetworkRequest satisfiedRequest = nri.getSatisfiedRequest();
+        final int requestId =  satisfiedRequest != null
+                ? satisfiedRequest.requestId : nri.mRequests.get(0).requestId;
         mNetworkInfoBlockingLogs.log(String.format(
-                "%s %d(%d) on netId %d", action, nri.mUid, nri.request.requestId, net.getNetId()));
+                "%s %d(%d) on netId %d", action, nri.mUid, requestId, net.getNetId()));
     }
 
     /**
@@ -1709,16 +1702,17 @@
             return newNc;
         }
 
-        Binder.withCleanCallingIdentity(
-                () -> {
-                    if (!mLocationPermissionChecker.checkLocationPermission(
-                            callerPkgName, null /* featureId */, callerUid, null /* message */)) {
-                        // Caller does not have the requisite location permissions. Reset the
-                        // owner's UID in the NetworkCapabilities.
-                        newNc.setOwnerUid(INVALID_UID);
-                    }
-                }
-        );
+        final long token = Binder.clearCallingIdentity();
+        try {
+            if (!mLocationPermissionChecker.checkLocationPermission(
+                    callerPkgName, null /* featureId */, callerUid, null /* message */)) {
+                // Caller does not have the requisite location permissions. Reset the
+                // owner's UID in the NetworkCapabilities.
+                newNc.setOwnerUid(INVALID_UID);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
 
         return newNc;
     }
@@ -1798,9 +1792,9 @@
 
     private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
         @Override
-        public void interfaceClassDataActivityChanged(String label, boolean active, long tsNanos) {
-            int deviceType = Integer.parseInt(label);
-            sendDataActivityBroadcast(deviceType, active, tsNanos);
+        public void interfaceClassDataActivityChanged(int networkType, boolean active, long tsNanos,
+                int uid) {
+            sendDataActivityBroadcast(networkType, active, tsNanos);
         }
     };
 
@@ -2309,10 +2303,13 @@
      */
     @VisibleForTesting
     public void systemReadyInternal() {
-        // Let PermissionMonitor#startMonitoring() running in the beginning of the systemReady
-        // before MultipathPolicyTracker.start(). Since mApps in PermissionMonitor needs to be
-        // populated first to ensure that listening network request which is sent by
-        // MultipathPolicyTracker won't be added NET_CAPABILITY_FOREGROUND capability.
+        // Since mApps in PermissionMonitor needs to be populated first to ensure that
+        // listening network request which is sent by MultipathPolicyTracker won't be added
+        // NET_CAPABILITY_FOREGROUND capability. Thus, MultipathPolicyTracker.start() must
+        // be called after PermissionMonitor#startMonitoring().
+        // Calling PermissionMonitor#startMonitoring() in systemReadyInternal() and the
+        // MultipathPolicyTracker.start() is called in NetworkPolicyManagerService#systemReady()
+        // to ensure the tracking will be initialized correctly.
         mPermissionMonitor.startMonitoring();
         mProxyTracker.loadGlobalProxy();
         registerNetdEventCallback();
@@ -2331,8 +2328,31 @@
 
         // Create network requests for always-on networks.
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS));
+    }
 
-        mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
+    /**
+     * Start listening for default data network activity state changes.
+     */
+    @Override
+    public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) {
+        // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here
+    }
+
+    /**
+     * Stop listening for default data network activity state changes.
+     */
+    @Override
+    public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) {
+        // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here
+    }
+
+    /**
+     * Check whether the default network radio is currently active.
+     */
+    @Override
+    public boolean isDefaultNetworkActive() {
+        // TODO: Replace isNetworkActive() in NMS.
+        return false;
     }
 
     /**
@@ -2607,7 +2627,6 @@
         dumpAvoidBadWifiSettings(pw);
 
         pw.println();
-        mMultipathPolicyTracker.dump(pw);
 
         if (ArrayUtils.contains(args, SHORT_ARG) == false) {
             pw.println();
@@ -2705,7 +2724,7 @@
      * Return an array of all current NetworkRequest sorted by request id.
      */
     @VisibleForTesting
-    protected NetworkRequestInfo[] requestsSortedById() {
+    NetworkRequestInfo[] requestsSortedById() {
         NetworkRequestInfo[] requests = new NetworkRequestInfo[0];
         requests = mNetworkRequests.values().toArray(requests);
         // Sort the array based off the NRI containing the min requestId in its requests.
@@ -3555,30 +3574,58 @@
             return false;
         }
         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
-            if (reason == UnneededFor.LINGER && nri.request.isBackgroundRequest()) {
+            if (reason == UnneededFor.LINGER
+                    && !nri.isMultilayerRequest()
+                    && nri.mRequests.get(0).isBackgroundRequest()) {
                 // Background requests don't affect lingering.
                 continue;
             }
 
-            // If this Network is already the highest scoring Network for a request, or if
-            // there is hope for it to become one if it validated, then it is needed.
-            if (nri.request.isRequest() && nai.satisfies(nri.request) &&
-                    (nai.isSatisfyingRequest(nri.request.requestId) ||
-                    // Note that this catches two important cases:
-                    // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
-                    //    is currently satisfying the request.  This is desirable when
-                    //    cellular ends up validating but WiFi does not.
-                    // 2. Unvalidated WiFi will not be reaped when validated cellular
-                    //    is currently satisfying the request.  This is desirable when
-                    //    WiFi ends up validating and out scoring cellular.
-                    nri.mSatisfier.getCurrentScore()
-                            < nai.getCurrentScoreAsValidated())) {
+            if (isNetworkPotentialSatisfier(nai, nri)) {
                 return false;
             }
         }
         return true;
     }
 
+    private boolean isNetworkPotentialSatisfier(
+            @NonNull final NetworkAgentInfo candidate, @NonNull final NetworkRequestInfo nri) {
+        // listen requests won't keep up a network satisfying it. If this is not a multilayer
+        // request, we can return immediately. For multilayer requests, we have to check to see if
+        // any of the multilayer requests may have a potential satisfier.
+        if (!nri.isMultilayerRequest() && nri.mRequests.get(0).isListen()) {
+            return false;
+        }
+        for (final NetworkRequest req : nri.mRequests) {
+            // As non-multilayer listen requests have already returned, the below would only happen
+            // for a multilayer request therefore continue to the next request if available.
+            if (req.isListen()) {
+                continue;
+            }
+            // If this Network is already the highest scoring Network for a request, or if
+            // there is hope for it to become one if it validated, then it is needed.
+            if (candidate.satisfies(req)) {
+                // As soon as a network is found that satisfies a request, return. Specifically for
+                // multilayer requests, returning as soon as a NetworkAgentInfo satisfies a request
+                // is important so as to not evaluate lower priority requests further in
+                // nri.mRequests.
+                final boolean isNetworkNeeded = candidate.isSatisfyingRequest(req.requestId)
+                        // Note that this catches two important cases:
+                        // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
+                        //    is currently satisfying the request.  This is desirable when
+                        //    cellular ends up validating but WiFi does not.
+                        // 2. Unvalidated WiFi will not be reaped when validated cellular
+                        //    is currently satisfying the request.  This is desirable when
+                        //    WiFi ends up validating and out scoring cellular.
+                        || nri.mSatisfier.getCurrentScore()
+                        < candidate.getCurrentScoreAsValidated();
+                return isNetworkNeeded;
+            }
+        }
+
+        return false;
+    }
+
     private NetworkRequestInfo getNriForAppRequest(
             NetworkRequest request, int callingUid, String requestedOperation) {
         final NetworkRequestInfo nri = mNetworkRequests.get(request);
@@ -3875,8 +3922,12 @@
                 new CaptivePortal(new CaptivePortalImpl(network).asBinder()));
         appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
 
-        Binder.withCleanCallingIdentity(() ->
-                mContext.startActivityAsUser(appIntent, UserHandle.CURRENT));
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mContext.startActivityAsUser(appIntent, UserHandle.CURRENT);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     private class CaptivePortalImpl extends ICaptivePortal.Stub {
@@ -4123,11 +4174,13 @@
             return ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED;
         }
 
-        Integer networkPreference = mMultipathPolicyTracker.getMultipathPreference(network);
-        if (networkPreference != null) {
+        final NetworkPolicyManager netPolicyManager =
+                 mContext.getSystemService(NetworkPolicyManager.class);
+
+        final int networkPreference = netPolicyManager.getMultipathPreference(network);
+        if (networkPreference != 0) {
             return networkPreference;
         }
-
         return mMultinetworkPolicyTracker.getMeteredMultipathPreference();
     }
 
@@ -4231,10 +4284,6 @@
                     mKeepaliveTracker.handleStopKeepalive(nai, slot, reason);
                     break;
                 }
-                case EVENT_SYSTEM_READY: {
-                    mMultipathPolicyTracker.start();
-                    break;
-                }
                 case EVENT_REVALIDATE_NETWORK: {
                     handleReportNetworkConnectivity((Network) msg.obj, msg.arg1, toBool(msg.arg2));
                     break;
@@ -5464,6 +5513,10 @@
             this(r, null);
         }
 
+        boolean isMultilayerRequest() {
+            return mRequests.size() > 1;
+        }
+
         private List<NetworkRequest> initializeRequests(NetworkRequest r) {
             final ArrayList<NetworkRequest> tempRequests = new ArrayList<>();
             tempRequests.add(new NetworkRequest(r));
@@ -5505,7 +5558,7 @@
         public void binderDied() {
             log("ConnectivityService NetworkRequestInfo binderDied(" +
                     mRequests + ", " + mBinder + ")");
-            releaseNetworkRequest(mRequests);
+            releaseNetworkRequests(mRequests);
         }
 
         @Override
@@ -5538,13 +5591,15 @@
         mAppOpsManager.checkPackage(callerUid, callerPackageName);
     }
 
-    private ArrayList<Integer> getSignalStrengthThresholds(NetworkAgentInfo nai) {
+    private ArrayList<Integer> getSignalStrengthThresholds(@NonNull final NetworkAgentInfo nai) {
         final SortedSet<Integer> thresholds = new TreeSet<>();
         synchronized (nai) {
-            for (NetworkRequestInfo nri : mNetworkRequests.values()) {
-                if (nri.request.networkCapabilities.hasSignalStrength() &&
-                        nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
-                    thresholds.add(nri.request.networkCapabilities.getSignalStrength());
+            for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
+                for (final NetworkRequest req : nri.mRequests) {
+                    if (req.networkCapabilities.hasSignalStrength()
+                            && nai.satisfiesImmutableCapabilitiesOf(req)) {
+                        thresholds.add(req.networkCapabilities.getSignalStrength());
+                    }
                 }
             }
         }
@@ -5831,7 +5886,7 @@
         return mNextNetworkProviderId.getAndIncrement();
     }
 
-    private void releaseNetworkRequest(List<NetworkRequest> networkRequests) {
+    private void releaseNetworkRequests(List<NetworkRequest> networkRequests) {
         for (int i = 0; i < networkRequests.size(); i++) {
             releaseNetworkRequest(networkRequests.get(i));
         }
@@ -7763,10 +7818,13 @@
 
         final int userId = UserHandle.getCallingUserId();
 
-        Binder.withCleanCallingIdentity(() -> {
+        final long token = Binder.clearCallingIdentity();
+        try {
             final IpMemoryStore ipMemoryStore = IpMemoryStore.getMemoryStore(mContext);
             ipMemoryStore.factoryReset();
-        });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
 
         // Turn airplane mode off
         setAirplaneMode(false);
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index 655d8ab..e8687e5 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -107,23 +107,23 @@
 
         String ifacePrefix = isTun ? TEST_TUN_PREFIX : TEST_TAP_PREFIX;
         String iface = ifacePrefix + sTestTunIndex.getAndIncrement();
-        return Binder.withCleanCallingIdentity(
-                () -> {
-                    try {
-                        ParcelFileDescriptor tunIntf =
-                                ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
-                        for (LinkAddress addr : linkAddrs) {
-                            mNetd.interfaceAddAddress(
-                                    iface,
-                                    addr.getAddress().getHostAddress(),
-                                    addr.getPrefixLength());
-                        }
+        final long token = Binder.clearCallingIdentity();
+        try {
+            ParcelFileDescriptor tunIntf =
+                    ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
+            for (LinkAddress addr : linkAddrs) {
+                mNetd.interfaceAddAddress(
+                        iface,
+                        addr.getAddress().getHostAddress(),
+                        addr.getPrefixLength());
+            }
 
-                        return new TestNetworkInterface(tunIntf, iface);
-                    } catch (RemoteException e) {
-                        throw e.rethrowFromSystemServer();
-                    }
-                });
+            return new TestNetworkInterface(tunIntf, iface);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     /**
@@ -317,7 +317,12 @@
 
         try {
             // This requires NETWORK_STACK privileges.
-            Binder.withCleanCallingIdentity(() -> mNMS.setInterfaceUp(iface));
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mNMS.setInterfaceUp(iface);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
 
             // Synchronize all accesses to mTestNetworkTracker to prevent the case where:
             // 1. TestNetworkAgent successfully binds to death of binder
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 7795ed3..3d71b0a 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -334,7 +334,13 @@
      */
     public void setProvNotificationVisible(boolean visible, int id, String action) {
         if (visible) {
-            Intent intent = new Intent(action);
+            // For legacy purposes, action is sent as the action + the phone ID from DcTracker.
+            // Split the string here and send the phone ID as an extra instead.
+            String[] splitAction = action.split(":");
+            Intent intent = new Intent(splitAction[0]);
+            try {
+                intent.putExtra("provision.phone.id", Integer.parseInt(splitAction[1]));
+            } catch (NumberFormatException ignored) { }
             PendingIntent pendingIntent = PendingIntent.getBroadcast(
                     mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE);
             showNotification(id, NotificationType.SIGN_IN, null, null, pendingIntent, false);
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index 5cb3d94..f6ca152 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -38,7 +38,9 @@
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.net.module.util.ProxyUtils;
 
+import java.util.Collections;
 import java.util.Objects;
 
 /**
@@ -163,9 +165,10 @@
         if (!TextUtils.isEmpty(host) || !TextUtils.isEmpty(pacFileUrl)) {
             ProxyInfo proxyProperties;
             if (!TextUtils.isEmpty(pacFileUrl)) {
-                proxyProperties = new ProxyInfo(Uri.parse(pacFileUrl));
+                proxyProperties = ProxyInfo.buildPacProxy(Uri.parse(pacFileUrl));
             } else {
-                proxyProperties = new ProxyInfo(host, port, exclList);
+                proxyProperties = ProxyInfo.buildDirectProxy(host, port,
+                        ProxyUtils.exclusionStringAsList(exclList));
             }
             if (!proxyProperties.isValid()) {
                 if (DBG) Log.d(TAG, "Invalid proxy properties, ignoring: " + proxyProperties);
@@ -204,7 +207,8 @@
                     return false;
                 }
             }
-            final ProxyInfo p = new ProxyInfo(proxyHost, proxyPort, "");
+            final ProxyInfo p = ProxyInfo.buildDirectProxy(proxyHost, proxyPort,
+                    Collections.emptyList());
             setGlobalProxy(p);
             return true;
         }
@@ -219,7 +223,8 @@
      */
     public void sendProxyBroadcast() {
         final ProxyInfo defaultProxy = getDefaultProxy();
-        final ProxyInfo proxyInfo = null != defaultProxy ? defaultProxy : new ProxyInfo("", 0, "");
+        final ProxyInfo proxyInfo = null != defaultProxy ?
+                defaultProxy : ProxyInfo.buildDirectProxy("", 0, Collections.emptyList());
         if (mPacManager.setCurrentProxyScriptUrl(proxyInfo) == PacManager.DONT_SEND_BROADCAST) {
             return;
         }
@@ -261,7 +266,7 @@
                 mGlobalProxy = new ProxyInfo(proxyInfo);
                 host = mGlobalProxy.getHost();
                 port = mGlobalProxy.getPort();
-                exclList = mGlobalProxy.getExclusionListAsString();
+                exclList = ProxyUtils.exclusionListAsString(mGlobalProxy.getExclusionList());
                 pacFileUrl = Uri.EMPTY.equals(proxyInfo.getPacFileUrl())
                         ? "" : proxyInfo.getPacFileUrl().toString();
             } else {
diff --git a/tests/net/common/java/android/net/NetworkProviderTest.kt b/tests/net/common/java/android/net/NetworkProviderTest.kt
index 77e9f12..bcc9072 100644
--- a/tests/net/common/java/android/net/NetworkProviderTest.kt
+++ b/tests/net/common/java/android/net/NetworkProviderTest.kt
@@ -29,6 +29,7 @@
 import com.android.net.module.util.ArrayTrackRecord
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
 import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.isDevSdkInRange
 import org.junit.After
 import org.junit.Before
 import org.junit.Test
@@ -173,10 +174,12 @@
     @Test
     fun testDeclareNetworkRequestUnfulfillable() {
         val mockContext = mock(Context::class.java)
-        val provider = createNetworkProvider(mockContext)
-        // ConnectivityManager not required at creation time
-        verifyNoMoreInteractions(mockContext)
         doReturn(mCm).`when`(mockContext).getSystemService(Context.CONNECTIVITY_SERVICE)
+        val provider = createNetworkProvider(mockContext)
+        // ConnectivityManager not required at creation time after R
+        if (!isDevSdkInRange(0, Build.VERSION_CODES.R)) {
+            verifyNoMoreInteractions(mockContext)
+        }
 
         mCm.registerNetworkProvider(provider)
 
diff --git a/tests/net/java/android/net/Ikev2VpnProfileTest.java b/tests/net/java/android/net/Ikev2VpnProfileTest.java
index ada5494..076e41d 100644
--- a/tests/net/java/android/net/Ikev2VpnProfileTest.java
+++ b/tests/net/java/android/net/Ikev2VpnProfileTest.java
@@ -29,6 +29,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.net.VpnProfile;
+import com.android.net.module.util.ProxyUtils;
 import com.android.org.bouncycastle.x509.X509V1CertificateGenerator;
 
 import org.junit.Before;
@@ -67,7 +68,8 @@
                     return "fooPackage";
                 }
             };
-    private final ProxyInfo mProxy = new ProxyInfo(SERVER_ADDR_STRING, -1, EXCL_LIST);
+    private final ProxyInfo mProxy = ProxyInfo.buildDirectProxy(
+            SERVER_ADDR_STRING, -1, ProxyUtils.exclusionStringAsList(EXCL_LIST));
 
     private X509Certificate mUserCert;
     private X509Certificate mServerRootCa;
diff --git a/tests/net/java/android/net/MacAddressTest.java b/tests/net/java/android/net/MacAddressTest.java
index 91c9a2a..6de31f6 100644
--- a/tests/net/java/android/net/MacAddressTest.java
+++ b/tests/net/java/android/net/MacAddressTest.java
@@ -22,11 +22,11 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import android.net.util.MacAddressUtils;
-
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.net.module.util.MacAddressUtils;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
index 3158cc8..7748288 100644
--- a/tests/net/java/android/net/NetworkUtilsTest.java
+++ b/tests/net/java/android/net/NetworkUtilsTest.java
@@ -16,24 +16,10 @@
 
 package android.net;
 
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.AF_UNIX;
-import static android.system.OsConstants.EPERM;
-import static android.system.OsConstants.SOCK_DGRAM;
-import static android.system.OsConstants.SOCK_STREAM;
-
 import static junit.framework.Assert.assertEquals;
 
-import static org.junit.Assert.fail;
-
-import android.system.ErrnoException;
-import android.system.Os;
-
 import androidx.test.runner.AndroidJUnit4;
 
-import libcore.io.IoUtils;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -139,50 +125,4 @@
         assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536),
                 NetworkUtils.routedIPv6AddressCount(set));
     }
-
-    private static void expectSocketSuccess(String msg, int domain, int type) {
-        try {
-            IoUtils.closeQuietly(Os.socket(domain, type, 0));
-        } catch (ErrnoException e) {
-            fail(msg + e.getMessage());
-        }
-    }
-
-    private static void expectSocketPemissionError(String msg, int domain, int type) {
-        try {
-            IoUtils.closeQuietly(Os.socket(domain, type, 0));
-            fail(msg);
-        } catch (ErrnoException e) {
-            assertEquals(msg, e.errno, EPERM);
-        }
-    }
-
-    private static void expectHasNetworking() {
-        expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
-                AF_UNIX, SOCK_STREAM);
-        expectSocketSuccess("Creating a AF_INET socket shouldn't have thrown ErrnoException",
-                AF_INET, SOCK_DGRAM);
-        expectSocketSuccess("Creating a AF_INET6 socket shouldn't have thrown ErrnoException",
-                AF_INET6, SOCK_DGRAM);
-    }
-
-    private static void expectNoNetworking() {
-        expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
-                AF_UNIX, SOCK_STREAM);
-        expectSocketPemissionError(
-                "Creating a AF_INET socket should have thrown ErrnoException(EPERM)",
-                AF_INET, SOCK_DGRAM);
-        expectSocketPemissionError(
-                "Creating a AF_INET6 socket should have thrown ErrnoException(EPERM)",
-                AF_INET6, SOCK_DGRAM);
-    }
-
-    @Test
-    public void testSetAllowNetworkingForProcess() {
-        expectHasNetworking();
-        NetworkUtils.setAllowNetworkingForProcess(false);
-        expectNoNetworking();
-        NetworkUtils.setAllowNetworkingForProcess(true);
-        expectHasNetworking();
-    }
 }
diff --git a/tests/net/java/com/android/internal/net/NetworkUtilsInternalTest.java b/tests/net/java/com/android/internal/net/NetworkUtilsInternalTest.java
new file mode 100644
index 0000000..3cfecd5
--- /dev/null
+++ b/tests/net/java/com/android/internal/net/NetworkUtilsInternalTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+package com.android.internal.net;
+
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.AF_UNIX;
+import static android.system.OsConstants.EPERM;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_STREAM;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.fail;
+
+import android.system.ErrnoException;
+import android.system.Os;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import libcore.io.IoUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@androidx.test.filters.SmallTest
+public class NetworkUtilsInternalTest {
+
+    private static void expectSocketSuccess(String msg, int domain, int type) {
+        try {
+            IoUtils.closeQuietly(Os.socket(domain, type, 0));
+        } catch (ErrnoException e) {
+            fail(msg + e.getMessage());
+        }
+    }
+
+    private static void expectSocketPemissionError(String msg, int domain, int type) {
+        try {
+            IoUtils.closeQuietly(Os.socket(domain, type, 0));
+            fail(msg);
+        } catch (ErrnoException e) {
+            assertEquals(msg, e.errno, EPERM);
+        }
+    }
+
+    private static void expectHasNetworking() {
+        expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
+                AF_UNIX, SOCK_STREAM);
+        expectSocketSuccess("Creating a AF_INET socket shouldn't have thrown ErrnoException",
+                AF_INET, SOCK_DGRAM);
+        expectSocketSuccess("Creating a AF_INET6 socket shouldn't have thrown ErrnoException",
+                AF_INET6, SOCK_DGRAM);
+    }
+
+    private static void expectNoNetworking() {
+        expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
+                AF_UNIX, SOCK_STREAM);
+        expectSocketPemissionError(
+                "Creating a AF_INET socket should have thrown ErrnoException(EPERM)",
+                AF_INET, SOCK_DGRAM);
+        expectSocketPemissionError(
+                "Creating a AF_INET6 socket should have thrown ErrnoException(EPERM)",
+                AF_INET6, SOCK_DGRAM);
+    }
+
+    @Test
+    public void testSetAllowNetworkingForProcess() {
+        expectHasNetworking();
+        NetworkUtilsInternal.setAllowNetworkingForProcess(false);
+        expectNoNetworking();
+        NetworkUtilsInternal.setAllowNetworkingForProcess(true);
+        expectHasNetworking();
+    }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 21dbbc6..a613e5e 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -4742,11 +4742,9 @@
 
     @Test
     public void testNetworkCallbackMaximum() {
-        // We can only have 99 callbacks, because MultipathPolicyTracker is
-        // already one of them.
-        final int MAX_REQUESTS = 99;
+        final int MAX_REQUESTS = 100;
         final int CALLBACKS = 89;
-        final int INTENTS = 10;
+        final int INTENTS = 11;
         assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
 
         NetworkRequest networkRequest = new NetworkRequest.Builder().build();
@@ -8109,7 +8107,16 @@
 
     @Test
     public void testDumpDoesNotCrash() {
-        StringWriter stringWriter = new StringWriter();
+        // Filing a couple requests prior to testing the dump.
+        final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
+        final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
+        final NetworkRequest genericRequest = new NetworkRequest.Builder()
+                .clearCapabilities().build();
+        final NetworkRequest wifiRequest = new NetworkRequest.Builder()
+                .addTransportType(TRANSPORT_WIFI).build();
+        mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
+        mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
+        final StringWriter stringWriter = new StringWriter();
 
         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
 
@@ -8131,11 +8138,11 @@
         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
 
-        ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
+        final ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
 
         assertTrue(nriOutput.length > 1);
         for (int i = 0; i < nriOutput.length - 1; i++) {
-            boolean isRequestIdInOrder =
+            final boolean isRequestIdInOrder =
                     nriOutput[i].mRequests.get(0).requestId
                             < nriOutput[i + 1].mRequests.get(0).requestId;
             assertTrue(isRequestIdInOrder);
diff --git a/tests/net/java/com/android/server/NetworkManagementServiceTest.java b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
index ea763d2..13516d7 100644
--- a/tests/net/java/com/android/server/NetworkManagementServiceTest.java
+++ b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
@@ -68,11 +68,12 @@
 @SmallTest
 public class NetworkManagementServiceTest {
     private NetworkManagementService mNMService;
-
     @Mock private Context mContext;
     @Mock private IBatteryStats.Stub mBatteryStatsService;
     @Mock private INetd.Stub mNetdService;
 
+    private static final int TEST_UID = 111;
+
     @NonNull
     @Captor
     private ArgumentCaptor<INetdUnsolicitedEventListener> mUnsolListenerCaptor;
@@ -165,14 +166,14 @@
         /**
          * Interface class activity.
          */
-        unsolListener.onInterfaceClassActivityChanged(true, 1, 1234, 0);
-        expectSoon(observer).interfaceClassDataActivityChanged("1", true, 1234);
+        unsolListener.onInterfaceClassActivityChanged(true, 1, 1234, TEST_UID);
+        expectSoon(observer).interfaceClassDataActivityChanged(1, true, 1234, TEST_UID);
 
-        unsolListener.onInterfaceClassActivityChanged(false, 9, 5678, 0);
-        expectSoon(observer).interfaceClassDataActivityChanged("9", false, 5678);
+        unsolListener.onInterfaceClassActivityChanged(false, 9, 5678, TEST_UID);
+        expectSoon(observer).interfaceClassDataActivityChanged(9, false, 5678, TEST_UID);
 
-        unsolListener.onInterfaceClassActivityChanged(false, 9, 4321, 0);
-        expectSoon(observer).interfaceClassDataActivityChanged("9", false, 4321);
+        unsolListener.onInterfaceClassActivityChanged(false, 9, 4321, TEST_UID);
+        expectSoon(observer).interfaceClassDataActivityChanged(9, false, 4321, TEST_UID);
 
         /**
          * IP address changes.
@@ -222,8 +223,6 @@
         assertFalse(mNMService.isFirewallEnabled());
     }
 
-    private static final int TEST_UID = 111;
-
     @Test
     public void testNetworkRestrictedDefault() {
         assertFalse(mNMService.isNetworkRestricted(TEST_UID));
@@ -235,23 +234,23 @@
         doReturn(true).when(mNetdService).bandwidthEnableDataSaver(anyBoolean());
 
         // Restrict usage of mobile data in background
-        mNMService.setUidMeteredNetworkDenylist(TEST_UID, true);
+        mNMService.setUidOnMeteredNetworkDenylist(TEST_UID, true);
         assertTrue("Should be true since mobile data usage is restricted",
                 mNMService.isNetworkRestricted(TEST_UID));
 
         mNMService.setDataSaverModeEnabled(true);
         verify(mNetdService).bandwidthEnableDataSaver(true);
 
-        mNMService.setUidMeteredNetworkDenylist(TEST_UID, false);
+        mNMService.setUidOnMeteredNetworkDenylist(TEST_UID, false);
         assertTrue("Should be true since data saver is on and the uid is not allowlisted",
                 mNMService.isNetworkRestricted(TEST_UID));
 
-        mNMService.setUidMeteredNetworkAllowlist(TEST_UID, true);
+        mNMService.setUidOnMeteredNetworkAllowlist(TEST_UID, true);
         assertFalse("Should be false since data saver is on and the uid is allowlisted",
                 mNMService.isNetworkRestricted(TEST_UID));
 
         // remove uid from allowlist and turn datasaver off again
-        mNMService.setUidMeteredNetworkAllowlist(TEST_UID, false);
+        mNMService.setUidOnMeteredNetworkAllowlist(TEST_UID, false);
         mNMService.setDataSaverModeEnabled(false);
         verify(mNetdService).bandwidthEnableDataSaver(false);
         assertFalse("Network should not be restricted when data saver is off",
diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
index fb0cfc0..89146f9 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
@@ -23,11 +23,11 @@
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.NetworkStatsHistory.FIELD_ALL;
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
-import static android.net.NetworkUtils.multiplySafeByRational;
 import static android.os.Process.myUid;
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 
+import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
 import static com.android.testutils.MiscAsserts.assertThrows;
 
 import static org.junit.Assert.assertArrayEquals;