Merge "Remove legacy-test and legacy-android-test targets"
diff --git a/Android.bp b/Android.bp
index 5935bfb..d58b483 100644
--- a/Android.bp
+++ b/Android.bp
@@ -704,7 +704,7 @@
         "android.hardware.vibrator-V1.1-java",
         "android.hardware.vibrator-V1.2-java",
         "android.hardware.wifi-V1.0-java-constants",
-        "networkstack-aidl-interfaces-java",
+        "networkstack-aidl-framework-java",
         "netd_aidl_parcelables-java",
     ],
 
@@ -818,7 +818,6 @@
         "core/java/android/net/DhcpResultsParcelable.aidl",
         "core/java/android/net/INetworkMonitor.aidl",
         "core/java/android/net/INetworkMonitorCallbacks.aidl",
-        "core/java/android/net/IIpMemoryStore.aidl",
         "core/java/android/net/INetworkStackConnector.aidl",
         "core/java/android/net/INetworkStackStatusCallback.aidl",
         "core/java/android/net/InitialConfigurationParcelable.aidl",
@@ -837,6 +836,16 @@
         "core/java/android/net/dhcp/IDhcpServerCallbacks.aidl",
         "core/java/android/net/ip/IIpClient.aidl",
         "core/java/android/net/ip/IIpClientCallbacks.aidl",
+    ],
+    api_dir: "aidl/networkstack",
+}
+
+aidl_interface {
+    name: "networkstack-aidl-framework",
+    local_include_dir: "core/java",
+    srcs: [
+        "core/java/android/net/TcpKeepalivePacketDataParcelable.aidl",
+        "core/java/android/net/IIpMemoryStore.aidl",
         "core/java/android/net/ipmemorystore/**/*.aidl",
     ],
     api_dir: "aidl/networkstack",
diff --git a/api/system-current.txt b/api/system-current.txt
index 8efc3de..9c45fb4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5492,6 +5492,7 @@
     field public static final String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT";
     field public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
     field public static final String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
+    field public static final String EXTRA_IS_USER_INTENT_EMERGENCY_CALL = "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL";
     field public static final int TTY_MODE_FULL = 1; // 0x1
     field public static final int TTY_MODE_HCO = 2; // 0x2
     field public static final int TTY_MODE_OFF = 0; // 0x0
@@ -6753,6 +6754,7 @@
     method public int getServiceType();
     method public static int getVideoStateFromCallType(int);
     method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile);
+    method public boolean hasKnownUserIntentEmergency();
     method public boolean isEmergencyCallTesting();
     method public boolean isVideoCall();
     method public boolean isVideoPaused();
@@ -6765,6 +6767,7 @@
     method public void setEmergencyCallTesting(boolean);
     method public void setEmergencyServiceCategories(int);
     method public void setEmergencyUrns(java.util.List<java.lang.String>);
+    method public void setHasKnownUserIntentEmergency(boolean);
     method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
     method public void updateCallType(android.telephony.ims.ImsCallProfile);
     method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index c04e61b..ca4a184 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -174,6 +174,8 @@
                 instrument.noWindowAnimation = true;
             } else if (opt.equals("--no-hidden-api-checks")) {
                 instrument.disableHiddenApiChecks = true;
+            } else if (opt.equals("--no-isolated-storage")) {
+                // NOTE: currently a no-op in this branch
             } else if (opt.equals("--user")) {
                 instrument.userId = parseUserArg(nextArgRequired());
             } else if (opt.equals("--abi")) {
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index dd21674..e166c31 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -2930,7 +2930,6 @@
 Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;-><init>()V
 Lcom/android/internal/telephony/GsmCdmaCall;->attachFake(Lcom/android/internal/telephony/Connection;Lcom/android/internal/telephony/Call$State;)V
 Lcom/android/internal/telephony/GsmCdmaCallTracker;->clearDisconnected()V
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->dialThreeWay(Ljava/lang/String;)Lcom/android/internal/telephony/Connection;
 Lcom/android/internal/telephony/GsmCdmaCallTracker;->disableDataCallInEmergencyCall(Ljava/lang/String;)V
 Lcom/android/internal/telephony/GsmCdmaCallTracker;->fakeHoldForegroundBeforeDial()V
 Lcom/android/internal/telephony/GsmCdmaCallTracker;->getPhone()Lcom/android/internal/telephony/GsmCdmaPhone;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 4bbc12f..e92efde 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -88,7 +88,6 @@
 import android.net.IpSecManager;
 import android.net.NetworkPolicyManager;
 import android.net.NetworkScoreManager;
-import android.net.NetworkStack;
 import android.net.NetworkWatchlistManager;
 import android.net.lowpan.ILowpanManager;
 import android.net.lowpan.LowpanManager;
@@ -296,13 +295,6 @@
             }
         });
 
-        registerService(Context.NETWORK_STACK_SERVICE, NetworkStack.class,
-                new StaticServiceFetcher<NetworkStack>() {
-                    @Override
-                    public NetworkStack createService() {
-                        return new NetworkStack();
-                    }});
-
         registerService(Context.IP_MEMORY_STORE_SERVICE, IpMemoryStore.class,
                 new CachedServiceFetcher<IpMemoryStore>() {
                     @Override
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 2803856..23f2904 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -2175,8 +2175,7 @@
      * encrypted.
      * <p> Use this socket if an authenticated socket link is possible. Authentication refers
      * to the authentication of the link key to prevent man-in-the-middle type of attacks. When a
-     * secure socket connection is not possible, use {#link createInsecureLeL2capCocSocket(int,
-     * int)}.
+     * secure socket connection is not possible, use {#link createInsecureL2capChannel(int)}.
      *
      * @param psm dynamic PSM value from remote device
      * @return a CoC #BluetoothSocket ready for an outgoing connection
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 493aac6..b072740 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -49,7 +49,6 @@
 import android.database.sqlite.SQLiteDatabase.CursorFactory;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
-import android.net.NetworkStack;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
@@ -3514,11 +3513,10 @@
     public static final String NETD_SERVICE = "netd";
 
     /**
-     * Use with {@link #getSystemService(String)} to retrieve a
-     * {@link NetworkStack} for communicating with the network stack
+     * Use with {@link android.os.ServiceManager.getService()} to retrieve a
+     * {@link NetworkStackClient} IBinder for communicating with the network stack
      * @hide
-     * @see #getSystemService(String)
-     * @see NetworkStack
+     * @see NetworkStackClient
      */
     public static final String NETWORK_STACK_SERVICE = "network_stack";
 
diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java
index ca49438..dbb894f 100644
--- a/core/java/android/net/NetworkStack.java
+++ b/core/java/android/net/NetworkStack.java
@@ -15,46 +15,17 @@
  */
 package android.net;
 
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
-import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.SystemService;
 import android.annotation.TestApi;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.PackageManager;
-import android.net.dhcp.DhcpServingParamsParcel;
-import android.net.dhcp.IDhcpServerCallbacks;
-import android.net.ip.IIpClientCallbacks;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.util.Slog;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
 
 /**
- * Service used to communicate with the network stack, which is running in a separate module.
+ *
+ * Constants for client code communicating with the network stack service.
  * @hide
  */
-@SystemService(Context.NETWORK_STACK_SERVICE)
 @SystemApi
 @TestApi
 public class NetworkStack {
-    private static final String TAG = NetworkStack.class.getSimpleName();
-
     /**
      * Permission granted only to the NetworkStack APK, defined in NetworkStackStub with signature
      * protection level.
@@ -65,235 +36,5 @@
     public static final String PERMISSION_MAINLINE_NETWORK_STACK =
             "android.permission.MAINLINE_NETWORK_STACK";
 
-    private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;
-
-    @NonNull
-    @GuardedBy("mPendingNetStackRequests")
-    private final ArrayList<NetworkStackCallback> mPendingNetStackRequests = new ArrayList<>();
-    @Nullable
-    @GuardedBy("mPendingNetStackRequests")
-    private INetworkStackConnector mConnector;
-
-    private volatile boolean mNetworkStackStartRequested = false;
-
-    private interface NetworkStackCallback {
-        void onNetworkStackConnected(INetworkStackConnector connector);
-    }
-
-    /** @hide */
-    public NetworkStack() { }
-
-    /**
-     * Create a DHCP server according to the specified parameters.
-     *
-     * <p>The server will be returned asynchronously through the provided callbacks.
-     * @hide
-     */
-    public void makeDhcpServer(final String ifName, final DhcpServingParamsParcel params,
-            final IDhcpServerCallbacks cb) {
-        requestConnector(connector -> {
-            try {
-                connector.makeDhcpServer(ifName, params, cb);
-            } catch (RemoteException e) {
-                e.rethrowFromSystemServer();
-            }
-        });
-    }
-
-    /**
-     * Create an IpClient on the specified interface.
-     *
-     * <p>The IpClient will be returned asynchronously through the provided callbacks.
-     * @hide
-     */
-    public void makeIpClient(String ifName, IIpClientCallbacks cb) {
-        requestConnector(connector -> {
-            try {
-                connector.makeIpClient(ifName, cb);
-            } catch (RemoteException e) {
-                e.rethrowFromSystemServer();
-            }
-        });
-    }
-
-    /**
-     * Create a NetworkMonitor.
-     *
-     * <p>The INetworkMonitor will be returned asynchronously through the provided callbacks.
-     * @hide
-     */
-    public void makeNetworkMonitor(
-            NetworkParcelable network, String name, INetworkMonitorCallbacks cb) {
-        requestConnector(connector -> {
-            try {
-                connector.makeNetworkMonitor(network, name, cb);
-            } catch (RemoteException e) {
-                e.rethrowFromSystemServer();
-            }
-        });
-    }
-
-    private class NetworkStackConnection implements ServiceConnection {
-        @Override
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            registerNetworkStackService(service);
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
-            // TODO: crash/reboot the system ?
-            Slog.wtf(TAG, "Lost network stack connector");
-        }
-    };
-
-    private void registerNetworkStackService(@NonNull IBinder service) {
-        final INetworkStackConnector connector = INetworkStackConnector.Stub.asInterface(service);
-
-        ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service, false /* allowIsolated */,
-                DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
-
-        final ArrayList<NetworkStackCallback> requests;
-        synchronized (mPendingNetStackRequests) {
-            requests = new ArrayList<>(mPendingNetStackRequests);
-            mPendingNetStackRequests.clear();
-            mConnector = connector;
-        }
-
-        for (NetworkStackCallback r : requests) {
-            r.onNetworkStackConnected(connector);
-        }
-    }
-
-    /**
-     * Start the network stack. Should be called only once on device startup.
-     *
-     * <p>This method will start the network stack either in the network stack process, or inside
-     * the system server on devices that do not support the network stack module. The network stack
-     * connector will then be delivered asynchronously to clients that requested it before it was
-     * started.
-     * @hide
-     */
-    public void start(Context context) {
-        mNetworkStackStartRequested = true;
-        // Try to bind in-process if the library is available
-        IBinder connector = null;
-        try {
-            final Class service = Class.forName(
-                    "com.android.server.NetworkStackService",
-                    true /* initialize */,
-                    context.getClassLoader());
-            connector = (IBinder) service.getMethod("makeConnector", Context.class)
-                    .invoke(null, context);
-        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
-            Slog.wtf(TAG, "Could not create network stack connector from NetworkStackService");
-            // TODO: crash/reboot system here ?
-            return;
-        } catch (ClassNotFoundException e) {
-            // Normal behavior if stack is provided by the app: fall through
-        }
-
-        // In-process network stack. Add the service to the service manager here.
-        if (connector != null) {
-            registerNetworkStackService(connector);
-            return;
-        }
-        // Start the network stack process. The service will be added to the service manager in
-        // NetworkStackConnection.onServiceConnected().
-        final Intent intent = new Intent(INetworkStackConnector.class.getName());
-        final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
-        intent.setComponent(comp);
-
-        if (comp == null) {
-            Slog.wtf(TAG, "Could not resolve the network stack with " + intent);
-            // TODO: crash/reboot system server ?
-            return;
-        }
-
-        final PackageManager pm = context.getPackageManager();
-        int uid = -1;
-        try {
-            uid = pm.getPackageUid(comp.getPackageName(), UserHandle.USER_SYSTEM);
-        } catch (PackageManager.NameNotFoundException e) {
-            Slog.wtf("Network stack package not found", e);
-            // Fall through
-        }
-
-        if (uid != Process.NETWORK_STACK_UID) {
-            throw new SecurityException("Invalid network stack UID: " + uid);
-        }
-
-        final int hasPermission =
-                pm.checkPermission(PERMISSION_MAINLINE_NETWORK_STACK, comp.getPackageName());
-        if (hasPermission != PERMISSION_GRANTED) {
-            throw new SecurityException(
-                    "Network stack does not have permission " + PERMISSION_MAINLINE_NETWORK_STACK);
-        }
-
-        if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
-                Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
-            Slog.wtf(TAG,
-                    "Could not bind to network stack in-process, or in app with " + intent);
-            // TODO: crash/reboot system server if no network stack after a timeout ?
-        }
-    }
-
-    /**
-     * For non-system server clients, get the connector registered by the system server.
-     */
-    private INetworkStackConnector getRemoteConnector() {
-        // Block until the NetworkStack connector is registered in ServiceManager.
-        // <p>This is only useful for non-system processes that do not have a way to be notified of
-        // registration completion. Adding a callback system would be too heavy weight considering
-        // that the connector is registered on boot, so it is unlikely that a client would request
-        // it before it is registered.
-        // TODO: consider blocking boot on registration and simplify much of the logic in this class
-        IBinder connector;
-        try {
-            final long before = System.currentTimeMillis();
-            while ((connector = ServiceManager.getService(Context.NETWORK_STACK_SERVICE)) == null) {
-                Thread.sleep(20);
-                if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
-                    Slog.e(TAG, "Timeout waiting for NetworkStack connector");
-                    return null;
-                }
-            }
-        } catch (InterruptedException e) {
-            Slog.e(TAG, "Error waiting for NetworkStack connector", e);
-            return null;
-        }
-
-        return INetworkStackConnector.Stub.asInterface(connector);
-    }
-
-    private void requestConnector(@NonNull NetworkStackCallback request) {
-        // TODO: PID check.
-        final int caller = Binder.getCallingUid();
-        if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) {
-            // Don't even attempt to obtain the connector and give a nice error message
-            throw new SecurityException(
-                    "Only the system server should try to bind to the network stack.");
-        }
-
-        if (!mNetworkStackStartRequested) {
-            // The network stack is not being started in this process, e.g. this process is not
-            // the system server. Get a remote connector registered by the system server.
-            final INetworkStackConnector connector = getRemoteConnector();
-            synchronized (mPendingNetStackRequests) {
-                mConnector = connector;
-            }
-            request.onNetworkStackConnected(connector);
-            return;
-        }
-
-        final INetworkStackConnector connector;
-        synchronized (mPendingNetStackRequests) {
-            connector = mConnector;
-            if (connector == null) {
-                mPendingNetStackRequests.add(request);
-                return;
-            }
-        }
-
-        request.onNetworkStackConnected(connector);
-    }
+    private NetworkStack() {}
 }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 08a5789..c385ca1 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -41,7 +41,7 @@
         "com_google_android_gles_jni_EGLImpl.cpp",
         "com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm
         "android_app_Activity.cpp",
-	"android_app_ActivityThread.cpp",
+        "android_app_ActivityThread.cpp",
         "android_app_NativeActivity.cpp",
         "android_app_admin_SecurityLog.cpp",
         "android_opengl_EGL14.cpp",
@@ -225,6 +225,7 @@
     ],
 
     static_libs: [
+        "libasync_safe",
         "libgif",
         "libseccomp_policy",
         "libgrallocusage",
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 3012c90..bc1332a 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -25,6 +25,8 @@
 
 #define LOG_TAG "Zygote"
 
+#include <async_safe/log.h>
+
 // sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
 #include <sys/mount.h>
 #include <linux/fs.h>
@@ -296,27 +298,23 @@
   int saved_errno = errno;
 
   while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
-     // Log process-death status that we care about.  In general it is
-     // not safe to call LOG(...) from a signal handler because of
-     // possible reentrancy.  However, we know a priori that the
-     // current implementation of LOG() is safe to call from a SIGCHLD
-     // handler in the zygote process.  If the LOG() implementation
-     // changes its locking strategy or its use of syscalls within the
-     // lazy-init critical section, its use here may become unsafe.
+     // Log process-death status that we care about.
     if (WIFEXITED(status)) {
-      ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+      async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG,
+                            "Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
     } else if (WIFSIGNALED(status)) {
-      ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
-      if (WCOREDUMP(status)) {
-        ALOGI("Process %d dumped core.", pid);
-      }
+      async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG,
+                            "Process %d exited due to signal %d (%s)%s", pid,
+                            WTERMSIG(status), strsignal(WTERMSIG(status)),
+                            WCOREDUMP(status) ? "; core dumped" : "");
     }
 
     // If the just-crashed process is the system_server, bring down zygote
     // so that it is restarted by init and system server will be restarted
     // from there.
     if (pid == gSystemServerPid) {
-      ALOGE("Exit zygote because system server (%d) has terminated", pid);
+      async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                            "Exit zygote because system server (pid %d) has terminated", pid);
       kill(getpid(), SIGKILL);
     }
 
@@ -329,14 +327,17 @@
   // Note that we shouldn't consider ECHILD an error because
   // the secondary zygote might have no children left to wait for.
   if (pid < 0 && errno != ECHILD) {
-    ALOGW("Zygote SIGCHLD error in waitpid: %s", strerror(errno));
+    async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG,
+                          "Zygote SIGCHLD error in waitpid: %s", strerror(errno));
   }
 
   if (blastulas_removed > 0) {
     if (write(gBlastulaPoolEventFD, &blastulas_removed, sizeof(blastulas_removed)) == -1) {
       // If this write fails something went terribly wrong.  We will now kill
       // the zygote and let the system bring it back up.
-      ALOGE("Zygote failed to write to blastula pool event FD: %s", strerror(errno));
+      async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                            "Zygote failed to write to blastula pool event FD: %s",
+                            strerror(errno));
       kill(getpid(), SIGKILL);
     }
   }
@@ -1115,8 +1116,8 @@
       RuntimeAbort(env, __LINE__, "Bad gids array");
     }
 
-    for (int gid_index = gids_num; --gids_num >= 0;) {
-      if (native_gid_proxy[gid_index] == AID_WAKELOCK) {
+    for (int gids_index = 0; gids_index < gids_num; ++gids_index) {
+      if (native_gid_proxy[gids_index] == AID_WAKELOCK) {
         gid_wakelock_found = true;
         break;
       }
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 4b247c6..78bbcf1 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -200,7 +200,7 @@
         <permission name="android.permission.USE_RESERVED_DISK"/>
     </privapp-permissions>
 
-    <privapp-permissions package="com.android.mainline.networkstack">
+    <privapp-permissions package="com.android.networkstack">
         <permission name="android.permission.ACCESS_NETWORK_CONDITIONS"/>
         <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
         <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index aa29174..3dc884e 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -17,7 +17,6 @@
 package android.security.keystore;
 
 import android.security.Credentials;
-import android.security.GateKeeper;
 import android.security.KeyStore;
 import android.security.keymaster.KeyCharacteristics;
 import android.security.keymaster.KeymasterArguments;
@@ -204,7 +203,12 @@
                         }
                     }
                 }
-
+                if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_3DES) {
+                    if (mKeySizeBits != 168) {
+                        throw new InvalidAlgorithmParameterException(
+                            "3DES key size must be 168 bits.");
+                    }
+                }
                 if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
                     if (mKeySizeBits < 64) {
                         throw new InvalidAlgorithmParameterException(
diff --git a/media/OWNERS b/media/OWNERS
index 03b751c..eb26367 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -11,3 +11,6 @@
 marcone@google.com
 sungsoo@google.com
 wjia@google.com
+
+# For maintaining sync with AndroidX code
+per-file ExifInterface.java = jinpark@google.com, sungsoo@google.com
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index ad25a06..5f324f7 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED;
+
 import android.annotation.UnsupportedAppUsage;
 import android.net.NetworkUtils;
 import android.os.IBinder;
@@ -23,21 +25,19 @@
 import android.util.Log;
 
 import java.io.BufferedInputStream;
-import java.io.InputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.CookieHandler;
-import java.net.CookieManager;
-import java.net.Proxy;
-import java.net.URL;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.NoRouteToHostException;
 import java.net.ProtocolException;
+import java.net.Proxy;
+import java.net.URL;
 import java.net.UnknownServiceException;
 import java.util.HashMap;
 import java.util.Map;
-
-import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /** @hide */
 public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
@@ -67,6 +67,7 @@
     // from com.squareup.okhttp.internal.http
     private final static int HTTP_TEMP_REDIRECT = 307;
     private final static int MAX_REDIRECTS = 20;
+    private AtomicBoolean mIsConnected = new AtomicBoolean(false);
 
     @UnsupportedAppUsage
     public MediaHTTPConnection() {
@@ -90,6 +91,7 @@
             mAllowCrossDomainRedirect = true;
             mURL = new URL(uri);
             mHeaders = convertHeaderStringToMap(headers);
+            mIsConnected.set(true);
         } catch (MalformedURLException e) {
             return null;
         }
@@ -140,7 +142,14 @@
     @Override
     @UnsupportedAppUsage
     public void disconnect() {
-        teardownConnection();
+        if (mIsConnected.getAndSet(false)) {
+            (new Thread() {
+                @Override
+                public void run() {
+                    teardownConnection();
+                }
+            }).start();
+        }
         mHeaders = null;
         mURL = null;
     }
@@ -325,7 +334,14 @@
     @Override
     @UnsupportedAppUsage
     public int readAt(long offset, int size) {
-        return native_readAt(offset, size);
+        if (!mIsConnected.get()) {
+            return -1;
+        }
+        int result = native_readAt(offset, size);
+        if (!mIsConnected.get()) {
+            return -1;
+        }
+        return result;
     }
 
     private int readAt(long offset, byte[] data, int size) {
diff --git a/packages/CaptivePortalLogin/Android.bp b/packages/CaptivePortalLogin/Android.bp
index 4ac652a..9c31b4d 100644
--- a/packages/CaptivePortalLogin/Android.bp
+++ b/packages/CaptivePortalLogin/Android.bp
@@ -18,7 +18,7 @@
     name: "CaptivePortalLogin",
     srcs: ["src/**/*.java"],
     sdk_version: "system_current",
-    certificate: "platform",
+    certificate: "networkstack",
     static_libs: [
         "android-support-v4",
         "metrics-constants-protos",
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index e15dca0..0894ee5 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -23,8 +23,8 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
-    <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
     <uses-permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS" />
+    <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
 
     <application android:label="@string/app_name"
                  android:usesCleartextTraffic="true"
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index d656593..b700bf3 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -35,11 +35,12 @@
 android_app {
     name: "NetworkStack",
     sdk_version: "system_current",
-    certificate: "platform",
+    certificate: "networkstack",
     privileged: true,
     static_libs: [
         "NetworkStackLib"
     ],
+    jarjar_rules: "jarjar-rules-shared.txt",
     manifest: "AndroidManifest.xml",
     required: ["NetworkStackPermissionStub"],
 }
\ No newline at end of file
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index 860ebfb..52c209e 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -17,19 +17,17 @@
  */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.mainline.networkstack"
+          package="com.android.networkstack"
           android:sharedUserId="android.uid.networkstack">
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
-    <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
     <!-- Signature permission defined in NetworkStackStub -->
     <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
     <!-- Send latency broadcast as current user -->
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
-    <uses-permission android:name="android.permission.NETWORK_STACK" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
     <application
diff --git a/packages/NetworkStack/jarjar-rules-shared.txt b/packages/NetworkStack/jarjar-rules-shared.txt
new file mode 100644
index 0000000..a8c712a
--- /dev/null
+++ b/packages/NetworkStack/jarjar-rules-shared.txt
@@ -0,0 +1,19 @@
+rule com.android.internal.util.** android.net.networkstack.util.@1
+
+rule android.net.shared.Inet4AddressUtils* android.net.networkstack.shared.Inet4AddressUtils@1
+rule android.net.shared.InetAddressUtils* android.net.networkstack.shared.InetAddressUtils@1
+
+# Ignore DhcpResultsParcelable, but jarjar DhcpResults
+# TODO: move DhcpResults into services.net and delete from here
+rule android.net.DhcpResultsParcelable* @0
+rule android.net.DhcpResults* android.net.networkstack.DhcpResults@1
+rule android.net.LocalLog* android.net.networkstack.LocalLog@1
+
+# TODO: remove from framework dependencies, then remove here
+rule android.net.InterfaceConfigurationParcel* android.net.networkstack.InterfaceConfigurationParcel@1
+rule android.net.TetherStatsParcel* android.net.networkstack.TetherStatsParcel@1
+
+# Used by UidRange, which is used by framework classes such as NetworkCapabilities.
+rule android.net.UidRangeParcel* android.net.networkstack.UidRangeParcel@1
+# TODO: move TcpKeepalivePacketData to services.net and delete
+rule android.net.TcpKeepalivePacketDataParcelable* android.net.networkstack.TcpKeepalivePacketDataParcelable@1
\ No newline at end of file
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java b/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
index 96d1a28..97d26c7 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
@@ -18,7 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.net.shared.FdEventsReader;
+import android.net.util.FdEventsReader;
 import android.os.Handler;
 import android.system.Os;
 
diff --git a/core/java/android/net/shared/FdEventsReader.java b/packages/NetworkStack/src/android/net/util/FdEventsReader.java
similarity index 98%
rename from core/java/android/net/shared/FdEventsReader.java
rename to packages/NetworkStack/src/android/net/util/FdEventsReader.java
index bffbfb1..1380ea7 100644
--- a/core/java/android/net/shared/FdEventsReader.java
+++ b/packages/NetworkStack/src/android/net/util/FdEventsReader.java
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package android.net.shared;
+package android.net.util;
 
 import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
 import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.net.util.SocketUtils;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.MessageQueue;
diff --git a/packages/NetworkStack/src/android/net/util/PacketReader.java b/packages/NetworkStack/src/android/net/util/PacketReader.java
index 94b1e9f..4aec6b6 100644
--- a/packages/NetworkStack/src/android/net/util/PacketReader.java
+++ b/packages/NetworkStack/src/android/net/util/PacketReader.java
@@ -18,7 +18,6 @@
 
 import static java.lang.Math.max;
 
-import android.net.shared.FdEventsReader;
 import android.os.Handler;
 import android.system.Os;
 
diff --git a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
index af71ac5..3414397 100644
--- a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
+++ b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
@@ -40,9 +40,7 @@
 import android.content.Context;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
-import android.net.SocketKeepalive;
-import android.net.TcpKeepalivePacketData;
-import android.net.TcpKeepalivePacketData.TcpSocketInfo;
+import android.net.TcpKeepalivePacketDataParcelable;
 import android.net.apf.ApfFilter.ApfConfiguration;
 import android.net.apf.ApfGenerator.IllegalInstructionException;
 import android.net.apf.ApfGenerator.Register;
@@ -1546,12 +1544,15 @@
         InetAddress srcAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_SRC_ADDR);
         InetAddress dstAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_DST_ADDR);
 
-        final TcpSocketInfo v4Tsi = new TcpSocketInfo(
-                srcAddr, srcPort, dstAddr, dstPort, seqNum, ackNum, window, windowScale);
-        final TcpKeepalivePacketData ipv4TcpKeepalivePacket =
-                TcpKeepalivePacketData.tcpKeepalivePacket(v4Tsi);
+        final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable();
+        parcel.srcAddress = srcAddr.getAddress();
+        parcel.srcPort = srcPort;
+        parcel.dstAddress = dstAddr.getAddress();
+        parcel.dstPort = dstPort;
+        parcel.seq = seqNum;
+        parcel.ack = ackNum;
 
-        apfFilter.addKeepalivePacketFilter(slot1, ipv4TcpKeepalivePacket.toStableParcelable());
+        apfFilter.addKeepalivePacketFilter(slot1, parcel);
         program = cb.getApfProgram();
 
         // Verify IPv4 keepalive ack packet is dropped
@@ -1580,11 +1581,17 @@
             // dst: 2404:0:0:0:0:0:faf2, port: 54321
             srcAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_SRC_ADDR);
             dstAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_DST_ADDR);
-            final TcpSocketInfo v6Tsi = new TcpSocketInfo(
-                    srcAddr, srcPort, dstAddr, dstPort, seqNum, ackNum, window, windowScale);
-            final TcpKeepalivePacketData ipv6TcpKeepalivePacket =
-                    TcpKeepalivePacketData.tcpKeepalivePacket(v6Tsi);
-            apfFilter.addKeepalivePacketFilter(slot1, ipv6TcpKeepalivePacket.toStableParcelable());
+
+            final TcpKeepalivePacketDataParcelable ipv6Parcel =
+                    new TcpKeepalivePacketDataParcelable();
+            ipv6Parcel.srcAddress = srcAddr.getAddress();
+            ipv6Parcel.srcPort = srcPort;
+            ipv6Parcel.dstAddress = dstAddr.getAddress();
+            ipv6Parcel.dstPort = dstPort;
+            ipv6Parcel.seq = seqNum;
+            ipv6Parcel.ack = ackNum;
+
+            apfFilter.addKeepalivePacketFilter(slot1, ipv6Parcel);
             program = cb.getApfProgram();
 
             // Verify IPv6 keepalive ack packet is dropped
@@ -1606,8 +1613,8 @@
             apfFilter.removeKeepalivePacketFilter(slot1);
 
             // Verify multiple filters
-            apfFilter.addKeepalivePacketFilter(slot1, ipv4TcpKeepalivePacket.toStableParcelable());
-            apfFilter.addKeepalivePacketFilter(slot2, ipv6TcpKeepalivePacket.toStableParcelable());
+            apfFilter.addKeepalivePacketFilter(slot1, parcel);
+            apfFilter.addKeepalivePacketFilter(slot2, ipv6Parcel);
             program = cb.getApfProgram();
 
             // Verify IPv4 keepalive ack packet is dropped
@@ -1643,7 +1650,7 @@
             // Remove keepalive filters
             apfFilter.removeKeepalivePacketFilter(slot1);
             apfFilter.removeKeepalivePacketFilter(slot2);
-        } catch (SocketKeepalive.InvalidPacketException e) {
+        } catch (UnsupportedOperationException e) {
             // TODO: support V6 packets
         }
 
diff --git a/packages/NetworkStackPermissionStub/Android.bp b/packages/NetworkStackPermissionStub/Android.bp
index 94870c9..dd70cf5 100644
--- a/packages/NetworkStackPermissionStub/Android.bp
+++ b/packages/NetworkStackPermissionStub/Android.bp
@@ -21,7 +21,7 @@
     // a classes.dex.
     srcs: ["src/**/*.java"],
     platform_apis: true,
-    certificate: "platform",
+    certificate: "networkstack",
     privileged: true,
     manifest: "AndroidManifest.xml",
 }
diff --git a/packages/NetworkStackPermissionStub/AndroidManifest.xml b/packages/NetworkStackPermissionStub/AndroidManifest.xml
index 2ccf5ff..a8742d7 100644
--- a/packages/NetworkStackPermissionStub/AndroidManifest.xml
+++ b/packages/NetworkStackPermissionStub/AndroidManifest.xml
@@ -17,7 +17,8 @@
  */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.mainline.networkstack.permissionstub">
+    package="com.android.networkstack.permissionstub"
+    android:sharedUserId="android.uid.networkstack">
     <!--
     This package only exists to define the below permissions, and enforce that they are only
     granted to apps sharing the same signature.
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index eec9380..b5fcde4b 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -87,6 +87,7 @@
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
 import android.net.NetworkStack;
+import android.net.NetworkStackClient;
 import android.net.NetworkState;
 import android.net.NetworkUtils;
 import android.net.NetworkWatchlistManager;
@@ -918,7 +919,8 @@
 
         mPermissionMonitor = new PermissionMonitor(mContext, mNMS);
 
-        //set up the listener for user state for creating user VPNs
+        // Set up the listener for user state for creating user VPNs.
+        // Should run on mHandler to avoid any races.
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_USER_STARTED);
         intentFilter.addAction(Intent.ACTION_USER_STOPPED);
@@ -926,7 +928,11 @@
         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
         intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
         mContext.registerReceiverAsUser(
-                mIntentReceiver, UserHandle.ALL, intentFilter, null, null);
+                mIntentReceiver,
+                UserHandle.ALL,
+                intentFilter,
+                null /* broadcastPermission */,
+                mHandler);
         mContext.registerReceiverAsUser(mUserPresentReceiver, UserHandle.SYSTEM,
                 new IntentFilter(Intent.ACTION_USER_PRESENT), null, null);
 
@@ -937,7 +943,11 @@
         intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         intentFilter.addDataScheme("package");
         mContext.registerReceiverAsUser(
-                mIntentReceiver, UserHandle.ALL, intentFilter, null, null);
+                mIntentReceiver,
+                UserHandle.ALL,
+                intentFilter,
+                null /* broadcastPermission */,
+                mHandler);
 
         try {
             mNMS.registerObserver(mTethering);
@@ -4127,17 +4137,27 @@
      * handler thread through their agent, this is asynchronous. When the capabilities objects
      * are computed they will be up-to-date as they are computed synchronously from here and
      * this is running on the ConnectivityService thread.
-     * TODO : Fix this and call updateCapabilities inline to remove out-of-order events.
      */
     private void updateAllVpnsCapabilities() {
+        Network defaultNetwork = getNetwork(getDefaultNetwork());
         synchronized (mVpns) {
             for (int i = 0; i < mVpns.size(); i++) {
                 final Vpn vpn = mVpns.valueAt(i);
-                vpn.updateCapabilities();
+                NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
+                updateVpnCapabilities(vpn, nc);
             }
         }
     }
 
+    private void updateVpnCapabilities(Vpn vpn, @Nullable NetworkCapabilities nc) {
+        ensureRunningOnConnectivityServiceThread();
+        NetworkAgentInfo vpnNai = getNetworkAgentInfoForNetId(vpn.getNetId());
+        if (vpnNai == null || nc == null) {
+            return;
+        }
+        updateCapabilities(vpnNai.getCurrentScore(), vpnNai, nc);
+    }
+
     @Override
     public boolean updateLockdownVpn() {
         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
@@ -4478,22 +4498,28 @@
 
     private void onUserAdded(int userId) {
         mPermissionMonitor.onUserAdded(userId);
+        Network defaultNetwork = getNetwork(getDefaultNetwork());
         synchronized (mVpns) {
             final int vpnsSize = mVpns.size();
             for (int i = 0; i < vpnsSize; i++) {
                 Vpn vpn = mVpns.valueAt(i);
                 vpn.onUserAdded(userId);
+                NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
+                updateVpnCapabilities(vpn, nc);
             }
         }
     }
 
     private void onUserRemoved(int userId) {
         mPermissionMonitor.onUserRemoved(userId);
+        Network defaultNetwork = getNetwork(getDefaultNetwork());
         synchronized (mVpns) {
             final int vpnsSize = mVpns.size();
             for (int i = 0; i < vpnsSize; i++) {
                 Vpn vpn = mVpns.valueAt(i);
                 vpn.onUserRemoved(userId);
+                NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork);
+                updateVpnCapabilities(vpn, nc);
             }
         }
     }
@@ -4562,6 +4588,7 @@
     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
+            ensureRunningOnConnectivityServiceThread();
             final String action = intent.getAction();
             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
             final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
@@ -5066,6 +5093,19 @@
         return getNetworkForRequest(mDefaultRequest.requestId);
     }
 
+    @Nullable
+    private Network getNetwork(@Nullable NetworkAgentInfo nai) {
+        return nai != null ? nai.network : null;
+    }
+
+    private void ensureRunningOnConnectivityServiceThread() {
+        if (mHandler.getLooper().getThread() != Thread.currentThread()) {
+            throw new IllegalStateException(
+                    "Not running on ConnectivityService thread: "
+                            + Thread.currentThread().getName());
+        }
+    }
+
     private boolean isDefaultNetwork(NetworkAgentInfo nai) {
         return nai == getDefaultNetwork();
     }
@@ -5095,7 +5135,7 @@
         if (DBG) log("registerNetworkAgent " + nai);
         final long token = Binder.clearCallingIdentity();
         try {
-            mContext.getSystemService(NetworkStack.class).makeNetworkMonitor(
+            getNetworkStack().makeNetworkMonitor(
                     toStableParcelable(nai.network), name, new NetworkMonitorCallbacks(nai));
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -5107,6 +5147,11 @@
         return nai.network.netId;
     }
 
+    @VisibleForTesting
+    protected NetworkStackClient getNetworkStack() {
+        return NetworkStackClient.getInstance();
+    }
+
     private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
         nai.onNetworkMonitorCreated(networkMonitor);
         if (VDBG) log("Got NetworkAgent Messenger");
@@ -5659,6 +5704,8 @@
         updateTcpBufferSizes(newNetwork.linkProperties.getTcpBufferSizes());
         mDnsManager.setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
         notifyIfacesChangedForNetworkStats();
+        // Fix up the NetworkCapabilities of any VPNs that don't specify underlying networks.
+        updateAllVpnsCapabilities();
     }
 
     private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
@@ -6098,6 +6145,10 @@
             // doing.
             updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
 
+            if (networkAgent.isVPN()) {
+                updateAllVpnsCapabilities();
+            }
+
             // Consider network even though it is not yet validated.
             final long now = SystemClock.elapsedRealtime();
             rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);
@@ -6359,7 +6410,11 @@
             success = mVpns.get(user).setUnderlyingNetworks(networks);
         }
         if (success) {
-            mHandler.post(() -> notifyIfacesChangedForNetworkStats());
+            mHandler.post(() -> {
+                // Update VPN's capabilities based on updated underlying network set.
+                updateAllVpnsCapabilities();
+                notifyIfacesChangedForNetworkStats();
+            });
         }
         return success;
     }
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 19bdc09..c91e1a1 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1859,7 +1859,7 @@
         final TetherState tetherState = new TetherState(
                 new IpServer(iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
                              makeControlCallback(), mConfig.enableLegacyDhcpServer,
-                             mDeps.getIpServerDependencies(mContext)));
+                             mDeps.getIpServerDependencies()));
         mTetherStates.put(iface, tetherState);
         tetherState.ipServer.start();
     }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 9141ccb..a7d16d8 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -240,7 +240,7 @@
         mNetworkCapabilities = new NetworkCapabilities();
         mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
         mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
-        updateCapabilities();
+        updateCapabilities(null /* defaultNetwork */);
 
         loadAlwaysOnPackage();
     }
@@ -267,22 +267,44 @@
         updateAlwaysOnNotification(detailedState);
     }
 
-    public void updateCapabilities() {
-        final Network[] underlyingNetworks = (mConfig != null) ? mConfig.underlyingNetworks : null;
-        // Only apps targeting Q and above can explicitly declare themselves as metered.
-        final boolean isAlwaysMetered =
-                mIsPackageTargetingAtLeastQ && (mConfig == null || mConfig.isMetered);
-        updateCapabilities(mContext.getSystemService(ConnectivityManager.class), underlyingNetworks,
-                mNetworkCapabilities, isAlwaysMetered);
-
-        if (mNetworkAgent != null) {
-            mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+    /**
+     * Updates {@link #mNetworkCapabilities} based on current underlying networks and returns a
+     * defensive copy.
+     *
+     * <p>Does not propagate updated capabilities to apps.
+     *
+     * @param defaultNetwork underlying network for VPNs following platform's default
+     */
+    public synchronized NetworkCapabilities updateCapabilities(
+            @Nullable Network defaultNetwork) {
+        if (mConfig == null) {
+            // VPN is not running.
+            return null;
         }
+
+        Network[] underlyingNetworks = mConfig.underlyingNetworks;
+        if (underlyingNetworks == null && defaultNetwork != null) {
+            // null underlying networks means to track the default.
+            underlyingNetworks = new Network[] { defaultNetwork };
+        }
+        // Only apps targeting Q and above can explicitly declare themselves as metered.
+        final boolean isAlwaysMetered = mIsPackageTargetingAtLeastQ && mConfig.isMetered;
+
+        applyUnderlyingCapabilities(
+                mContext.getSystemService(ConnectivityManager.class),
+                underlyingNetworks,
+                mNetworkCapabilities,
+                isAlwaysMetered);
+
+        return new NetworkCapabilities(mNetworkCapabilities);
     }
 
     @VisibleForTesting
-    public static void updateCapabilities(ConnectivityManager cm, Network[] underlyingNetworks,
-            NetworkCapabilities caps, boolean isAlwaysMetered) {
+    public static void applyUnderlyingCapabilities(
+            ConnectivityManager cm,
+            Network[] underlyingNetworks,
+            NetworkCapabilities caps,
+            boolean isAlwaysMetered) {
         int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
         int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
         int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
@@ -295,6 +317,7 @@
         boolean hadUnderlyingNetworks = false;
         if (null != underlyingNetworks) {
             for (Network underlying : underlyingNetworks) {
+                // TODO(b/124469351): Get capabilities directly from ConnectivityService instead.
                 final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying);
                 if (underlyingCaps == null) continue;
                 hadUnderlyingNetworks = true;
@@ -1005,9 +1028,8 @@
     }
 
     /**
-     * Establish a VPN network and return the file descriptor of the VPN
-     * interface. This methods returns {@code null} if the application is
-     * revoked or not prepared.
+     * Establish a VPN network and return the file descriptor of the VPN interface. This methods
+     * returns {@code null} if the application is revoked or not prepared.
      *
      * @param config The parameters to configure the network.
      * @return The file descriptor of the VPN interface.
@@ -1099,8 +1121,6 @@
                 // as rules are deleted. This prevents data leakage as the rules are moved over.
                 agentDisconnect(oldNetworkAgent);
             }
-            // Set up VPN's capabilities such as meteredness.
-            updateCapabilities();
 
             if (oldConnection != null) {
                 mContext.unbindService(oldConnection);
@@ -1256,6 +1276,11 @@
         return ranges;
     }
 
+    /**
+     * Updates UID ranges for this VPN and also updates its internal capabilities.
+     *
+     * <p>Should be called on primary ConnectivityService thread.
+     */
     public void onUserAdded(int userHandle) {
         // If the user is restricted tie them to the parent user's VPN
         UserInfo user = UserManager.get(mContext).getUserInfo(userHandle);
@@ -1266,8 +1291,9 @@
                     try {
                         addUserToRanges(existingRanges, userHandle, mConfig.allowedApplications,
                                 mConfig.disallowedApplications);
+                        // ConnectivityService will call {@link #updateCapabilities} and apply
+                        // those for VPN network.
                         mNetworkCapabilities.setUids(existingRanges);
-                        updateCapabilities();
                     } catch (Exception e) {
                         Log.wtf(TAG, "Failed to add restricted user to owner", e);
                     }
@@ -1277,6 +1303,11 @@
         }
     }
 
+    /**
+     * Updates UID ranges for this VPN and also updates its capabilities.
+     *
+     * <p>Should be called on primary ConnectivityService thread.
+     */
     public void onUserRemoved(int userHandle) {
         // clean up if restricted
         UserInfo user = UserManager.get(mContext).getUserInfo(userHandle);
@@ -1288,8 +1319,9 @@
                         final List<UidRange> removedRanges =
                             uidRangesForUser(userHandle, existingRanges);
                         existingRanges.removeAll(removedRanges);
+                        // ConnectivityService will call {@link #updateCapabilities} and
+                        // apply those for VPN network.
                         mNetworkCapabilities.setUids(existingRanges);
-                        updateCapabilities();
                     } catch (Exception e) {
                         Log.wtf(TAG, "Failed to remove restricted user to owner", e);
                     }
@@ -1502,6 +1534,12 @@
         return success;
     }
 
+    /**
+     * Updates underlying network set.
+     *
+     * <p>Note: Does not updates capabilities. Call {@link #updateCapabilities} from
+     * ConnectivityService thread to get updated capabilities.
+     */
     public synchronized boolean setUnderlyingNetworks(Network[] networks) {
         if (!isCallerEstablishedOwnerLocked()) {
             return false;
@@ -1518,7 +1556,6 @@
                 }
             }
         }
-        updateCapabilities();
         return true;
     }
 
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
index 3fddac1..173d786 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
@@ -61,8 +61,8 @@
     /**
      * Get dependencies to be used by IpServer.
      */
-    public IpServer.Dependencies getIpServerDependencies(Context context) {
-        return new IpServer.Dependencies(context);
+    public IpServer.Dependencies getIpServerDependencies() {
+        return new IpServer.Dependencies();
     }
 
     /**
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index f1b03d1..81d6b63 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -344,6 +344,11 @@
     private final class PackageReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
+            final String action = intent.getAction();
+            if (action == null) {
+                Slog.e(TAG, "Cannot handle package broadcast with null action");
+                return;
+            }
             final Uri data = intent.getData();
             if (data == null) {
                 Slog.e(TAG, "Cannot handle package broadcast with null data");
@@ -361,7 +366,7 @@
                 userIds = new int[] { UserHandle.getUserId(extraUid) };
             }
 
-            switch (intent.getAction()) {
+            switch (action) {
                 case ACTION_PACKAGE_ADDED:
                     if (replacing) {
                         onPackageUpgraded(packageName, userIds);
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 33b8641..640b155 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -19,6 +19,9 @@
 per-file CompilerStats.java = agampe@google.com
 per-file CompilerStats.java = calin@google.com
 per-file CompilerStats.java = ngeoffray@google.com
+per-file DynamicCodeLoggingService.java = agampe@google.com
+per-file DynamicCodeLoggingService.java = calin@google.com
+per-file DynamicCodeLoggingService.java = ngeoffray@google.com
 per-file InstructionSets.java = agampe@google.com
 per-file InstructionSets.java = calin@google.com
 per-file InstructionSets.java = ngeoffray@google.com
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2338fff..406822c 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -37,6 +37,7 @@
 import android.database.sqlite.SQLiteCompatibilityWalFlags;
 import android.database.sqlite.SQLiteGlobal;
 import android.hardware.display.DisplayManagerInternal;
+import android.net.NetworkStackClient;
 import android.os.BaseBundle;
 import android.os.Binder;
 import android.os.Build;
@@ -1240,9 +1241,7 @@
 
             traceBeginAndSlog("StartNetworkStack");
             try {
-                final android.net.NetworkStack networkStack =
-                        context.getSystemService(android.net.NetworkStack.class);
-                networkStack.start(context);
+                NetworkStackClient.getInstance().start(context);
             } catch (Throwable e) {
                 reportWtf("starting Network Stack", e);
             }
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 9946cc3..8ad4d76 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -3,6 +3,7 @@
     srcs: ["java/**/*.java"],
     static_libs: [
         "netd_aidl_interface-java",
+        "networkstack-aidl-interfaces-java",
     ]
 }
 
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
new file mode 100644
index 0000000..1eb7b98
--- /dev/null
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -0,0 +1,289 @@
+/*
+ * 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.
+ */
+package android.net;
+
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.net.dhcp.DhcpServingParamsParcel;
+import android.net.dhcp.IDhcpServerCallbacks;
+import android.net.ip.IIpClientCallbacks;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+
+/**
+ * Service used to communicate with the network stack, which is running in a separate module.
+ * @hide
+ */
+public class NetworkStackClient {
+    private static final String TAG = NetworkStackClient.class.getSimpleName();
+
+    private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;
+
+    private static NetworkStackClient sInstance;
+
+    @NonNull
+    @GuardedBy("mPendingNetStackRequests")
+    private final ArrayList<NetworkStackCallback> mPendingNetStackRequests = new ArrayList<>();
+    @Nullable
+    @GuardedBy("mPendingNetStackRequests")
+    private INetworkStackConnector mConnector;
+
+    private volatile boolean mNetworkStackStartRequested = false;
+
+    private interface NetworkStackCallback {
+        void onNetworkStackConnected(INetworkStackConnector connector);
+    }
+
+    private NetworkStackClient() { }
+
+    /**
+     * Get the NetworkStackClient singleton instance.
+     */
+    public static synchronized NetworkStackClient getInstance() {
+        if (sInstance == null) {
+            sInstance = new NetworkStackClient();
+        }
+        return sInstance;
+    }
+
+    /**
+     * Create a DHCP server according to the specified parameters.
+     *
+     * <p>The server will be returned asynchronously through the provided callbacks.
+     */
+    public void makeDhcpServer(final String ifName, final DhcpServingParamsParcel params,
+            final IDhcpServerCallbacks cb) {
+        requestConnector(connector -> {
+            try {
+                connector.makeDhcpServer(ifName, params, cb);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        });
+    }
+
+    /**
+     * Create an IpClient on the specified interface.
+     *
+     * <p>The IpClient will be returned asynchronously through the provided callbacks.
+     */
+    public void makeIpClient(String ifName, IIpClientCallbacks cb) {
+        requestConnector(connector -> {
+            try {
+                connector.makeIpClient(ifName, cb);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        });
+    }
+
+    /**
+     * Create a NetworkMonitor.
+     *
+     * <p>The INetworkMonitor will be returned asynchronously through the provided callbacks.
+     */
+    public void makeNetworkMonitor(
+            NetworkParcelable network, String name, INetworkMonitorCallbacks cb) {
+        requestConnector(connector -> {
+            try {
+                connector.makeNetworkMonitor(network, name, cb);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        });
+    }
+
+    private class NetworkStackConnection implements ServiceConnection {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            registerNetworkStackService(service);
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            // TODO: crash/reboot the system ?
+            Slog.wtf(TAG, "Lost network stack connector");
+        }
+    };
+
+    private void registerNetworkStackService(@NonNull IBinder service) {
+        final INetworkStackConnector connector = INetworkStackConnector.Stub.asInterface(service);
+
+        ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service, false /* allowIsolated */,
+                DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+
+        final ArrayList<NetworkStackCallback> requests;
+        synchronized (mPendingNetStackRequests) {
+            requests = new ArrayList<>(mPendingNetStackRequests);
+            mPendingNetStackRequests.clear();
+            mConnector = connector;
+        }
+
+        for (NetworkStackCallback r : requests) {
+            r.onNetworkStackConnected(connector);
+        }
+    }
+
+    /**
+     * Start the network stack. Should be called only once on device startup.
+     *
+     * <p>This method will start the network stack either in the network stack process, or inside
+     * the system server on devices that do not support the network stack module. The network stack
+     * connector will then be delivered asynchronously to clients that requested it before it was
+     * started.
+     */
+    public void start(Context context) {
+        mNetworkStackStartRequested = true;
+        // Try to bind in-process if the library is available
+        IBinder connector = null;
+        try {
+            final Class service = Class.forName(
+                    "com.android.server.NetworkStackService",
+                    true /* initialize */,
+                    context.getClassLoader());
+            connector = (IBinder) service.getMethod("makeConnector", Context.class)
+                    .invoke(null, context);
+        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+            Slog.wtf(TAG, "Could not create network stack connector from NetworkStackService");
+            // TODO: crash/reboot system here ?
+            return;
+        } catch (ClassNotFoundException e) {
+            // Normal behavior if stack is provided by the app: fall through
+        }
+
+        // In-process network stack. Add the service to the service manager here.
+        if (connector != null) {
+            registerNetworkStackService(connector);
+            return;
+        }
+        // Start the network stack process. The service will be added to the service manager in
+        // NetworkStackConnection.onServiceConnected().
+        final Intent intent = new Intent(INetworkStackConnector.class.getName());
+        final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
+        intent.setComponent(comp);
+
+        if (comp == null) {
+            Slog.wtf(TAG, "Could not resolve the network stack with " + intent);
+            // TODO: crash/reboot system server ?
+            return;
+        }
+        final PackageManager pm = context.getPackageManager();
+        int uid = -1;
+        try {
+            uid = pm.getPackageUid(comp.getPackageName(), UserHandle.USER_SYSTEM);
+        } catch (PackageManager.NameNotFoundException e) {
+            Slog.wtf("Network stack package not found", e);
+            // Fall through
+        }
+        if (uid != Process.NETWORK_STACK_UID) {
+            throw new SecurityException("Invalid network stack UID: " + uid);
+        }
+
+        final int hasPermission =
+                pm.checkPermission(PERMISSION_MAINLINE_NETWORK_STACK, comp.getPackageName());
+        if (hasPermission != PERMISSION_GRANTED) {
+            throw new SecurityException(
+                    "Network stack does not have permission " + PERMISSION_MAINLINE_NETWORK_STACK);
+        }
+
+        if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
+                Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
+            Slog.wtf(TAG,
+                    "Could not bind to network stack in-process, or in app with " + intent);
+            // TODO: crash/reboot system server if no network stack after a timeout ?
+        }
+    }
+
+    /**
+     * For non-system server clients, get the connector registered by the system server.
+     */
+    private INetworkStackConnector getRemoteConnector() {
+        // Block until the NetworkStack connector is registered in ServiceManager.
+        // <p>This is only useful for non-system processes that do not have a way to be notified of
+        // registration completion. Adding a callback system would be too heavy weight considering
+        // that the connector is registered on boot, so it is unlikely that a client would request
+        // it before it is registered.
+        // TODO: consider blocking boot on registration and simplify much of the logic in this class
+        IBinder connector;
+        try {
+            final long before = System.currentTimeMillis();
+            while ((connector = ServiceManager.getService(Context.NETWORK_STACK_SERVICE)) == null) {
+                Thread.sleep(20);
+                if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
+                    Slog.e(TAG, "Timeout waiting for NetworkStack connector");
+                    return null;
+                }
+            }
+        } catch (InterruptedException e) {
+            Slog.e(TAG, "Error waiting for NetworkStack connector", e);
+            return null;
+        }
+
+        return INetworkStackConnector.Stub.asInterface(connector);
+    }
+
+    private void requestConnector(@NonNull NetworkStackCallback request) {
+        // TODO: PID check.
+        final int caller = Binder.getCallingUid();
+        if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) {
+            // Don't even attempt to obtain the connector and give a nice error message
+            throw new SecurityException(
+                    "Only the system server should try to bind to the network stack.");
+        }
+
+        if (!mNetworkStackStartRequested) {
+            // The network stack is not being started in this process, e.g. this process is not
+            // the system server. Get a remote connector registered by the system server.
+            final INetworkStackConnector connector = getRemoteConnector();
+            synchronized (mPendingNetStackRequests) {
+                mConnector = connector;
+            }
+            request.onNetworkStackConnected(connector);
+            return;
+        }
+
+        final INetworkStackConnector connector;
+        synchronized (mPendingNetStackRequests) {
+            connector = mConnector;
+            if (connector == null) {
+                mPendingNetStackRequests.add(request);
+                return;
+            }
+        }
+
+        request.onNetworkStackConnected(connector);
+    }
+}
diff --git a/core/java/android/net/dhcp/DhcpServerCallbacks.java b/services/net/java/android/net/dhcp/DhcpServerCallbacks.java
similarity index 100%
rename from core/java/android/net/dhcp/DhcpServerCallbacks.java
rename to services/net/java/android/net/dhcp/DhcpServerCallbacks.java
diff --git a/core/java/android/net/ip/IpClientCallbacks.java b/services/net/java/android/net/ip/IpClientCallbacks.java
similarity index 100%
rename from core/java/android/net/ip/IpClientCallbacks.java
rename to services/net/java/android/net/ip/IpClientCallbacks.java
diff --git a/services/net/java/android/net/ip/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java
index 2a2a67a..bf917bf 100644
--- a/services/net/java/android/net/ip/IpClientUtil.java
+++ b/services/net/java/android/net/ip/IpClientUtil.java
@@ -23,8 +23,7 @@
 import android.net.DhcpResultsParcelable;
 import android.net.LinkProperties;
 import android.net.LinkPropertiesParcelable;
-import android.net.NetworkStack;
-import android.net.ip.IIpClientCallbacks;
+import android.net.NetworkStackClient;
 import android.os.ConditionVariable;
 
 import java.io.FileDescriptor;
@@ -76,30 +75,17 @@
      *
      * <p>This is a convenience method to allow clients to use {@link IpClientCallbacks} instead of
      * {@link IIpClientCallbacks}.
-     * @see {@link NetworkStack#makeIpClient(String, IIpClientCallbacks)}
+     * @see {@link NetworkStackClient#makeIpClient(String, IIpClientCallbacks)}
      */
     public static void makeIpClient(Context context, String ifName, IpClientCallbacks callback) {
-        context.getSystemService(NetworkStack.class)
-                .makeIpClient(ifName, new IpClientCallbacksProxy(callback));
-    }
-
-    /**
-     * Create a new IpClient.
-     *
-     * <p>This is a convenience method to allow clients to use {@link IpClientCallbacksProxy}
-     * instead of {@link IIpClientCallbacks}.
-     * @see {@link NetworkStack#makeIpClient(String, IIpClientCallbacks)}
-     */
-    public static void makeIpClient(
-            Context context, String ifName, IpClientCallbacksProxy callback) {
-        context.getSystemService(NetworkStack.class)
-                .makeIpClient(ifName, callback);
+        // TODO: migrate clients and remove context argument
+        NetworkStackClient.getInstance().makeIpClient(ifName, new IpClientCallbacksProxy(callback));
     }
 
     /**
      * Wrapper to relay calls from {@link IIpClientCallbacks} to {@link IpClientCallbacks}.
      */
-    public static class IpClientCallbacksProxy extends IIpClientCallbacks.Stub {
+    private static class IpClientCallbacksProxy extends IIpClientCallbacks.Stub {
         protected final IpClientCallbacks mCb;
 
         /**
diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java
index 7910c9a..34fc735 100644
--- a/services/net/java/android/net/ip/IpServer.java
+++ b/services/net/java/android/net/ip/IpServer.java
@@ -22,7 +22,6 @@
 import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
 import static android.net.util.NetworkConstants.asByte;
 
-import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.INetd;
 import android.net.INetworkStackStatusCallback;
@@ -31,7 +30,7 @@
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
-import android.net.NetworkStack;
+import android.net.NetworkStackClient;
 import android.net.RouteInfo;
 import android.net.dhcp.DhcpServerCallbacks;
 import android.net.dhcp.DhcpServingParamsParcel;
@@ -132,10 +131,6 @@
     }
 
     public static class Dependencies {
-        private final Context mContext;
-        public Dependencies(Context context) {
-            mContext = context;
-        }
         public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
             return new RouterAdvertisementDaemon(ifParams);
         }
@@ -153,7 +148,7 @@
          */
         public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
                 DhcpServerCallbacks cb) {
-            mContext.getSystemService(NetworkStack.class).makeDhcpServer(ifName, params, cb);
+            NetworkStackClient.getInstance().makeDhcpServer(ifName, params, cb);
         }
     }
 
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 268e70f..c60eb56 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -289,6 +289,19 @@
             "android.telecom.extra.OUTGOING_CALL_EXTRAS";
 
     /**
+     * An optional boolean extra on {@link android.content.Intent#ACTION_CALL_EMERGENCY} to tell
+     * whether the user's dial intent is emergency; this is required to specify when the dialed
+     * number is ambiguous, identified as both emergency number and any other non-emergency number;
+     * e.g. in some situation, 611 could be both an emergency number in a country and a
+     * non-emergency number of a carrier's customer service hotline.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_IS_USER_INTENT_EMERGENCY_CALL =
+            "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL";
+
+    /**
      * @hide
      */
     public static final String EXTRA_UNKNOWN_CALL_HANDLE =
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 51c8f65..50b8f79 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -2059,6 +2059,11 @@
      * @hide - not meant for public use
      */
     public interface RcsColumns {
+        // TODO(sahinc): Turn this to true once the schema finalizes, so that people can update
+        //  their messaging databases. NOTE: move the switch/case update in MmsSmsDatabaseHelper to
+        //  the latest version of the database before turning this flag to true.
+        boolean IS_RCS_TABLE_SCHEMA_CODE_COMPLETE = false;
+
         /**
          * The authority for the content provider
          */
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 59167b7..73f0556 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -350,6 +350,9 @@
     /** Indicates if the call is for testing purpose */
     private boolean mEmergencyCallTesting = false;
 
+    /** Indicates if we have known the intent of the user for the call is emergency */
+    private boolean mHasKnownUserIntentEmergency = false;
+
     /**
      * Extras associated with this {@link ImsCallProfile}.
      * <p>
@@ -789,12 +792,13 @@
      *
      * @hide
      */
-    public void setEmergencyCallInfo(EmergencyNumber num) {
+    public void setEmergencyCallInfo(EmergencyNumber num, boolean hasKnownUserIntentEmergency) {
         setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmaskInternalDial());
         setEmergencyUrns(num.getEmergencyUrns());
         setEmergencyCallRouting(num.getEmergencyCallRouting());
         setEmergencyCallTesting(num.getEmergencyNumberSourceBitmask()
                 == EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST);
+        setHasKnownUserIntentEmergency(hasKnownUserIntentEmergency);
     }
 
     /**
@@ -860,6 +864,19 @@
     }
 
     /**
+     * Set if we have known the user intent of the call is emergency.
+     *
+     * This is only used to specify when the dialed number is ambiguous when it can be identified
+     * as both emergency number and any other non-emergency number; e.g. in some situation, 611
+     * could be both an emergency number in a country and a non-emergency number of a carrier's
+     * customer service hotline.
+     */
+    @VisibleForTesting
+    public void setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency) {
+        mHasKnownUserIntentEmergency = hasKnownUserIntentEmergency;
+    }
+
+    /**
      * Get the emergency service categories, only valid if {@link #getServiceType} returns
      * {@link #SERVICE_TYPE_EMERGENCY}
      *
@@ -916,4 +933,16 @@
     public boolean isEmergencyCallTesting() {
         return mEmergencyCallTesting;
     }
+
+    /**
+     * Checks if we have known the user intent of the call is emergency.
+     *
+     * This is only used to specify when the dialed number is ambiguous when it can be identified
+     * as both emergency number and any other non-emergency number; e.g. in some situation, 611
+     * could be both an emergency number in a country and a non-emergency number of a carrier's
+     * customer service hotline.
+     */
+    public boolean hasKnownUserIntentEmergency() {
+        return mHasKnownUserIntentEmergency;
+    }
 }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index c83ab84..d1a0692 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -20,6 +20,7 @@
 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
+import static android.net.ConnectivityManager.NETID_UNSET;
 import static android.net.ConnectivityManager.TYPE_ETHERNET;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
@@ -123,7 +124,7 @@
 import android.net.NetworkParcelable;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
-import android.net.NetworkStack;
+import android.net.NetworkStackClient;
 import android.net.NetworkUtils;
 import android.net.ProxyInfo;
 import android.net.RouteInfo;
@@ -245,7 +246,7 @@
     @Mock INetworkStatsService mStatsService;
     @Mock INetworkPolicyManager mNpm;
     @Mock INetd mMockNetd;
-    @Mock NetworkStack mNetworkStack;
+    @Mock NetworkStackClient mNetworkStack;
 
     private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
 
@@ -885,11 +886,14 @@
 
         public void setUids(Set<UidRange> uids) {
             mNetworkCapabilities.setUids(uids);
-            updateCapabilities();
+            updateCapabilities(null /* defaultNetwork */);
         }
 
         @Override
         public int getNetId() {
+            if (mMockNetworkAgent == null) {
+                return NETID_UNSET;
+            }
             return mMockNetworkAgent.getNetwork().netId;
         }
 
@@ -911,12 +915,13 @@
         }
 
         @Override
-        public void updateCapabilities() {
-            if (!mConnected) return;
-            super.updateCapabilities();
-            // Because super.updateCapabilities will update the capabilities of the agent but not
-            // the mock agent, the mock agent needs to know about them.
+        public NetworkCapabilities updateCapabilities(Network defaultNetwork) {
+            if (!mConnected) return null;
+            super.updateCapabilities(defaultNetwork);
+            // Because super.updateCapabilities will update the capabilities of the agent but
+            // not the mock agent, the mock agent needs to know about them.
             copyCapabilitiesToNetworkAgent();
+            return new NetworkCapabilities(mNetworkCapabilities);
         }
 
         private void copyCapabilitiesToNetworkAgent() {
@@ -1061,6 +1066,11 @@
         }
 
         @Override
+        protected NetworkStackClient getNetworkStack() {
+            return mNetworkStack;
+        }
+
+        @Override
         public WakeupMessage makeWakeupMessage(
                 Context context, Handler handler, String cmdName, int cmd, Object obj) {
             return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
@@ -4664,6 +4674,7 @@
 
         vpnNetworkAgent.connect(false);
         mMockVpn.connect();
+        mMockVpn.setUnderlyingNetworks(new Network[0]);
 
         genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
         genericNotVpnNetworkCallback.assertNoCallback();
@@ -4696,6 +4707,7 @@
 
         ranges.add(new UidRange(uid, uid));
         mMockVpn.setUids(ranges);
+        vpnNetworkAgent.setUids(ranges);
 
         genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
         genericNotVpnNetworkCallback.assertNoCallback();
@@ -4729,12 +4741,11 @@
     }
 
     @Test
-    public void testVpnWithAndWithoutInternet() {
+    public void testVpnWithoutInternet() {
         final int uid = Process.myUid();
 
         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(defaultCallback);
-        defaultCallback.assertNoCallback();
 
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
@@ -4756,11 +4767,30 @@
         vpnNetworkAgent.disconnect();
         defaultCallback.assertNoCallback();
 
-        vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+        mCm.unregisterNetworkCallback(defaultCallback);
+    }
+
+    @Test
+    public void testVpnWithInternet() {
+        final int uid = Process.myUid();
+
+        final TestNetworkCallback defaultCallback = new TestNetworkCallback();
+        mCm.registerDefaultNetworkCallback(defaultCallback);
+
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.connect(true);
+
+        defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
+        assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
+
+        MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+        final ArraySet<UidRange> ranges = new ArraySet<>();
+        ranges.add(new UidRange(uid, uid));
         mMockVpn.setNetworkAgent(vpnNetworkAgent);
         mMockVpn.setUids(ranges);
         vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
         mMockVpn.connect();
+
         defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
@@ -4768,14 +4798,6 @@
         defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
 
-        vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
-        ranges.clear();
-        mMockVpn.setNetworkAgent(vpnNetworkAgent);
-        mMockVpn.setUids(ranges);
-        vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
-        mMockVpn.connect();
-        defaultCallback.assertNoCallback();
-
         mCm.unregisterNetworkCallback(defaultCallback);
     }
 
@@ -4878,6 +4900,70 @@
     }
 
     @Test
+    public void testNullUnderlyingNetworks() {
+        final int uid = Process.myUid();
+
+        final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
+        final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
+                .removeCapability(NET_CAPABILITY_NOT_VPN)
+                .addTransportType(TRANSPORT_VPN)
+                .build();
+        NetworkCapabilities nc;
+        mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
+        vpnNetworkCallback.assertNoCallback();
+
+        final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+        final ArraySet<UidRange> ranges = new ArraySet<>();
+        ranges.add(new UidRange(uid, uid));
+        mMockVpn.setNetworkAgent(vpnNetworkAgent);
+        mMockVpn.connect();
+        mMockVpn.setUids(ranges);
+        vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
+
+        vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
+        nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
+        assertTrue(nc.hasTransport(TRANSPORT_VPN));
+        assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
+        assertFalse(nc.hasTransport(TRANSPORT_WIFI));
+        // By default, VPN is set to track default network (i.e. its underlying networks is null).
+        // In case of no default network, VPN is considered metered.
+        assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
+
+        // Connect to Cell; Cell is the default network.
+        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.connect(true);
+
+        vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+                vpnNetworkAgent);
+
+        // Connect to WiFi; WiFi is the new default.
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiNetworkAgent.connect(true);
+
+        vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
+                && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+                vpnNetworkAgent);
+
+        // Disconnect Cell. The default network did not change, so there shouldn't be any changes in
+        // the capabilities.
+        mCellNetworkAgent.disconnect();
+
+        // Disconnect wifi too. Now we have no default network.
+        mWiFiNetworkAgent.disconnect();
+
+        vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+                vpnNetworkAgent);
+
+        mMockVpn.disconnect();
+    }
+
+    @Test
     public void testNetworkBlockedStatus() {
         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
         final NetworkRequest cellRequest = new NetworkRequest.Builder()
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index 9578ded..aa6cbda 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -37,7 +37,6 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkMisc;
-import android.net.NetworkStack;
 import android.os.INetworkManagementService;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -74,16 +73,12 @@
     @Mock NetworkMisc mMisc;
     @Mock NetworkNotificationManager mNotifier;
     @Mock Resources mResources;
-    @Mock NetworkStack mNetworkStack;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         when(mCtx.getResources()).thenReturn(mResources);
         when(mCtx.getPackageName()).thenReturn("com.android.server.connectivity");
-        when(mCtx.getSystemServiceName(NetworkStack.class))
-                .thenReturn(Context.NETWORK_STACK_SERVICE);
-        when(mCtx.getSystemService(Context.NETWORK_STACK_SERVICE)).thenReturn(mNetworkStack);
 
         mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, HIGH_RATE_LIMIT);
     }
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index a4a735d..533d7ad 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -195,10 +195,6 @@
     }
 
     public class MockIpServerDependencies extends IpServer.Dependencies {
-        MockIpServerDependencies() {
-            super(null);
-        }
-
         @Override
         public RouterAdvertisementDaemon getRouterAdvertisementDaemon(
                 InterfaceParams ifParams) {
@@ -266,7 +262,7 @@
         }
 
         @Override
-        public IpServer.Dependencies getIpServerDependencies(Context context) {
+        public IpServer.Dependencies getIpServerDependencies() {
             return mIpServerDependencies;
         }
 
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 46de3d0..f169d6b 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -566,7 +566,7 @@
 
         final NetworkCapabilities caps = new NetworkCapabilities();
 
-        Vpn.updateCapabilities(
+        Vpn.applyUnderlyingCapabilities(
                 mConnectivityManager, new Network[] {}, caps, false /* isAlwaysMetered */);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
         assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
@@ -577,7 +577,7 @@
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        Vpn.updateCapabilities(
+        Vpn.applyUnderlyingCapabilities(
                 mConnectivityManager,
                 new Network[] {mobile},
                 caps,
@@ -591,7 +591,7 @@
         assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        Vpn.updateCapabilities(
+        Vpn.applyUnderlyingCapabilities(
                 mConnectivityManager, new Network[] {wifi}, caps, false /* isAlwaysMetered */);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
         assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
@@ -602,7 +602,7 @@
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        Vpn.updateCapabilities(
+        Vpn.applyUnderlyingCapabilities(
                 mConnectivityManager, new Network[] {wifi}, caps, true /* isAlwaysMetered */);
         assertTrue(caps.hasTransport(TRANSPORT_VPN));
         assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
@@ -613,7 +613,7 @@
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
         assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
 
-        Vpn.updateCapabilities(
+        Vpn.applyUnderlyingCapabilities(
                 mConnectivityManager,
                 new Network[] {mobile, wifi},
                 caps,