Merge "Surface "neverForLocation" through public API." into sc-dev
diff --git a/core/api/current.txt b/core/api/current.txt
index cb20f4b..9775e08 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6944,6 +6944,7 @@
     method @Nullable public String onChoosePrivateKeyAlias(@NonNull android.content.Context, @NonNull android.content.Intent, int, @Nullable android.net.Uri, @Nullable String);
     method public void onNetworkLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent, long, @IntRange(from=1) int);
     method public final void onReceive(@NonNull android.content.Context, @NonNull android.content.Intent);
+    method public void onSecurityLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent);
   }
 
   public final class DeviceAdminInfo implements android.os.Parcelable {
@@ -7021,6 +7022,7 @@
     field public static final String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
     field public static final String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
     field public static final String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.PROFILE_PROVISIONING_COMPLETE";
+    field public static final String ACTION_SECURITY_LOGS_AVAILABLE = "android.app.action.SECURITY_LOGS_AVAILABLE";
     field public static final int BUGREPORT_FAILURE_FAILED_COMPLETING = 0; // 0x0
     field public static final int BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE = 1; // 0x1
     field public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
@@ -7316,6 +7318,7 @@
     field public static final String DELEGATION_NETWORK_LOGGING = "delegation-network-logging";
     field public static final String DELEGATION_PACKAGE_ACCESS = "delegation-package-access";
     field public static final String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant";
+    field public static final String DELEGATION_SECURITY_LOGGING = "delegation-security-logging";
     field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
     field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3
     field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4
@@ -41805,7 +41808,7 @@
     method @NonNull public android.os.Bundle getCarrierConfigValues();
     method @Deprecated public static android.telephony.SmsManager getDefault();
     method public static int getDefaultSmsSubscriptionId();
-    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSmsCapacityOnIcc();
+    method @IntRange(from=0) @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public int getSmsCapacityOnIcc();
     method @Deprecated public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS) public void getSmsMessagesForFinancialApp(android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.SmsManager.FinancialSmsCallback);
     method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSmscAddress();
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index c812e8e..f7a3514 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -450,6 +450,21 @@
     public abstract boolean hasRunningForegroundService(int uid, int foregroundServiceType);
 
     /**
+     * Returns {@code true} if the given notification channel currently has a
+     * notification associated with a foreground service.  This is an AMS check
+     * because that is the source of truth for the FGS state.
+     */
+    public abstract boolean hasForegroundServiceNotification(String pkg, @UserIdInt int userId,
+            String channelId);
+
+    /**
+     * If the given app has any FGSs whose notifications are in the given channel,
+     * stop them.
+     */
+    public abstract void stopForegroundServicesForChannel(String pkg, @UserIdInt int userId,
+            String channelId);
+
+    /**
      * Registers the specified {@code processObserver} to be notified of future changes to
      * process state.
      */
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 60506b5..f4e214c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -12423,10 +12423,6 @@
          */
         public static final int DECORATION_FULL_CONSTRAINED = 4;
 
-        private static final boolean DEFAULT_BACKPORT_S_NOTIF_RULES = false;
-        private static final int DEFAULT_FULLY_CUSTOM_DECORATION = DECORATION_MINIMAL;
-        private static final int DEFAULT_DECORATED_DECORATION = DECORATION_PARTIAL;
-
         /**
          * Used by unit tests to force that this class returns its default values, which is required
          * in cases where the ContentResolver instance is a mock.
@@ -12439,11 +12435,7 @@
          * @hide
          */
         public static boolean shouldBackportSNotifRules(@NonNull ContentResolver contentResolver) {
-            if (sForceDefaults) {
-                return DEFAULT_BACKPORT_S_NOTIF_RULES;
-            }
-            return Settings.Global.getInt(contentResolver, Settings.Global.BACKPORT_S_NOTIF_RULES,
-                        DEFAULT_BACKPORT_S_NOTIF_RULES ? 1 : 0) == 1;
+            return false;
         }
 
         /**
@@ -12452,14 +12444,7 @@
          */
         public static int getFullyCustomViewNotifDecoration(
                 @NonNull ContentResolver contentResolver) {
-            if (sForceDefaults) {
-                return DEFAULT_FULLY_CUSTOM_DECORATION;
-            }
-            final int decoration = Settings.Global.getInt(contentResolver,
-                    Settings.Global.FULLY_CUSTOM_VIEW_NOTIF_DECORATION,
-                    DEFAULT_FULLY_CUSTOM_DECORATION);
-            // clamp to a valid decoration value
-            return Math.max(DECORATION_NONE, Math.min(decoration, DECORATION_FULL_CONSTRAINED));
+            return DECORATION_MINIMAL;
         }
 
         /**
@@ -12468,14 +12453,7 @@
          */
         public static int getDecoratedCustomViewNotifDecoration(
                 @NonNull ContentResolver contentResolver) {
-            if (sForceDefaults) {
-                return DEFAULT_DECORATED_DECORATION;
-            }
-            final int decoration = Settings.Global.getInt(contentResolver,
-                    Settings.Global.DECORATED_CUSTOM_VIEW_NOTIF_DECORATION,
-                    DEFAULT_DECORATED_DECORATION);
-            // clamp to a valid decoration value (and don't allow decoration to be NONE or MINIMAL)
-            return Math.max(DECORATION_PARTIAL, Math.min(decoration, DECORATION_FULL_CONSTRAINED));
+            return DECORATION_PARTIAL;
         }
     }
 }
diff --git a/core/java/android/app/admin/DelegatedAdminReceiver.java b/core/java/android/app/admin/DelegatedAdminReceiver.java
index 25b8eab..36097c9 100644
--- a/core/java/android/app/admin/DelegatedAdminReceiver.java
+++ b/core/java/android/app/admin/DelegatedAdminReceiver.java
@@ -18,6 +18,7 @@
 
 import static android.app.admin.DeviceAdminReceiver.ACTION_CHOOSE_PRIVATE_KEY_ALIAS;
 import static android.app.admin.DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE;
+import static android.app.admin.DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE;
 import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_ALIAS;
 import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID;
 import static android.app.admin.DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_URI;
@@ -115,6 +116,29 @@
     }
 
     /**
+     * Called each time a new batch of security logs can be retrieved. This callback method will
+     * only ever be called when security logging is enabled. The logs can only be retrieved while
+     * security logging is enabled.
+     *
+     * <p>If a secondary user or profile is created, this callback won't be received until all users
+     * become affiliated again (even if security logging is enabled). It will also no longer be
+     * possible to retrieve the security logs. See {@link DevicePolicyManager#setAffiliationIds}.
+     *
+     * <p> This callback is only applicable if the delegated app has
+     * {@link DevicePolicyManager#DELEGATION_SECURITY_LOGGING} capability. Additionally, it must
+     * declare an intent filter for {@link DeviceAdminReceiver#ACTION_SECURITY_LOGS_AVAILABLE} in
+     * the receiver's manifest in order to receive this callback. The default implementation
+     * simply throws {@link UnsupportedOperationException}.
+     *
+     * @param context The running context as per {@link #onReceive}.
+     * @param intent The received intent as per {@link #onReceive}.
+     * @see DevicePolicyManager#retrieveSecurityLogs
+     */
+    public void onSecurityLogsAvailable(@NonNull Context context, @NonNull Intent intent) {
+        throw new UnsupportedOperationException("onSecurityLogsAvailable should be implemented");
+    }
+
+    /**
      * Intercept delegated device administrator broadcasts. Implementations should not override
      * this method; implement the convenience callbacks for each action instead.
      */
@@ -132,6 +156,8 @@
             long batchToken = intent.getLongExtra(EXTRA_NETWORK_LOGS_TOKEN, -1);
             int networkLogsCount = intent.getIntExtra(EXTRA_NETWORK_LOGS_COUNT, 0);
             onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount);
+        } else if (ACTION_SECURITY_LOGS_AVAILABLE.equals(action)) {
+            onSecurityLogsAvailable(context, intent);
         } else {
             Log.w(TAG, "Unhandled broadcast: " + action);
         }
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index cccc929..747a2de 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -290,7 +290,6 @@
 
     /**
      * Broadcast action: notify that a new batch of security logs is ready to be collected.
-     * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     @BroadcastBehavior(explicitOnly = true)
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 594b005..426159f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1905,6 +1905,20 @@
     public static final String DELEGATION_CERT_SELECTION = "delegation-cert-selection";
 
     /**
+     * Grants access to {@link #setSecurityLoggingEnabled}, {@link #isSecurityLoggingEnabled},
+     * {@link #retrieveSecurityLogs}, and {@link #retrievePreRebootSecurityLogs}. Once granted the
+     * delegated app will start receiving {@link DelegatedAdminReceiver#onSecurityLogsAvailable}
+     * callback, and Device owner or Profile Owner will no longer receive the
+     * {@link DeviceAdminReceiver#onSecurityLogsAvailable} callback. There can be at most one app
+     * that has this delegation. If another app already had delegated security logging access, it
+     * will lose the delegation when a new app is delegated.
+     *
+     * <p> Can only be granted by Device Owner or Profile Owner of an organnization owned and
+     * managed profile.
+     */
+    public static final String DELEGATION_SECURITY_LOGGING = "delegation-security-logging";
+
+    /**
      * No management for current user in-effect. This is the default.
      * @hide
      */
@@ -11241,7 +11255,7 @@
     public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
         throwIfParentInstance("setSecurityLoggingEnabled");
         try {
-            mService.setSecurityLoggingEnabled(admin, enabled);
+            mService.setSecurityLoggingEnabled(admin, mContext.getPackageName(), enabled);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -11260,7 +11274,7 @@
     public boolean isSecurityLoggingEnabled(@Nullable ComponentName admin) {
         throwIfParentInstance("isSecurityLoggingEnabled");
         try {
-            return mService.isSecurityLoggingEnabled(admin);
+            return mService.isSecurityLoggingEnabled(admin, mContext.getPackageName());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -11285,10 +11299,12 @@
      * @see #isAffiliatedUser
      * @see DeviceAdminReceiver#onSecurityLogsAvailable
      */
+    @SuppressLint("NullableCollection")
     public @Nullable List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
         throwIfParentInstance("retrieveSecurityLogs");
         try {
-            ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin);
+            ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(
+                    admin, mContext.getPackageName());
             if (list != null) {
                 return list.getList();
             } else {
@@ -11438,11 +11454,13 @@
      * @see #isAffiliatedUser
      * @see #retrieveSecurityLogs
      */
+    @SuppressLint("NullableCollection")
     public @Nullable List<SecurityEvent> retrievePreRebootSecurityLogs(
             @NonNull ComponentName admin) {
         throwIfParentInstance("retrievePreRebootSecurityLogs");
         try {
-            ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(admin);
+            ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(
+                    admin, mContext.getPackageName());
             if (list != null) {
                 return list.getList();
             } else {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index e98720c..7901791 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -386,10 +386,10 @@
     List<String> getAffiliationIds(in ComponentName admin);
     boolean isAffiliatedUser();
 
-    void setSecurityLoggingEnabled(in ComponentName admin, boolean enabled);
-    boolean isSecurityLoggingEnabled(in ComponentName admin);
-    ParceledListSlice retrieveSecurityLogs(in ComponentName admin);
-    ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin);
+    void setSecurityLoggingEnabled(in ComponentName admin, String packageName, boolean enabled);
+    boolean isSecurityLoggingEnabled(in ComponentName admin, String packageName);
+    ParceledListSlice retrieveSecurityLogs(in ComponentName admin, String packageName);
+    ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin, String packageName);
     long forceNetworkLogs();
     long forceSecurityLogs();
 
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 8fd0de7..a6b4b47 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -520,9 +520,7 @@
                 return;
             }
             int layoutId = rvToApply.getLayoutId();
-            // If our stale view has been prepared to match active, and the new
-            // layout matches, try recycling it
-            if (content == null && layoutId == mLayoutId) {
+            if (rvToApply.canRecycleView(mView)) {
                 try {
                     rvToApply.reapply(mContext, mView, mInteractionHandler, mCurrentSize,
                             mColorResources);
diff --git a/core/java/android/hardware/biometrics/ComponentInfoInternal.java b/core/java/android/hardware/biometrics/ComponentInfoInternal.java
index fa34e0b..3b61a56 100644
--- a/core/java/android/hardware/biometrics/ComponentInfoInternal.java
+++ b/core/java/android/hardware/biometrics/ComponentInfoInternal.java
@@ -27,11 +27,11 @@
  */
 public class ComponentInfoInternal implements Parcelable {
 
-    public final String componentId;
-    public final String hardwareVersion;
-    public final String firmwareVersion;
-    public final String serialNumber;
-    public final String softwareVersion;
+    @NonNull public final String componentId;
+    @NonNull public final String hardwareVersion;
+    @NonNull public final String firmwareVersion;
+    @NonNull public final String serialNumber;
+    @NonNull public final String softwareVersion;
 
     /**
      * Constructs a {@link ComponentInfoInternal} from another instance.
@@ -45,8 +45,9 @@
     /**
      * @hide
      */
-    public ComponentInfoInternal(String componentId, String hardwareVersion,
-            String firmwareVersion, String serialNumber, String softwareVersion) {
+    public ComponentInfoInternal(@NonNull String componentId, @NonNull String hardwareVersion,
+            @NonNull String firmwareVersion, @NonNull String serialNumber,
+            @NonNull String softwareVersion) {
         this.componentId = componentId;
         this.hardwareVersion = hardwareVersion;
         this.firmwareVersion = firmwareVersion;
diff --git a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java
index eda0ded..17b2abf 100644
--- a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java
+++ b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java
@@ -34,7 +34,7 @@
     public final int sensorId;
     @SensorProperties.Strength public final int sensorStrength;
     public final int maxEnrollmentsPerUser;
-    public final List<ComponentInfoInternal> componentInfo;
+    @NonNull public final List<ComponentInfoInternal> componentInfo;
     public final boolean resetLockoutRequiresHardwareAuthToken;
     public final boolean resetLockoutRequiresChallenge;
 
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index a3c6f2f..b7b1a14 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -2030,7 +2030,9 @@
                 // Tell listeners that the cameras and torch modes are unavailable and schedule a
                 // reconnection to camera service. When camera service is reconnected, the camera
                 // and torch statuses will be updated.
-                for (int i = 0; i < mDeviceStatus.size(); i++) {
+                // Iterate from the end to the beginning befcause onStatusChangedLocked removes
+                // entries from the ArrayMap.
+                for (int i = mDeviceStatus.size() - 1; i >= 0; i--) {
                     String cameraId = mDeviceStatus.keyAt(i);
                     onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, cameraId);
                 }
diff --git a/core/java/android/hardware/face/FaceSensorProperties.java b/core/java/android/hardware/face/FaceSensorProperties.java
index 6ddea50..f613127 100644
--- a/core/java/android/hardware/face/FaceSensorProperties.java
+++ b/core/java/android/hardware/face/FaceSensorProperties.java
@@ -17,6 +17,7 @@
 package android.hardware.face;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.hardware.biometrics.ComponentInfoInternal;
 import android.hardware.biometrics.SensorProperties;
 
@@ -74,7 +75,8 @@
      * @hide
      */
     public FaceSensorProperties(int sensorId, int sensorStrength,
-            List<ComponentInfo> componentInfo, @FaceSensorProperties.SensorType int sensorType) {
+            @NonNull List<ComponentInfo> componentInfo,
+            @FaceSensorProperties.SensorType int sensorType) {
         super(sensorId, sensorStrength, componentInfo);
         mSensorType = sensorType;
     }
diff --git a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java
index 50ea60a2..44dffb2 100644
--- a/core/java/android/hardware/face/FaceSensorPropertiesInternal.java
+++ b/core/java/android/hardware/face/FaceSensorPropertiesInternal.java
@@ -16,6 +16,7 @@
 
 package android.hardware.face;
 
+import android.annotation.NonNull;
 import android.hardware.biometrics.ComponentInfoInternal;
 import android.hardware.biometrics.SensorProperties;
 import android.hardware.biometrics.SensorPropertiesInternal;
@@ -48,7 +49,7 @@
      * Initializes SensorProperties with specified values
      */
     public FaceSensorPropertiesInternal(int sensorId, @SensorProperties.Strength int strength,
-            int maxEnrollmentsPerUser, List<ComponentInfoInternal> componentInfo,
+            int maxEnrollmentsPerUser, @NonNull List<ComponentInfoInternal> componentInfo,
             @FaceSensorProperties.SensorType int sensorType, boolean supportsFaceDetection,
             boolean supportsSelfIllumination, boolean resetLockoutRequiresChallenge) {
         // resetLockout is managed by the HAL and requires a HardwareAuthToken for all face
diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java b/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java
index a338575..71b705f 100644
--- a/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java
+++ b/core/java/android/hardware/fingerprint/FingerprintSensorProperties.java
@@ -17,6 +17,7 @@
 package android.hardware.fingerprint;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.hardware.biometrics.ComponentInfoInternal;
 import android.hardware.biometrics.SensorProperties;
 
@@ -94,7 +95,7 @@
      * @hide
      */
     public FingerprintSensorProperties(int sensorId, int sensorStrength,
-            List<ComponentInfo> componentInfo, @SensorType int sensorType) {
+            @NonNull List<ComponentInfo> componentInfo, @SensorType int sensorType) {
         super(sensorId, sensorStrength, componentInfo);
         mSensorType = sensorType;
     }
diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
index 1b13370..58f6e62 100644
--- a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
+++ b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
@@ -62,7 +62,7 @@
 
     public FingerprintSensorPropertiesInternal(int sensorId,
             @SensorProperties.Strength int strength, int maxEnrollmentsPerUser,
-            List<ComponentInfoInternal> componentInfo,
+            @NonNull List<ComponentInfoInternal> componentInfo,
             @FingerprintSensorProperties.SensorType int sensorType,
             boolean resetLockoutRequiresHardwareAuthToken, int sensorLocationX, int sensorLocationY,
             int sensorRadius) {
@@ -83,7 +83,7 @@
      */
     public FingerprintSensorPropertiesInternal(int sensorId,
             @SensorProperties.Strength int strength, int maxEnrollmentsPerUser,
-            List<ComponentInfoInternal> componentInfo,
+            @NonNull List<ComponentInfoInternal> componentInfo,
             @FingerprintSensorProperties.SensorType int sensorType,
             boolean resetLockoutRequiresHardwareAuthToken) {
         // TODO(b/179175438): Value should be provided from the HAL
@@ -99,7 +99,7 @@
     // TODO(b/179175438): Remove this constructor once all HALs move to AIDL.
     public FingerprintSensorPropertiesInternal(@NonNull Context context, int sensorId,
             @SensorProperties.Strength int strength, int maxEnrollmentsPerUser,
-            List<ComponentInfoInternal> componentInfo,
+            @NonNull List<ComponentInfoInternal> componentInfo,
             @FingerprintSensorProperties.SensorType int sensorType,
             boolean resetLockoutRequiresHardwareAuthToken) {
         super(sensorId, strength, maxEnrollmentsPerUser, componentInfo,
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index eaa8bd4..f69a7d7 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -60,8 +60,8 @@
     private static final String TAG = "ContextHubManager";
 
     /**
-     * An extra containing an int from {@link AuthorizationState} describing the client's
-     * authorization state.
+     * An extra containing one of the {@code AUTHORIZATION_*} constants such as
+     * {@link #AUTHORIZATION_GRANTED} describing the client's authorization state.
      */
     public static final String EXTRA_CLIENT_AUTHORIZATION_STATE =
             "android.hardware.location.extra.CLIENT_AUTHORIZATION_STATE";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f1c80af..71ffa92 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -15795,48 +15795,6 @@
         public static final String SHOW_NEW_NOTIF_DISMISS = "show_new_notif_dismiss";
 
         /**
-         * Whether to enforce the new notification rules (aka rules that are only applied to
-         * notifications from apps targeting S) on all notifications.
-         * - Collapsed custom view notifications will get the new 76dp height instead of 106dp.
-         * - Custom view notifications will be partially decorated.
-         * - Large icons will be given an aspect ratio of up to 16:9.
-         *
-         * Values are:
-         * 0: Disabled (Only apps targeting S will receive the new rules)
-         * 1: Enabled (All apps will receive the new rules)
-         * @hide
-         */
-        public static final String BACKPORT_S_NOTIF_RULES = "backport_s_notif_rules";
-
-        /**
-         * The decoration to put on fully custom views that target S.
-         *
-         * <p>Values are:
-         * <br>0: DECORATION_NONE: no decorations.
-         * <br>1: DECORATION_MINIMAL: most minimal template; just the icon and the expander.
-         * <br>2: DECORATION_PARTIAL: basic template without the top line.
-         * <br>3: DECORATION_FULL_COMPATIBLE: basic template with the top line; 40dp of height.
-         * <br>4: DECORATION_FULL_CONSTRAINED: basic template with the top line;  28dp of height.
-         * <p>See {@link android.app.Notification.DevFlags} for more details.
-         * @hide
-         */
-        public static final String FULLY_CUSTOM_VIEW_NOTIF_DECORATION =
-                "fully_custom_view_notif_decoration";
-
-        /**
-         * The decoration to put on decorated custom views that target S.
-         *
-         * <p>Values are:
-         * <br>2: DECORATION_PARTIAL: basic template without the top line.
-         * <br>3: DECORATION_FULL_COMPATIBLE: basic template with the top line; 40dp of height.
-         * <br>4: DECORATION_FULL_CONSTRAINED: basic template with the top line;  28dp of height.
-         * <p>See {@link android.app.Notification.DevFlags} for more details.
-         * @hide
-         */
-        public static final String DECORATED_CUSTOM_VIEW_NOTIF_DECORATION =
-                "decorated_custom_view_notif_decoration";
-
-        /**
          * Block untrusted touches mode.
          *
          * Can be one of:
diff --git a/core/java/android/util/Slog.java b/core/java/android/util/Slog.java
index f61ab29..d3eaeae 100644
--- a/core/java/android/util/Slog.java
+++ b/core/java/android/util/Slog.java
@@ -30,11 +30,11 @@
  */
 public final class Slog {
 
-    @GuardedBy("sMessageBuilder")
-    private static final StringBuilder sMessageBuilder = new StringBuilder();
+    @GuardedBy("Slog.class")
+    private static StringBuilder sMessageBuilder;
 
-    @GuardedBy("sMessageBuilder")
-    private static final Formatter sFormatter = new Formatter(sMessageBuilder, Locale.ENGLISH);
+    @GuardedBy("Slog.class")
+    private static Formatter sFormatter;
 
     private Slog() {
     }
@@ -226,7 +226,12 @@
     }
 
     private static String getMessage(String format, @Nullable Object... args) {
-        synchronized (sMessageBuilder) {
+        synchronized (Slog.class) {
+            if (sMessageBuilder == null) {
+                // Lazy load so they're not created if not used by the process
+                sMessageBuilder = new StringBuilder();
+                sFormatter = new Formatter(sMessageBuilder, Locale.ENGLISH);
+            }
             sFormatter.format(format, args);
             String message = sMessageBuilder.toString();
             sMessageBuilder.setLength(0);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 35d5d8e..7455b8b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import static android.content.res.Resources.ID_NULL;
+import static android.view.ContentInfo.SOURCE_DRAG_AND_DROP;
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
@@ -26747,6 +26748,21 @@
      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
      * in DragEvent. The method uses these to determine what is happening in the drag and drop
      * operation.
+     * </p>
+     * <p>
+     * The default implementation returns false, except if an {@link OnReceiveContentListener}
+     * is {@link #setOnReceiveContentListener set} for this view. If an
+     * {@link OnReceiveContentListener} is set, the default implementation...
+     * <ul>
+     * <li>returns true for an
+     * {@link android.view.DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event
+     * <li>calls {@link #performReceiveContent} for an
+     * {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event
+     * <li>returns true for an {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event, if
+     * the listener consumed some or all of the content
+     * </ul>
+     * </p>
+     *
      * @param event The {@link android.view.DragEvent} sent by the system.
      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
      * in DragEvent, indicating the type of drag event represented by this object.
@@ -26766,6 +26782,24 @@
      * </p>
      */
     public boolean onDragEvent(DragEvent event) {
+        if (mListenerInfo == null || mListenerInfo.mOnReceiveContentListener == null) {
+            return false;
+        }
+        // Accept drag events by default if there's an OnReceiveContentListener set.
+        if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
+            return true;
+        }
+        if (event.getAction() == DragEvent.ACTION_DROP) {
+            final DragAndDropPermissions permissions = DragAndDropPermissions.obtain(event);
+            if (permissions != null) {
+                permissions.takeTransient();
+            }
+            final ContentInfo payload = new ContentInfo.Builder(
+                    event.getClipData(), SOURCE_DRAG_AND_DROP).build();
+            ContentInfo remainingPayload = performReceiveContent(payload);
+            // Return true unless none of the payload was consumed.
+            return remainingPayload != payload;
+        }
         return false;
     }
 
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 5f55887..58dfc0d 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -117,12 +117,12 @@
     /**
      * The natural frequency of the stretch spring.
      */
-    private static final double NATURAL_FREQUENCY = 14.4222;
+    private static final double NATURAL_FREQUENCY = 17.55;
 
     /**
      * The damping ratio of the stretch spring.
      */
-    private static final double DAMPING_RATIO = 0.875;
+    private static final double DAMPING_RATIO = 0.92;
 
     /** @hide */
     @IntDef({TYPE_GLOW, TYPE_STRETCH})
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 2b73923..319e788 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -2196,7 +2196,7 @@
                 int recycledViewIndex = findViewIndexToRecycle(target, rvToApply);
                 if (recycledViewIndex >= 0) {
                     View child = target.getChildAt(recycledViewIndex);
-                    if (getViewLayoutId(child) == rvToApply.getLayoutId()) {
+                    if (rvToApply.canRecycleView(child)) {
                         if (nextChild < recycledViewIndex) {
                             target.removeViews(nextChild, recycledViewIndex - nextChild);
                         }
@@ -2254,7 +2254,7 @@
                     // application are placed before.
                     ViewTree recycled = target.mChildren.get(recycledViewIndex);
                     // We can only recycle the view if the layout id is the same.
-                    if (getViewLayoutId(recycled.mRoot) == rvToApply.getLayoutId()) {
+                    if (rvToApply.canRecycleView(recycled.mRoot)) {
                         if (recycledViewIndex > nextChild) {
                             target.removeChildren(nextChild, recycledViewIndex - nextChild);
                         }
@@ -3726,7 +3726,8 @@
      *
      * The {@code stableId} will be used to identify a potential view to recycled when the remote
      * view is inflated. Views can be re-used if inserted in the same order, potentially with
-     * some views appearing / disappearing.
+     * some views appearing / disappearing. To be recycled the view must not change the layout
+     * used to inflate it or its view id (see {@link RemoteViews#setViewId}).
      *
      * Note: if a view is re-used, all the actions will be re-applied on it. However, its properties
      * are not reset, so what was applied in previous round will have an effect. As a view may be
@@ -5116,6 +5117,7 @@
         View v = inflater.inflate(rv.getLayoutId(), parent, false);
         if (mViewId != View.NO_ID) {
             v.setId(mViewId);
+            v.setTagInternal(R.id.remote_views_override_id, mViewId);
         }
         v.setTagInternal(R.id.widget_frame, rv.getLayoutId());
         return v;
@@ -5335,6 +5337,24 @@
         reapply(context, v, handler, size, colorResources, true);
     }
 
+    /** @hide */
+    public boolean canRecycleView(@Nullable View v) {
+        if (v == null) {
+            return false;
+        }
+        Integer previousLayoutId = (Integer) v.getTag(R.id.widget_frame);
+        if (previousLayoutId == null) {
+            return false;
+        }
+        Integer overrideIdTag = (Integer) v.getTag(R.id.remote_views_override_id);
+        int overrideId = overrideIdTag == null ? View.NO_ID : overrideIdTag;
+        // If mViewId is View.NO_ID, we only recycle if overrideId is also View.NO_ID.
+        // Otherwise, it might be that, on a previous iteration, the view's ID was set to
+        // something else, and it should now be reset to the ID defined in the XML layout file,
+        // whatever it is.
+        return previousLayoutId == getLayoutId() && mViewId == overrideId;
+    }
+
     // Note: topLevel should be true only for calls on the topLevel RemoteViews, internal calls
     // should set it to false.
     private void reapply(Context context, View v, InteractionHandler handler, SizeF size,
@@ -5347,7 +5367,7 @@
         // (orientation or size), we throw an exception, since the layouts may be completely
         // unrelated.
         if (hasMultipleLayouts()) {
-            if ((Integer) v.getTag(R.id.widget_frame) != rvToApply.getLayoutId()) {
+            if (!rvToApply.canRecycleView(v)) {
                 throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" +
                         " that does not share the same root layout id.");
             }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index dba7fa9..940a3c9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -13071,11 +13071,37 @@
         return getLayout().getOffsetForHorizontal(line, x);
     }
 
+    /**
+     * Handles drag events sent by the system following a call to
+     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
+     * startDragAndDrop()}.
+     *
+     * <p>If this text view is not editable, delegates to the default {@link View#onDragEvent}
+     * implementation.
+     *
+     * <p>If this text view is editable, accepts all drag actions (returns true for an
+     * {@link android.view.DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event and all
+     * subsequent drag events). While the drag is in progress, updates the cursor position
+     * to follow the touch location. Once a drop event is received, handles content insertion
+     * via {@link #performReceiveContent}.
+     *
+     * @param event The {@link android.view.DragEvent} sent by the system.
+     * The {@link android.view.DragEvent#getAction()} method returns an action type constant
+     * defined in DragEvent, indicating the type of drag event represented by this object.
+     * @return Returns true if this text view is editable and delegates to super otherwise.
+     * See {@link View#onDragEvent}.
+     */
     @Override
     public boolean onDragEvent(DragEvent event) {
+        if (mEditor == null || !mEditor.hasInsertionController()) {
+            // If this TextView is not editable, defer to the default View implementation. This
+            // will check for the presence of an OnReceiveContentListener and accept/reject
+            // drag events depending on whether the listener is/isn't set.
+            return super.onDragEvent(event);
+        }
         switch (event.getAction()) {
             case DragEvent.ACTION_DRAG_STARTED:
-                return mEditor != null && mEditor.hasInsertionController();
+                return true;
 
             case DragEvent.ACTION_DRAG_ENTERED:
                 TextView.this.requestFocus();
diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS
index 7ade05c..e6c911e 100644
--- a/core/java/com/android/internal/app/OWNERS
+++ b/core/java/com/android/internal/app/OWNERS
@@ -3,6 +3,9 @@
 per-file *Chooser* = file:/packages/SystemUI/OWNERS
 per-file SimpleIconFactory.java = file:/packages/SystemUI/OWNERS
 per-file NetInitiatedActivity.java = file:/location/java/android/location/OWNERS
-per-file IVoice* = file:/core/java/android/service/voice/OWNERS
-per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
 per-file *BatteryStats* = file:/BATTERY_STATS_OWNERS
+
+# Voice Interaction
+per-file *Assist* = file:/core/java/android/service/voice/OWNERS
+per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
+per-file *Voice* = file:/core/java/android/service/voice/OWNERS
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index 6f377b9..93cde3d 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -353,8 +353,8 @@
         mTouchSlop = configuration.getScaledPagingTouchSlop();
         mMinimumVelocity = (int) (MIN_FLING_VELOCITY * density);
         mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
-        mLeftEdge = new EdgeEffect(context);
-        mRightEdge = new EdgeEffect(context);
+        mLeftEdge = new EdgeEffect(context, attrs);
+        mRightEdge = new EdgeEffect(context, attrs);
 
         mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density);
         mCloseEnough = (int) (CLOSE_ENOUGH * density);
@@ -387,6 +387,28 @@
     }
 
     /**
+     * Returns the {@link EdgeEffect#getType()} for the edge effects.
+     * @return the {@link EdgeEffect#getType()} for the edge effects.
+     * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+     */
+    @EdgeEffect.EdgeEffectType
+    public int getEdgeEffectType() {
+        // Both left and right edge have the same edge effect type
+        return mLeftEdge.getType();
+    }
+
+    /**
+     * Sets the {@link EdgeEffect#setType(int)} for the edge effects.
+     * @param type The edge effect type to use for the edge effects.
+     * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+     */
+    public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) {
+        mLeftEdge.setType(type);
+        mRightEdge.setType(type);
+        invalidate();
+    }
+
+    /**
      * Set a PagerAdapter that will supply views for this pager as needed.
      *
      * @param adapter Adapter to use
@@ -1891,7 +1913,7 @@
                 }
                 if (mIsBeingDragged) {
                     // Scroll to follow the motion event
-                    if (performDrag(x)) {
+                    if (performDrag(x, y)) {
                         postInvalidateOnAnimation();
                     }
                 }
@@ -1918,6 +1940,17 @@
                     mIsBeingDragged = true;
                     requestParentDisallowInterceptTouchEvent(true);
                     setScrollState(SCROLL_STATE_DRAGGING);
+                } else if (mLeftEdge.getDistance() != 0
+                        || mRightEdge.getDistance() != 0) {
+                    // Caught the edge glow animation
+                    mIsBeingDragged = true;
+                    setScrollState(SCROLL_STATE_DRAGGING);
+                    if (mLeftEdge.getDistance() != 0) {
+                        mLeftEdge.onPullDistance(0f, 1 - mLastMotionY / getHeight());
+                    }
+                    if (mRightEdge.getDistance() != 0) {
+                        mRightEdge.onPullDistance(0f, mLastMotionY / getHeight());
+                    }
                 } else {
                     completeScroll(false);
                     mIsBeingDragged = false;
@@ -2009,7 +2042,7 @@
                     // Scroll to follow the motion event
                     final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
                     final float x = ev.getX(activePointerIndex);
-                    needsInvalidate |= performDrag(x);
+                    needsInvalidate |= performDrag(x, ev.getY(activePointerIndex));
                 }
                 break;
             case MotionEvent.ACTION_UP:
@@ -2080,12 +2113,43 @@
         }
     }
 
-    private boolean performDrag(float x) {
+    /**
+     * If either of the horizontal edge glows are currently active, this consumes part or all of
+     * deltaX on the edge glow.
+     *
+     * @param deltaX The pointer motion, in pixels, in the horizontal direction, positive
+     *                         for moving down and negative for moving up.
+     * @param y The vertical position of the pointer.
+     * @return The amount of <code>deltaX</code> that has been consumed by the
+     * edge glow.
+     */
+    private float releaseHorizontalGlow(float deltaX, float y) {
+        // First allow releasing existing overscroll effect:
+        float consumed = 0;
+        float displacement = y / getHeight();
+        float pullDistance = (float) deltaX / getWidth();
+        if (mLeftEdge.getDistance() != 0) {
+            consumed = -mLeftEdge.onPullDistance(-pullDistance, 1 - displacement);
+        } else if (mRightEdge.getDistance() != 0) {
+            consumed = mRightEdge.onPullDistance(pullDistance, displacement);
+        }
+        return consumed * getWidth();
+    }
+
+    private boolean performDrag(float x, float y) {
         boolean needsInvalidate = false;
 
+        final float dX = mLastMotionX - x;
         final int width = getPaddedWidth();
-        final float deltaX = mLastMotionX - x;
         mLastMotionX = x;
+        final float releaseConsumed = releaseHorizontalGlow(dX, y);
+        final float deltaX = dX - releaseConsumed;
+        if (releaseConsumed != 0) {
+            needsInvalidate = true;
+        }
+        if (Math.abs(deltaX) < 0.0001f) { // ignore rounding errors from releaseHorizontalGlow()
+            return needsInvalidate;
+        }
 
         final EdgeEffect startEdge;
         final EdgeEffect endEdge;
@@ -2128,14 +2192,14 @@
         if (scrollStart < startBound) {
             if (startAbsolute) {
                 final float over = startBound - scrollStart;
-                startEdge.onPull(Math.abs(over) / width);
+                startEdge.onPullDistance(over / width, 1 - y / getHeight());
                 needsInvalidate = true;
             }
             clampedScrollStart = startBound;
         } else if (scrollStart > endBound) {
             if (endAbsolute) {
                 final float over = scrollStart - endBound;
-                endEdge.onPull(Math.abs(over) / width);
+                endEdge.onPullDistance(over / width, y / getHeight());
                 needsInvalidate = true;
             }
             clampedScrollStart = endBound;
@@ -2228,7 +2292,9 @@
      */
     private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) {
         int targetPage;
-        if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity) {
+        if (Math.abs(deltaX) > mFlingDistance && Math.abs(velocity) > mMinimumVelocity
+                && mLeftEdge.getDistance() == 0 // don't fling while stretched
+                && mRightEdge.getDistance() == 0) {
             targetPage = currentPage - (velocity < 0 ? mLeftIncr : 0);
         } else {
             final float truncator = currentPage >= mCurItem ? 0.4f : 0.6f;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d88f259..45fd96a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4824,7 +4824,7 @@
          TODO(159952358): STOPSHIP: This must be updated to the new "internal" protectionLevel
     -->
     <permission android:name="android.permission.DOMAIN_VERIFICATION_AGENT"
-        android:protectionLevel="signature|privileged" />
+        android:protectionLevel="internal|privileged" />
 
     <!-- @SystemApi @hide Must be required by the domain verification agent's intent
          BroadcastReceiver, to ensure that only the system can interact with it.
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 7bc4663..c3b35c8 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -252,5 +252,8 @@
   <item type="id" name="remote_views_next_child" />
 
   <!-- View tag associating a view with its stable id for potential recycling. -->
-  <item type="id" name = "remote_views_stable_id" />
+  <item type="id" name="remote_views_stable_id" />
+
+  <!-- View tag associating a view with its overridden id, to ensure valid recycling only. -->
+  <item type="id" name="remote_views_override_id" />
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 541c18c..cdeb71c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4324,8 +4324,11 @@
   <java-symbol type="bool" name="config_cecRcProfileSourceMediaContextSensitiveMenuNotHandled_allowed" />
   <java-symbol type="bool" name="config_cecRcProfileSourceMediaContextSensitiveMenuNotHandled_default" />
 
+  <!-- Ids for RemoteViews -->
   <java-symbol type="id" name="remote_views_next_child" />
   <java-symbol type="id" name="remote_views_stable_id" />
+  <java-symbol type="id" name="remote_views_override_id" />
+
   <!-- View and control prompt -->
   <java-symbol type="drawable" name="ic_accessibility_24dp" />
   <java-symbol type="string" name="view_and_control_notification_title" />
diff --git a/core/tests/coretests/BstatsTestApp/AndroidManifest.xml b/core/tests/coretests/BstatsTestApp/AndroidManifest.xml
index 1e6bdc6..fcb1e71 100644
--- a/core/tests/coretests/BstatsTestApp/AndroidManifest.xml
+++ b/core/tests/coretests/BstatsTestApp/AndroidManifest.xml
@@ -19,7 +19,7 @@
 
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
 
-    <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="25"/>
+    <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="26"/>
 
     <application>
         <activity android:name=".TestActivity"
diff --git a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
index 4fe7d70..13d529c 100644
--- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
@@ -124,6 +124,7 @@
         sContext.getPackageManager().setApplicationEnabledSetting(TEST_PKG,
                 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
         sTestPkgUid = sContext.getPackageManager().getPackageUid(TEST_PKG, 0);
+        executeCmd("cmd deviceidle whitelist +" + TEST_PKG);
 
         final ArrayMap<String, String> desiredConstants = new ArrayMap<>();
         desiredConstants.put(KEY_TRACK_CPU_TIMES_BY_PROC_STATE, Boolean.toString(true));
@@ -134,6 +135,7 @@
 
     @AfterClass
     public static void tearDownOnce() throws Exception {
+        executeCmd("cmd deviceidle whitelist -" + TEST_PKG);
         if (sBatteryStatsConstsUpdated) {
             Settings.Global.putString(sContext.getContentResolver(),
                     Settings.Global.BATTERY_STATS_CONSTANTS, sOriginalBatteryStatsConsts);
@@ -382,7 +384,7 @@
     }
 
     @Test
-    @SkipPresubmit("b/180015146 flakey")
+    @SkipPresubmit("b/183225190 flaky")
     public void testCpuFreqTimes_stateFgService() throws Exception {
         if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
             Log.w(TAG, "Skipping " + testName.getMethodName()
@@ -515,7 +517,6 @@
     }
 
     @Test
-    @SkipPresubmit("b/180015146")
     public void testCpuFreqTimes_trackingDisabled() throws Exception {
         if (!sCpuFreqTimesAvailable || !sPerProcStateTimesAvailable) {
             Log.w(TAG, "Skipping " + testName.getMethodName()
@@ -625,7 +626,7 @@
         splitter.setString(settingsDump);
         String next;
         while (splitter.hasNext()) {
-            next = splitter.next();
+            next = splitter.next().trim();
             if (next.startsWith(key)) {
                 return next.split("=")[1];
             }
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 9b124ce..1924e5f 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -493,6 +493,8 @@
         <!-- Permission required for hotword detection service CTS tests -->
         <permission name="android.permission.MANAGE_HOTWORD_DETECTION" />
         <permission name="android.permission.MANAGE_APP_HIBERNATION"/>
+        <!-- Permission required for CTS test - ResourceObserverNativeTest -->
+        <permission name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/drawable/RippleAnimationSession.java b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
index b57f7af..94d5c22 100644
--- a/graphics/java/android/graphics/drawable/RippleAnimationSession.java
+++ b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
@@ -26,8 +26,8 @@
 import android.graphics.Paint;
 import android.graphics.RecordingCanvas;
 import android.graphics.animation.RenderNodeAnimator;
-import android.util.ArraySet;
 import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
 import android.view.animation.PathInterpolator;
 
@@ -41,8 +41,8 @@
     private static final int ENTER_ANIM_DURATION = 450;
     private static final int EXIT_ANIM_DURATION = 300;
     private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
-    private static final TimeInterpolator PATH_INTERPOLATOR =
-            new PathInterpolator(.2f, 0, 0, 1f);
+    private static final Interpolator FAST_OUT_LINEAR_IN =
+            new PathInterpolator(0.4f, 0f, 1f, 1f);
     private Consumer<RippleAnimationSession> mOnSessionEnd;
     private final AnimationProperties<Float, Paint> mProperties;
     private AnimationProperties<CanvasProperty<Float>, CanvasProperty<Paint>> mCanvasProperties;
@@ -59,7 +59,7 @@
         mSparkle.addUpdateListener(anim -> {
             final long now = AnimationUtils.currentAnimationTimeMillis();
             final long elapsed = now - mStartTime - ENTER_ANIM_DURATION;
-            final float phase = (float) elapsed / 30000f;
+            final float phase = (float) elapsed / 800;
             mProperties.getShader().setNoisePhase(phase);
             notifyUpdate();
         });
@@ -174,7 +174,7 @@
     private void startAnimation(Animator expand) {
         expand.setDuration(ENTER_ANIM_DURATION);
         expand.addListener(new AnimatorListener(this));
-        expand.setInterpolator(LINEAR_INTERPOLATOR);
+        expand.setInterpolator(FAST_OUT_LINEAR_IN);
         expand.start();
         if (!mSparkle.isRunning()) {
             mSparkle.start();
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index fb2b9b3..d5711c8 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -914,7 +914,7 @@
         shader.setColor(color);
         shader.setOrigin(w / 2, y / 2);
         shader.setTouch(x, y);
-        shader.setResolution(w, h);
+        shader.setResolution(w, h, mState.mDensity);
         shader.setNoisePhase(0);
         shader.setRadius(radius);
         shader.setProgress(.0f);
diff --git a/graphics/java/android/graphics/drawable/RippleShader.java b/graphics/java/android/graphics/drawable/RippleShader.java
index ea9ba32..5dd250c 100644
--- a/graphics/java/android/graphics/drawable/RippleShader.java
+++ b/graphics/java/android/graphics/drawable/RippleShader.java
@@ -20,13 +20,15 @@
 import android.graphics.Color;
 import android.graphics.RuntimeShader;
 import android.graphics.Shader;
+import android.util.DisplayMetrics;
 
 final class RippleShader extends RuntimeShader {
     private static final String SHADER_UNIFORMS =  "uniform vec2 in_origin;\n"
             + "uniform vec2 in_touch;\n"
             + "uniform float in_progress;\n"
             + "uniform float in_maxRadius;\n"
-            + "uniform vec2 in_resolution;\n"
+            + "uniform vec2 in_resolutionScale;\n"
+            + "uniform vec2 in_noiseScale;\n"
             + "uniform float in_hasMask;\n"
             + "uniform float in_noisePhase;\n"
             + "uniform vec4 in_color;\n"
@@ -40,18 +42,15 @@
             + "}"
             + "const float PI = 3.1415926535897932384626;\n"
             + "\n"
-            + "float threshold(float v, float l, float h) {\n"
-            + "  return step(l, v) * (1.0 - step(h, v));\n"
-            + "}\n"
-            + "\n"
             + "float sparkles(vec2 uv, float t) {\n"
             + "  float n = triangleNoise(uv);\n"
             + "  float s = 0.0;\n"
             + "  for (float i = 0; i < 4; i += 1) {\n"
-            + "    float l = i * 0.25;\n"
-            + "    float h = l + 0.005;\n"
-            + "    float o = abs(sin(0.1 * PI * (t + i)));\n"
-            + "    s += threshold(n + o, l, h);\n"
+            + "    float l = i * 0.01;\n"
+            + "    float h = l + 0.1;\n"
+            + "    float o = smoothstep(n - l, h, n);\n"
+            + "    o *= abs(sin(PI * o * (t + 0.55 * i)));\n"
+            + "    s += o;\n"
             + "  }\n"
             + "  return saturate(s);\n"
             + "}\n"
@@ -83,7 +82,9 @@
             + "    vec2 center = mix(in_touch, in_origin, fadeIn);\n"
             + "    float ring = getRingMask(p, center, in_maxRadius, fadeIn);\n"
             + "    float alpha = min(fadeIn, 1. - fadeOutNoise);\n"
-            + "    float sparkle = sparkles(p, in_noisePhase) * ring * alpha;\n"
+            + "    vec2 uv = p * in_resolutionScale;\n"
+            + "    vec2 densityUv = uv - mod(uv, in_noiseScale);\n"
+            + "    float sparkle = sparkles(densityUv, in_noisePhase) * ring * alpha;\n"
             + "    float fade = min(fadeIn, 1. - fadeOutRipple);\n"
             + "    vec4 circle = in_color * (softCircle(p, center, in_maxRadius "
             + "      * fadeIn, 0.2) * fade);\n"
@@ -135,7 +136,10 @@
                 color.green(), color.blue(), color.alpha()});
     }
 
-    public void setResolution(float w, float h) {
-        setUniform("in_resolution", w, h);
+    public void setResolution(float w, float h, int density) {
+        float noiseScale = 0.8f;
+        float densityScale = density * DisplayMetrics.DENSITY_DEFAULT_SCALE * 0.5f * noiseScale;
+        setUniform("in_resolutionScale", new float[] {1f / w, 1f / h});
+        setUniform("in_noiseScale", new float[] {densityScale / w, densityScale / h});
     }
 }
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index d7112d6..0d61399 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -612,7 +612,9 @@
         }
 
         /**
-         * Sets the context the record belongs to.
+         * Sets the context the record belongs to. This context will be used to pull information,
+         * such as attribution tags, which will be associated with the AudioRecord. However, the
+         * context itself will not be retained by the AudioRecord.
          * @param context a non-null {@link Context} instance
          * @return the same Builder instance.
          */
diff --git a/packages/SettingsLib/TwoTargetPreference/Android.bp b/packages/SettingsLib/TwoTargetPreference/Android.bp
index f2e79b9..078e8c3 100644
--- a/packages/SettingsLib/TwoTargetPreference/Android.bp
+++ b/packages/SettingsLib/TwoTargetPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
 android_library {
     name: "SettingsLibTwoTargetPreference",
 
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index c520568..068efac 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -139,7 +139,6 @@
                     Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
                     Settings.Global.AUTOMATIC_POWER_SAVE_MODE,
                     Settings.Global.AVERAGE_TIME_TO_DISCHARGE,
-                    Settings.Global.BACKPORT_S_NOTIF_RULES,
                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
                     Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME,
                     Settings.Global.BROADCAST_BG_CONSTANTS,
@@ -217,7 +216,6 @@
                     Settings.Global.DEBUG_APP,
                     Settings.Global.DEBUG_VIEW_ATTRIBUTES,
                     Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE,
-                    Settings.Global.DECORATED_CUSTOM_VIEW_NOTIF_DECORATION,
                     Settings.Global.DEFAULT_DNS_SERVER,
                     Settings.Global.DEFAULT_INSTALL_LOCATION,
                     Settings.Global.DEFAULT_RESTRICT_BACKGROUND_DATA,
@@ -289,7 +287,6 @@
                     Settings.Global.WIFI_ON_WHEN_PROXY_DISCONNECTED,
                     Settings.Global.FSTRIM_MANDATORY_INTERVAL,
                     Settings.Global.FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED,
-                    Settings.Global.FULLY_CUSTOM_VIEW_NOTIF_DECORATION,
                     Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
                     Settings.Global.GLOBAL_HTTP_PROXY_HOST,
                     Settings.Global.GLOBAL_HTTP_PROXY_PAC,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 8d8e442..b86ae6d 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -435,6 +435,9 @@
 
     <uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION"/>
 
+    <!-- Permission required for CTS test - ResourceObserverNativeTest -->
+    <uses-permission android:name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 338aa3a..3904201 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -336,7 +336,7 @@
         </receiver>
 
         <activity android:name=".screenshot.LongScreenshotActivity"
-                  android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
+                  android:theme="@style/LongScreenshotActivity"
                   android:process=":screenshot"
                   android:exported="false"
                   android:finishOnTaskLaunch="true" />
diff --git a/packages/SystemUI/res/layout/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml
index 7ba28a8..19bcf95 100644
--- a/packages/SystemUI/res/layout/long_screenshot.xml
+++ b/packages/SystemUI/res/layout/long_screenshot.xml
@@ -24,51 +24,27 @@
 
     <Button
         android:id="@+id/save"
+        style="@android:style/Widget.DeviceDefault.Button.Colored"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="@string/save"
-        app:layout_constraintEnd_toStartOf="@id/cancel"
-        app:layout_constraintHorizontal_chainStyle="packed"
+        android:layout_marginLeft="8dp"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toTopOf="@id/guideline" />
+        app:layout_constraintBottom_toTopOf="@id/preview" />
 
-    <Button
-        android:id="@+id/cancel"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/cancel"
-        app:layout_constraintEnd_toStartOf="@id/edit"
-        app:layout_constraintStart_toEndOf="@id/save"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toTopOf="@id/guideline" />
-
-    <Button
-        android:id="@+id/edit"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/screenshot_edit_label"
-        app:layout_constraintEnd_toStartOf="@id/share"
-        app:layout_constraintStart_toEndOf="@id/cancel"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toTopOf="@id/guideline" />
-
-    <Button
+    <ImageButton
         android:id="@+id/share"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@*android:string/share"
+        style="@android:style/Widget.Material.Button.Borderless"
+        android:tint="?android:textColorPrimary"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:padding="6dp"
+        android:src="@drawable/ic_screenshot_share"
+        android:layout_marginRight="8dp"
         app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toEndOf="@+id/edit"
         app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toTopOf="@id/guideline" />
-
-    <androidx.constraintlayout.widget.Guideline
-        android:id="@+id/guideline"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        app:layout_constraintGuide_percent="0.1" />
+        app:layout_constraintBottom_toTopOf="@id/preview" />
 
     <ImageView
         android:id="@+id/preview"
@@ -78,7 +54,7 @@
         android:layout_marginHorizontal="48dp"
         app:layout_constrainedHeight="true"
         app:layout_constrainedWidth="true"
-        app:layout_constraintTop_toBottomOf="@id/guideline"
+        app:layout_constraintTop_toBottomOf="@id/save"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
@@ -93,7 +69,7 @@
         android:layout_marginBottom="42dp"
         app:layout_constrainedHeight="true"
         app:layout_constrainedWidth="true"
-        app:layout_constraintTop_toBottomOf="@id/guideline"
+        app:layout_constraintTop_toTopOf="@id/preview"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
@@ -110,7 +86,7 @@
         android:layout_width="200dp"
         android:layout_height="200dp"
         android:elevation="2dp"
-        app:layout_constraintTop_toBottomOf="@id/guideline"
+        app:layout_constraintTop_toTopOf="@id/preview"
         app:layout_constraintLeft_toLeftOf="parent"
         app:handleThickness="@dimen/screenshot_crop_handle_thickness"
         app:handleColor="@*android:color/accent_device_default"
@@ -119,5 +95,24 @@
         app:borderColor="#fff"
         />
 
+    <Button
+        android:id="@+id/edit"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="8dp"
+        style="@android:style/Widget.DeviceDefault.Button.Colored"
+        android:backgroundTint="?android:colorBackground"
+        android:drawableStart="@drawable/ic_screenshot_edit"
+        android:drawableTint="?android:textColorPrimary"
+        android:paddingStart="16dp"
+        android:paddingEnd="8dp"
+        android:paddingVertical="8dp"
+        android:textColor="?android:textColorPrimary"
+        android:text="@string/screenshot_edit_label"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+    />
+
 </androidx.constraintlayout.widget.ConstraintLayout>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index ff9ea01..4a661dc 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -610,6 +610,11 @@
         <item name="android:windowCloseOnTouchOutside">true</item>
     </style>
 
+    <!-- Screenshots -->
+    <style name="LongScreenshotActivity" parent="@android:style/Theme.DeviceDefault.DayNight">
+        <item name="android:windowNoTitle">true</item>
+    </style>
+
     <!-- Privacy dialog -->
     <style name="PrivacyDialog" parent="ScreenRecord">
         <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index b9f9b1bc..98b3fe4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -321,6 +321,7 @@
         mSensorProps = findFirstUdfps();
         // At least one UDFPS sensor exists
         checkArgument(mSensorProps != null);
+        mStatusBar.setSensorRect(getSensorLocation());
 
         mCoreLayoutParams = new WindowManager.LayoutParams(
                 // TODO(b/152419866): Use the UDFPS window type when it becomes available.
@@ -367,7 +368,8 @@
      */
     public RectF getSensorLocation() {
         // This is currently used to calculate the amount of space available for notifications
-        // on lockscreen. Keyguard is only shown in portrait mode for now, so this will need to
+        // on lockscreen and for the udfps light reveal animation on keyguard.
+        // Keyguard is only shown in portrait mode for now, so this will need to
         // be updated if that ever changes.
         return new RectF(mSensorProps.sensorLocationX - mSensorProps.sensorRadius,
                 mSensorProps.sensorLocationY - mSensorProps.sensorRadius,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index 31cdada..6a004c2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -76,7 +76,6 @@
 
     private ImageView mPreview;
     private View mSave;
-    private View mCancel;
     private View mEdit;
     private View mShare;
     private CropView mCropView;
@@ -117,7 +116,6 @@
 
         mPreview = requireViewById(R.id.preview);
         mSave = requireViewById(R.id.save);
-        mCancel = requireViewById(R.id.cancel);
         mEdit = requireViewById(R.id.edit);
         mShare = requireViewById(R.id.share);
         mCropView = requireViewById(R.id.crop_view);
@@ -125,7 +123,6 @@
         mCropView.setCropInteractionListener(mMagnifierView);
 
         mSave.setOnClickListener(this::onClicked);
-        mCancel.setOnClickListener(this::onClicked);
         mEdit.setOnClickListener(this::onClicked);
         mShare.setOnClickListener(this::onClicked);
 
@@ -313,7 +310,6 @@
 
     private void setButtonsEnabled(boolean enabled) {
         mSave.setEnabled(enabled);
-        mCancel.setEnabled(enabled);
         mEdit.setEnabled(enabled);
         mShare.setEnabled(enabled);
     }
@@ -350,8 +346,6 @@
         setButtonsEnabled(false);
         if (id == R.id.save) {
             startExport(PendingAction.SAVE);
-        } else if (id == R.id.cancel) {
-            finishAndRemoveTask();
         } else if (id == R.id.edit) {
             mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_EDIT);
             startExport(PendingAction.EDIT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
index c1feaca..563470d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
@@ -82,6 +82,31 @@
     }
 }
 
+class CircleReveal(
+    /** X-value of the circle center of the reveal. */
+    val centerX: Float,
+    /** Y-value of the circle center of the reveal. */
+    val centerY: Float,
+    /** Radius of initial state of circle reveal */
+    val startRadius: Float,
+    /** Radius of end state of circle reveal */
+    val endRadius: Float
+) : LightRevealEffect {
+    override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {
+        val interpolatedAmount = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(amount)
+        val fadeAmount =
+            LightRevealEffect.getPercentPastThreshold(interpolatedAmount, 0.75f)
+        val radius = startRadius + ((endRadius - startRadius) * interpolatedAmount)
+        scrim.revealGradientEndColorAlpha = 1f - fadeAmount
+        scrim.setRevealGradientBounds(
+            centerX - radius /* left */,
+            centerY - radius /* top */,
+            centerX + radius /* right */,
+            centerY + radius /* bottom */
+        )
+    }
+}
+
 class PowerButtonReveal(
     /** Approximate Y-value of the center of the power button on the physical device. */
     val powerButtonY: Float
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index e119907..3daa2b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -132,6 +132,7 @@
         mHiddenShelfIconSize = res.getDimensionPixelOffset(R.dimen.hidden_shelf_icon_size);
         mGapHeight = res.getDimensionPixelSize(R.dimen.qs_notification_padding);
 
+        mShelfIcons.setInNotificationIconShelf(true);
         if (!mShowNotificationShelf) {
             setVisibility(GONE);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 6b144c6..25de551 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -152,6 +152,7 @@
     private boolean mDozing;
     private boolean mOnLockScreen;
     private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
+    private boolean mInNotificationIconShelf;
     private boolean mChangingViewPositions;
     private int mAddAnimationStartIndex = -1;
     private int mCannedAnimationStartIndex = -1;
@@ -702,6 +703,10 @@
         mLockScreenMode = lockScreenMode;
     }
 
+    public void setInNotificationIconShelf(boolean inShelf) {
+        mInNotificationIconShelf = inShelf;
+    }
+
     public class IconState extends ViewState {
         public static final int NO_VALUE = NotificationIconContainer.NO_VALUE;
         public float iconAppearAmount = 1.0f;
@@ -813,7 +818,7 @@
                     }
                 }
                 icon.setVisibleState(visibleState, animationsAllowed);
-                icon.setIconColor(mThemedTextColorPrimary,
+                icon.setIconColor(mInNotificationIconShelf ? mThemedTextColorPrimary : iconColor,
                         needsCannedAnimation && animationsAllowed);
                 if (animate) {
                     animateTo(icon, animationProperties);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 427df5e..0e1fe22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -22,6 +22,7 @@
 import static android.app.StatusBarManager.WindowVisibleState;
 import static android.app.StatusBarManager.windowStateToString;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.InsetsState.containsType;
 import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -46,6 +47,7 @@
 import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
 import static com.android.wm.shell.bubbles.BubbleController.TASKBAR_CHANGED_BROADCAST;
 
+import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -74,6 +76,7 @@
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.graphics.PointF;
+import android.graphics.RectF;
 import android.media.AudioAttributes;
 import android.metrics.LogMaker;
 import android.net.Uri;
@@ -179,6 +182,7 @@
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.AutoHideUiElement;
 import com.android.systemui.statusbar.BackDropView;
+import com.android.systemui.statusbar.CircleReveal;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.FeatureFlags;
@@ -382,6 +386,8 @@
     private ChargingRippleView mChargingRipple;
     private WiredChargingRippleController mChargingRippleAnimationController;
     private PowerButtonReveal mPowerButtonReveal;
+    private CircleReveal mCircleReveal;
+    private ValueAnimator mCircleRevealAnimator = ValueAnimator.ofFloat(0f, 1f);
 
     private final Object mQueueLock = new Object();
 
@@ -1206,7 +1212,9 @@
         mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim);
         mChargingRippleAnimationController.setViewHost(mNotificationShadeWindowView);
 
-        if (mFeatureFlags.useNewLockscreenAnimations() && mDozeParameters.getAlwaysOn()) {
+
+        if (mFeatureFlags.useNewLockscreenAnimations()
+                && (mDozeParameters.getAlwaysOn() || mDozeParameters.isQuickPickupEnabled())) {
             mLightRevealScrim.setVisibility(View.VISIBLE);
             mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
         } else {
@@ -3353,6 +3361,9 @@
         mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING,
                 ()-> {
                 hideKeyguard();
+                if (shouldShowCircleReveal()) {
+                    startCircleReveal();
+                }
                 mStatusBarKeyguardViewManager.onKeyguardFadedAway();
             }).start();
     }
@@ -3666,15 +3677,16 @@
         updateQsExpansionEnabled();
         mKeyguardViewMediator.setDozing(mDozing);
 
-        final boolean usePowerButtonEffect =
-                (isDozing && mWakefulnessLifecycle.getLastSleepReason()
-                        == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON)
-                        || (!isDozing && mWakefulnessLifecycle.getLastWakeReason()
-                        == PowerManager.WAKE_REASON_POWER_BUTTON);
-
-        mLightRevealScrim.setRevealEffect(usePowerButtonEffect
-                ? mPowerButtonReveal
-                : LiftReveal.INSTANCE);
+        if (!isDozing && shouldShowCircleReveal()) {
+            startCircleReveal();
+        } else if ((isDozing && mWakefulnessLifecycle.getLastSleepReason()
+                == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON)
+                || (!isDozing && mWakefulnessLifecycle.getLastWakeReason()
+                == PowerManager.WAKE_REASON_POWER_BUTTON)) {
+            mLightRevealScrim.setRevealEffect(mPowerButtonReveal);
+        } else if (!mCircleRevealAnimator.isRunning()) {
+            mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
+        }
 
         mNotificationsController.requestNotificationUpdate("onDozingChanged");
         updateDozingState();
@@ -3684,6 +3696,22 @@
         Trace.endSection();
     }
 
+    private void startCircleReveal() {
+        mLightRevealScrim.setRevealEffect(mCircleReveal);
+        mCircleRevealAnimator.cancel();
+        mCircleRevealAnimator.addUpdateListener(animation ->
+                mLightRevealScrim.setRevealAmount(
+                        (float) mCircleRevealAnimator.getAnimatedValue()));
+        mCircleRevealAnimator.setDuration(900);
+        mCircleRevealAnimator.start();
+    }
+
+    private boolean shouldShowCircleReveal() {
+        return mCircleReveal != null && !mCircleRevealAnimator.isRunning()
+                && mKeyguardUpdateMonitor.isUdfpsEnrolled()
+                && mBiometricUnlockController.getBiometricType() == FINGERPRINT;
+    }
+
     private void updateKeyguardState() {
         mKeyguardStateController.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
                 mStatusBarKeyguardViewManager.isOccluded());
@@ -4170,6 +4198,15 @@
                 mBiometricUnlockController.getBiometricType());
     }
 
+    /**
+     * Set the location of the sensor on UDFPS if existent.
+     */
+    public void setSensorRect(RectF rect) {
+        final float startRadius = (rect.right - rect.left) / 2f;
+        mCircleReveal = new CircleReveal(rect.centerX(), rect.centerY(),
+                startRadius, rect.centerY() - startRadius);
+    }
+
     @VisibleForTesting
     public void updateScrimController() {
         Trace.beginSection("StatusBar#updateScrimController");
diff --git a/services/api/Android.bp b/services/api/Android.bp
index b8ca548..bbc8c72 100644
--- a/services/api/Android.bp
+++ b/services/api/Android.bp
@@ -14,6 +14,12 @@
 
 package {
     default_visibility: ["//visibility:private"],
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
 }
 
 filegroup {
@@ -26,4 +32,4 @@
     name: "non-updatable-system-server-removed.txt",
     srcs: ["non-updatable-removed.txt"],
     visibility: ["//frameworks/base/api"],
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 3c445ae..1b352c7 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -160,6 +160,7 @@
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.function.Predicate;
 
@@ -559,6 +560,45 @@
         return smap != null ? smap.mStartingBackground.size() >= mMaxStartingBackground : false;
     }
 
+    boolean hasForegroundServiceNotificationLocked(String pkg, int userId, String channelId) {
+        final ServiceMap smap = mServiceMap.get(userId);
+        if (smap != null) {
+            for (int i = 0; i < smap.mServicesByInstanceName.size(); i++) {
+                final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i);
+                if (sr.appInfo.packageName.equals(pkg) && sr.isForeground) {
+                    if (Objects.equals(sr.foregroundNoti.getChannelId(), channelId)) {
+                        if (DEBUG_FOREGROUND_SERVICE) {
+                            Slog.d(TAG_SERVICE, "Channel u" + userId + "/pkg=" + pkg
+                                    + "/channelId=" + channelId
+                                    + " has fg service notification");
+                        }
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    void stopForegroundServicesForChannelLocked(String pkg, int userId, String channelId) {
+        final ServiceMap smap = mServiceMap.get(userId);
+        if (smap != null) {
+            for (int i = 0; i < smap.mServicesByInstanceName.size(); i++) {
+                final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i);
+                if (sr.appInfo.packageName.equals(pkg) && sr.isForeground) {
+                    if (Objects.equals(sr.foregroundNoti.getChannelId(), channelId)) {
+                        if (DEBUG_FOREGROUND_SERVICE) {
+                            Slog.d(TAG_SERVICE, "Stopping FGS u" + userId + "/pkg=" + pkg
+                                    + "/channelId=" + channelId
+                                    + " for conversation channel clear");
+                        }
+                        stopServiceLocked(sr, false);
+                    }
+                }
+            }
+        }
+    }
+
     private ServiceMap getServiceMapLocked(int callingUser) {
         ServiceMap smap = mServiceMap.get(callingUser);
         if (smap == null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0e8644a..c4548a3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15911,6 +15911,22 @@
         }
 
         @Override
+        public boolean hasForegroundServiceNotification(String pkg, int userId,
+                String channelId) {
+            synchronized (ActivityManagerService.this) {
+                return mServices.hasForegroundServiceNotificationLocked(pkg, userId, channelId);
+            }
+        }
+
+        @Override
+        public void stopForegroundServicesForChannel(String pkg, int userId,
+                String channelId) {
+            synchronized (ActivityManagerService.this) {
+                mServices.stopForegroundServicesForChannelLocked(pkg, userId, channelId);
+            }
+        }
+
+        @Override
         public void registerProcessObserver(IProcessObserver processObserver) {
             ActivityManagerService.this.registerProcessObserver(processObserver);
         }
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 9e79b02..273b9c3 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -30,6 +30,10 @@
 michaelwr@google.com
 narayan@google.com
 
+# Voice Interaction
+per-file *Assist* = file:/core/java/android/service/voice/OWNERS
+per-file *Voice* = file:/core/java/android/service/voice/OWNERS
+
 per-file SettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com
 
 per-file CarUserSwitchingDialog.java = keunyoung@google.com, felipeal@google.com, gurunagarajan@google.com
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index 5083c5e..6017e92 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -597,7 +597,8 @@
                     mPreAuthInfo.confirmationRequested,
                     FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
                     latency,
-                    mDebugEnabled);
+                    mDebugEnabled,
+                    -1 /* sensorId */);
         } else {
             final long latency = System.currentTimeMillis() - mStartTimeMs;
 
@@ -625,7 +626,8 @@
                     error,
                     0 /* vendorCode */,
                     mDebugEnabled,
-                    latency);
+                    latency,
+                    -1 /* sensorId */);
         }
     }
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
index de57186..282261e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
@@ -127,7 +127,8 @@
                 getContext().getPackageName(), mBiometricUtils, getSensorId(), mAuthenticatorIds);
         FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
                 mStatsModality,
-                BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL);
+                BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL,
+                -1 /* sensorId */);
         mCurrentTask.start(mRemoveCallback);
     }
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
index e3feb74..7f6903a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
@@ -118,7 +118,8 @@
                     getTargetUserId(), identifier.getBiometricId());
             FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
                     mStatsModality,
-                    BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK);
+                    BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK,
+                    -1 /* sensorId */);
         }
         mEnrolledList.clear();
     }
diff --git a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
index edde3d4..4da644d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/LoggableMonitor.java
@@ -126,7 +126,8 @@
                 mStatsClient,
                 acquiredInfo,
                 vendorCode,
-                Utils.isDebugEnabled(context, targetUserId));
+                Utils.isDebugEnabled(context, targetUserId),
+                -1 /* sensorId */);
     }
 
     protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) {
@@ -164,7 +165,8 @@
                 error,
                 vendorCode,
                 Utils.isDebugEnabled(context, targetUserId),
-                sanitizeLatency(latency));
+                sanitizeLatency(latency),
+                -1 /* sensorId */);
     }
 
     protected final void logOnAuthenticated(Context context, boolean authenticated,
@@ -214,7 +216,8 @@
                 requireConfirmation,
                 authState,
                 sanitizeLatency(latency),
-                Utils.isDebugEnabled(context, targetUserId));
+                Utils.isDebugEnabled(context, targetUserId),
+                -1 /* sensorId */);
     }
 
     protected final void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) {
@@ -240,7 +243,8 @@
                 mStatsModality,
                 targetUserId,
                 sanitizeLatency(latency),
-                enrollSuccessful);
+                enrollSuccessful,
+                -1 /* sensorId */);
     }
 
     private long sanitizeLatency(long latency) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index b6c5048..ca29057 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -27,6 +27,7 @@
 import android.hardware.biometrics.IInvalidationCallback;
 import android.hardware.biometrics.ITestSession;
 import android.hardware.biometrics.ITestSessionCallback;
+import android.hardware.biometrics.common.ComponentInfo;
 import android.hardware.biometrics.face.IFace;
 import android.hardware.biometrics.face.SensorProps;
 import android.hardware.face.Face;
@@ -137,8 +138,7 @@
 
             final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
             if (prop.commonProps.componentInfo != null) {
-                for (android.hardware.biometrics.common.ComponentInfo info
-                        : prop.commonProps.componentInfo) {
+                for (ComponentInfo info : prop.commonProps.componentInfo) {
                     componentInfo.add(new ComponentInfoInternal(info.componentId,
                             info.hardwareVersion, info.firmwareVersion, info.serialNumber,
                             info.softwareVersion));
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index c7d2f0f..c6f39aa 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -546,7 +546,8 @@
 
             FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
                     BiometricsProtoEnums.MODALITY_FACE,
-                    BiometricsProtoEnums.ISSUE_HAL_DEATH);
+                    BiometricsProtoEnums.ISSUE_HAL_DEATH,
+                    -1 /* sensorId */);
         }
 
         mScheduler.recordCrashState();
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index d8aaa22..50756c8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -387,7 +387,8 @@
 
                 FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
                         BiometricsProtoEnums.MODALITY_FACE,
-                        BiometricsProtoEnums.ISSUE_HAL_DEATH);
+                        BiometricsProtoEnums.ISSUE_HAL_DEATH,
+                        -1 /* sensorId */);
             }
 
             mScheduler.recordCrashState();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index f8af650..1b5def6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -29,6 +29,7 @@
 import android.hardware.biometrics.IInvalidationCallback;
 import android.hardware.biometrics.ITestSession;
 import android.hardware.biometrics.ITestSessionCallback;
+import android.hardware.biometrics.common.ComponentInfo;
 import android.hardware.biometrics.fingerprint.IFingerprint;
 import android.hardware.biometrics.fingerprint.SensorProps;
 import android.hardware.fingerprint.Fingerprint;
@@ -141,8 +142,7 @@
 
             final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
             if (prop.commonProps.componentInfo != null) {
-                for (android.hardware.biometrics.common.ComponentInfo info
-                        : prop.commonProps.componentInfo) {
+                for (ComponentInfo info : prop.commonProps.componentInfo) {
                     componentInfo.add(new ComponentInfoInternal(info.componentId,
                             info.hardwareVersion, info.firmwareVersion, info.serialNumber,
                             info.softwareVersion));
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index b9dee7d..5631647 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -526,7 +526,8 @@
 
             FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
                     BiometricsProtoEnums.MODALITY_FINGERPRINT,
-                    BiometricsProtoEnums.ISSUE_HAL_DEATH);
+                    BiometricsProtoEnums.ISSUE_HAL_DEATH,
+                    -1 /* sensorId */);
         }
 
         mScheduler.recordCrashState();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index 136caeb..f2992cc 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -390,7 +390,8 @@
 
                 FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
                         BiometricsProtoEnums.MODALITY_FINGERPRINT,
-                        BiometricsProtoEnums.ISSUE_HAL_DEATH);
+                        BiometricsProtoEnums.ISSUE_HAL_DEATH,
+                        -1 /* sensorId */);
             }
 
             mScheduler.recordCrashState();
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index f8a913a..c010906 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1134,8 +1134,13 @@
             recordStableDisplayStatsIfNeededLocked(display);
             recordTopInsetLocked(display);
         }
-        addDisplayPowerControllerLocked(display);
-        mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
+        final int groupId = mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(displayId);
+        if (groupId != Display.INVALID_DISPLAY_GROUP) {
+            addDisplayPowerControllerLocked(display);
+            mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
+        } else {
+            mDisplayStates.append(displayId, Display.STATE_ON);
+        }
         mDisplayBrightnesses.append(displayId, display.getDisplayInfoLocked().brightnessDefault);
 
         DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
@@ -1214,8 +1219,7 @@
             final int displayId = display.getDisplayIdLocked();
             final int state = mDisplayStates.get(displayId);
 
-            // Only send a request for display state if the display state has already been
-            // initialized by DisplayPowercontroller.
+            // Only send a request for display state if display state has already been initialized.
             if (state != Display.STATE_UNKNOWN) {
                 final float brightness = mDisplayBrightnesses.get(displayId);
                 return device.requestDisplayStateLocked(state, brightness);
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index fcfa674..6c2e6eb 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -433,31 +433,37 @@
         final int displayId = display.getDisplayIdLocked();
 
         // Get current display group data
-        int groupId = getDisplayGroupIdFromDisplayIdLocked(displayId);
+        final int groupId = getDisplayGroupIdFromDisplayIdLocked(displayId);
         final DisplayGroup oldGroup = getDisplayGroupLocked(groupId);
 
         // Get the new display group if a change is needed
         final DisplayInfo info = display.getDisplayInfoLocked();
         final boolean needsOwnDisplayGroup = (info.flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0;
         final boolean hasOwnDisplayGroup = groupId != Display.DEFAULT_DISPLAY_GROUP;
-        if (groupId == Display.INVALID_DISPLAY_GROUP
-                || hasOwnDisplayGroup != needsOwnDisplayGroup) {
-            groupId = assignDisplayGroupIdLocked(needsOwnDisplayGroup);
-        }
-
-        // Create a new group if needed
-        DisplayGroup newGroup = getDisplayGroupLocked(groupId);
-        if (newGroup == null) {
-            newGroup = new DisplayGroup(groupId);
-            mDisplayGroups.append(groupId, newGroup);
-        }
-        if (oldGroup != newGroup) {
+        final boolean needsDisplayGroup = needsOwnDisplayGroup || info.type == Display.TYPE_INTERNAL
+                || info.type == Display.TYPE_EXTERNAL;
+        if (!needsDisplayGroup) {
             if (oldGroup != null) {
                 oldGroup.removeDisplayLocked(display);
             }
+            return;
+        }
+        if (groupId == Display.INVALID_DISPLAY_GROUP
+                || hasOwnDisplayGroup != needsOwnDisplayGroup) {
+            if (oldGroup != null) {
+                oldGroup.removeDisplayLocked(display);
+            }
+
+            final int newGroupId = assignDisplayGroupIdLocked(needsOwnDisplayGroup);
+            // Create a new group if needed
+            DisplayGroup newGroup = getDisplayGroupLocked(newGroupId);
+            if (newGroup == null) {
+                newGroup = new DisplayGroup(newGroupId);
+                mDisplayGroups.append(newGroupId, newGroup);
+            }
             newGroup.addDisplayLocked(display);
-            display.updateDisplayGroupIdLocked(groupId);
-            Slog.i(TAG, "Setting new display group " + groupId + " for display "
+            display.updateDisplayGroupIdLocked(newGroupId);
+            Slog.i(TAG, "Setting new display group " + newGroupId + " for display "
                     + displayId + ", from previous group: "
                     + (oldGroup != null ? oldGroup.getGroupId() : "null"));
         }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e588366..eb4f9d3 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3576,15 +3576,30 @@
                     pkg, uid, channelId, conversationId, true, includeDeleted);
         }
 
+        // Returns 'true' if the given channel has a notification associated
+        // with an active foreground service.
+        private void enforceDeletingChannelHasNoFgService(String pkg, int userId,
+                String channelId) {
+            if (mAmi.hasForegroundServiceNotification(pkg, userId, channelId)) {
+                Slog.w(TAG, "Package u" + userId + "/" + pkg
+                        + " may not delete notification channel '"
+                        + channelId + "' with fg service");
+                throw new SecurityException("Not allowed to delete channel " + channelId
+                        + " with a foreground service");
+            }
+        }
+
         @Override
         public void deleteNotificationChannel(String pkg, String channelId) {
             checkCallerIsSystemOrSameApp(pkg);
             final int callingUid = Binder.getCallingUid();
+            final int callingUser = UserHandle.getUserId(callingUid);
             if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
                 throw new IllegalArgumentException("Cannot delete default channel");
             }
+            enforceDeletingChannelHasNoFgService(pkg, callingUser, channelId);
             cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channelId, 0, 0, true,
-                    UserHandle.getUserId(callingUid), REASON_CHANNEL_BANNED, null);
+                    callingUser, REASON_CHANNEL_BANNED, null);
             mPreferencesHelper.deleteNotificationChannel(pkg, callingUid, channelId);
             mListeners.notifyNotificationChannelChanged(pkg,
                     UserHandle.getUserHandleForUid(callingUid),
@@ -3597,19 +3612,23 @@
         public void deleteConversationNotificationChannels(String pkg, int uid,
                 String conversationId) {
             checkCallerIsSystem();
-            final int callingUid = Binder.getCallingUid();
             List<NotificationChannel> channels =
                     mPreferencesHelper.getNotificationChannelsByConversationId(
                             pkg, uid, conversationId);
             if (!channels.isEmpty()) {
+                // Preflight for fg service notifications in these channels:  do nothing
+                // unless they're all eligible
+                final int appUserId = UserHandle.getUserId(uid);
                 for (NotificationChannel nc : channels) {
+                    final String channelId = nc.getId();
+                    mAmi.stopForegroundServicesForChannel(pkg, appUserId, channelId);
                     cancelAllNotificationsInt(MY_UID, MY_PID, pkg, nc.getId(), 0, 0, true,
-                            UserHandle.getUserId(callingUid), REASON_CHANNEL_BANNED, null);
-                    mPreferencesHelper.deleteNotificationChannel(pkg, callingUid, nc.getId());
+                            appUserId, REASON_CHANNEL_BANNED, null);
+                    mPreferencesHelper.deleteNotificationChannel(pkg, uid, channelId);
                     mListeners.notifyNotificationChannelChanged(pkg,
-                            UserHandle.getUserHandleForUid(callingUid),
+                            UserHandle.getUserHandleForUid(uid),
                             mPreferencesHelper.getNotificationChannel(
-                                    pkg, callingUid, nc.getId(), true),
+                                    pkg, uid, channelId, true),
                             NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
                 }
                 handleSavePolicyFile();
@@ -3640,13 +3659,20 @@
             NotificationChannelGroup groupToDelete =
                     mPreferencesHelper.getNotificationChannelGroup(groupId, pkg, callingUid);
             if (groupToDelete != null) {
+                // Preflight for allowability
+                final int userId = UserHandle.getUserId(callingUid);
+                List<NotificationChannel> groupChannels = groupToDelete.getChannels();
+                for (int i = 0; i < groupChannels.size(); i++) {
+                    enforceDeletingChannelHasNoFgService(pkg, userId,
+                            groupChannels.get(i).getId());
+                }
                 List<NotificationChannel> deletedChannels =
                         mPreferencesHelper.deleteNotificationChannelGroup(pkg, callingUid, groupId);
                 for (int i = 0; i < deletedChannels.size(); i++) {
                     final NotificationChannel deletedChannel = deletedChannels.get(i);
                     cancelAllNotificationsInt(MY_UID, MY_PID, pkg, deletedChannel.getId(), 0, 0,
                             true,
-                            UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED,
+                            userId, REASON_CHANNEL_BANNED,
                             null);
                     mListeners.notifyNotificationChannelChanged(pkg,
                             UserHandle.getUserHandleForUid(callingUid),
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index dbd1211..27b1648 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -103,7 +103,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.Set;
 
 /**
@@ -312,7 +311,7 @@
                     // Initialize any users that can't be switched to, as their state would
                     // never be setup in onSwitchUser(). We will switch to the system user right
                     // after this, and its state will be setup there.
-                    updatePackageManager(mImpl.updateOverlaysForUser(users.get(i).id));
+                    updatePackageManagerLocked(mImpl.updateOverlaysForUser(users.get(i).id));
                 }
             }
         }
@@ -329,9 +328,8 @@
             // ensure overlays in the settings are up-to-date, and propagate
             // any asset changes to the rest of the system
             synchronized (mLock) {
-                updateActivityManager(updatePackageManager(mImpl.updateOverlaysForUser(newUserId)));
+                updateTargetPackagesLocked(mImpl.updateOverlaysForUser(newUserId));
             }
-            persistSettings();
         } finally {
             traceEnd(TRACE_TAG_RRO);
         }
@@ -415,7 +413,8 @@
                                 packageName, userId);
                         if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) {
                             try {
-                                updateTargetPackages(mImpl.onPackageAdded(packageName, userId));
+                                updateTargetPackagesLocked(
+                                        mImpl.onPackageAdded(packageName, userId));
                             } catch (OperationFailedException e) {
                                 Slog.e(TAG, "onPackageAdded internal error", e);
                             }
@@ -437,7 +436,8 @@
                                 packageName, userId);
                         if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) {
                             try {
-                                updateTargetPackages(mImpl.onPackageChanged(packageName, userId));
+                                updateTargetPackagesLocked(
+                                        mImpl.onPackageChanged(packageName, userId));
                             } catch (OperationFailedException e) {
                                 Slog.e(TAG, "onPackageChanged internal error", e);
                             }
@@ -459,7 +459,8 @@
                                 packageName, userId);
                         if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) {
                             try {
-                                updateTargetPackages(mImpl.onPackageReplacing(packageName, userId));
+                                updateTargetPackagesLocked(
+                                        mImpl.onPackageReplacing(packageName, userId));
                             } catch (OperationFailedException e) {
                                 Slog.e(TAG, "onPackageReplacing internal error", e);
                             }
@@ -481,7 +482,8 @@
                                 packageName, userId);
                         if (pkg != null && !mPackageManager.isInstantApp(packageName, userId)) {
                             try {
-                                updateTargetPackages(mImpl.onPackageReplaced(packageName, userId));
+                                updateTargetPackagesLocked(
+                                        mImpl.onPackageReplaced(packageName, userId));
                             } catch (OperationFailedException e) {
                                 Slog.e(TAG, "onPackageReplaced internal error", e);
                             }
@@ -500,7 +502,7 @@
                 for (int userId : userIds) {
                     synchronized (mLock) {
                         mPackageManager.onPackageRemoved(packageName, userId);
-                        updateTargetPackages(mImpl.onPackageRemoved(packageName, userId));
+                        updateTargetPackagesLocked(mImpl.onPackageRemoved(packageName, userId));
                     }
                 }
             } finally {
@@ -519,7 +521,7 @@
                         try {
                             traceBegin(TRACE_TAG_RRO, "OMS ACTION_USER_ADDED");
                             synchronized (mLock) {
-                                updatePackageManager(mImpl.updateOverlaysForUser(userId));
+                                updatePackageManagerLocked(mImpl.updateOverlaysForUser(userId));
                             }
                         } finally {
                             traceEnd(TRACE_TAG_RRO);
@@ -624,7 +626,8 @@
                 try {
                     synchronized (mLock) {
                         try {
-                            updateTargetPackages(mImpl.setEnabled(overlay, enable, realUserId));
+                            updateTargetPackagesLocked(
+                                    mImpl.setEnabled(overlay, enable, realUserId));
                             return true;
                         } catch (OperationFailedException e) {
                             return false;
@@ -656,9 +659,10 @@
                 try {
                     synchronized (mLock) {
                         try {
-                            mImpl.setEnabledExclusive(overlay,
-                                    false /* withinCategory */, realUserId)
-                                .ifPresent(OverlayManagerService.this::updateTargetPackages);
+                            mImpl.setEnabledExclusive(
+                                    overlay, false /* withinCategory */, realUserId)
+                                    .ifPresent(
+                                            OverlayManagerService.this::updateTargetPackagesLocked);
                             return true;
                         } catch (OperationFailedException e) {
                             return false;
@@ -693,7 +697,7 @@
                         try {
                             mImpl.setEnabledExclusive(overlay,
                                     true /* withinCategory */, realUserId)
-                                .ifPresent(OverlayManagerService.this::updateTargetPackages);
+                                .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked);
                             return true;
                         } catch (OperationFailedException e) {
                             return false;
@@ -728,7 +732,7 @@
                     synchronized (mLock) {
                         try {
                             mImpl.setPriority(overlay, parentOverlay, realUserId)
-                                .ifPresent(OverlayManagerService.this::updateTargetPackages);
+                                .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked);
                             return true;
                         } catch (OperationFailedException e) {
                             return false;
@@ -759,7 +763,8 @@
                 try {
                     synchronized (mLock) {
                         try {
-                            updateTargetPackages(mImpl.setHighestPriority(overlay, realUserId));
+                            updateTargetPackagesLocked(
+                                    mImpl.setHighestPriority(overlay, realUserId));
                             return true;
                         } catch (OperationFailedException e) {
                             return false;
@@ -791,7 +796,7 @@
                     synchronized (mLock) {
                         try {
                             mImpl.setLowestPriority(overlay, realUserId)
-                                .ifPresent(OverlayManagerService.this::updateTargetPackages);
+                                .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked);
                             return true;
                         } catch (OperationFailedException e) {
                             return false;
@@ -945,27 +950,12 @@
                 throw new IllegalArgumentException("null transaction");
             }
 
-            // map: userId -> set<package-name>: target packages of overlays in
-            // this transaction
-            final SparseArray<Set<String>> transactionTargets = new SparseArray<>();
-
-            // map: userId -> set<package-name>: packages that need to reload
-            // their resources due to changes to the overlays in this
-            // transaction
-            final SparseArray<List<String>> affectedPackagesToUpdate = new SparseArray<>();
-
             synchronized (mLock) {
                 // execute the requests (as calling user)
+                Set<PackageAndUser> affectedPackagesToUpdate = null;
                 for (final OverlayManagerTransaction.Request request : transaction) {
-                    executeRequest(request).forEach(
-                            target -> {
-                                Set<String> userTargets = transactionTargets.get(target.userId);
-                                if (userTargets == null) {
-                                    userTargets = new ArraySet<>();
-                                    transactionTargets.put(target.userId, userTargets);
-                                }
-                                userTargets.add(target.packageName);
-                            });
+                    affectedPackagesToUpdate = CollectionUtils.addAll(affectedPackagesToUpdate,
+                            executeRequest(request));
                 }
 
                 // past the point of no return: the entire transaction has been
@@ -973,37 +963,11 @@
                 // system_server
                 final long ident = Binder.clearCallingIdentity();
                 try {
-                    persistSettings();
-
-                    // inform the package manager about the new paths
-                    for (int index = 0; index < transactionTargets.size(); index++) {
-                        final int userId = transactionTargets.keyAt(index);
-                        final List<String> affectedTargets =
-                                updatePackageManager(transactionTargets.valueAt(index), userId);
-                        affectedPackagesToUpdate.put(userId, affectedTargets);
-                    }
+                    updateTargetPackagesLocked(affectedPackagesToUpdate);
                 } finally {
                     Binder.restoreCallingIdentity(ident);
                 }
-            } // synchronized (mLock)
-
-            FgThread.getHandler().post(() -> {
-                final long ident = Binder.clearCallingIdentity();
-                try {
-                    // schedule apps to refresh
-                    updateActivityManager(affectedPackagesToUpdate);
-
-                    // broadcast the ACTION_OVERLAY_CHANGED intents
-                    for (int index = 0; index < transactionTargets.size(); index++) {
-                        final int userId = transactionTargets.keyAt(index);
-                        for (String pkg: transactionTargets.valueAt(index)) {
-                            broadcastActionOverlayChanged(pkg, userId);
-                        }
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
-            });
+            }
         }
 
         @Override
@@ -1382,32 +1346,37 @@
         }
     }
 
-    private void updateTargetPackages(@Nullable PackageAndUser updatedTarget) {
+    private void updateTargetPackagesLocked(@Nullable PackageAndUser updatedTarget) {
         if (updatedTarget != null) {
-            updateTargetPackages(Set.of(updatedTarget));
+            updateTargetPackagesLocked(Set.of(updatedTarget));
         }
     }
 
-    private void updateTargetPackages(@Nullable Set<PackageAndUser> updatedTargets) {
+    private void updateTargetPackagesLocked(@Nullable Set<PackageAndUser> updatedTargets) {
         if (CollectionUtils.isEmpty(updatedTargets)) {
             return;
         }
-        persistSettings();
+        persistSettingsLocked();
         final SparseArray<ArraySet<String>> userTargets = groupTargetsByUserId(updatedTargets);
-        FgThread.getHandler().post(() -> {
-            for (int i = 0, n = userTargets.size(); i < n; i++) {
-                final ArraySet<String> targets = userTargets.valueAt(i);
-                final int userId = userTargets.keyAt(i);
+        for (int i = 0, n = userTargets.size(); i < n; i++) {
+            final ArraySet<String> targets = userTargets.valueAt(i);
+            final int userId = userTargets.keyAt(i);
+            final List<String> affectedPackages = updatePackageManagerLocked(targets, userId);
+            if (affectedPackages.isEmpty()) {
+                // The package manager paths are already up-to-date.
+                continue;
+            }
 
-                // Update the overlay paths in package manager.
-                final List<String> affectedPackages = updatePackageManager(targets, userId);
+            FgThread.getHandler().post(() -> {
+                // Send configuration changed events for all target packages that have been affected
+                // by overlay state changes.
                 updateActivityManager(affectedPackages, userId);
 
-                // Overlays targeting shared libraries may cause more packages to need to be
-                // refreshed.
+                // Do not send broadcasts for all affected targets. Overlays targeting the framework
+                // or shared libraries may cause too many broadcasts to be sent at once.
                 broadcastActionOverlayChanged(targets, userId);
-            }
-        });
+            });
+        }
     }
 
     @Nullable
@@ -1430,20 +1399,17 @@
 
     private static void broadcastActionOverlayChanged(@NonNull final Set<String> targetPackages,
             final int userId) {
-        CollectionUtils.forEach(targetPackages,
-                target -> broadcastActionOverlayChanged(target, userId));
-    }
-
-    private static void broadcastActionOverlayChanged(String targetPackage, final int userId) {
-        final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
-                Uri.fromParts("package", targetPackage, null));
-        intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        try {
-            ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, null, null,
-                    null, android.app.AppOpsManager.OP_NONE, null, false, false, userId);
-        } catch (RemoteException e) {
-            // Intentionally left empty.
-        }
+        CollectionUtils.forEach(targetPackages, target -> {
+            final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
+                    Uri.fromParts("package", target, null));
+            intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+            try {
+                ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, null,
+                        null, null, android.app.AppOpsManager.OP_NONE, null, false, false, userId);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "broadcastActionOverlayChanged remote exception", e);
+            }
+        });
     }
 
     /**
@@ -1455,18 +1421,13 @@
         try {
             am.scheduleApplicationInfoChanged(targetPackageNames, userId);
         } catch (RemoteException e) {
-            // Intentionally left empty.
-        }
-    }
-
-    private void updateActivityManager(@NonNull SparseArray<List<String>> targetPackageNames) {
-        for (int i = 0, n = targetPackageNames.size(); i < n; i++) {
-            updateActivityManager(targetPackageNames.valueAt(i), targetPackageNames.keyAt(i));
+            Slog.e(TAG, "updateActivityManager remote exception", e);
         }
     }
 
     @NonNull
-    private SparseArray<List<String>> updatePackageManager(@Nullable Set<PackageAndUser> targets) {
+    private SparseArray<List<String>> updatePackageManagerLocked(
+            @Nullable Set<PackageAndUser> targets) {
         if (CollectionUtils.isEmpty(targets)) {
             return new SparseArray<>();
         }
@@ -1474,7 +1435,7 @@
         final SparseArray<ArraySet<String>> userTargets = groupTargetsByUserId(targets);
         for (int i = 0, n = userTargets.size(); i < n; i++) {
             final int userId = userTargets.keyAt(i);
-            affectedTargets.put(userId, updatePackageManager(userTargets.valueAt(i), userId));
+            affectedTargets.put(userId, updatePackageManagerLocked(userTargets.valueAt(i), userId));
         }
         return affectedTargets;
     }
@@ -1485,10 +1446,10 @@
      *         targetPackageNames: the target themselves and shared libraries)
      */
     @NonNull
-    private List<String> updatePackageManager(@NonNull Collection<String> targetPackageNames,
+    private List<String> updatePackageManagerLocked(@NonNull Collection<String> targetPackageNames,
             final int userId) {
         try {
-            traceBegin(TRACE_TAG_RRO, "OMS#updatePackageManager " + targetPackageNames);
+            traceBegin(TRACE_TAG_RRO, "OMS#updatePackageManagerLocked " + targetPackageNames);
             if (DEBUG) {
                 Slog.d(TAG, "Update package manager about changed overlays");
             }
@@ -1535,20 +1496,18 @@
         }
     }
 
-    private void persistSettings() {
+    private void persistSettingsLocked() {
         if (DEBUG) {
             Slog.d(TAG, "Writing overlay settings");
         }
-        synchronized (mLock) {
-            FileOutputStream stream = null;
-            try {
-                stream = mSettingsFile.startWrite();
-                mSettings.persist(stream);
-                mSettingsFile.finishWrite(stream);
-            } catch (IOException | XmlPullParserException e) {
-                mSettingsFile.failWrite(stream);
-                Slog.e(TAG, "failed to persist overlay state", e);
-            }
+        FileOutputStream stream = null;
+        try {
+            stream = mSettingsFile.startWrite();
+            mSettings.persist(stream);
+            mSettingsFile.finishWrite(stream);
+        } catch (IOException | XmlPullParserException e) {
+            mSettingsFile.failWrite(stream);
+            Slog.e(TAG, "failed to persist overlay state", e);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 8283ac6..fe19956 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2861,6 +2861,100 @@
         }
     }
 
+    @GuardedBy("mUsersLock")
+    @VisibleForTesting
+    void upgradeUserTypesLU(@NonNull List<UserTypeFactory.UserTypeUpgrade> upgradeOps,
+            @NonNull ArrayMap<String, UserTypeDetails> userTypes,
+            final int formerUserTypeVersion,
+            @NonNull Set<Integer> userIdsToWrite) {
+        for (UserTypeFactory.UserTypeUpgrade userTypeUpgrade : upgradeOps) {
+            if (DBG) {
+                Slog.i(LOG_TAG, "Upgrade: " + userTypeUpgrade.getFromType() + " to: "
+                        + userTypeUpgrade.getToType() + " maxVersion: "
+                        + userTypeUpgrade.getUpToVersion());
+            }
+
+            // upgrade user type if version up to getUpToVersion()
+            if (formerUserTypeVersion <= userTypeUpgrade.getUpToVersion()) {
+                for (int i = 0; i < mUsers.size(); i++) {
+                    UserData userData = mUsers.valueAt(i);
+                    if (userTypeUpgrade.getFromType().equals(userData.info.userType)) {
+                        final UserTypeDetails newUserType = userTypes.get(
+                                userTypeUpgrade.getToType());
+
+                        if (newUserType == null) {
+                            throw new IllegalStateException(
+                                    "Upgrade destination user type not defined: "
+                                            + userTypeUpgrade.getToType());
+                        }
+
+                        upgradeProfileToTypeLU(userData.info, newUserType);
+                        userIdsToWrite.add(userData.info.id);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Changes the user type of a profile to a new user type.
+     * @param userInfo    The user to be updated.
+     * @param newUserType The new user type.
+     */
+    @GuardedBy("mUsersLock")
+    @VisibleForTesting
+    void upgradeProfileToTypeLU(@NonNull UserInfo userInfo, @NonNull UserTypeDetails newUserType) {
+        Slog.i(LOG_TAG, "Upgrading user " + userInfo.id
+                + " from " + userInfo.userType
+                + " to " + newUserType.getName());
+
+        if (!userInfo.isProfile()) {
+            throw new IllegalStateException(
+                    "Can only upgrade profile types. " + userInfo.userType
+                            + " is not a profile type.");
+        }
+
+        // Exceeded maximum profiles for parent user: log error, but allow upgrade
+        if (!canAddMoreProfilesToUser(newUserType.getName(), userInfo.profileGroupId, false)) {
+            Slog.w(LOG_TAG,
+                    "Exceeded maximum profiles of type " + newUserType.getName() + " for user "
+                            + userInfo.id + ". Maximum allowed= "
+                            + newUserType.getMaxAllowedPerParent());
+        }
+
+        final UserTypeDetails oldUserType = mUserTypes.get(userInfo.userType);
+        final int oldFlags;
+        if (oldUserType != null) {
+            oldFlags = oldUserType.getDefaultUserInfoFlags();
+        } else {
+            // if oldUserType is missing from config_user_types.xml -> can only assume FLAG_PROFILE
+            oldFlags = UserInfo.FLAG_PROFILE;
+        }
+
+        //convert userData to newUserType
+        userInfo.userType = newUserType.getName();
+        // remove old default flags and add newUserType's default flags
+        userInfo.flags = newUserType.getDefaultUserInfoFlags() | (userInfo.flags ^ oldFlags);
+
+        // merge existing base restrictions with the new type's default restrictions
+        synchronized (mRestrictionsLock) {
+            if (!BundleUtils.isEmpty(newUserType.getDefaultRestrictions())) {
+                final Bundle newRestrictions = BundleUtils.clone(
+                        mBaseUserRestrictions.getRestrictions(userInfo.id));
+                UserRestrictionsUtils.merge(newRestrictions,
+                        newUserType.getDefaultRestrictions());
+                updateUserRestrictionsInternalLR(newRestrictions, userInfo.id);
+                if (DBG) {
+                    Slog.i(LOG_TAG, "Updated user " + userInfo.id
+                            + " restrictions to " + newRestrictions);
+                }
+            }
+        }
+
+        // re-compute badge index
+        userInfo.profileBadge = getFreeProfileBadgeLU(userInfo.profileGroupId, userInfo.userType);
+    }
+
     @GuardedBy({"mPackagesLock", "mRestrictionsLock"})
     private void fallbackToSingleUserLP() {
         int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN
@@ -5759,98 +5853,4 @@
         }
         return mDevicePolicyManagerInternal;
     }
-
-    @GuardedBy("mUsersLock")
-    @VisibleForTesting
-    void upgradeUserTypesLU(@NonNull List<UserTypeFactory.UserTypeUpgrade> upgradeOps,
-            @NonNull ArrayMap<String, UserTypeDetails> userTypes,
-            final int formerUserTypeVersion,
-            @NonNull Set<Integer> userIdsToWrite) {
-        for (UserTypeFactory.UserTypeUpgrade userTypeUpgrade : upgradeOps) {
-            if (DBG) {
-                Slog.i(LOG_TAG, "Upgrade: " + userTypeUpgrade.getFromType() + " to: "
-                        + userTypeUpgrade.getToType() + " maxVersion: "
-                        + userTypeUpgrade.getUpToVersion());
-            }
-
-            // upgrade user type if version up to getUpToVersion()
-            if (formerUserTypeVersion <= userTypeUpgrade.getUpToVersion()) {
-                for (int i = 0; i < mUsers.size(); i++) {
-                    UserData userData = mUsers.valueAt(i);
-                    if (userTypeUpgrade.getFromType().equals(userData.info.userType)) {
-                        final UserTypeDetails newUserType = userTypes.get(
-                                userTypeUpgrade.getToType());
-
-                        if (newUserType == null) {
-                            throw new IllegalStateException(
-                                    "Upgrade destination user type not defined: "
-                                            + userTypeUpgrade.getToType());
-                        }
-
-                        upgradeProfileToTypeLU(userData.info, newUserType);
-                        userIdsToWrite.add(userData.info.id);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Changes the user type of a profile to a new user type.
-     * @param userInfo    The user to be updated.
-     * @param newUserType The new user type.
-     */
-    @GuardedBy("mUsersLock")
-    @VisibleForTesting
-    void upgradeProfileToTypeLU(@NonNull UserInfo userInfo, @NonNull UserTypeDetails newUserType) {
-        Slog.i(LOG_TAG, "Upgrading user " + userInfo.id
-                + " from " + userInfo.userType
-                + " to " + newUserType.getName());
-
-        if (!userInfo.isProfile()) {
-            throw new IllegalStateException(
-                    "Can only upgrade profile types. " + userInfo.userType
-                            + " is not a profile type.");
-        }
-
-        // Exceeded maximum profiles for parent user: log error, but allow upgrade
-        if (!canAddMoreProfilesToUser(newUserType.getName(), userInfo.profileGroupId, false)) {
-            Slog.w(LOG_TAG,
-                    "Exceeded maximum profiles of type " + newUserType.getName() + " for user "
-                            + userInfo.id + ". Maximum allowed= "
-                            + newUserType.getMaxAllowedPerParent());
-        }
-
-        final UserTypeDetails oldUserType = mUserTypes.get(userInfo.userType);
-        final int oldFlags;
-        if (oldUserType != null) {
-            oldFlags = oldUserType.getDefaultUserInfoFlags();
-        } else {
-            // if oldUserType is missing from config_user_types.xml -> can only assume FLAG_PROFILE
-            oldFlags = UserInfo.FLAG_PROFILE;
-        }
-
-        //convert userData to newUserType
-        userInfo.userType = newUserType.getName();
-        // remove old default flags and add newUserType's default flags
-        userInfo.flags = newUserType.getDefaultUserInfoFlags() | (userInfo.flags ^ oldFlags);
-
-        // merge existing base restrictions with the new type's default restrictions
-        synchronized (mRestrictionsLock) {
-            if (!BundleUtils.isEmpty(newUserType.getDefaultRestrictions())) {
-                final Bundle newRestrictions = BundleUtils.clone(
-                        mBaseUserRestrictions.getRestrictions(userInfo.id));
-                UserRestrictionsUtils.merge(newRestrictions,
-                        newUserType.getDefaultRestrictions());
-                updateUserRestrictionsInternalLR(newRestrictions, userInfo.id);
-                if (DBG) {
-                    Slog.i(LOG_TAG, "Updated user " + userInfo.id
-                            + " restrictions to " + newRestrictions);
-                }
-            }
-        }
-
-        // re-compute badge index
-        userInfo.profileBadge = getFreeProfileBadgeLU(userInfo.profileGroupId, userInfo.userType);
-    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index a46a8d5..64a26ec 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.os.Build.IS_USER;
+import static android.view.CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED;
 
 import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
 import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
@@ -135,6 +136,8 @@
                     return runGetLetterboxBackgroundColor(pw);
                 case "reset":
                     return runReset(pw);
+                case "disable-blur":
+                    return runSetBlurDisabled(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -214,6 +217,33 @@
         return 0;
     }
 
+    private int runSetBlurDisabled(PrintWriter pw) throws RemoteException {
+        String arg = getNextArg();
+        if (arg == null) {
+            pw.println("Blur supported on device: " + CROSS_WINDOW_BLUR_SUPPORTED);
+            pw.println("Blur enabled: " + mInternal.mBlurController.mBlurEnabled);
+            return 0;
+        }
+
+        final boolean disableBlur;
+        switch (arg) {
+            case "true":
+            case "1":
+                disableBlur = true;
+                break;
+            case "false":
+            case "0":
+                disableBlur = false;
+                break;
+            default:
+                getErrPrintWriter().println("Error: expected true, 1, false, 0, but got " + arg);
+                return -1;
+        }
+
+        mInterface.setForceCrossWindowBlurDisabled(disableBlur);
+        return 0;
+    }
+
     private void printInitialDisplayDensity(PrintWriter pw , int displayId) {
         try {
             final int initialDensity = mInterface.getInitialDisplayDensity(displayId);
@@ -725,6 +755,7 @@
         pw.println("    Set display scaling mode.");
         pw.println("  dismiss-keyguard");
         pw.println("    Dismiss the keyguard, prompting user for auth if necessary.");
+        pw.println("  disable-blur [true|1|false|0]");
         pw.println("  user-rotation [-d DISPLAY_ID] [free|lock] [rotation]");
         pw.println("    Print or set user rotation mode and user rotation.");
         pw.println("  dump-visible-window-views");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a8131e4..283895b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -51,6 +51,7 @@
 import static android.app.admin.DevicePolicyManager.DELEGATION_NETWORK_LOGGING;
 import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
 import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
+import static android.app.admin.DevicePolicyManager.DELEGATION_SECURITY_LOGGING;
 import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
 import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
 import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
@@ -430,6 +431,7 @@
         DELEGATION_INSTALL_EXISTING_PACKAGE,
         DELEGATION_KEEP_UNINSTALLED_PACKAGES,
         DELEGATION_NETWORK_LOGGING,
+        DELEGATION_SECURITY_LOGGING,
         DELEGATION_CERT_SELECTION,
     };
 
@@ -440,9 +442,18 @@
                     DELEGATION_NETWORK_LOGGING,
             });
 
+    // Subset of delegations that can only be delegated by Device Owner or Profile Owner of an
+    // organization-owned and managed profile.
+    private static final List<String>
+            DEVICE_OWNER_OR_ORGANIZATION_OWNED_MANAGED_PROFILE_OWNER_DELEGATIONS =
+            Arrays.asList(new String[]{
+                    DELEGATION_SECURITY_LOGGING,
+            });
+
     // Subset of delegations that only one single package within a given user can hold
     private static final List<String> EXCLUSIVE_DELEGATIONS = Arrays.asList(new String[] {
             DELEGATION_NETWORK_LOGGING,
+            DELEGATION_SECURITY_LOGGING,
             DELEGATION_CERT_SELECTION,
     });
 
@@ -6024,6 +6035,10 @@
         if (!Collections.disjoint(scopes, DEVICE_OWNER_OR_MANAGED_PROFILE_OWNER_DELEGATIONS)) {
             Preconditions.checkCallAuthorization(isDeviceOwner(caller)
                     || (isProfileOwner(caller) && isManagedProfile(caller.getUserId())));
+        } else if (!Collections.disjoint(
+                scopes, DEVICE_OWNER_OR_ORGANIZATION_OWNED_MANAGED_PROFILE_OWNER_DELEGATIONS)) {
+            Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+                    || isProfileOwnerOfOrganizationOwnedDevice(caller));
         } else {
             Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
         }
@@ -7658,6 +7673,10 @@
             receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action,
                     deviceOwnerUserId);
         }
+        if (action.equals(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE)) {
+            receiverComponent = resolveDelegateReceiver(DELEGATION_SECURITY_LOGGING, action,
+                    deviceOwnerUserId);
+        }
         if (receiverComponent == null) {
             synchronized (getLockObject()) {
                 receiverComponent = mOwners.getDeviceOwnerComponent();
@@ -7674,6 +7693,10 @@
         if (action.equals(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE)) {
             receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action, userId);
         }
+        if (action.equals(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE)) {
+            receiverComponent = resolveDelegateReceiver(
+                DELEGATION_SECURITY_LOGGING, action, userId);
+        }
         if (receiverComponent == null) {
             receiverComponent = getOwnerComponent(userId);
         }
@@ -13920,16 +13943,24 @@
     }
 
     @Override
-    public void setSecurityLoggingEnabled(ComponentName admin, boolean enabled) {
+    public void setSecurityLoggingEnabled(ComponentName admin, String packageName,
+            boolean enabled) {
         if (!mHasFeature) {
             return;
         }
-        Objects.requireNonNull(admin);
-        final CallerIdentity caller = getCallerIdentity(admin);
+        final CallerIdentity caller = getCallerIdentity(admin, packageName);
 
         synchronized (getLockObject()) {
-            Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)
-                    || isDeviceOwner(caller));
+            if (admin != null) {
+                Preconditions.checkCallAuthorization(
+                        isProfileOwnerOfOrganizationOwnedDevice(caller)
+                        || isDeviceOwner(caller));
+            } else {
+                // A delegate app passes a null admin component, which is expected
+                Preconditions.checkCallAuthorization(
+                        isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+            }
+
             if (enabled == mInjector.securityLogGetLoggingEnabledProperty()) {
                 return;
             }
@@ -13949,17 +13980,23 @@
     }
 
     @Override
-    public boolean isSecurityLoggingEnabled(ComponentName admin) {
+    public boolean isSecurityLoggingEnabled(ComponentName admin, String packageName) {
         if (!mHasFeature) {
             return false;
         }
 
         synchronized (getLockObject()) {
             if (!isCallerWithSystemUid()) {
-                Objects.requireNonNull(admin);
-                final CallerIdentity caller = getCallerIdentity(admin);
-                Preconditions.checkCallAuthorization(
-                        isProfileOwnerOfOrganizationOwnedDevice(caller) || isDeviceOwner(caller));
+                final CallerIdentity caller = getCallerIdentity(admin, packageName);
+                if (admin != null) {
+                    Preconditions.checkCallAuthorization(
+                            isProfileOwnerOfOrganizationOwnedDevice(caller)
+                            || isDeviceOwner(caller));
+                } else {
+                    // A delegate app passes a null admin component, which is expected
+                    Preconditions.checkCallAuthorization(
+                            isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+                }
             }
             return mInjector.securityLogGetLoggingEnabledProperty();
         }
@@ -13977,15 +14014,23 @@
     }
 
     @Override
-    public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin) {
+    public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin,
+            String packageName) {
         if (!mHasFeature) {
             return null;
         }
-        Objects.requireNonNull(admin, "ComponentName is null");
 
-        final CallerIdentity caller = getCallerIdentity(admin);
-        Preconditions.checkCallAuthorization(isDeviceOwner(caller)
-                || isProfileOwnerOfOrganizationOwnedDevice(caller));
+        final CallerIdentity caller = getCallerIdentity(admin, packageName);
+        if (admin != null) {
+            Preconditions.checkCallAuthorization(
+                    isProfileOwnerOfOrganizationOwnedDevice(caller)
+                    || isDeviceOwner(caller));
+        } else {
+            // A delegate app passes a null admin component, which is expected
+            Preconditions.checkCallAuthorization(
+                    isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+        }
+
         Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile()
                 || areAllUsersAffiliatedWithDeviceLocked());
 
@@ -14015,15 +14060,22 @@
     }
 
     @Override
-    public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin) {
+    public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin,
+            String packageName) {
         if (!mHasFeature) {
             return null;
         }
-        Objects.requireNonNull(admin, "ComponentName is null");
 
-        final CallerIdentity caller = getCallerIdentity(admin);
-        Preconditions.checkCallAuthorization(isDeviceOwner(caller)
-                || isProfileOwnerOfOrganizationOwnedDevice(caller));
+        final CallerIdentity caller = getCallerIdentity(admin, packageName);
+        if (admin != null) {
+            Preconditions.checkCallAuthorization(
+                    isProfileOwnerOfOrganizationOwnedDevice(caller)
+                    || isDeviceOwner(caller));
+        } else {
+            // A delegate app passes a null admin component, which is expected
+            Preconditions.checkCallAuthorization(
+                    isCallerDelegate(caller, DELEGATION_SECURITY_LOGGING));
+        }
         Preconditions.checkCallAuthorization(isOrganizationOwnedDeviceWithManagedProfile()
                 || areAllUsersAffiliatedWithDeviceLocked());
 
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index 7e85f9d..3465499 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -255,7 +255,7 @@
 
 static JNIEnv* getOrAttachJniEnv(JavaVM* jvm);
 
-class RealTimedQueueWrapper : public TimedQueueWrapper {
+class RealTimedQueueWrapper final : public TimedQueueWrapper {
 public:
     RealTimedQueueWrapper(JavaVM* jvm) {
         mThread = std::thread([this, jvm]() {
@@ -268,11 +268,11 @@
         CHECK(!mThread.joinable()) << "call stop first";
     }
 
-    void addJob(MountId id, Milliseconds after, Job what) final {
+    void addJob(MountId id, Milliseconds timeout, Job what) final {
         const auto now = Clock::now();
         {
             std::unique_lock lock(mMutex);
-            mJobs.insert(TimedJob{id, now + after, std::move(what)});
+            mJobs.insert(TimedJob{id, now + timeout, std::move(what)});
         }
         mCondition.notify_all();
     }
@@ -293,29 +293,28 @@
 private:
     void runTimers() {
         static constexpr TimePoint kInfinityTs{Clock::duration::max()};
-        TimePoint nextJobTs = kInfinityTs;
         std::unique_lock lock(mMutex);
         for (;;) {
-            mCondition.wait_until(lock, nextJobTs, [this, nextJobTs]() {
+            const TimePoint nextJobTs = mJobs.empty() ? kInfinityTs : mJobs.begin()->when;
+            mCondition.wait_until(lock, nextJobTs, [this, oldNextJobTs = nextJobTs]() {
                 const auto now = Clock::now();
-                const auto firstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs;
-                return !mRunning || firstJobTs <= now || firstJobTs < nextJobTs;
+                const auto newFirstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs;
+                return newFirstJobTs <= now || newFirstJobTs < oldNextJobTs || !mRunning;
             });
             if (!mRunning) {
                 return;
             }
 
             const auto now = Clock::now();
-            auto it = mJobs.begin();
-            // Always acquire begin(). We can't use it after unlock as mTimedJobs can change.
-            for (; it != mJobs.end() && it->when <= now; it = mJobs.begin()) {
+            // Always re-acquire begin(). We can't use it after unlock as mTimedJobs can change.
+            for (auto it = mJobs.begin(); it != mJobs.end() && it->when <= now;
+                 it = mJobs.begin()) {
                 auto jobNode = mJobs.extract(it);
 
                 lock.unlock();
                 jobNode.value().what();
                 lock.lock();
             }
-            nextJobTs = it != mJobs.end() ? it->when : kInfinityTs;
         }
     }
 
@@ -328,7 +327,7 @@
         }
     };
     bool mRunning = true;
-    std::set<TimedJob> mJobs;
+    std::multiset<TimedJob> mJobs;
     std::condition_variable mCondition;
     std::mutex mMutex;
     std::thread mThread;
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS
index 5a4431e..5492dc8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS
@@ -1,2 +1 @@
-calin@google.com
-ngeoffray@google.com
+include platform/art:/OWNERS
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index bcd853c..dcb2c15 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -186,11 +186,14 @@
         LogicalDisplay display2 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0));
         LogicalDisplay display3 = add(createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, 0));
 
+        // Physical displays should be automatically put into the default group.
         assertEquals(Display.DEFAULT_DISPLAY_GROUP,
                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display1)));
         assertEquals(Display.DEFAULT_DISPLAY_GROUP,
                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display2)));
-        assertEquals(Display.DEFAULT_DISPLAY_GROUP,
+
+        // Virtual displays should belong to no group by default.
+        assertEquals(Display.INVALID_DISPLAY_GROUP,
                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
     }
 
@@ -212,13 +215,13 @@
         assertNotEquals(Display.DEFAULT_DISPLAY_GROUP,
                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
 
-        // Now switch it back to the default group by removing the flag and issuing an update
+        // Now switch it to the invalid group by removing the flag and issuing an update
         DisplayDeviceInfo info = device3.getSourceInfo();
         info.flags = info.flags & ~DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP;
         mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
 
-        // Verify the new group is correct.
-        assertEquals(Display.DEFAULT_DISPLAY_GROUP,
+        // Verify the virtual display has not been placed into a group.
+        assertEquals(Display.INVALID_DISPLAY_GROUP,
                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
     }
 
diff --git a/telecomm/java/android/telecom/CallDiagnosticService.java b/telecomm/java/android/telecom/CallDiagnosticService.java
index f5357b1..011dc17 100644
--- a/telecomm/java/android/telecom/CallDiagnosticService.java
+++ b/telecomm/java/android/telecom/CallDiagnosticService.java
@@ -27,6 +27,8 @@
 import android.os.HandlerExecutor;
 import android.os.IBinder;
 import android.os.RemoteException;
+
+import android.telephony.CallQuality;
 import android.util.ArrayMap;
 
 import com.android.internal.telecom.ICallDiagnosticService;
@@ -111,6 +113,12 @@
                 @NonNull DisconnectCause disconnectCause) throws RemoteException {
             handleCallDisconnected(callId, disconnectCause);
         }
+
+        @Override
+        public void callQualityChanged(String callId, CallQuality callQuality)
+                throws RemoteException {
+            handleCallQualityChanged(callId, callQuality);
+        }
     }
 
     /**
@@ -375,6 +383,21 @@
     }
 
     /**
+     * Handles a change reported by Telecom to the call quality for a call.
+     * @param callId the call ID the change applies to.
+     * @param callQuality The new call quality.
+     */
+    private void handleCallQualityChanged(@NonNull String callId,
+            @NonNull CallQuality callQuality) {
+        Log.i(this, "handleCallQualityChanged; call=%s, cq=%s", callId, callQuality);
+        CallDiagnostics callDiagnostics;
+        callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
+        if (callDiagnostics != null) {
+            callDiagnostics.onCallQualityReceived(callQuality);
+        }
+    }
+
+    /**
      * Handles a request from a {@link CallDiagnostics} to send a device to device message (received
      * via {@link CallDiagnostics#sendDeviceToDeviceMessage(int, int)}.
      * @param callDiagnostics
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 6dab6df..2dc18e8 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -44,6 +44,7 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.telephony.CallQuality;
 import android.telephony.ims.ImsStreamMediaProfile;
 import android.util.ArraySet;
 import android.view.Surface;
@@ -978,6 +979,23 @@
     public static final String EXTRA_DEVICE_TO_DEVICE_MESSAGE_VALUE =
             "android.telecom.extra.DEVICE_TO_DEVICE_MESSAGE_VALUE";
 
+    /**
+     * Connection event used to communicate a {@link android.telephony.CallQuality} report from
+     * telephony to Telecom for relaying to
+     * {@link DiagnosticCall#onCallQualityReceived(CallQuality)}.
+     * @hide
+     */
+    public static final String EVENT_CALL_QUALITY_REPORT =
+            "android.telecom.event.CALL_QUALITY_REPORT";
+
+    /**
+     * Extra sent with {@link #EVENT_CALL_QUALITY_REPORT} containing the
+     * {@link android.telephony.CallQuality} data.
+     * @hide
+     */
+    public static final String EXTRA_CALL_QUALITY_REPORT =
+            "android.telecom.extra.CALL_QUALITY_REPORT";
+
     // Flag controlling whether PII is emitted into the logs
     private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
 
diff --git a/telecomm/java/com/android/internal/telecom/ICallDiagnosticService.aidl b/telecomm/java/com/android/internal/telecom/ICallDiagnosticService.aidl
index fc9879a..4bd369f 100644
--- a/telecomm/java/com/android/internal/telecom/ICallDiagnosticService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallDiagnosticService.aidl
@@ -20,6 +20,7 @@
 import android.telecom.CallAudioState;
 import android.telecom.DisconnectCause;
 import android.telecom.ParcelableCall;
+import android.telephony.CallQuality;
 import com.android.internal.telecom.ICallDiagnosticServiceAdapter;
 
 /**
@@ -34,6 +35,7 @@
     void updateCallAudioState(in CallAudioState callAudioState);
     void removeDiagnosticCall(in String callId);
     void receiveDeviceToDeviceMessage(in String callId, int message, int value);
+    void callQualityChanged(in String callId, in CallQuality callQuality);
     void receiveBluetoothCallQualityReport(in BluetoothCallQualityReport qualityReport);
     void notifyCallDisconnected(in String callId, in DisconnectCause disconnectCause);
 }
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 4926687..17af463 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -19,6 +19,7 @@
 import android.Manifest;
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -2207,7 +2208,9 @@
      *
      * @return the total number of SMS records which can be stored on the SIM card.
      */
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @RequiresPermission(anyOf = {android.Manifest.permission.READ_PHONE_STATE,
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE})
+    @IntRange(from = 0)
     public int getSmsCapacityOnIcc() {
         int ret = 0;
         try {