Merge "Restructure Module code [ com.android.tethering ]"
diff --git a/StubLibraries.bp b/StubLibraries.bp
index e0c3022..3d28bf8 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -253,38 +253,11 @@
 }
 
 /////////////////////////////////////////////////////////////////////
-// Following droidstubs modules are for extra APIs for modules,
+// Following droidstub module for extra APIs for modules,
 // namely @SystemApi(client=MODULE_LIBRARIES) APIs.
 /////////////////////////////////////////////////////////////////////
 
 droidstubs {
-    name: "module-lib-api",
-    defaults: ["metalava-full-api-stubs-default"],
-    arg_files: ["core/res/AndroidManifest.xml"],
-    args: metalava_framework_docs_args + module_libs,
-
-    // Do not generate stubs as they are not needed
-    generate_stubs: false,
-
-    check_api: {
-        current: {
-            api_file: "api/module-lib-current.txt",
-            removed_api_file: "api/module-lib-removed.txt",
-        },
-        last_released: {
-            api_file: ":android.api.module-lib.latest",
-            removed_api_file: ":removed.api.module-lib.latest",
-            baseline_file: ":module-lib-api-incompatibilities-with-last-released"
-        },
-        api_lint: {
-            enabled: true,
-            new_since: ":android.api.module-lib.latest",
-            baseline_file: "api/module-lib-lint-baseline.txt",
-        },
-    },
-}
-
-droidstubs {
     name: "module-lib-api-stubs-docs-non-updatable",
     defaults: ["metalava-non-updatable-api-stubs-default"],
     arg_files: ["core/res/AndroidManifest.xml"],
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 97ef62b..d10e33f 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -131,6 +131,8 @@
 import android.net.lowpan.LowpanManager;
 import android.net.nsd.INsdManager;
 import android.net.nsd.NsdManager;
+import android.net.vcn.IVcnManagementService;
+import android.net.vcn.VcnManager;
 import android.net.wifi.WifiFrameworkInitializer;
 import android.net.wifi.nl80211.WifiNl80211Manager;
 import android.nfc.NfcManager;
@@ -371,6 +373,14 @@
                         ctx, () -> ServiceManager.getService(Context.TETHERING_SERVICE));
             }});
 
+        registerService(Context.VCN_MANAGEMENT_SERVICE, VcnManager.class,
+                new CachedServiceFetcher<VcnManager>() {
+            @Override
+            public VcnManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getService(Context.VCN_MANAGEMENT_SERVICE);
+                IVcnManagementService service = IVcnManagementService.Stub.asInterface(b);
+                return new VcnManager(ctx, service);
+            }});
 
         registerService(Context.IPSEC_SERVICE, IpSecManager.class,
                 new CachedServiceFetcher<IpSecManager>() {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 872c377..7047f73 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -18,6 +18,7 @@
 package android.bluetooth;
 
 import android.Manifest;
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -686,6 +687,8 @@
     private final Map<LeScanCallback, ScanCallback> mLeScanClients;
     private static final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>>
                 sMetadataListeners = new HashMap<>();
+    private final Map<BluetoothConnectionCallback, Executor>
+            mBluetoothConnectionCallbackExecutorMap = new HashMap<>();
 
     /**
      * Bluetooth metadata listener. Overrides the default BluetoothMetadataListener
@@ -3538,6 +3541,133 @@
                 @Nullable byte[] value);
     }
 
+    private final IBluetoothConnectionCallback mConnectionCallback =
+            new IBluetoothConnectionCallback.Stub() {
+        @Override
+        public void onDeviceConnected(BluetoothDevice device) {
+            for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
+                    mBluetoothConnectionCallbackExecutorMap.entrySet()) {
+                BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
+                Executor executor = callbackExecutorEntry.getValue();
+                executor.execute(() -> callback.onDeviceConnected(device));
+            }
+        }
+
+        @Override
+        public void onDeviceDisconnected(BluetoothDevice device) {
+            for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
+                    mBluetoothConnectionCallbackExecutorMap.entrySet()) {
+                BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
+                Executor executor = callbackExecutorEntry.getValue();
+                executor.execute(() -> callback.onDeviceDisconnected(device));
+            }
+        }
+    };
+
+    /**
+     * Registers the BluetoothConnectionCallback to receive callback events when a bluetooth device
+     * (classic or low energy) is connected or disconnected.
+     *
+     * @param executor is the callback executor
+     * @param callback is the connection callback you wish to register
+     * @return true if the callback was registered successfully, false otherwise
+     * @throws IllegalArgumentException if the callback is already registered
+     * @hide
+     */
+    public boolean registerBluetoothConnectionCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull BluetoothConnectionCallback callback) {
+        if (DBG) Log.d(TAG, "registerBluetoothConnectionCallback()");
+        if (callback == null) {
+            return false;
+        }
+
+        // If the callback map is empty, we register the service-to-app callback
+        if (mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
+            try {
+                mServiceLock.readLock().lock();
+                if (mService != null) {
+                    if (!mService.registerBluetoothConnectionCallback(mConnectionCallback)) {
+                        return false;
+                    }
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "", e);
+                mBluetoothConnectionCallbackExecutorMap.remove(callback);
+            } finally {
+                mServiceLock.readLock().unlock();
+            }
+        }
+
+        // Adds the passed in callback to our map of callbacks to executors
+        synchronized (mBluetoothConnectionCallbackExecutorMap) {
+            if (mBluetoothConnectionCallbackExecutorMap.containsKey(callback)) {
+                throw new IllegalArgumentException("This callback has already been registered");
+            }
+            mBluetoothConnectionCallbackExecutorMap.put(callback, executor);
+        }
+
+        return true;
+    }
+
+    /**
+     * Unregisters the BluetoothConnectionCallback that was previously registered by the application
+     *
+     * @param callback is the connection callback you wish to unregister
+     * @return true if the callback was unregistered successfully, false otherwise
+     * @hide
+     */
+    public boolean unregisterBluetoothConnectionCallback(
+            @NonNull BluetoothConnectionCallback callback) {
+        if (DBG) Log.d(TAG, "unregisterBluetoothConnectionCallback()");
+        if (callback == null) {
+            return false;
+        }
+
+        synchronized (mBluetoothConnectionCallbackExecutorMap) {
+            if (mBluetoothConnectionCallbackExecutorMap.remove(callback) != null) {
+                return false;
+            }
+        }
+
+        if (!mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
+            return true;
+        }
+
+        // If the callback map is empty, we unregister the service-to-app callback
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null) {
+                return mService.unregisterBluetoothConnectionCallback(mConnectionCallback);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+
+        return false;
+    }
+
+    /**
+     * This abstract class is used to implement callbacks for when a bluetooth classic or Bluetooth
+     * Low Energy (BLE) device is either connected or disconnected.
+     *
+     * @hide
+     */
+    public abstract class BluetoothConnectionCallback {
+        /**
+         * Callback triggered when a bluetooth device (classic or BLE) is connected
+         * @param device is the connected bluetooth device
+         */
+        public void onDeviceConnected(BluetoothDevice device) {}
+
+        /**
+         * Callback triggered when a bluetooth device (classic or BLE) is disconnected
+         * @param device is the disconnected bluetooth device
+         */
+        public void onDeviceDisconnected(BluetoothDevice device) {}
+    }
+
     /**
      * Converts old constant of priority to the new for connection policy
      *
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index e6609ca..392dd64 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3402,6 +3402,7 @@
             VIBRATOR_SERVICE,
             //@hide: STATUS_BAR_SERVICE,
             CONNECTIVITY_SERVICE,
+            VCN_MANAGEMENT_SERVICE,
             //@hide: IP_MEMORY_STORE_SERVICE,
             IPSEC_SERVICE,
             VPN_MANAGEMENT_SERVICE,
@@ -3966,6 +3967,16 @@
     public static final String CONNECTIVITY_SERVICE = "connectivity";
 
     /**
+     * Use with {@link #getSystemService(String)} to retrieve a {@link android.net.vcn.VcnManager}
+     * for managing Virtual Carrier Networks
+     *
+     * @see #getSystemService(String)
+     * @see android.net.vcn.VcnManager
+     * @hide
+     */
+    public static final String VCN_MANAGEMENT_SERVICE = "vcn_management";
+
+    /**
      * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.net.INetd} for communicating with the network stack
      * @hide
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 72217a1..267057c 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -189,7 +189,7 @@
      * Waits for the event to be delivered to the application and handled.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(trackingBug = 171972397)
     public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2;  // see InputDispatcher.h
 
     /** @hide */
diff --git a/core/java/android/net/vcn/IVcnManagementService.aidl b/core/java/android/net/vcn/IVcnManagementService.aidl
new file mode 100644
index 0000000..af06906
--- /dev/null
+++ b/core/java/android/net/vcn/IVcnManagementService.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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.vcn;
+
+/**
+ * @hide
+ */
+interface IVcnManagementService {
+}
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
new file mode 100644
index 0000000..d563b03
--- /dev/null
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.vcn;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * VcnManager publishes APIs for applications to configure and manage Virtual Carrier Networks
+ *
+ * @hide
+ */
+@SystemService(Context.VCN_MANAGEMENT_SERVICE)
+public final class VcnManager {
+    @NonNull private static final String TAG = VcnManager.class.getSimpleName();
+
+    @NonNull private final Context mContext;
+    @NonNull private final IVcnManagementService mService;
+
+    /**
+     * Construct an instance of VcnManager within an application context.
+     *
+     * @param ctx the application context for this manager
+     * @param service the VcnManagementService binder backing this manager
+     *
+     * @hide
+     */
+    public VcnManager(@NonNull Context ctx, @NonNull IVcnManagementService service) {
+        mContext = requireNonNull(ctx, "missing context");
+        mService = requireNonNull(service, "missing service");
+    }
+}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 2aa5c13..7a48a2a 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -724,7 +724,7 @@
      * Returns the identifier of this process' parent.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(trackingBug = 171962076)
     public static final int myPpid() {
         return Os.getppid();
     }
diff --git a/core/java/android/os/SharedMemory.java b/core/java/android/os/SharedMemory.java
index 7512352..136e3de 100644
--- a/core/java/android/os/SharedMemory.java
+++ b/core/java/android/os/SharedMemory.java
@@ -158,7 +158,7 @@
      *
      * @hide Exposed for native ASharedMemory_dupFromJava()
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(trackingBug = 171971817)
     public int getFd() {
         return mFileDescriptor.getInt$();
     }
diff --git a/packages/DynamicSystemInstallationService/res/values/strings.xml b/packages/DynamicSystemInstallationService/res/values/strings.xml
index 719fc73..bfeef0a 100644
--- a/packages/DynamicSystemInstallationService/res/values/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values/strings.xml
@@ -37,6 +37,9 @@
     <string name="toast_dynsystem_discarded">Discarded dynamic system</string>
     <!-- Toast when we fail to launch into Dynamic System [CHAR LIMIT=128] -->
     <string name="toast_failed_to_reboot_to_dynsystem">Can\u2019t restart or load dynamic system</string>
+    <!-- Toast when we fail to disable Dynamic System [CHAR LIMIT=128] -->
+    <string name="toast_failed_to_disable_dynsystem">Failed to disable dynamic system</string>
+
 
     <!-- URL of Dynamic System Key Revocation List [DO NOT TRANSLATE] -->
     <string name="key_revocation_list_url" translatable="false">https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json</string>
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 12505bc..ac27580 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -375,8 +375,17 @@
             return;
         }
 
-        // Per current design, we don't have disable() API. AOT is disabled on next reboot.
-        // TODO: Use better status query when b/125079548 is done.
+        if (!mDynSystem.setEnable(/* enable = */ false, /* oneShot = */ false)) {
+            Log.e(TAG, "Failed to disable DynamicSystem.");
+
+            // Dismiss status bar and show a toast.
+            sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+            Toast.makeText(this,
+                    getString(R.string.toast_failed_to_disable_dynsystem),
+                    Toast.LENGTH_LONG).show();
+            return;
+        }
+
         PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
 
         if (powerManager != null) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 21ad6de..da2a3de 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1147,7 +1147,11 @@
 
         mKeepaliveTracker = new KeepaliveTracker(mContext, mHandler);
         mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager,
-                mContext.getSystemService(NotificationManager.class));
+                // Pass a NotificationManager obtained from a context with UserHandle.ALL, then
+                // NetworkNotificationManager can put up a notification to all users.
+                // TODO: Create NotificationManager in NetworkNotificationManager directly.
+                (NotificationManager) mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */)
+                        .getSystemService(Context.NOTIFICATION_SERVICE));
 
         final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 8cc5fea..1cdc95a 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1604,10 +1604,12 @@
         if (!checkNotifyPermission("notifyDisplayInfoChanged()")) {
             return;
         }
+        String str = "notifyDisplayInfoChanged: PhoneId=" + phoneId + " subId=" + subId
+                + " telephonyDisplayInfo=" + telephonyDisplayInfo;
         if (VDBG) {
-            log("notifyDisplayInfoChanged: PhoneId=" + phoneId
-                    + " subId=" + subId + " telephonyDisplayInfo=" + telephonyDisplayInfo);
+            log(str);
         }
+        mLocalLog.log(str);
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
                 mTelephonyDisplayInfos[phoneId] = telephonyDisplayInfo;
@@ -2295,10 +2297,10 @@
                 pw.println("mOutgoingCallEmergencyNumber=" + mOutgoingCallEmergencyNumber[i]);
                 pw.println("mOutgoingSmsEmergencyNumber=" + mOutgoingSmsEmergencyNumber[i]);
                 pw.println("mBarringInfo=" + mBarringInfo.get(i));
+                pw.println("mTelephonyDisplayInfo=" + mTelephonyDisplayInfos[i]);
                 pw.decreaseIndent();
             }
             pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);
-
             pw.println("mPhoneCapability=" + mPhoneCapability);
             pw.println("mActiveDataSubId=" + mActiveDataSubId);
             pw.println("mRadioPowerState=" + mRadioPowerState);
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
new file mode 100644
index 0000000..db7e16c
--- /dev/null
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.vcn.IVcnManagementService;
+
+/**
+ * VcnManagementService manages Virtual Carrier Network profiles and lifecycles.
+ *
+ * <pre>The internal structure of the VCN Management subsystem is as follows:
+ *
+ * +------------------------+ 1:1                                 +--------------------------------+
+ * |  VcnManagementService  | ------------ Creates -------------> |  TelephonySubscriptionManager  |
+ * |                        |                                     |                                |
+ * | Manages configs and    |                                     | Tracks subscriptions, carrier  |
+ * | VcnInstance lifecycles | <--- Notifies of subscription & --- | privilege changes, caches maps |
+ * +------------------------+      carrier privilege changes      +--------------------------------+
+ *      | 1:N          ^
+ *      |              |
+ *      |              +-------------------------------+
+ *      +---------------+                              |
+ *                      |                              |
+ *         Creates when config present,                |
+ *        subscription group active, and               |
+ *      providing app is carrier privileged     Notifies of safe
+ *                      |                      mode state changes
+ *                      v                              |
+ * +-----------------------------------------------------------------------+
+ * |                              VcnInstance                              |
+ * |                                                                       |
+ * |   Manages tunnel lifecycles based on fulfillable NetworkRequest(s)    |
+ * |                        and overall safe-mode                          |
+ * +-----------------------------------------------------------------------+
+ *                      | 1:N                          ^
+ *              Creates to fulfill                     |
+ *           NetworkRequest(s), tears        Notifies of VcnTunnel
+ *          down when no longer needed   teardown (e.g. Network reaped)
+ *                      |                 and safe-mode timer changes
+ *                      v                              |
+ * +-----------------------------------------------------------------------+
+ * |                               VcnTunnel                               |
+ * |                                                                       |
+ * |       Manages a single (IKEv2) tunnel session and NetworkAgent,       |
+ * |  handles mobility events, (IPsec) Tunnel setup and safe-mode timers   |
+ * +-----------------------------------------------------------------------+
+ *                      | 1:1                          ^
+ *                      |                              |
+ *          Creates upon instantiation      Notifies of changes in
+ *                      |                 selected underlying network
+ *                      |                     or its properties
+ *                      v                              |
+ * +-----------------------------------------------------------------------+
+ * |                       UnderlyingNetworkTracker                        |
+ * |                                                                       |
+ * | Manages lifecycle of underlying physical networks, filing requests to |
+ * | bring them up, and releasing them as they become no longer necessary  |
+ * +-----------------------------------------------------------------------+
+ * </pre>
+ *
+ * @hide
+ */
+public class VcnManagementService extends IVcnManagementService.Stub {
+    @NonNull private static final String TAG = VcnManagementService.class.getSimpleName();
+
+    public static final boolean VDBG = false; // STOPSHIP: if true
+
+    /* Binder context for this service */
+    @NonNull private final Context mContext;
+    @NonNull private final Dependencies mDeps;
+
+    private VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) {
+        mContext = requireNonNull(context, "Missing context");
+        mDeps = requireNonNull(deps, "Missing dependencies");
+    }
+
+    // Package-visibility for SystemServer to create instances.
+    static VcnManagementService create(@NonNull Context context) {
+        return new VcnManagementService(context, new Dependencies());
+    }
+
+    private static class Dependencies {}
+
+    /** Notifies the VcnManagementService that external dependencies can be set up */
+    public void systemReady() {}
+}
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 26356b4..3d22d6d 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -30,7 +30,6 @@
 import android.net.NetworkSpecifier;
 import android.net.TelephonyNetworkSpecifier;
 import android.net.wifi.WifiInfo;
-import android.os.UserHandle;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -75,8 +74,11 @@
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
+    // The context is for the current user (system server)
     private final Context mContext;
     private final TelephonyManager mTelephonyManager;
+    // The notification manager is created from a context for User.ALL, so notifications
+    // will be sent to all users.
     private final NotificationManager mNotificationManager;
     // Tracks the types of notifications managed by this instance, from creation to cancellation.
     private final SparseIntArray mNotificationTypeMap;
@@ -282,7 +284,7 @@
 
         mNotificationTypeMap.put(id, eventId);
         try {
-            mNotificationManager.notifyAsUser(tag, eventId, notification, UserHandle.ALL);
+            mNotificationManager.notify(tag, eventId, notification);
         } catch (NullPointerException npe) {
             Slog.d(TAG, "setNotificationVisible: visible notificationManager error", npe);
         }
@@ -311,7 +313,7 @@
                    nameOf(eventId)));
         }
         try {
-            mNotificationManager.cancelAsUser(tag, eventId, UserHandle.ALL);
+            mNotificationManager.cancel(tag, eventId);
         } catch (NullPointerException npe) {
             Slog.d(TAG, String.format(
                     "failed to clear notification tag=%s event=%s", tag, nameOf(eventId)), npe);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index a55df60..1a83272 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -199,6 +199,8 @@
     // automated reconnection
 
     private final Context mContext;
+    // The context is for specific user which is created from mUserId
+    private final Context mUserIdContext;
     @VisibleForTesting final Dependencies mDeps;
     private final NetworkInfo mNetworkInfo;
     private int mLegacyState;
@@ -399,6 +401,7 @@
             int userId, @NonNull KeyStore keyStore, SystemServices systemServices,
             Ikev2SessionCreator ikev2SessionCreator) {
         mContext = context;
+        mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
         mDeps = deps;
         mNetd = netService;
         mUserId = userId;
@@ -1925,9 +1928,10 @@
         final UserHandle user = UserHandle.of(mUserId);
         final long token = Binder.clearCallingIdentity();
         try {
-            final NotificationManager notificationManager = NotificationManager.from(mContext);
+            final NotificationManager notificationManager =
+                    mUserIdContext.getSystemService(NotificationManager.class);
             if (!visible) {
-                notificationManager.cancelAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, user);
+                notificationManager.cancel(TAG, SystemMessage.NOTE_VPN_DISCONNECTED);
                 return;
             }
             final Intent intent = new Intent();
@@ -1947,8 +1951,7 @@
                             .setVisibility(Notification.VISIBILITY_PUBLIC)
                             .setOngoing(true)
                             .setColor(mContext.getColor(R.color.system_notification_accent_color));
-            notificationManager.notifyAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED,
-                    builder.build(), user);
+            notificationManager.notify(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, builder.build());
         } finally {
             Binder.restoreCallingIdentity(token);
         }
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 3a262d6..06cebac 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -65,6 +65,7 @@
 
     @NonNull private final Context mContext;
     @NonNull private final ConnectivityService mConnService;
+    @NonNull private final NotificationManager mNotificationManager;
     @NonNull private final Handler mHandler;
     @NonNull private final Vpn mVpn;
     @NonNull private final VpnProfile mProfile;
@@ -93,6 +94,7 @@
         mHandler = Objects.requireNonNull(handler);
         mVpn = Objects.requireNonNull(vpn);
         mProfile = Objects.requireNonNull(profile);
+        mNotificationManager = mContext.getSystemService(NotificationManager.class);
 
         final Intent configIntent = new Intent(ACTION_VPN_SETTINGS);
         mConfigIntent = PendingIntent.getActivity(mContext, 0 /* requestCode */, configIntent,
@@ -266,11 +268,11 @@
                         .setColor(mContext.getColor(
                                 com.android.internal.R.color.system_notification_accent_color));
 
-        NotificationManager.from(mContext).notify(null, SystemMessage.NOTE_VPN_STATUS,
+        mNotificationManager.notify(null /* tag */, SystemMessage.NOTE_VPN_STATUS,
                 builder.build());
     }
 
     private void hideNotification() {
-        NotificationManager.from(mContext).cancel(null, SystemMessage.NOTE_VPN_STATUS);
+        mNotificationManager.cancel(null, SystemMessage.NOTE_VPN_STATUS);
     }
 }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index cc8c751..ae693c7 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1018,6 +1018,7 @@
         IStorageManager storageManager = null;
         NetworkManagementService networkManagement = null;
         IpSecService ipSecService = null;
+        VcnManagementService vcnManagement = null;
         NetworkStatsService networkStats = null;
         NetworkPolicyManagerService networkPolicy = null;
         IConnectivityManager connectivity = null;
@@ -1453,6 +1454,15 @@
             }
             t.traceEnd();
 
+            t.traceBegin("StartVcnManagementService");
+            try {
+                vcnManagement = VcnManagementService.create(context);
+                ServiceManager.addService(Context.VCN_MANAGEMENT_SERVICE, vcnManagement);
+            } catch (Throwable e) {
+                reportWtf("starting VCN Management Service", e);
+            }
+            t.traceEnd();
+
             t.traceBegin("StartTextServicesManager");
             mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
             t.traceEnd();
@@ -2228,6 +2238,7 @@
         final MediaRouterService mediaRouterF = mediaRouter;
         final MmsServiceBroker mmsServiceF = mmsService;
         final IpSecService ipSecServiceF = ipSecService;
+        final VcnManagementService vcnManagementF = vcnManagement;
         final WindowManagerService windowManagerF = wm;
         final ConnectivityManager connectivityF = (ConnectivityManager)
                 context.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -2316,6 +2327,15 @@
                 reportWtf("making IpSec Service ready", e);
             }
             t.traceEnd();
+            t.traceBegin("MakeVcnManagementServiceReady");
+            try {
+                if (vcnManagementF != null) {
+                    vcnManagementF.systemReady();
+                }
+            } catch (Throwable e) {
+                reportWtf("making VcnManagementService ready", e);
+            }
+            t.traceEnd();
             t.traceBegin("MakeNetworkStatsServiceReady");
             try {
                 if (networkStatsF != null) {
diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index e57b030..7aecfdd 100644
--- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -124,11 +124,7 @@
     }
 
     private static boolean isUpdatedSystemApp(ApplicationInfo ai) {
-        if ((ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
-            return true;
-        }
-
-        return false;
+        return (ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
     }
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 23d450b..56c2500 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2802,7 +2802,11 @@
     /** Current network is LTE_CA {@hide} */
     @UnsupportedAppUsage
     public static final int NETWORK_TYPE_LTE_CA = TelephonyProtoEnums.NETWORK_TYPE_LTE_CA; // = 19.
-    /** Current network is NR(New Radio) 5G. */
+    /**
+     * Current network is NR (New Radio) 5G.
+     * This will only be returned for 5G SA.
+     * For 5G NSA, the network type will be {@link #NETWORK_TYPE_LTE}.
+     */
     public static final int NETWORK_TYPE_NR = TelephonyProtoEnums.NETWORK_TYPE_NR; // 20.
 
     private static final @NetworkType int[] NETWORK_TYPES = {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 3705aaa..3a46291 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -251,6 +251,7 @@
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.AdditionalAnswers;
 import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
 import org.mockito.Mock;
@@ -452,6 +453,13 @@
         }
 
         @Override
+        public Context createContextAsUser(UserHandle user, int flags) {
+            final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this));
+            doReturn(user).when(asUser).getUser();
+            return asUser;
+        }
+
+        @Override
         public ContentResolver getContentResolver() {
             return mContentResolver;
         }
@@ -4992,22 +5000,22 @@
         // simulate that situation and check if ConnectivityService could filter that case.
         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         waitForIdle();
-        verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
-                eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
+        verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notify(anyString(),
+                eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
         // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
         // shown.
         mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         waitForIdle();
-        verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
-                eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
+        verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancel(anyString(),
+                eq(NotificationType.PRIVATE_DNS_BROKEN.eventId));
         // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
         // shown again.
         mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         waitForIdle();
-        verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
-                eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
+        verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notify(anyString(),
+                eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index 47db5d4..fa4df4e 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -114,7 +114,7 @@
         final String tag = NetworkNotificationManager.tagFor(id);
         mManager.showNotification(id, PRIVATE_DNS_BROKEN, nai, null, null, true);
         verify(mNotificationManager, times(1))
-                .notifyAsUser(eq(tag), eq(PRIVATE_DNS_BROKEN.eventId), any(), any());
+                .notify(eq(tag), eq(PRIVATE_DNS_BROKEN.eventId), any());
         final int transportType = NetworkNotificationManager.approximateTransportType(nai);
         if (transportType == NetworkCapabilities.TRANSPORT_WIFI) {
             verify(mResources, times(1)).getString(title, eq(any()));
@@ -164,8 +164,8 @@
             final int id = ids.get(i);
             final int eventId = types.get(i).eventId;
             final String tag = NetworkNotificationManager.tagFor(id);
-            verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any());
-            verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(eventId), any());
+            verify(mNotificationManager, times(1)).notify(eq(tag), eq(eventId), any());
+            verify(mNotificationManager, times(1)).cancel(eq(tag), eq(eventId));
         }
     }
 
@@ -174,13 +174,13 @@
         mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false);
         mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false);
 
-        verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
 
         mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
 
         final int eventId = NO_INTERNET.eventId;
         final String tag = NetworkNotificationManager.tagFor(102);
-        verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any());
+        verify(mNotificationManager, times(1)).notify(eq(tag), eq(eventId), any());
     }
 
     @Test
@@ -191,7 +191,7 @@
         mManager.showNotification(103, LOST_INTERNET, mWifiNai, mCellNai, null, false);
         mManager.showNotification(104, NETWORK_SWITCH, mWifiNai, mCellNai, null, false);
 
-        verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
     }
 
     @Test
@@ -201,19 +201,16 @@
 
         // Show first NO_INTERNET
         mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
-        verify(mNotificationManager, times(1))
-                .notifyAsUser(eq(tag), eq(NO_INTERNET.eventId), any(), any());
+        verify(mNotificationManager, times(1)).notify(eq(tag), eq(NO_INTERNET.eventId), any());
 
         // Captive portal detection triggers SIGN_IN a bit later, clearing the previous NO_INTERNET
         mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
-        verify(mNotificationManager, times(1))
-                .cancelAsUser(eq(tag), eq(NO_INTERNET.eventId), any());
-        verify(mNotificationManager, times(1))
-                .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any());
+        verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId));
+        verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any());
 
         // Network disconnects
         mManager.clearNotification(id);
-        verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(SIGN_IN.eventId), any());
+        verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId));
     }
 
     @Test
@@ -223,18 +220,17 @@
 
         // Show first SIGN_IN
         mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
-        verify(mNotificationManager, times(1))
-                .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any());
+        verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any());
         reset(mNotificationManager);
 
         // NO_INTERNET arrives after, but is ignored.
         mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
-        verify(mNotificationManager, never()).cancelAsUser(any(), anyInt(), any());
-        verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
+        verify(mNotificationManager, never()).cancel(any(), anyInt());
+        verify(mNotificationManager, never()).notify(any(), anyInt(), any());
 
         // Network disconnects
         mManager.clearNotification(id);
-        verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(SIGN_IN.eventId), any());
+        verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId));
     }
 
     @Test
@@ -246,24 +242,20 @@
         // to previous type or not. If they are equal then clear the notification; if they are not
         // equal then return.
         mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
-        verify(mNotificationManager, times(1))
-                .notifyAsUser(eq(tag), eq(NO_INTERNET.eventId), any(), any());
+        verify(mNotificationManager, times(1)).notify(eq(tag), eq(NO_INTERNET.eventId), any());
 
         // Previous notification is NO_INTERNET and given type is NO_INTERNET too. The notification
         // should be cleared.
         mManager.clearNotification(id, NO_INTERNET);
-        verify(mNotificationManager, times(1))
-                .cancelAsUser(eq(tag), eq(NO_INTERNET.eventId), any());
+        verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId));
 
         // SIGN_IN is popped-up.
         mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
-        verify(mNotificationManager, times(1))
-                .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any());
+        verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any());
 
         // The notification type is not matching previous one, PARTIAL_CONNECTIVITY won't be
         // cleared.
         mManager.clearNotification(id, PARTIAL_CONNECTIVITY);
-        verify(mNotificationManager, never())
-                .cancelAsUser(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId), any());
+        verify(mNotificationManager, never()).cancel(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId));
     }
 }
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index daa2627..2fa0914 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -45,6 +45,7 @@
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -106,6 +107,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.AdditionalAnswers;
 import org.mockito.Answers;
 import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
@@ -215,6 +217,8 @@
         when(mContext.getOpPackageName()).thenReturn(TEST_VPN_PKG);
         when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
         when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps);
+        when(mContext.getSystemServiceName(NotificationManager.class))
+                .thenReturn(Context.NOTIFICATION_SERVICE);
         when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
                 .thenReturn(mNotificationManager);
         when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE)))
@@ -594,26 +598,23 @@
 
         // Don't show a notification for regular disconnected states.
         vpn.updateState(DetailedState.DISCONNECTED, TAG);
-        order.verify(mNotificationManager, atLeastOnce())
-                .cancelAsUser(anyString(), anyInt(), eq(userHandle));
+        order.verify(mNotificationManager, atLeastOnce()).cancel(anyString(), anyInt());
 
         // Start showing a notification for disconnected once always-on.
         vpn.setAlwaysOnPackage(PKGS[0], false, null, mKeyStore);
-        order.verify(mNotificationManager)
-                .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
+        order.verify(mNotificationManager).notify(anyString(), anyInt(), any());
 
         // Stop showing the notification once connected.
         vpn.updateState(DetailedState.CONNECTED, TAG);
-        order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
+        order.verify(mNotificationManager).cancel(anyString(), anyInt());
 
         // Show the notification if we disconnect again.
         vpn.updateState(DetailedState.DISCONNECTED, TAG);
-        order.verify(mNotificationManager)
-                .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
+        order.verify(mNotificationManager).notify(anyString(), anyInt(), any());
 
         // Notification should be cleared after unsetting always-on package.
         vpn.setAlwaysOnPackage(null, false, null, mKeyStore);
-        order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
+        order.verify(mNotificationManager).cancel(anyString(), anyInt());
     }
 
     @Test
@@ -1272,6 +1273,10 @@
      * Mock some methods of vpn object.
      */
     private Vpn createVpn(@UserIdInt int userId) {
+        final Context asUserContext = mock(Context.class, AdditionalAnswers.delegatesTo(mContext));
+        doReturn(UserHandle.of(userId)).when(asUserContext).getUser();
+        when(mContext.createContextAsUser(eq(UserHandle.of(userId)), anyInt()))
+                .thenReturn(asUserContext);
         return new Vpn(Looper.myLooper(), mContext, new TestDeps(), mNetService,
                 userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
     }