Merge "Apply syncPipSurfaceState synchronously" into udc-dev
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 9bd2970..0c9569f 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -4157,6 +4157,7 @@
 
   public static class WindowInfosListenerForTest.WindowInfo {
     field @NonNull public final android.graphics.Rect bounds;
+    field public final int displayId;
     field public final boolean isTrustedOverlay;
     field public final boolean isVisible;
     field @NonNull public final String name;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 960d10a..048289f 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2628,15 +2628,6 @@
             return Build.VERSION_CODES.CUR_DEVELOPMENT;
         }
 
-        // STOPSHIP: hack for the pre-release SDK
-        if (platformSdkCodenames.length == 0
-                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
-                targetCode)) {
-            Slog.w(TAG, "Package requires development platform " + targetCode
-                    + ", returning current version " + Build.VERSION.SDK_INT);
-            return Build.VERSION.SDK_INT;
-        }
-
         // Otherwise, we're looking at an incompatible pre-release SDK.
         if (platformSdkCodenames.length > 0) {
             outError[0] = "Requires development platform " + targetCode
@@ -2708,15 +2699,6 @@
             return Build.VERSION_CODES.CUR_DEVELOPMENT;
         }
 
-        // STOPSHIP: hack for the pre-release SDK
-        if (platformSdkCodenames.length == 0
-                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
-                minCode)) {
-            Slog.w(TAG, "Package requires min development platform " + minCode
-                    + ", returning current version " + Build.VERSION.SDK_INT);
-            return Build.VERSION.SDK_INT;
-        }
-
         // Otherwise, we're looking at an incompatible pre-release SDK.
         if (platformSdkCodenames.length > 0) {
             outError[0] = "Requires development platform " + minCode
diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
index 8cc4cdb..3e1c5bb 100644
--- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
@@ -316,15 +316,6 @@
             return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
         }
 
-        // STOPSHIP: hack for the pre-release SDK
-        if (platformSdkCodenames.length == 0
-                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
-                        minCode)) {
-            Slog.w(TAG, "Parsed package requires min development platform " + minCode
-                    + ", returning current version " + Build.VERSION.SDK_INT);
-            return input.success(Build.VERSION.SDK_INT);
-        }
-
         // Otherwise, we're looking at an incompatible pre-release SDK.
         if (platformSdkCodenames.length > 0) {
             return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
@@ -377,27 +368,19 @@
             return input.success(targetVers);
         }
 
-        // If it's a pre-release SDK and the codename matches this platform, it
-        // definitely targets this SDK.
-        if (matchTargetCode(platformSdkCodenames, targetCode)) {
-            return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
-        }
-
-        // STOPSHIP: hack for the pre-release SDK
-        if (platformSdkCodenames.length == 0
-                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
-                        targetCode)) {
-            Slog.w(TAG, "Parsed package requires development platform " + targetCode
-                    + ", returning current version " + Build.VERSION.SDK_INT);
-            return input.success(Build.VERSION.SDK_INT);
-        }
-
         try {
             if (allowUnknownCodenames && UnboundedSdkLevel.isAtMost(targetCode)) {
                 return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
             }
         } catch (IllegalArgumentException e) {
-            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, "Bad package SDK");
+            // isAtMost() throws it when encountering an older SDK codename
+            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, e.getMessage());
+        }
+
+        // If it's a pre-release SDK and the codename matches this platform, it
+        // definitely targets this SDK.
+        if (matchTargetCode(platformSdkCodenames, targetCode)) {
+            return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
         }
 
         // Otherwise, we're looking at an incompatible pre-release SDK.
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 48b5cac..d352be1 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -3202,8 +3202,9 @@
      * or if the camera device isn't a primary rear/front camera, the minimum required output
      * stream configurations are the same as for applications targeting SDK version older than
      * 31.</p>
-     * <p>Refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} and {@link android.hardware.camera2.CameraDevice#createCaptureSession } for additional mandatory
-     * stream configurations on a per-capability basis.</p>
+     * <p>Refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} and
+     * {@link android.hardware.camera2.CameraDevice#legacy-level-guaranteed-configurations }
+     * for additional mandatory stream configurations on a per-capability basis.</p>
      * <p>*1: For JPEG format, the sizes may be restricted by below conditions:</p>
      * <ul>
      * <li>The HAL may choose the aspect ratio of each Jpeg size to be one of well known ones
@@ -3321,12 +3322,11 @@
      * {@link android.hardware.camera2.CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL }
      * and {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES }.
      * This is an app-readable conversion of the mandatory stream combination
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
+     * {@link android.hardware.camera2.CameraDevice#legacy-level-guaranteed-configurations tables}.</p>
      * <p>The array of
      * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
      * generated according to the documented
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession guideline} based on
-     * specific device level and capabilities.
+     * {@link android.hardware.camera2.CameraDevice#legacy-level-guaranteed-configurations guideline} based on specific device level and capabilities.
      * Clients can use the array as a quick reference to find an appropriate camera stream
      * combination.
      * As per documentation, the stream combinations with given PREVIEW, RECORD and
@@ -3355,12 +3355,11 @@
     /**
      * <p>An array of mandatory concurrent stream combinations.
      * This is an app-readable conversion of the concurrent mandatory stream combination
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
+     * {@link android.hardware.camera2.CameraDevice#concurrent-stream-guaranteed-configurations tables}.</p>
      * <p>The array of
      * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
      * generated according to the documented
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession guideline} for each
-     * device which has its Id present in the set returned by
+     * {@link android.hardware.camera2.CameraDevice#concurrent-stream-guaranteed-configurations guideline} for each device which has its Id present in the set returned by
      * {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds }.
      * Clients can use the array as a quick reference to find an appropriate camera stream
      * combination.
@@ -3465,7 +3464,8 @@
      * <p>If a camera device supports multi-resolution output streams for a particular format, for
      * each of its mandatory stream combinations, the camera device will support using a
      * MultiResolutionImageReader for the MAXIMUM stream of supported formats. Refer to
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession } for additional details.</p>
+     * {@link android.hardware.camera2.CameraDevice#legacy-level-additional-guaranteed-combinations-with-multiresolutionoutputs }
+     * for additional details.</p>
      * <p>To use multi-resolution input streams, the supported formats can be queried by {@link android.hardware.camera2.params.MultiResolutionStreamConfigurationMap#getInputFormats }.
      * A reprocessable CameraCaptureSession can then be created using an {@link android.hardware.camera2.params.InputConfiguration InputConfiguration} constructed with
      * the input MultiResolutionStreamInfo group, queried by {@link android.hardware.camera2.params.MultiResolutionStreamConfigurationMap#getInputInfo }.</p>
@@ -3473,8 +3473,8 @@
      * {@code YUV} output, or multi-resolution {@code PRIVATE} input and multi-resolution
      * {@code PRIVATE} output, {@code JPEG} and {@code YUV} are guaranteed to be supported
      * multi-resolution output stream formats. Refer to
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession } for
-     * details about the additional mandatory stream combinations in this case.</p>
+     * {@link android.hardware.camera2.CameraDevice#legacy-level-additional-guaranteed-combinations-with-multiresolutionoutputs }}
+     * for details about the additional mandatory stream combinations in this case.</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      */
     @PublicKey
@@ -3586,12 +3586,11 @@
      * {@link android.hardware.camera2.CaptureRequest } has {@link CaptureRequest#SENSOR_PIXEL_MODE android.sensor.pixelMode} set
      * to {@link android.hardware.camera2.CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION }.
      * This is an app-readable conversion of the maximum resolution mandatory stream combination
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
+     * {@link android.hardware.camera2.CameraDevice#additional-guaranteed-combinations-for-ultra-high-resolution-sensors tables}.</p>
      * <p>The array of
      * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
      * generated according to the documented
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession guideline} for each
-     * device which has the
+     * {@link android.hardware.camera2.CameraDevice#additional-guaranteed-combinations-for-ultra-high-resolution-sensors guideline} for each device which has the
      * {@link android.hardware.camera2.CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR }
      * capability.
      * Clients can use the array as a quick reference to find an appropriate camera stream
@@ -3614,12 +3613,11 @@
      * 10-bit output capability
      * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT }
      * This is an app-readable conversion of the 10 bit output mandatory stream combination
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
+     * {@link android.hardware.camera2.CameraDevice#10-bit-output-additional-guaranteed-configurations tables}.</p>
      * <p>The array of
      * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
      * generated according to the documented
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession guideline} for each
-     * device which has the
+     * {@link android.hardware.camera2.CameraDevice#10-bit-output-additional-guaranteed-configurations guideline} for each device which has the
      * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT }
      * capability.
      * Clients can use the array as a quick reference to find an appropriate camera stream
@@ -3639,12 +3637,12 @@
      * <p>An array of mandatory stream combinations which are applicable when device lists
      * {@code PREVIEW_STABILIZATION} in {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES android.control.availableVideoStabilizationModes}.
      * This is an app-readable conversion of the preview stabilization mandatory stream
-     * combination {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
+     * combination
+     * {@link android.hardware.camera2.CameraDevice#preview-stabilization-guaranteed-stream-configurations tables}.</p>
      * <p>The array of
      * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
      * generated according to the documented
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession guideline} for each
-     * device which supports {@code PREVIEW_STABILIZATION}
+     * {@link android.hardware.camera2.CameraDevice#preview-stabilization-guaranteed-stream-configurations guideline} for each device which supports {@code PREVIEW_STABILIZATION}
      * Clients can use the array as a quick reference to find an appropriate camera stream
      * combination.
      * The mandatory stream combination array will be {@code null} in case the device does not
@@ -3717,8 +3715,8 @@
      * <p>The guaranteed stream combinations related to stream use case for a camera device with
      * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE }
      * capability is documented in the camera device
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession guideline}. The
-     * application is strongly recommended to use one of the guaranteed stream combinations.
+     * {@link android.hardware.camera2.CameraDevice#stream-use-case-capability-additional-guaranteed-configurations guideline}. The application is strongly recommended to use one of the guaranteed stream
+     * combinations.
      * If the application creates a session with a stream combination not in the guaranteed
      * list, or with mixed DEFAULT and non-DEFAULT use cases within the same session,
      * the camera device may ignore some stream use cases due to hardware constraints
@@ -3754,13 +3752,11 @@
     /**
      * <p>An array of mandatory stream combinations with stream use cases.
      * This is an app-readable conversion of the mandatory stream combination
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession tables} with
-     * each stream's use case being set.</p>
+     * {@link android.hardware.camera2.CameraDevice#stream-use-case-capability-additional-guaranteed-configurations tables} with each stream's use case being set.</p>
      * <p>The array of
      * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
      * generated according to the documented
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession guideline} for a
-     * camera device with
+     * {@link android.hardware.camera2.CameraDevice#stream-use-case-capability-additional-guaranteed-configurations guideline} for a camera device with
      * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE }
      * capability.
      * The mandatory stream combination array will be {@code null} in case the device doesn't
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index ad68866..99b297a 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -636,8 +636,9 @@
      * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}) support at
      * least the following stream combinations:
      *
+     * <h5>LEGACY-level guaranteed configurations</h5>
+     *
      * <table>
-     * <tr><th colspan="7">LEGACY-level guaranteed configurations</th></tr>
      * <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th>  <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
      * <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
      * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
@@ -656,8 +657,9 @@
      * support at least the following stream combinations in addition to those for
      * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY} devices:
      *
+     * <h5>LIMITED-level additional guaranteed configurations</h5>
+     *
      * <table>
-     * <tr><th colspan="7">LIMITED-level additional guaranteed configurations</th></tr>
      * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
      * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>High-resolution video recording with preview.</td> </tr>
@@ -674,8 +676,9 @@
      * support at least the following stream combinations in addition to those for
      * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
      *
+     * <h5>FULL-level additional guaranteed configurations</h5>
+     *
      * <table>
-     * <tr><th colspan="7">FULL-level additional guaranteed configurations</th></tr>
      * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
      * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution GPU processing with preview.</td> </tr>
@@ -693,8 +696,9 @@
      * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} and
      * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
      *
+     * <h5>RAW-capability additional guaranteed configurations</h5>
+     *
      * <table>
-     * <tr><th colspan="7">RAW-capability additional guaranteed configurations</th></tr>
      * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
      * <tr> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>No-preview DNG capture.</td> </tr>
@@ -716,8 +720,9 @@
      * list for FULL-level devices, so this table is only relevant for LIMITED-level devices that
      * support the BURST_CAPTURE capability.
      *
+     * <h5>BURST-capability additional guaranteed configurations</h5>
+     *
      * <table>
-     * <tr><th colspan="5">BURST-capability additional guaranteed configurations</th></tr>
      * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
      * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>Maximum-resolution GPU processing with preview.</td> </tr>
@@ -733,8 +738,9 @@
      * RAW capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
      * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}):
      *
+     * <h5>LEVEL-3 additional guaranteed configurations</h5>
+     *
      * <table>
-     * <tr><th colspan="11">LEVEL-3 additional guaranteed configurations</th></tr>
      * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
      * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code 640x480}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td> <td>In-app viewfinder analysis with dynamic selection of output format.</td> </tr>
@@ -748,8 +754,9 @@
      * <p> Note: The sizes mentioned for these concurrent streams are the maximum sizes guaranteed
      * to be supported. Sizes smaller than these, obtained by {@link StreamConfigurationMap#getOutputSizes} for a particular format, are supported as well. </p>
      *
+     * <h5>Concurrent stream guaranteed configurations</h5>
+     *
      * <table>
-     * <tr><th colspan="5">Concurrent stream guaranteed configurations</th></tr>
      * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
      * <tr> <td>{@code YUV}</td><td id="rb">{@code s1440p}</td>  <td colspan="2" id="rb"></td> <td>In-app video / image processing.</td> </tr>
@@ -794,8 +801,9 @@
      * stream combinations ({@code MULTI_RES} in the Max size column refers to a {@link
      * MultiResolutionImageReader} created based on the variable max resolutions supported):
      *
+     * <h5>LEGACY-level additional guaranteed combinations with MultiResolutionoutputs</h5>
+     *
      * <table>
-     * <tr><th colspan="7">LEGACY-level additional guaranteed combinations with MultiResolutionoutputs</th></tr>
      * <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th>  <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
      * <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
      * <tr> <td>{@code PRIV}</td><td id="rb">{@code MULTI_RES}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
@@ -814,8 +822,10 @@
      *
      * <p> Devices with the ULTRA_HIGH_RESOLUTION_SENSOR capability have some additional guarantees
      * which clients can take advantage of : </p>
+     *
+     * <h5>Additional guaranteed combinations for ULTRA_HIGH_RESOLUTION sensors</h5>
+     *
      * <table>
-     * <tr><th colspan="10">Additional guaranteed combinations for ULTRA_HIGH_RESOLUTION sensors</th></tr>
      * <tr> <th colspan="3" id="rb">Target 1</th> <th colspan="3" id="rb">Target 2</th>  <th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
      * <tr> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th></tr>
      * <tr> <td>{@code YUV / JPEG / RAW}</td><td id="rb">{@code MAX_RES}</td><td id="rb">{@code MAX}</td><td id="rb">{@code PRIV / YUV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code PREVIEW}</td><td colspan="3" id="rb"></td> <td>Ultra high res still image capture with preview</td> </tr>
@@ -834,8 +844,10 @@
      * <p> 10-bit output capable
      * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT}
      * devices support at least the following stream combinations: </p>
+     *
+     * <h5>10-bit output additional guaranteed configurations</h5>
+     *
      * <table>
-     * <tr><th colspan="7">10-bit output additional guaranteed configurations</th></tr>
      * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
      * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> }</td> <td colspan="4" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
@@ -887,8 +899,9 @@
      * CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE}) support below additional
      * stream combinations:
      *
+     * <h5>STREAM_USE_CASE capability additional guaranteed configurations</h5>
+     *
      * <table>
-     * <tr><th colspan="10">STREAM_USE_CASE capability additional guaranteed configurations</th></tr>
      * <tr><th colspan="3" id="rb">Target 1</th><th colspan="3" id="rb">Target 2</th><th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th> </tr>
      * <tr> <td>{@code YUV / PRIV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td colspan="3" id="rb"></td> <td colspan="3" id="rb"></td> <td>Simple preview or in-app image processing</td> </tr>
@@ -911,8 +924,9 @@
      * stream use-case in {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_USE_CASES},
      * support the additional stream combinations below:
      *
+     * <h5>STREAM_USE_CASE_CROPPED_RAW capability additional guaranteed configurations</h5>
+     *
      * <table>
-     * <tr><th colspan="10">STREAM_USE_CASE_CROPPED_RAW capability additional guaranteed configurations</th></tr>
      * <tr><th colspan="3" id="rb">Target 1</th><th colspan="3" id="rb">Target 2</th><th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th> </tr>
      * <tr> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td colspan="3" id="rb"></td> <td colspan="3" id="rb"></td> <td>Cropped RAW still capture without preview</td> </tr>
@@ -926,8 +940,10 @@
      * the following stream combinations are guaranteed,
      * for CaptureRequests where {@link CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE} is set to
      * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION} <p>
+     *
+     * <h5>Preview stabilization guaranteed stream configurations</h5>
+     *
      * <table>
-     * <tr><th colspan="7">Preview stabilization guaranteed stream configurations</th></tr>
      * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
      * <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code s1440p}</td><td colspan="2" id="rb"></td> <td>Stabilized preview, GPU video processing, or no-preview stabilized video recording.</td> </tr>
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 4950373..dfc27ca 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1213,7 +1213,8 @@
      * <ul>
      * <li>Profile {@link android.hardware.camera2.params.DynamicRangeProfiles#HLG10 }</li>
      * <li>All mandatory stream combinations for this specific capability as per
-     *   documentation {@link android.hardware.camera2.CameraDevice#createCaptureSession }</li>
+     *   documentation
+     *   {@link android.hardware.camera2.CameraDevice#10-bit-output-additional-guaranteed-configurations }</li>
      * <li>In case the device is not able to capture some combination of supported
      *   standard 8-bit and/or 10-bit dynamic range profiles within the same capture request,
      *   then those constraints must be listed in
@@ -1252,9 +1253,10 @@
      * </ul>
      * <p>{@link android.hardware.camera2.CameraCharacteristics#SCALER_AVAILABLE_STREAM_USE_CASES }
      * lists all of the supported stream use cases.</p>
-     * <p>Refer to {@link android.hardware.camera2.CameraDevice#createCaptureSession } for the
-     * mandatory stream combinations involving stream use cases, which can also be queried
-     * via {@link android.hardware.camera2.params.MandatoryStreamCombination }.</p>
+     * <p>Refer to
+     * {@link android.hardware.camera2.CameraDevice#stream-use-case-capability-additional-guaranteed-configurations }
+     * for the mandatory stream combinations involving stream use cases, which can also be
+     * queried via {@link android.hardware.camera2.params.MandatoryStreamCombination }.</p>
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      */
     public static final int REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE = 19;
@@ -1752,7 +1754,8 @@
      * <p>This camera device does not have enough capabilities to qualify as a <code>FULL</code> device or
      * better.</p>
      * <p>Only the stream configurations listed in the <code>LEGACY</code> and <code>LIMITED</code> tables in the
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
+     * {@link android.hardware.camera2.CameraDevice#limited-level-additional-guaranteed-configurations }
+     * documentation are guaranteed to be supported.</p>
      * <p>All <code>LIMITED</code> devices support the <code>BACKWARDS_COMPATIBLE</code> capability, indicating basic
      * support for color image capture. The only exception is that the device may
      * alternatively support only the <code>DEPTH_OUTPUT</code> capability, if it can only output depth
@@ -1779,7 +1782,8 @@
     /**
      * <p>This camera device is capable of supporting advanced imaging applications.</p>
      * <p>The stream configurations listed in the <code>FULL</code>, <code>LEGACY</code> and <code>LIMITED</code> tables in the
-     * {@link android.hardware.camera2.CameraDevice#createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
+     * {@link android.hardware.camera2.CameraDevice#full-level-additional-guaranteed-configurations }
+     * documentation are guaranteed to be supported.</p>
      * <p>A <code>FULL</code> device will support below capabilities:</p>
      * <ul>
      * <li><code>BURST_CAPTURE</code> capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
@@ -1807,7 +1811,9 @@
 
     /**
      * <p>This camera device is running in backward compatibility mode.</p>
-     * <p>Only the stream configurations listed in the <code>LEGACY</code> table in the {@link android.hardware.camera2.CameraDevice#createCaptureSession createCaptureSession} documentation are supported.</p>
+     * <p>Only the stream configurations listed in the <code>LEGACY</code> table in the
+     * {@link android.hardware.camera2.CameraDevice#legacy-level-guaranteed-configurations }
+     * documentation are supported.</p>
      * <p>A <code>LEGACY</code> device does not support per-frame control, manual sensor control, manual
      * post-processing, arbitrary cropping regions, and has relaxed performance constraints.
      * No additional capabilities beyond <code>BACKWARD_COMPATIBLE</code> will ever be listed by a
@@ -1830,7 +1836,9 @@
      * <p>This camera device is capable of YUV reprocessing and RAW data capture, in addition to
      * FULL-level capabilities.</p>
      * <p>The stream configurations listed in the <code>LEVEL_3</code>, <code>RAW</code>, <code>FULL</code>, <code>LEGACY</code> and
-     * <code>LIMITED</code> tables in the {@link android.hardware.camera2.CameraDevice#createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
+     * <code>LIMITED</code> tables in the
+     * {@link android.hardware.camera2.CameraDevice#level-3-additional-guaranteed-configurations }
+     * documentation are guaranteed to be supported.</p>
      * <p>The following additional capabilities are guaranteed to be supported:</p>
      * <ul>
      * <li><code>YUV_REPROCESSING</code> capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
index d87226c..65d4b43 100644
--- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
@@ -77,18 +77,18 @@
     private static final String TAG = "CameraAdvancedExtensionSessionImpl";
 
     private final Executor mExecutor;
-    private final CameraDevice mCameraDevice;
+    private CameraDevice mCameraDevice;
     private final Map<String, CameraMetadataNative> mCharacteristicsMap;
     private final long mExtensionClientId;
     private final Handler mHandler;
     private final HandlerThread mHandlerThread;
     private final CameraExtensionSession.StateCallback mCallbacks;
-    private final IAdvancedExtenderImpl mAdvancedExtender;
+    private IAdvancedExtenderImpl mAdvancedExtender;
     // maps registered camera surfaces to extension output configs
     private final HashMap<Surface, CameraOutputConfig> mCameraConfigMap = new HashMap<>();
     // maps camera extension output ids to camera registered image readers
     private final HashMap<Integer, ImageReader> mReaderMap = new HashMap<>();
-    private final RequestProcessor mRequestProcessor = new RequestProcessor();
+    private RequestProcessor mRequestProcessor = new RequestProcessor();
     private final int mSessionId;
 
     private Surface mClientRepeatingRequestSurface;
@@ -100,7 +100,7 @@
     private final ExtensionSessionStatsAggregator mStatsAggregator;
 
     private boolean mInitialized;
-
+    private boolean mSessionClosed;
 
     // Lock to synchronize cross-thread access to device public interface
     final Object mInterfaceLock;
@@ -237,6 +237,7 @@
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper());
         mInitialized = false;
+        mSessionClosed = false;
         mInitializeHandler = new InitializeSessionHandler();
         mSessionId = sessionId;
         mInterfaceLock = cameraDevice.mInterfaceLock;
@@ -424,7 +425,7 @@
                 mSessionProcessor.setParameters(request);
 
                 seqId = mSessionProcessor.startRepeating(new RequestCallbackHandler(request,
-                        executor, listener));
+                        executor, listener, mCameraDevice.getId()));
             } catch (RemoteException e) {
                 throw new CameraAccessException(CameraAccessException.CAMERA_ERROR,
                         "Failed to enable repeating request, extension service failed to respond!");
@@ -452,7 +453,7 @@
                     mSessionProcessor.setParameters(request);
 
                     seqId = mSessionProcessor.startCapture(new RequestCallbackHandler(request,
-                            executor, listener), isPostviewRequested);
+                            executor, listener, mCameraDevice.getId()), isPostviewRequested);
                 } catch (RemoteException e) {
                     throw new CameraAccessException(CameraAccessException.CAMERA_ERROR, "Failed " +
                             " to submit capture request, extension service failed to respond!");
@@ -460,8 +461,8 @@
             } else if ((mClientRepeatingRequestSurface != null) &&
                     request.containsTarget(mClientRepeatingRequestSurface)) {
                 try {
-                    seqId = mSessionProcessor.startTrigger(request,
-                            new RequestCallbackHandler(request, executor, listener));
+                    seqId = mSessionProcessor.startTrigger(request, new RequestCallbackHandler(
+                            request, executor, listener, mCameraDevice.getId()));
                 } catch (RemoteException e) {
                     throw new CameraAccessException(CameraAccessException.CAMERA_ERROR, "Failed " +
                             " to submit trigger request, extension service failed to respond!");
@@ -528,6 +529,7 @@
                     mCaptureSession.stopRepeating();
                     mSessionProcessor.stopRepeating();
                     mSessionProcessor.onCaptureSessionEnd();
+                    mSessionClosed = true;
                 } catch (RemoteException e) {
                     Log.e(TAG, "Failed to stop the repeating request or end the session,"
                             + " , extension service does not respond!") ;
@@ -560,6 +562,9 @@
 
             if (mSessionProcessor != null) {
                 try {
+                    if (!mSessionClosed) {
+                        mSessionProcessor.onCaptureSessionEnd();
+                    }
                     mSessionProcessor.deInitSession();
                 } catch (RemoteException e) {
                     Log.e(TAG, "Failed to de-initialize session processor, extension service"
@@ -584,6 +589,10 @@
 
             mClientRepeatingRequestSurface = null;
             mClientCaptureSurface = null;
+            mCaptureSession = null;
+            mRequestProcessor = null;
+            mCameraDevice = null;
+            mAdvancedExtender = null;
         }
 
         if (notifyClose && !skipCloseNotification) {
@@ -706,13 +715,16 @@
         private final CaptureRequest mClientRequest;
         private final Executor mClientExecutor;
         private final ExtensionCaptureCallback mClientCallbacks;
+        private final String mCameraId;
 
         private RequestCallbackHandler(@NonNull CaptureRequest clientRequest,
                 @NonNull Executor clientExecutor,
-                @NonNull ExtensionCaptureCallback clientCallbacks) {
+                @NonNull ExtensionCaptureCallback clientCallbacks,
+                @NonNull String cameraId) {
             mClientRequest = clientRequest;
             mClientExecutor = clientExecutor;
             mClientCallbacks = clientCallbacks;
+            mCameraId = cameraId;
         }
 
         @Override
@@ -784,7 +796,7 @@
             }
 
             result.set(CaptureResult.SENSOR_TIMESTAMP, timestamp);
-            TotalCaptureResult totalResult = new TotalCaptureResult(mCameraDevice.getId(), result,
+            TotalCaptureResult totalResult = new TotalCaptureResult(mCameraId, result,
                     mClientRequest, requestId, timestamp, new ArrayList<>(), mSessionId,
                     new PhysicalCaptureResultInfo[0]);
             final long ident = Binder.clearCallingIdentity();
@@ -1036,14 +1048,20 @@
         public int submitBurst(List<Request> requests, IRequestCallback callback) {
             int seqId = -1;
             try {
-                CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback);
-                ArrayList<CaptureRequest> captureRequests = new ArrayList<>();
-                for (Request request : requests) {
-                    captureRequests.add(initializeCaptureRequest(mCameraDevice, request,
-                            mCameraConfigMap));
+                synchronized (mInterfaceLock) {
+                    if (!mInitialized) {
+                        return seqId;
+                    }
+
+                    CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback);
+                    ArrayList<CaptureRequest> captureRequests = new ArrayList<>();
+                    for (Request request : requests) {
+                        captureRequests.add(initializeCaptureRequest(mCameraDevice, request,
+                                mCameraConfigMap));
+                    }
+                    seqId = mCaptureSession.captureBurstRequests(captureRequests,
+                            new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback);
                 }
-                seqId = mCaptureSession.captureBurstRequests(captureRequests,
-                        new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback);
             } catch (CameraAccessException e) {
                 Log.e(TAG, "Failed to submit capture requests!");
             } catch (IllegalStateException e) {
@@ -1057,11 +1075,17 @@
         public int setRepeating(Request request, IRequestCallback callback) {
             int seqId = -1;
             try {
-                CaptureRequest repeatingRequest = initializeCaptureRequest(mCameraDevice,
+                synchronized (mInterfaceLock) {
+                    if (!mInitialized) {
+                        return seqId;
+                    }
+
+                    CaptureRequest repeatingRequest = initializeCaptureRequest(mCameraDevice,
                             request, mCameraConfigMap);
-                CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback);
-                seqId = mCaptureSession.setSingleRepeatingRequest(repeatingRequest,
-                        new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback);
+                    CaptureCallbackHandler captureCallback = new CaptureCallbackHandler(callback);
+                    seqId = mCaptureSession.setSingleRepeatingRequest(repeatingRequest,
+                            new CameraExtensionUtils.HandlerExecutor(mHandler), captureCallback);
+                }
             } catch (CameraAccessException e) {
                 Log.e(TAG, "Failed to enable repeating request!");
             } catch (IllegalStateException e) {
@@ -1074,7 +1098,13 @@
         @Override
         public void abortCaptures() {
             try {
-                mCaptureSession.abortCaptures();
+                synchronized (mInterfaceLock) {
+                    if (!mInitialized) {
+                        return;
+                    }
+
+                    mCaptureSession.abortCaptures();
+                }
             } catch (CameraAccessException e) {
                 Log.e(TAG, "Failed during capture abort!");
             } catch (IllegalStateException e) {
@@ -1085,7 +1115,13 @@
         @Override
         public void stopRepeating() {
             try {
-                mCaptureSession.stopRepeating();
+                synchronized (mInterfaceLock) {
+                    if (!mInitialized) {
+                        return;
+                    }
+
+                    mCaptureSession.stopRepeating();
+                }
             } catch (CameraAccessException e) {
                 Log.e(TAG, "Failed during repeating capture stop!");
             } catch (IllegalStateException e) {
diff --git a/core/java/android/window/WindowInfosListenerForTest.java b/core/java/android/window/WindowInfosListenerForTest.java
index cfbeeff..25bf85c 100644
--- a/core/java/android/window/WindowInfosListenerForTest.java
+++ b/core/java/android/window/WindowInfosListenerForTest.java
@@ -58,6 +58,11 @@
         public final String name;
 
         /**
+         * The display id the window is on.
+         */
+        public final int displayId;
+
+        /**
          * The window's position and size in display space.
          */
         @NonNull
@@ -73,10 +78,11 @@
          */
         public final boolean isVisible;
 
-        WindowInfo(@NonNull IBinder windowToken, @NonNull String name, @NonNull Rect bounds,
-                int inputConfig) {
+        WindowInfo(@NonNull IBinder windowToken, @NonNull String name, int displayId,
+                @NonNull Rect bounds, int inputConfig) {
             this.windowToken = windowToken;
             this.name = name;
+            this.displayId = displayId;
             this.bounds = bounds;
             this.isTrustedOverlay = (inputConfig & InputConfig.TRUSTED_OVERLAY) != 0;
             this.isVisible = (inputConfig & InputConfig.NOT_VISIBLE) == 0;
@@ -139,8 +145,8 @@
         for (var handle : windowHandles) {
             var bounds = new Rect(handle.frameLeft, handle.frameTop, handle.frameRight,
                     handle.frameBottom);
-            windowInfos.add(new WindowInfo(handle.getWindowToken(), handle.name, bounds,
-                    handle.inputConfig));
+            windowInfos.add(new WindowInfo(handle.getWindowToken(), handle.name, handle.displayId,
+                    bounds, handle.inputConfig));
         }
         return windowInfos;
     }
diff --git a/core/tests/coretests/src/android/app/KeyguardManagerTest.java b/core/tests/coretests/src/android/app/KeyguardManagerTest.java
index 7231fbd..958906c 100644
--- a/core/tests/coretests/src/android/app/KeyguardManagerTest.java
+++ b/core/tests/coretests/src/android/app/KeyguardManagerTest.java
@@ -19,6 +19,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.doReturn;
@@ -26,6 +27,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 
@@ -209,6 +211,42 @@
         verifyDeviceLockedAndRemoveLock();
     }
 
+    @Test
+    public void createConfirmDeviceCredentialForRemoteValidationIntent() {
+        RemoteLockscreenValidationSession remoteLockscreenValidationSession =
+                new RemoteLockscreenValidationSession.Builder()
+                        .setSourcePublicKey("sourcePublicKey".getBytes())
+                        .build();
+        ComponentName componentName = new ComponentName("pkg", "cls");
+        String title = "title";
+        String description = "description";
+        String checkboxLabel = "checkboxLabel";
+        String alternateButtonLabel = "alternateButtonLabel";
+
+        Intent intent = mKeyguardManager.createConfirmDeviceCredentialForRemoteValidationIntent(
+                remoteLockscreenValidationSession,
+                componentName,
+                title,
+                description,
+                checkboxLabel,
+                alternateButtonLabel
+        );
+
+        assertNotNull(intent);
+        assertEquals(KeyguardManager.ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL, intent.getAction());
+        assertEquals(remoteLockscreenValidationSession,
+                intent.getParcelableExtra(
+                        KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION,
+                        RemoteLockscreenValidationSession.class));
+        assertEquals(componentName,
+                intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME, ComponentName.class));
+        assertEquals(title, intent.getStringExtra(KeyguardManager.EXTRA_TITLE));
+        assertEquals(description, intent.getStringExtra(KeyguardManager.EXTRA_DESCRIPTION));
+        assertEquals(checkboxLabel, intent.getStringExtra(KeyguardManager.EXTRA_CHECKBOX_LABEL));
+        assertEquals(alternateButtonLabel,
+                intent.getStringExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL));
+    }
+
     private void verifyDeviceLockedAndRemoveLock() {
         assertTrue(mKeyguardManager.isDeviceSecure());
         assertTrue("Failed to remove new password that was set in the test case.",
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java b/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java
index b2e42ba..df4fb44 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java
@@ -25,7 +25,6 @@
 import android.app.Activity;
 import android.compat.testing.PlatformCompatChangeRule;
 import android.os.Bundle;
-import android.platform.test.annotations.IwTest;
 import android.platform.test.annotations.PlatinumTest;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
@@ -74,7 +73,6 @@
     }
 
     @PlatinumTest(focusArea = "accessibility")
-    @IwTest(focusArea = "accessibility")
     @Test
     public void testFontsScaleNonLinearly() {
         final ActivityScenario<TestActivity> scenario = rule.getScenario();
@@ -106,7 +104,6 @@
     }
 
     @PlatinumTest(focusArea = "accessibility")
-    @IwTest(focusArea = "accessibility")
     @Test
     public void testOnConfigurationChanged_doesNotCrash() {
         final ActivityScenario<TestActivity> scenario = rule.getScenario();
@@ -121,7 +118,6 @@
     }
 
     @PlatinumTest(focusArea = "accessibility")
-    @IwTest(focusArea = "accessibility")
     @Test
     public void testUpdateConfiguration_doesNotCrash() {
         final ActivityScenario<TestActivity> scenario = rule.getScenario();
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
index 96190c4b..1e6e503 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -28,6 +28,7 @@
 import android.util.Pair;
 import android.view.Display;
 import android.view.DisplayAddress;
+import android.view.Surface;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -36,6 +37,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 
 import java.util.Objects;
@@ -229,27 +231,43 @@
      * @since {@link WindowExtensions#VENDOR_API_LEVEL_3}
      */
     @Override
+    @NonNull
     public DisplayMetrics getRearDisplayMetrics() {
-        DisplayMetrics metrics = null;
+        DisplayMetrics rearDisplayMetrics = null;
 
         // DISPLAY_CATEGORY_REAR displays are only available when you are in the concurrent
         // display state, so we have to look through all displays to match the address
-        Display[] displays = mDisplayManager.getDisplays(
+        final Display[] displays = mDisplayManager.getDisplays(
                 DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
+
+
         for (int i = 0; i < displays.length; i++) {
             DisplayAddress.Physical address =
                     (DisplayAddress.Physical) displays[i].getAddress();
             if (mRearDisplayAddress == address.getPhysicalDisplayId()) {
-                metrics = new DisplayMetrics();
-                displays[i].getRealMetrics(metrics);
+                rearDisplayMetrics = new DisplayMetrics();
+                final Display rearDisplay = displays[i];
+
+                // We must always retrieve the metrics for the rear display regardless of if it is
+                // the default display or not.
+                rearDisplay.getRealMetrics(rearDisplayMetrics);
+
+                // TODO(b/287170025): This should be something like if (!rearDisplay.isEnabled)
+                //  instead. Currently when the rear display is disabled, its state is STATE_OFF.
+                if (rearDisplay.getDisplayId() != Display.DEFAULT_DISPLAY) {
+                    final Display defaultDisplay = mDisplayManager
+                            .getDisplay(Display.DEFAULT_DISPLAY);
+                    rotateRearDisplayMetricsIfNeeded(defaultDisplay.getRotation(),
+                            rearDisplay.getRotation(), rearDisplayMetrics);
+                }
                 break;
             }
         }
 
         synchronized (mLock) {
             // Update the rear display metrics with our latest value if one was received
-            if (metrics != null) {
-                mRearDisplayMetrics = metrics;
+            if (rearDisplayMetrics != null) {
+                mRearDisplayMetrics = rearDisplayMetrics;
             }
 
             return Objects.requireNonNullElseGet(mRearDisplayMetrics, DisplayMetrics::new);
@@ -540,6 +558,34 @@
         return mLastReportedRearDisplayPresentationStatus;
     }
 
+    @VisibleForTesting
+    static void rotateRearDisplayMetricsIfNeeded(
+            @Surface.Rotation int defaultDisplayRotation,
+            @Surface.Rotation int rearDisplayRotation,
+            @NonNull DisplayMetrics inOutMetrics) {
+        // If the rear display has a non-zero rotation, it means the backing DisplayContent /
+        // DisplayRotation is fresh.
+        if (rearDisplayRotation != Surface.ROTATION_0) {
+            return;
+        }
+
+        // If the default display is 0 or 180, the rear display must also be 0 or 180.
+        if (defaultDisplayRotation == Surface.ROTATION_0
+                || defaultDisplayRotation == Surface.ROTATION_180) {
+            return;
+        }
+
+        final int heightPixels = inOutMetrics.heightPixels;
+        final int widthPixels = inOutMetrics.widthPixels;
+        inOutMetrics.widthPixels = heightPixels;
+        inOutMetrics.heightPixels = widthPixels;
+
+        final int noncompatHeightPixels = inOutMetrics.noncompatHeightPixels;
+        final int noncompatWidthPixels = inOutMetrics.noncompatWidthPixels;
+        inOutMetrics.noncompatWidthPixels = noncompatHeightPixels;
+        inOutMetrics.noncompatHeightPixels = noncompatWidthPixels;
+    }
+
     /**
      * Callback for the {@link DeviceStateRequest} to be notified of when the request has been
      * activated or cancelled. This callback provides information to the client library
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java
new file mode 100644
index 0000000..ccb4ebe
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.area;
+
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.Presubmit;
+import android.util.DisplayMetrics;
+import android.view.Surface;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WindowAreaComponentImplTests {
+
+    private final DisplayMetrics mTestDisplayMetrics = new DisplayMetrics();
+
+    @Before
+    public void setup() {
+        mTestDisplayMetrics.widthPixels = 1;
+        mTestDisplayMetrics.heightPixels = 2;
+        mTestDisplayMetrics.noncompatWidthPixels = 3;
+        mTestDisplayMetrics.noncompatHeightPixels = 4;
+    }
+
+    /**
+     * Cases where the rear display metrics does not need to be transformed.
+     */
+    @Test
+    public void testRotateRearDisplayMetrics_noTransformNeeded() {
+        final DisplayMetrics originalMetrics = new DisplayMetrics();
+        originalMetrics.setTo(mTestDisplayMetrics);
+
+        WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+                Surface.ROTATION_0, Surface.ROTATION_0, mTestDisplayMetrics);
+        assertEquals(originalMetrics, mTestDisplayMetrics);
+
+        WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+                Surface.ROTATION_180, Surface.ROTATION_180, mTestDisplayMetrics);
+        assertEquals(originalMetrics, mTestDisplayMetrics);
+
+        WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+                Surface.ROTATION_0, Surface.ROTATION_180, mTestDisplayMetrics);
+        assertEquals(originalMetrics, mTestDisplayMetrics);
+
+        WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+                Surface.ROTATION_180, Surface.ROTATION_0, mTestDisplayMetrics);
+        assertEquals(originalMetrics, mTestDisplayMetrics);
+    }
+
+    /**
+     * Cases where the rear display metrics need to be transformed.
+     */
+    @Test
+    public void testRotateRearDisplayMetrics_transformNeeded() {
+        DisplayMetrics originalMetrics = new DisplayMetrics();
+        originalMetrics.setTo(mTestDisplayMetrics);
+
+        DisplayMetrics expectedMetrics = new DisplayMetrics();
+        expectedMetrics.setTo(mTestDisplayMetrics);
+        expectedMetrics.widthPixels = mTestDisplayMetrics.heightPixels;
+        expectedMetrics.heightPixels = mTestDisplayMetrics.widthPixels;
+        expectedMetrics.noncompatWidthPixels = mTestDisplayMetrics.noncompatHeightPixels;
+        expectedMetrics.noncompatHeightPixels = mTestDisplayMetrics.noncompatWidthPixels;
+
+        WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+                Surface.ROTATION_90, Surface.ROTATION_0, mTestDisplayMetrics);
+        assertEquals(expectedMetrics, mTestDisplayMetrics);
+
+        mTestDisplayMetrics.setTo(originalMetrics);
+        WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+                Surface.ROTATION_270, Surface.ROTATION_0, mTestDisplayMetrics);
+        assertEquals(expectedMetrics, mTestDisplayMetrics);
+    }
+}
diff --git a/libs/WindowManager/Shell/res/color/taskbar_background_dark.xml b/libs/WindowManager/Shell/res/color/taskbar_background_dark.xml
index 01df006..f75d842 100644
--- a/libs/WindowManager/Shell/res/color/taskbar_background_dark.xml
+++ b/libs/WindowManager/Shell/res/color/taskbar_background_dark.xml
@@ -16,5 +16,5 @@
   -->
 <!-- Should be the same as in packages/apps/Launcher3/res/color-night-v31/taskbar_background.xml -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral1_500" android:lStar="20" />
+    <item android:color="@android:color/system_neutral1_500" android:lStar="6" />
 </selector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java
index 55052e6..beb1c5f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java
@@ -523,6 +523,7 @@
      */
     @Nullable private SpringAnimation getSpringAnimationFromView(
             DynamicAnimation.ViewProperty property, View view) {
+        if (view == null) return null;
         return (SpringAnimation) view.getTag(getTagIdForProperty(property));
     }
 
@@ -531,11 +532,13 @@
      * system.
      */
     @Nullable private ViewPropertyAnimator getViewPropertyAnimatorFromView(View view) {
+        if (view == null) return null;
         return (ViewPropertyAnimator) view.getTag(R.id.reorder_animator_tag);
     }
 
     /** Retrieves the target animator from the view via the view tag system. */
     @Nullable private ObjectAnimator getTargetAnimatorFromView(View view) {
+        if (view == null) return null;
         return (ObjectAnimator) view.getTag(R.id.target_animator_tag);
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index acbdbf9..cff3172 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -710,4 +710,19 @@
     static DesktopModeTaskRepository provideDesktopModeTaskRepository() {
         return new DesktopModeTaskRepository();
     }
+
+    //
+    // Misc
+    //
+
+    // TODO: Temporarily move dependencies to this instead of ShellInit since that is needed to add
+    // the callback. We will be moving to a different explicit startup mechanism in a follow- up CL.
+    @WMSingleton
+    @ShellCreateTriggerOverride
+    @Provides
+    static Object provideIndependentShellComponentsToCreate(
+            DefaultMixedHandler defaultMixedHandler,
+            Optional<DesktopModeController> desktopModeController) {
+        return new Object();
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 4dbb50f..cf38990 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -534,8 +534,7 @@
             return;
         }
 
-        final Rect displayBounds = mPipBoundsState.getDisplayBounds();
-        final Rect destinationBounds = new Rect(displayBounds);
+        final Rect destinationBounds = new Rect(getExitDestinationBounds());
         final int direction = syncWithSplitScreenBounds(destinationBounds, requestEnterSplit)
                 ? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN
                 : TRANSITION_DIRECTION_LEAVE_PIP;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 86b0f33..e04e9f7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -351,7 +351,7 @@
         if (taskInfo != null) {
             startExpandAnimation(taskInfo, mPipOrganizer.getSurfaceControl(),
                     mPipBoundsState.getBounds(), mPipBoundsState.getBounds(),
-                    new Rect(mExitDestinationBounds), Surface.ROTATION_0);
+                    new Rect(mExitDestinationBounds), Surface.ROTATION_0, null /* startT */);
         }
         mExitDestinationBounds.setEmpty();
         mCurrentPipTaskToken = null;
@@ -604,14 +604,8 @@
             }
         }
 
-        // Set the initial frame as scaling the end to the start.
         final Rect destinationBounds = new Rect(pipChange.getEndAbsBounds());
         destinationBounds.offset(-offset.x, -offset.y);
-        startTransaction.setWindowCrop(pipLeash, destinationBounds.width(),
-                destinationBounds.height());
-        mSurfaceTransactionHelper.scale(startTransaction, pipLeash, destinationBounds,
-                currentBounds);
-        startTransaction.apply();
 
         // Check if it is fixed rotation.
         final int rotationDelta;
@@ -641,7 +635,7 @@
             rotationDelta = Surface.ROTATION_0;
         }
         startExpandAnimation(taskInfo, pipLeash, currentBounds, currentBounds, destinationBounds,
-                rotationDelta);
+                rotationDelta, startTransaction);
     }
 
     private void startExpandAndRotationAnimation(@NonNull TransitionInfo info,
@@ -697,7 +691,7 @@
 
     private void startExpandAnimation(final TaskInfo taskInfo, final SurfaceControl leash,
             final Rect baseBounds, final Rect startBounds, final Rect endBounds,
-            final int rotationDelta) {
+            final int rotationDelta, @Nullable SurfaceControl.Transaction startTransaction) {
         final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
                 taskInfo.pictureInPictureParams, endBounds);
         final PipAnimationController.PipTransitionAnimator animator =
@@ -705,9 +699,14 @@
                         endBounds, sourceHintRect, TRANSITION_DIRECTION_LEAVE_PIP,
                         0 /* startingAngle */, rotationDelta);
         animator.setTransitionDirection(TRANSITION_DIRECTION_LEAVE_PIP)
-                .setPipAnimationCallback(mPipAnimationCallback)
+                .setDuration(mEnterExitAnimationDuration);
+        if (startTransaction != null) {
+            animator.setPipTransactionHandler(mTransactionConsumer).applySurfaceControlTransaction(
+                    leash, startTransaction, PipAnimationController.FRACTION_START);
+            startTransaction.apply();
+        }
+        animator.setPipAnimationCallback(mPipAnimationCallback)
                 .setPipTransactionHandler(mPipOrganizer.getPipTransactionHandler())
-                .setDuration(mEnterExitAnimationDuration)
                 .start();
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchState.java
index 7f62c62..5d858fa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchState.java
@@ -410,6 +410,7 @@
         final String innerPrefix = prefix + "  ";
         pw.println(prefix + TAG);
         pw.println(innerPrefix + "mAllowTouches=" + mAllowTouches);
+        pw.println(innerPrefix + "mAllowInputEvents=" + mAllowInputEvents);
         pw.println(innerPrefix + "mActivePointerId=" + mActivePointerId);
         pw.println(innerPrefix + "mLastTouchDisplayId=" + mLastTouchDisplayId);
         pw.println(innerPrefix + "mDownTouch=" + mDownTouch);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index 8024a4c..843e5af 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -424,6 +424,7 @@
             // the change count). This lets us categorize things into above/below/between
             // while maintaining their relative ordering.
             final int belowLayers = info.getChanges().size();
+            final int middleLayers = info.getChanges().size() * 2;
             final int aboveLayers = info.getChanges().size() * 3;
             for (int i = 0; i < info.getChanges().size(); ++i) {
                 final TransitionInfo.Change change = info.getChanges().get(i);
@@ -441,14 +442,19 @@
                             belowLayers - i, info, t, mLeashMap);
                     apps.add(target);
                     if (TransitionUtil.isClosingType(change.getMode())) {
-                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
-                                "  adding pausing leaf taskId=%d", taskInfo.taskId);
-                        // raise closing (pausing) task to "above" layer so it isn't covered
-                        t.setLayer(target.leash, aboveLayers - i);
                         mPausingTasks.add(new TaskState(change, target.leash));
                         if (taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
+                            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                                    "  adding pausing leaf home taskId=%d", taskInfo.taskId);
                             // This can only happen if we have a separate recents/home (3p launcher)
                             mPausingSeparateHome = true;
+                        } else {
+                            final int layer = aboveLayers - i;
+                            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                                    "  adding pausing leaf taskId=%d at layer=%d",
+                                    taskInfo.taskId, layer);
+                            // raise closing (pausing) task to "above" layer so it isn't covered
+                            t.setLayer(target.leash, layer);
                         }
                         if (taskInfo.pictureInPictureParams != null
                                 && taskInfo.pictureInPictureParams.isAutoEnterEnabled()) {
@@ -456,8 +462,12 @@
                         }
                     } else if (taskInfo != null
                             && taskInfo.topActivityType == ACTIVITY_TYPE_RECENTS) {
-                        // There's a 3p launcher, so make sure recents goes above that.
-                        t.setLayer(target.leash, aboveLayers - i);
+                        final int layer = middleLayers - i;
+                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                                "  setting recents activity layer=%d", layer);
+                        // There's a 3p launcher, so make sure recents goes above that, but under
+                        // the pausing apps.
+                        t.setLayer(target.leash, layer);
                     } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                         // do nothing
                     } else if (TransitionUtil.isOpeningType(change.getMode())) {
@@ -468,16 +478,18 @@
                 } else if (taskInfo != null && TransitionInfo.isIndependent(change, info)) {
                     // Root tasks
                     if (TransitionUtil.isClosingType(change.getMode())) {
+                        final int layer = aboveLayers - i;
                         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
-                                "  adding pausing taskId=%d", taskInfo.taskId);
+                                "  adding pausing taskId=%d at layer=%d", taskInfo.taskId, layer);
                         // raise closing (pausing) task to "above" layer so it isn't covered
-                        t.setLayer(change.getLeash(), aboveLayers - i);
+                        t.setLayer(change.getLeash(), layer);
                         mPausingTasks.add(new TaskState(change, null /* leash */));
                     } else if (TransitionUtil.isOpeningType(change.getMode())) {
+                        final int layer = belowLayers - i;
                         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
-                                "  adding opening taskId=%d", taskInfo.taskId);
+                                "  adding opening taskId=%d at layer=%d", taskInfo.taskId, layer);
                         // Put into the "below" layer space.
-                        t.setLayer(change.getLeash(), belowLayers - i);
+                        t.setLayer(change.getLeash(), layer);
                         mOpeningTasks.add(new TaskState(change, null /* leash */));
                     }
                 } else if (TransitionUtil.isDividerBar(change)) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index da14d03..964ba9f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -2365,6 +2365,11 @@
                     prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out);
                 }
             }
+
+            // When split in the background, it should be only opening/dismissing transition and
+            // would keep out not empty. Prevent intercepting all transitions for split screen when
+            // it is in the background and not identify to handle it.
+            return (!out.isEmpty() || isSplitScreenVisible()) ? out : null;
         } else {
             if (isOpening && getStageOfTask(triggerTask) != null) {
                 // One task is appearing into split, prepare to enter split screen.
@@ -2373,8 +2378,8 @@
                 mSplitTransitions.setEnterTransition(transition, request.getRemoteTransition(),
                         TRANSIT_SPLIT_SCREEN_PAIR_OPEN, !mIsDropEntering);
             }
+            return out;
         }
-        return out;
     }
 
     /**
@@ -2506,8 +2511,9 @@
                         && getStageType(dismissStages.valueAt(0)) == STAGE_TYPE_MAIN)
                         || mMainStage.getChildCount() == 0 ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN;
                 // If there is a fullscreen opening change, we should not bring stage to top.
-                prepareExitSplitScreen(record.mContainShowFullscreenChange
-                        ? STAGE_TYPE_UNDEFINED : dismissTop, wct);
+                prepareExitSplitScreen(
+                        !record.mContainShowFullscreenChange && isSplitScreenVisible()
+                        ? dismissTop : STAGE_TYPE_UNDEFINED, wct);
                 mSplitTransitions.startDismissTransition(wct, this, dismissTop,
                         EXIT_REASON_APP_FINISHED);
                 // This can happen in some pathological cases. For example:
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
index 72f25f3..d1f0980 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
@@ -17,7 +17,6 @@
 package com.android.wm.shell.flicker.splitscreen
 
 import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.traces.component.ComponentNameMatcher
@@ -62,7 +61,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     override fun cujCompleted() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
index ed3df9c..63c5d14 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
@@ -17,7 +17,6 @@
 package com.android.wm.shell.flicker.splitscreen
 
 import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
@@ -60,7 +59,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     override fun cujCompleted() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
index b4c6afd..03b8a75 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
@@ -61,7 +60,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     override fun cujCompleted() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt
index 2cedc35..674ba40 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt
@@ -17,7 +17,6 @@
 package com.android.wm.shell.flicker.splitscreen
 
 import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
@@ -64,7 +63,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     override fun cujCompleted() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt
index a5ad97d..c3c5f88 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.traces.component.ComponentNameMatcher
@@ -64,7 +63,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     open fun cujCompleted() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt
index fa6a4bf..37cd18f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
@@ -70,7 +69,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     fun cujCompleted() = flicker.splitScreenDismissed(primaryApp, secondaryApp, toHome = false)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt
index d2beb67..0ec6dc9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
@@ -57,7 +56,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     fun cujCompleted() = flicker.splitScreenDismissed(primaryApp, secondaryApp, toHome = true)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt
index e95fd94..190e2e7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
@@ -60,7 +59,6 @@
     }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     open fun cujCompleted() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt
index 63b74e2..3a1d1a4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.NavBar
@@ -72,7 +71,6 @@
     }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     fun cujCompleted() =
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt
index e94da87..2033b7d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.NavBar
@@ -69,7 +68,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     fun cujCompleted() =
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt
index f41117f..b7a7110 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.NavBar
@@ -72,7 +71,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     fun cujCompleted() =
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt
index 12f610b..b1ce62f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.NavBar
@@ -67,7 +66,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     fun cujCompleted() =
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt
index 77818d3..14f0745 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
@@ -66,7 +65,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     fun cujCompleted() = flicker.splitScreenEntered(primaryApp, secondaryApp, fromOtherApp = true)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt
index 6ff2290..65fb135 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.NavBar
@@ -136,7 +135,6 @@
     }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     open fun cujCompleted() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt
index 400adea..b333aba 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.NavBar
@@ -65,7 +64,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     fun cujCompleted() = flicker.splitScreenEntered(primaryApp, secondaryApp, fromOtherApp = true)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt
index 1ec4340..a27540e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.NavBar
@@ -63,7 +62,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     fun cujCompleted() = flicker.splitScreenEntered(primaryApp, secondaryApp, fromOtherApp = true)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt
index 9757153..18bf4ff 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.NavBar
@@ -63,7 +62,6 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
     fun cujCompleted() = flicker.splitScreenEntered(primaryApp, secondaryApp, fromOtherApp = true)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt
index c19a38d..c5fe61e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.splitscreen.benchmark
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
@@ -66,7 +65,7 @@
         }
 
     @PlatinumTest(focusArea = "sysui")
-    @IwTest(focusArea = "sysui") @Presubmit @Test open fun cujCompleted() {}
+    @Presubmit @Test open fun cujCompleted() {}
 
     companion object {
         @Parameterized.Parameters(name = "{0}")
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 9be7728..0eb657a 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -709,7 +709,7 @@
     /**
      * Returns the Mean Sea Level altitude of this location in meters.
      *
-     * <p>This is only valid if {@link #hasMslAltitude()} is true.
+     * @throws IllegalStateException if {@link #hasMslAltitude()} is false.
      */
     public @FloatRange double getMslAltitudeMeters() {
         Preconditions.checkState(hasMslAltitude(),
@@ -744,7 +744,7 @@
      * percentile confidence level. This means that there is 68% chance that the true Mean Sea Level
      * altitude of this location falls within {@link #getMslAltitudeMeters()} +/- this uncertainty.
      *
-     * <p>This is only valid if {@link #hasMslAltitudeAccuracy()} is true.
+     * @throws IllegalStateException if {@link #hasMslAltitudeAccuracy()} is false.
      */
     public @FloatRange(from = 0.0) float getMslAltitudeAccuracyMeters() {
         Preconditions.checkState(hasMslAltitudeAccuracy(),
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index f86b9af..23f87ab 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -1566,7 +1566,7 @@
         FileInputStream in = null;
         try {
             in = new FileInputStream(fileDescriptor);
-            loadAttributes(in, fileDescriptor);
+            loadAttributes(in);
         } finally {
             closeQuietly(in);
             if (isFdDuped) {
@@ -1637,7 +1637,7 @@
                 mSeekableFileDescriptor = null;
             }
         }
-        loadAttributes(inputStream, null);
+        loadAttributes(inputStream);
     }
 
     /**
@@ -1963,7 +1963,7 @@
      * This function decides which parser to read the image data according to the given input stream
      * type and the content of the input stream.
      */
-    private void loadAttributes(@NonNull InputStream in, @Nullable FileDescriptor fd) {
+    private void loadAttributes(@NonNull InputStream in) {
         if (in == null) {
             throw new NullPointerException("inputstream shouldn't be null");
         }
@@ -1993,7 +1993,7 @@
                         break;
                     }
                     case IMAGE_TYPE_HEIF: {
-                        getHeifAttributes(inputStream, fd);
+                        getHeifAttributes(inputStream);
                         break;
                     }
                     case IMAGE_TYPE_ORF: {
@@ -2580,7 +2580,7 @@
             } else if (isSeekableFD(in.getFD())) {
                 mSeekableFileDescriptor = in.getFD();
             }
-            loadAttributes(in, null);
+            loadAttributes(in);
         } finally {
             closeQuietly(in);
             if (modernFd != null) {
@@ -3068,66 +3068,59 @@
         }
     }
 
-    private void getHeifAttributes(ByteOrderedDataInputStream in, @Nullable FileDescriptor fd)
-            throws IOException {
+    private void getHeifAttributes(ByteOrderedDataInputStream in) throws IOException {
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
         try {
-            if (fd != null) {
-                retriever.setDataSource(fd);
-            } else {
-                retriever.setDataSource(new MediaDataSource() {
-                    long mPosition;
+            retriever.setDataSource(new MediaDataSource() {
+                long mPosition;
 
-                    @Override
-                    public void close() throws IOException {}
+                @Override
+                public void close() throws IOException {}
 
-                    @Override
-                    public int readAt(long position, byte[] buffer, int offset, int size)
-                            throws IOException {
-                        if (size == 0) {
-                            return 0;
-                        }
-                        if (position < 0) {
-                            return -1;
-                        }
-                        try {
-                            if (mPosition != position) {
-                                // We don't allow seek to positions after the available bytes,
-                                // the input stream won't be able to seek back then.
-                                // However, if we hit an exception before (mPosition set to -1),
-                                // let it try the seek in hope it might recover.
-                                if (mPosition >= 0 && position >= mPosition + in.available()) {
-                                    return -1;
-                                }
-                                in.seek(position);
-                                mPosition = position;
-                            }
-
-                            // If the read will cause us to go over the available bytes,
-                            // reduce the size so that we stay in the available range.
-                            // Otherwise the input stream may not be able to seek back.
-                            if (size > in.available()) {
-                                size = in.available();
-                            }
-
-                            int bytesRead = in.read(buffer, offset, size);
-                            if (bytesRead >= 0) {
-                                mPosition += bytesRead;
-                                return bytesRead;
-                            }
-                        } catch (IOException e) {
-                            // absorb the exception and fall through to the 'failed read' path below
-                        }
-                        mPosition = -1; // need to seek on next read
+                @Override
+                public int readAt(long position, byte[] buffer, int offset, int size)
+                        throws IOException {
+                    if (size == 0) {
+                        return 0;
+                    }
+                    if (position < 0) {
                         return -1;
                     }
+                    try {
+                        if (mPosition != position) {
+                            // We don't allow seek to positions after the available bytes,
+                            // the input stream won't be able to seek back then.
+                            // However, if we hit an exception before (mPosition set to -1),
+                            // let it try the seek in hope it might recover.
+                            if (mPosition >= 0 && position >= mPosition + in.available()) {
+                                return -1;
+                            }
+                            in.seek(position);
+                            mPosition = position;
+                        }
 
-                    @Override
-                    public long getSize() throws IOException {
-                        return -1;
-                    }
-                });
-            }
+                        // If the read will cause us to go over the available bytes,
+                        // reduce the size so that we stay in the available range.
+                        // Otherwise the input stream may not be able to seek back.
+                        if (size > in.available()) {
+                            size = in.available();
+                        }
+
+                        int bytesRead = in.read(buffer, offset, size);
+                        if (bytesRead >= 0) {
+                            mPosition += bytesRead;
+                            return bytesRead;
+                        }
+                    } catch (IOException e) {}
+                    mPosition = -1; // need to seek on next read
+                    return -1;
+                }
+
+                @Override
+                public long getSize() throws IOException {
+                    return -1;
+                }
+            });
 
             String exifOffsetStr = retriever.extractMetadata(
                     MediaMetadataRetriever.METADATA_KEY_EXIF_OFFSET);
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 6744359..9b238e1 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -49,7 +49,6 @@
 import libcore.io.IoUtils;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Comparator;
@@ -256,19 +255,17 @@
 
         // get orientation
         if (MediaFile.isExifMimeType(mimeType)) {
-            try (FileInputStream is = new FileInputStream(file)) {
-                exif = new ExifInterface(is.getFD());
-                switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0)) {
-                    case ExifInterface.ORIENTATION_ROTATE_90:
-                        orientation = 90;
-                        break;
-                    case ExifInterface.ORIENTATION_ROTATE_180:
-                        orientation = 180;
-                        break;
-                    case ExifInterface.ORIENTATION_ROTATE_270:
-                        orientation = 270;
-                        break;
-                }
+            exif = new ExifInterface(file);
+            switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0)) {
+                case ExifInterface.ORIENTATION_ROTATE_90:
+                    orientation = 90;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_180:
+                    orientation = 180;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_270:
+                    orientation = 270;
+                    break;
             }
         }
 
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 094a33f..ed68d1e 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -455,6 +455,11 @@
                 if (mRule.getTargetMixType() != AudioMix.MIX_TYPE_PLAYERS) {
                     throw new IllegalArgumentException("Unsupported device on non-playback mix");
                 }
+            } else if (mDeviceSystemType == AudioSystem.DEVICE_OUT_REMOTE_SUBMIX) {
+                if (mRule.getTargetMixType() != AudioMix.MIX_TYPE_PLAYERS) {
+                    throw new IllegalArgumentException(
+                            "DEVICE_OUT_REMOTE_SUBMIX device is not supported on non-playback mix");
+                }
             } else {
                 if ((mRouteFlags & ROUTE_FLAG_SUPPORTED) == ROUTE_FLAG_RENDER) {
                     throw new IllegalArgumentException(
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index f1cffb6..48367f9 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -159,7 +159,14 @@
      * @param surface  The surface to which the content of the virtual display should be rendered,
      *                 or null if there is none initially.
      * @param flags    A combination of virtual display flags. See {@link DisplayManager} for the
-     *                 full list of flags.
+     *                 full list of flags. Note that
+     *                 {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION}
+     *                 is always enabled. The following flags may be overridden, depending on how
+     *                 the component with {android.Manifest.permission.MANAGE_MEDIA_PROJECTION}
+     *                 handles the user's consent:
+     *                 {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
+     *                 {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR},
+     *                 {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC}.
      * @param callback Callback invoked when the virtual display's state changes, or null.
      * @param handler  The {@link android.os.Handler} on which the callback should be invoked, or
      *                 null if the callback should be invoked on the calling thread's main
diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java
index bbca882..ac8a7f3 100644
--- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java
+++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java
@@ -24,7 +24,11 @@
 import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_AUDIO_SESSION_ID;
 import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_UID;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
 import android.media.AudioFormat;
+import android.media.AudioSystem;
 import android.media.audiopolicy.AudioMix;
 import android.media.audiopolicy.AudioMixingRule;
 import android.media.audiopolicy.AudioPolicyConfig;
@@ -145,6 +149,84 @@
         equalsTester.testEquals();
     }
 
+    @Test
+    public void buildRenderToRemoteSubmix_success() {
+        final String deviceAddress = "address";
+        final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder()
+                .setTargetMixRole(MIX_ROLE_PLAYERS)
+                .addMixRule(RULE_MATCH_UID, 42).build())
+                .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
+                .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER)
+                .setDevice(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, /*address=*/deviceAddress).build();
+
+        assertEquals(deviceAddress, audioMix.getRegistration());
+        assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat());
+        assertEquals(AudioMix.ROUTE_FLAG_RENDER, audioMix.getRouteFlags());
+    }
+
+    @Test
+    public void buildLoopbackAndRenderToRemoteSubmix_success() {
+        final String deviceAddress = "address";
+        final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder()
+                .setTargetMixRole(MIX_ROLE_PLAYERS)
+                .addMixRule(RULE_MATCH_UID, 42).build())
+                .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
+                .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK_RENDER)
+                .setDevice(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, /*address=*/deviceAddress).build();
+
+        assertEquals(deviceAddress, audioMix.getRegistration());
+        assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat());
+        assertEquals(AudioMix.ROUTE_FLAG_LOOP_BACK_RENDER, audioMix.getRouteFlags());
+    }
+
+    @Test
+    public void buildRenderToSpeaker_success() {
+        final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder()
+                .setTargetMixRole(MIX_ROLE_PLAYERS)
+                .addMixRule(RULE_MATCH_UID, 42).build())
+                .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
+                .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER)
+                .setDevice(AudioSystem.DEVICE_OUT_SPEAKER, /*address=*/"").build();
+
+        assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat());
+        assertEquals(AudioMix.ROUTE_FLAG_RENDER, audioMix.getRouteFlags());
+    }
+
+    @Test
+    public void buildLoopbackForPlayerMix_success() {
+        final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder()
+                .setTargetMixRole(MIX_ROLE_PLAYERS)
+                .addMixRule(RULE_MATCH_UID, 42).build())
+                .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
+                .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
+
+        assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat());
+        assertEquals(AudioMix.ROUTE_FLAG_LOOP_BACK, audioMix.getRouteFlags());
+    }
+
+    @Test
+    public void buildLoopbackWithDevice_throws() {
+        assertThrows(IllegalArgumentException.class, () -> new AudioMix.Builder(
+                new AudioMixingRule.Builder()
+                        .setTargetMixRole(MIX_ROLE_PLAYERS)
+                        .addMixRule(RULE_MATCH_UID, 42).build())
+                .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
+                .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK)
+                .setDevice(AudioSystem.DEVICE_OUT_SPEAKER, /*address=*/"").build());
+    }
+
+    @Test
+    public void buildRenderWithoutDevice_throws() {
+        assertThrows(IllegalArgumentException.class, () -> new AudioMix.Builder(
+                new AudioMixingRule.Builder()
+                        .setTargetMixRole(MIX_ROLE_PLAYERS)
+                        .addMixRule(RULE_MATCH_UID, 42).build())
+                .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
+                .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER).build());
+    }
+
+
+
     private static AudioMix writeToAndFromParcel(AudioMix audioMix) {
         AudioPolicyConfig apc = new AudioPolicyConfig(new ArrayList<>(List.of(audioMix)));
         Parcel parcel = Parcel.obtain();
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 3e2b800..3adb882 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -643,8 +643,10 @@
          array must also be populated with a content description for each image. -->
     <array name="avatar_images"/>
 
-    <!-- Content descriptions for each of the images in the avatar_images array. -->
-    <string-array name="avatar_image_descriptions"/>
+    <!-- Content descriptions for each of the images in the avatar_images array. When overlaid
+         these values should be translated, but this empty array must not be translated or it may
+         replace the real descriptions with an empty array. -->
+    <string-array name="avatar_image_descriptions" translatable="false"/>
 
     <!-- NOTE: if you change this, you must also add the corresponding scale key and lookup table to
      frameworks/base/core/java/android/content/res/FontScaleConverterFactory.java -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java
index bcbd1ca..848b177 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java
@@ -243,7 +243,7 @@
                 int index = indexFromPosition(position);
                 viewHolder.setSelected(position == mSelectedPosition);
                 viewHolder.setDrawable(mImageDrawables.get(index));
-                if (mImageDescriptions != null) {
+                if (mImageDescriptions != null && index < mImageDescriptions.size()) {
                     viewHolder.setContentDescription(mImageDescriptions.get(index));
                 } else {
                     viewHolder.setContentDescription(getString(
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 0aa121d..5c03698 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -362,7 +362,7 @@
         android:killAfterRestore="false"
         android:hardwareAccelerated="true"
         android:label="@string/app_label"
-        android:icon="@drawable/icon"
+        android:icon="@drawable/android14_patch_adaptive"
         android:process="com.android.systemui"
         android:supportsRtl="true"
         android:theme="@style/Theme.SystemUI"
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index 8cba2ab..702cc05 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -56,7 +56,6 @@
         "com.android.systemui.falcon.four" to listOf(ClockMetadata("DIGITAL_CLOCK_GROWTH")),
         "com.android.systemui.falcon.five" to listOf(ClockMetadata("DIGITAL_CLOCK_HANDWRITTEN")),
         "com.android.systemui.falcon.six" to listOf(ClockMetadata("DIGITAL_CLOCK_INFLATE")),
-        "com.android.systemui.falcon.seven" to listOf(ClockMetadata("DIGITAL_CLOCK_METRO")),
         "com.android.systemui.falcon.eight" to listOf(ClockMetadata("DIGITAL_CLOCK_NUMBEROVERLAP")),
         "com.android.systemui.falcon.nine" to listOf(ClockMetadata("DIGITAL_CLOCK_WEATHER")),
     )
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 28f5f3d..badad58 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -358,12 +358,12 @@
     <!-- Message shown to prepare for an unattended update (OTA). Also known as an over-the-air (OTA) update.  [CHAR LIMIT=70] -->
     <string name="kg_prompt_unattended_update_pattern">Draw pattern to install update later</string>
 
-    <!-- Message shown after an unattended update (OTA) asking the user to enter their PIN. Also known as an over-the-air (OTA) update.  [CHAR LIMIT=70] -->
+    <!--  Message shown after an unattended mainline (major) update asking the user to enter their PIN. [CHAR LIMIT=70] -->
     <string name="kg_prompt_after_update_pin">Device updated. Enter PIN to continue.</string>
 
-    <!-- Message shown after an unattended update (OTA) asking the user to enter their password. Also known as an over-the-air (OTA) update.  [CHAR LIMIT=70] -->
+    <!-- Message shown after an unattended mainline (major) update asking the user to enter their password. [CHAR LIMIT=70] -->
     <string name="kg_prompt_after_update_password">Device updated. Enter password to continue.</string>
 
-    <!-- Message shown after an unattended update (OTA) asking the user to enter their pattern. Also known as an over-the-air (OTA) update.  [CHAR LIMIT=70] -->
+    <!-- Message shown after an unattended mainline (major) update asking the user to enter their pattern. [CHAR LIMIT=70] -->
     <string name="kg_prompt_after_update_pattern">Device updated. Draw pattern to continue.</string>
 </resources>
diff --git a/packages/SystemUI/res/drawable/android14_patch_adaptive.xml b/packages/SystemUI/res/drawable/android14_patch_adaptive.xml
new file mode 100644
index 0000000..423e351
--- /dev/null
+++ b/packages/SystemUI/res/drawable/android14_patch_adaptive.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2023 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/android14_patch_adaptive_background"/>
+    <foreground android:drawable="@drawable/android14_patch_adaptive_foreground"/>
+    <monochrome android:drawable="@drawable/android14_patch_monochrome"/>
+</adaptive-icon>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/android14_patch_adaptive_background.xml b/packages/SystemUI/res/drawable/android14_patch_adaptive_background.xml
new file mode 100644
index 0000000..afeae4b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/android14_patch_adaptive_background.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2023 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+  <path
+      android:pathData="M0,0 L108,0 L108,108 L0,108 z"
+      android:fillColor="@android:color/system_neutral1_800"/>
+  <path
+      android:pathData="M44.51,43.32L44.86,42.27C47.04,54.48 52.81,86.71 52.81,50.14C52.81,49.99 52.92,49.86 53.06,49.86H55.04C55.18,49.86 55.3,49.98 55.3,50.14C55.27,114.18 44.51,43.32 44.51,43.32Z"
+      android:fillColor="@android:color/system_accent3_400"/>
+  <path
+      android:name="planetary head"
+      android:pathData="M38.81,42.23L33.63,51.21C33.33,51.72 33.51,52.38 34.02,52.68C34.54,52.98 35.2,52.8 35.49,52.28L40.74,43.2C49.22,47 58.92,47 67.4,43.2L72.65,52.28C72.96,52.79 73.62,52.96 74.13,52.65C74.62,52.35 74.79,51.71 74.51,51.21L69.33,42.23C78.23,37.39 84.32,28.38 85.21,17.74H22.93C23.82,28.38 29.91,37.39 38.81,42.23Z"
+      android:fillColor="#ffffff"/>
+  <!-- yes it's an easter egg in a vector drawable -->
+  <path
+      android:name="planetary body"
+      android:pathData="M22.9,0 L85.1,0 L85.1,15.5 L22.9,15.5 z"
+      android:fillColor="#ffffff" />
+  <path
+      android:pathData="M54.96,43.32H53.1C52.92,43.32 52.77,43.47 52.77,43.65V48.04C52.77,48.22 52.92,48.37 53.1,48.37H54.96C55.15,48.37 55.3,48.22 55.3,48.04V43.65C55.3,43.47 55.15,43.32 54.96,43.32Z"
+      android:fillColor="@android:color/system_accent3_400"/>
+  <path
+      android:pathData="M54.99,40.61H53.08C52.91,40.61 52.77,40.75 52.77,40.92V41.56C52.77,41.73 52.91,41.87 53.08,41.87H54.99C55.16,41.87 55.3,41.73 55.3,41.56V40.92C55.3,40.75 55.16,40.61 54.99,40.61Z"
+      android:fillColor="@android:color/system_accent3_400"/>
+  <path
+      android:pathData="M41.49,47.88H40.86V48.51H41.49V47.88Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M44.13,57.08H43.5V57.71H44.13V57.08Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M72.29,66.76H71.66V67.39H72.29V66.76Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M59.31,53.41H58.68V54.04H59.31V53.41Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M64.47,48.19H63.84V48.83H64.47V48.19Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M60.58,59.09H59.95V59.72H60.58V59.09Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M66.95,56.7H65.69V57.97H66.95V56.7Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M44.13,60.71H43.5V61.34H44.13V60.71Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M49.66,51.33H48.4V52.6H49.66V51.33Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M57.78,63.83H56.52V65.09H57.78V63.83Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M61.1,68.57H59.83V69.83H61.1V68.57Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M40.43,53.73H39.16V54.99H40.43V53.73Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M74.47,44H73.21V45.26H74.47V44Z"
+      android:fillColor="#ffffff"/>
+  <path
+      android:pathData="M36.8,64.58H35.54V65.84H36.8V64.58Z"
+      android:fillColor="#ffffff"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/android14_patch_adaptive_foreground.xml b/packages/SystemUI/res/drawable/android14_patch_adaptive_foreground.xml
new file mode 100644
index 0000000..ced4305
--- /dev/null
+++ b/packages/SystemUI/res/drawable/android14_patch_adaptive_foreground.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2023 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+  <path
+      android:pathData="M54.03,33.03C52.99,33.03 52.14,33.86 52.14,34.87V37.14C52.14,37.34 52.3,37.5 52.5,37.5C52.69,37.5 52.85,37.34 52.85,37.14V36.53C52.85,36.14 53.17,35.82 53.56,35.82H54.51C54.9,35.82 55.22,36.14 55.22,36.53V37.14C55.22,37.34 55.38,37.5 55.57,37.5C55.77,37.5 55.93,37.34 55.93,37.14V34.87C55.93,33.86 55.08,33.03 54.03,33.03H54.03Z"
+      android:fillColor="@android:color/system_accent3_400"/>
+  <path
+      android:pathData="M108,0H0V108H108V0ZM54,80.67C68.73,80.67 80.67,68.73 80.67,54C80.67,39.27 68.73,27.33 54,27.33C39.27,27.33 27.33,39.27 27.33,54C27.33,68.73 39.27,80.67 54,80.67Z"
+      android:fillColor="@android:color/system_accent1_400"
+      android:fillType="evenOdd"/>
+  <group>
+    <!-- the text doesn't look great everywhere but you can remove the clip to try it out. -->
+    <clip-path />
+    <path
+        android:pathData="M28.58,32.18L29.18,31.5L33.82,33.02L33.12,33.81L32.15,33.48L30.92,34.87L31.37,35.8L30.68,36.58L28.58,32.18L28.58,32.18ZM31.25,33.18L29.87,32.71L30.51,34.02L31.25,33.18V33.18Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M38,29.76L34.61,28.79L36.23,31.04L35.42,31.62L32.8,27.99L33.5,27.48L36.88,28.45L35.26,26.21L36.08,25.62L38.7,29.25L38,29.76Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M39.23,23.87L40.63,23.27C41.79,22.77 43.13,23.28 43.62,24.43C44.11,25.57 43.56,26.89 42.4,27.39L40.99,27.99L39.23,23.87ZM42.03,26.54C42.73,26.24 42.96,25.49 42.68,24.83C42.4,24.17 41.69,23.82 41,24.11L40.51,24.32L41.55,26.75L42.03,26.54Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M45.91,21.43L47.64,21.09C48.47,20.93 49.12,21.41 49.27,22.15C49.38,22.72 49.15,23.14 48.63,23.45L50.57,25.08L49.39,25.31L47.57,23.79L47.41,23.82L47.76,25.63L46.78,25.83L45.91,21.43H45.91ZM47.87,22.86C48.16,22.8 48.34,22.59 48.29,22.34C48.24,22.07 48,21.96 47.71,22.02L47.07,22.14L47.24,22.98L47.87,22.86Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M52.17,22.69C52.19,21.41 53.24,20.39 54.52,20.41C55.8,20.43 56.82,21.49 56.8,22.76C56.78,24.04 55.72,25.06 54.45,25.04C53.17,25.02 52.15,23.96 52.17,22.69ZM55.79,22.75C55.8,22.02 55.23,21.39 54.51,21.38C53.78,21.37 53.19,21.98 53.18,22.7C53.17,23.43 53.73,24.06 54.47,24.07C55.19,24.08 55.78,23.47 55.79,22.75H55.79Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M60,21.01L60.98,21.2L60.12,25.6L59.14,25.41L60,21.01Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M64.3,22.03L65.73,22.58C66.91,23.03 67.51,24.32 67.07,25.49C66.62,26.65 65.31,27.22 64.13,26.77L62.71,26.22L64.3,22.03L64.3,22.03ZM64.46,25.9C65.17,26.17 65.86,25.8 66.12,25.12C66.37,24.45 66.11,23.71 65.4,23.44L64.91,23.25L63.97,25.72L64.46,25.9Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M73.59,27.94L72.94,27.44L73.51,26.69L74.92,27.77L72.2,31.34L71.45,30.76L73.59,27.94Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M76.18,33.75L74.69,32.14L75.25,31.62L78.81,31.42L79.4,32.05L77.47,33.85L77.86,34.27L77.22,34.86L76.83,34.44L76.12,35.11L75.47,34.41L76.18,33.75ZM77.72,32.31L76.12,32.4L76.82,33.15L77.72,32.31Z"
+        android:fillColor="#ffffff"/>
+  </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/android14_patch_monochrome.xml b/packages/SystemUI/res/drawable/android14_patch_monochrome.xml
new file mode 100644
index 0000000..beef85c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/android14_patch_monochrome.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2023 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+  <group>
+    <clip-path
+        android:pathData="M0,0h108v108h-108z"/>
+    <group>
+      <clip-path
+          android:pathData="M22,22h64v64h-64z"/>
+      <path
+          android:pathData="M54,78C67.25,78 78,67.25 78,54C78,40.75 67.25,30 54,30C40.75,30 30,40.75 30,54C30,67.25 40.75,78 54,78Z"
+          android:strokeWidth="5"
+          android:fillColor="#00000000"
+          android:strokeColor="#000000"/>
+      <group>
+        <clip-path
+            android:pathData="M77.5,54C77.5,66.98 66.98,77.5 54,77.5C41.02,77.5 30.5,66.98 30.5,54C30.5,41.02 41.02,30.5 54,30.5C66.98,30.5 77.5,41.02 77.5,54Z"/>
+        <path
+            android:pathData="M61.5,46.06C56.7,47.89 51.4,47.89 46.61,46.06L44.04,50.51C43.49,51.46 42.28,51.79 41.33,51.24C40.39,50.69 40.06,49.48 40.61,48.53L43.06,44.28C37.97,41.03 34.54,35.56 34,29.19L33.88,27.74H74.22L74.1,29.19C73.57,35.56 70.14,41.03 65.04,44.28L67.51,48.56C68.03,49.49 67.71,50.66 66.8,51.21C65.87,51.77 64.65,51.47 64.08,50.54L64.07,50.51L61.5,46.06Z"
+            android:fillColor="#000000"/>
+      </group>
+      <path
+          android:pathData="M51.33,67.33h1.33v1.33h-1.33z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M48.67,62h1.33v1.33h-1.33z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M56.67,70h1.33v1.33h-1.33z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M56.67,62h2.67v2.67h-2.67z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M67.33,62h1.33v1.33h-1.33z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M59.33,51.33h2.67v2.67h-2.67z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M62,59.33h1.33v1.33h-1.33z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M70,54h1.33v1.33h-1.33z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M35.33,56.67h1.33v1.33h-1.33z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M35.33,48.67h1.33v1.33h-1.33z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M40.67,59.33h2.67v2.67h-2.67z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M46,51.33h1.33v1.33h-1.33z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M43.33,67.33h1.33v1.33h-1.33z"
+          android:fillColor="#000000"/>
+      <path
+          android:pathData="M54,54h1.33v1.33h-1.33z"
+          android:fillColor="#000000"/>
+    </group>
+  </group>
+</vector>
diff --git a/packages/SystemUI/res/layout/qs_customize_tile_frame.xml b/packages/SystemUI/res/layout/qs_customize_tile_frame.xml
index a2250b1..0fd3c5b 100644
--- a/packages/SystemUI/res/layout/qs_customize_tile_frame.xml
+++ b/packages/SystemUI/res/layout/qs_customize_tile_frame.xml
@@ -17,7 +17,7 @@
 
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="@dimen/qs_tile_height"
+    android:layout_height="wrap_content"
     android:layout_width="match_parent"
     android:layout_marginTop="@dimen/qs_tile_margin_top_bottom"
     android:layout_marginBottom="@dimen/qs_tile_margin_top_bottom"
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index f277e8a..da4547b 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -76,4 +76,10 @@
     <!-- Bouncer user switcher margins -->
     <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">0dp</dimen>
     <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">0dp</dimen>
+
+    <!-- Power Menu Lite -->
+    <!-- These values are for small screen landscape. For larger landscape screens, they are
+         overlaid -->
+    <dimen name="global_actions_button_size">72dp</dimen>
+    <dimen name="global_actions_button_padding">26dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-sw410dp-land/dimens.xml b/packages/SystemUI/res/values-sw410dp-land/dimens.xml
index c4d9b9b..6045606 100644
--- a/packages/SystemUI/res/values-sw410dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw410dp-land/dimens.xml
@@ -18,4 +18,8 @@
     <!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
     <dimen name="biometric_auth_pattern_view_size">248dp</dimen>
     <dimen name="biometric_auth_pattern_view_max_size">348dp</dimen>
+
+    <!-- Power Menu Lite -->
+    <dimen name="global_actions_button_size">96dp</dimen>
+    <dimen name="global_actions_button_padding">38dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/xml/combined_qs_header_scene.xml b/packages/SystemUI/res/xml/combined_qs_header_scene.xml
index 38c1640..8512f6f 100644
--- a/packages/SystemUI/res/xml/combined_qs_header_scene.xml
+++ b/packages/SystemUI/res/xml/combined_qs_header_scene.xml
@@ -16,12 +16,14 @@
   -->
 <MotionScene
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto">
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:motion="http://schemas.android.com/apk/res-auto">
 
     <Transition
         android:id="@+id/header_transition"
         app:constraintSetEnd="@id/qs_header_constraint"
-        app:constraintSetStart="@id/qqs_header_constraint">
+        app:constraintSetStart="@id/qqs_header_constraint"
+        motion:layoutDuringTransition="honorRequest">
         <KeyFrameSet>
             <!-- These positions are to prevent visual movement of @id/date -->
             <KeyPosition
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
index a724514..b52ee01 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
@@ -148,7 +148,8 @@
     /**
      * The status of this lock screen. Primarily used for widgets on LockScreen.
      */
-    private enum StatusMode {
+    @VisibleForTesting
+    protected enum StatusMode {
         Normal, // Normal case (sim card present, it's not locked)
         NetworkLocked, // SIM card is 'network locked'.
         SimMissing, // SIM card is missing.
@@ -158,6 +159,7 @@
         SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
         SimNotReady, // SIM is not ready yet. May never be on devices w/o a SIM.
         SimIoError, // SIM card is faulty
+        SimRestricted, // SIM Card restricted, present but not usable due to carrier restrictions.
         SimUnknown // SIM card is unknown
     }
 
@@ -493,6 +495,7 @@
                         getContext().getText(R.string.keyguard_sim_error_message_short),
                         text);
                 break;
+            case SimRestricted: // fall through
             case SimUnknown:
                 carrierText = null;
                 break;
@@ -535,19 +538,19 @@
     /**
      * Determine the current status of the lock screen given the SIM state and other stuff.
      */
-    private CarrierTextManager.StatusMode getStatusForIccState(int simState) {
-        final boolean missingAndNotProvisioned =
-                !mKeyguardUpdateMonitor.isDeviceProvisioned()
-                        && (simState == TelephonyManager.SIM_STATE_ABSENT
-                        || simState == TelephonyManager.SIM_STATE_PERM_DISABLED);
+    @VisibleForTesting
+    protected CarrierTextManager.StatusMode getStatusForIccState(int simState) {
+        if (!mKeyguardUpdateMonitor.isDeviceProvisioned()
+                && (simState == TelephonyManager.SIM_STATE_ABSENT
+                        || simState == TelephonyManager.SIM_STATE_PERM_DISABLED)) {
+            return CarrierTextManager.StatusMode.SimMissingLocked;
+        }
 
-        // Assume we're NETWORK_LOCKED if not provisioned
-        simState = missingAndNotProvisioned ? TelephonyManager.SIM_STATE_NETWORK_LOCKED : simState;
         switch (simState) {
             case TelephonyManager.SIM_STATE_ABSENT:
                 return CarrierTextManager.StatusMode.SimMissing;
             case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
-                return CarrierTextManager.StatusMode.SimMissingLocked;
+                return CarrierTextManager.StatusMode.NetworkLocked;
             case TelephonyManager.SIM_STATE_NOT_READY:
                 return CarrierTextManager.StatusMode.SimNotReady;
             case TelephonyManager.SIM_STATE_PIN_REQUIRED:
@@ -562,6 +565,8 @@
                 return CarrierTextManager.StatusMode.SimUnknown;
             case TelephonyManager.SIM_STATE_CARD_IO_ERROR:
                 return CarrierTextManager.StatusMode.SimIoError;
+            case TelephonyManager.SIM_STATE_CARD_RESTRICTED:
+                return CarrierTextManager.StatusMode.SimRestricted;
         }
         return CarrierTextManager.StatusMode.SimUnknown;
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index e057188..d7e8616 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -53,6 +53,7 @@
     private boolean mDismissing;
     protected AsyncTask<?, ?, ?> mPendingLockCheck;
     protected boolean mResumed;
+    protected boolean mLockedOut;
 
     private final KeyDownListener mKeyDownListener = (keyCode, keyEvent) -> {
         // Fingerprint sensor sends a KeyEvent.KEYCODE_UNKNOWN.
@@ -137,6 +138,8 @@
     // Prevent user from using the PIN/Password entry until scheduled deadline.
     protected void handleAttemptLockout(long elapsedRealtimeDeadline) {
         mView.setPasswordEntryEnabled(false);
+        mView.setPasswordEntryInputEnabled(false);
+        mLockedOut = true;
         long elapsedRealtime = SystemClock.elapsedRealtime();
         long secondsInFuture = (long) Math.ceil(
                 (elapsedRealtimeDeadline - elapsedRealtime) / 1000.0);
@@ -158,6 +161,7 @@
             @Override
             public void onFinish() {
                 mMessageAreaController.setMessage("");
+                mLockedOut = false;
                 resetState();
             }
         }.start();
@@ -193,6 +197,7 @@
 
     protected void verifyPasswordAndUnlock() {
         if (mDismissing) return; // already verified but haven't been dismissed; don't do it again.
+        if (mLockedOut) return;
 
         final LockscreenCredential password = mView.getEnteredCredential();
         mView.setPasswordEntryInputEnabled(false);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 1d7c35d..03d9eb3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -23,6 +23,7 @@
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART;
+import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
@@ -99,14 +100,16 @@
         switch (reason) {
             case PROMPT_REASON_RESTART:
                 return R.string.kg_prompt_reason_restart_password;
+            case PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE:
+                return R.string.kg_prompt_after_update_password;
             case PROMPT_REASON_TIMEOUT:
                 return R.string.kg_prompt_reason_timeout_password;
             case PROMPT_REASON_DEVICE_ADMIN:
                 return R.string.kg_prompt_reason_device_admin;
             case PROMPT_REASON_USER_REQUEST:
-                return R.string.kg_prompt_reason_user_request;
+                return R.string.kg_prompt_after_user_lockdown_password;
             case PROMPT_REASON_PREPARE_FOR_UPDATE:
-                return R.string.kg_prompt_reason_timeout_password;
+                return R.string.kg_prompt_unattended_update_password;
             case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT:
                 return R.string.kg_prompt_reason_timeout_password;
             case PROMPT_REASON_TRUSTAGENT_EXPIRED:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index 64b1c50..3d255a5 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -304,6 +304,9 @@
             case PROMPT_REASON_RESTART:
                 resId = R.string.kg_prompt_reason_restart_pattern;
                 break;
+            case PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE:
+                resId = R.string.kg_prompt_after_update_pattern;
+                break;
             case PROMPT_REASON_TIMEOUT:
                 resId = R.string.kg_prompt_reason_timeout_pattern;
                 break;
@@ -311,10 +314,10 @@
                 resId = R.string.kg_prompt_reason_device_admin;
                 break;
             case PROMPT_REASON_USER_REQUEST:
-                resId = R.string.kg_prompt_reason_user_request;
+                resId = R.string.kg_prompt_after_user_lockdown_pattern;
                 break;
             case PROMPT_REASON_PREPARE_FOR_UPDATE:
-                resId = R.string.kg_prompt_reason_timeout_pattern;
+                resId = R.string.kg_prompt_unattended_update_pattern;
                 break;
             case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT:
                 resId = R.string.kg_prompt_reason_timeout_pattern;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 5cb2c5c..38e5dc5 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -21,6 +21,7 @@
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART;
+import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED;
 import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
@@ -113,14 +114,16 @@
         switch (reason) {
             case PROMPT_REASON_RESTART:
                 return R.string.kg_prompt_reason_restart_pin;
+            case PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE:
+                return R.string.kg_prompt_after_update_pin;
             case PROMPT_REASON_TIMEOUT:
                 return R.string.kg_prompt_reason_timeout_pin;
             case PROMPT_REASON_DEVICE_ADMIN:
                 return R.string.kg_prompt_reason_device_admin;
             case PROMPT_REASON_USER_REQUEST:
-                return R.string.kg_prompt_reason_user_request;
+                return R.string.kg_prompt_after_user_lockdown_pin;
             case PROMPT_REASON_PREPARE_FOR_UPDATE:
-                return R.string.kg_prompt_reason_timeout_pin;
+                return R.string.kg_prompt_unattended_update_pin;
             case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT:
                 return R.string.kg_prompt_reason_timeout_pin;
             case PROMPT_REASON_TRUSTAGENT_EXPIRED:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 4211f55..841b5b3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -474,7 +474,8 @@
                     return false;
                 }
                 // Avoid dragging the pattern view
-                if (mSecurityViewFlipper.getSecurityView().disallowInterceptTouch(event)) {
+                if (mSecurityViewFlipper.getSecurityView() != null
+                        && mSecurityViewFlipper.getSecurityView().disallowInterceptTouch(event)) {
                     return false;
                 }
                 int index = event.findPointerIndex(mActivePointerId);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
index 419303d..21960e2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
@@ -103,6 +103,12 @@
     int PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT = 15;
 
     /**
+     * Strong auth is required because the device has just booted because of an automatic
+     * mainline update.
+     */
+    int PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE = 16;
+
+    /**
      * Reset the view and prepare to take input. This should do things like clearing the
      * password or pattern and clear error messages.
      */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index c7e817e..ae061c0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -2045,11 +2045,47 @@
     private final HashMap<Integer, Boolean> mIsUnlockWithFingerprintPossible = new HashMap<>();
 
     /**
-     * When we receive a
-     * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
+     * When we receive a {@link android.content.Intent#ACTION_SIM_STATE_CHANGED} broadcast,
      * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
      * we need a single object to pass to the handler.  This class helps decode
      * the intent and provide a {@link SimData} result.
+     *
+     * Below is the Sim state mapping matrixs:
+     * +---+-----------------------------------------------------+----------------------------+
+     * |   |Telephony FWK broadcast with action                  |SystemUI mapping SIM state  |
+     * |   |android.content.Intent#ACTION_SIM_STATE_CHANGED      |refer to android.telephony. |
+     * |NO.+-------------------------+---------------------------+TelephonyManager#getSimState|
+     * |   |EXTRA_SIM_STATE          |EXTRA_SIM_LOCKED_REASON    |                            |
+     * |   |(Intent#XXX)             |(Intent#XXX)               |TelephonyManager#SimState   |
+     * +===+=====================================================+============================+
+     * |1  |SIM_STATE_UNKNOWN        |always null                |SIM_STATE_UNKNOWN           |
+     * +---+-------------------------+---------------------------+----------------------------+
+     * |2  |SIM_STATE_ABSENT         |always null                |SIM_STATE_ABSENT            |
+     * +---+-------------------------+---------------------------+----------------------------+
+     * |3  |SIM_STATE_CARD_IO_ERROR  |SIM_STATE_CARD_IO_ERROR    |SIM_STATE_CARD_IO_ERROR     |
+     * +---+-------------------------+---------------------------+----------------------------+
+     * |4  |SIM_STATE_CARD_RESTRICTED|SIM_STATE_CARD_RESTRICTED  |SIM_STATE_CARD_RESTRICTED   |
+     * +---+-------------------------+---------------------------+----------------------------+
+     * |5  |SIM_STATE_LOCKED         |SIM_LOCKED_ON_PIN          |SIM_STATE_PIN_REQUIRED      |
+     * +---+-------------------------+---------------------------+----------------------------+
+     * |6  |SIM_STATE_LOCKED         |SIM_LOCKED_ON_PUK          |SIM_STATE_PUK_REQUIRED      |
+     * +---+-------------------------+---------------------------+----------------------------+
+     * |7  |SIM_STATE_LOCKED         |SIM_LOCKED_NETWORK         |SIM_STATE_NETWORK_LOCKED    |
+     * +---+-------------------------+---------------------------+----------------------------+
+     * |8  |SIM_STATE_LOCKED         |SIM_ABSENT_ON_PERM_DISABLED|SIM_STATE_PERM_DISABLED     |
+     * +---+-------------------------+---------------------------+----------------------------+
+     * |9  |SIM_STATE_NOT_READY      |always null                |SIM_STATE_NOT_READY         |
+     * +---+-------------------------+---------------------------+----------------------------+
+     * |10 |SIM_STATE_IMSI           |always null                |SIM_STATE_READY             |
+     * +---+-------------------------+---------------------------+----------------------------+
+     * |11 |SIM_STATE_READY          |always null                |SIM_STATE_READY             |
+     * +---+-------------------------+---------------------------+----------------------------+
+     * |12 |SIM_STATE_LOADED         |always null                |SIM_STATE_READY             |
+     * +---+-------------------------+---------------------------+----------------------------+
+     *
+     * Note that, it seems #10 imsi ready case(i.e. SIM_STATE_IMSI) is never triggered from
+     * Android Pie(telephony FWK doesn't trigger this broadcast any more), but it is still
+     * OK keep this mapping logic.
      */
     private static class SimData {
         public int simState;
@@ -2063,26 +2099,16 @@
         }
 
         static SimData fromIntent(Intent intent) {
-            int state;
             if (!Intent.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
                 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
             }
+            int state = TelephonyManager.SIM_STATE_UNKNOWN;
             String stateExtra = intent.getStringExtra(Intent.EXTRA_SIM_STATE);
             int slotId = intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0);
             int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
                     SubscriptionManager.INVALID_SUBSCRIPTION_ID);
             if (Intent.SIM_STATE_ABSENT.equals(stateExtra)) {
-                final String absentReason = intent
-                        .getStringExtra(Intent.EXTRA_SIM_LOCKED_REASON);
-
-                if (Intent.SIM_ABSENT_ON_PERM_DISABLED.equals(
-                        absentReason)) {
-                    state = TelephonyManager.SIM_STATE_PERM_DISABLED;
-                } else {
-                    state = TelephonyManager.SIM_STATE_ABSENT;
-                }
-            } else if (Intent.SIM_STATE_READY.equals(stateExtra)) {
-                state = TelephonyManager.SIM_STATE_READY;
+                state = TelephonyManager.SIM_STATE_ABSENT;
             } else if (Intent.SIM_STATE_LOCKED.equals(stateExtra)) {
                 final String lockedReason = intent
                         .getStringExtra(Intent.EXTRA_SIM_LOCKED_REASON);
@@ -2090,22 +2116,24 @@
                     state = TelephonyManager.SIM_STATE_PIN_REQUIRED;
                 } else if (Intent.SIM_LOCKED_ON_PUK.equals(lockedReason)) {
                     state = TelephonyManager.SIM_STATE_PUK_REQUIRED;
+                } else if (Intent.SIM_LOCKED_NETWORK.equals(lockedReason)) {
+                    state = TelephonyManager.SIM_STATE_NETWORK_LOCKED;
                 } else if (Intent.SIM_ABSENT_ON_PERM_DISABLED.equals(lockedReason)) {
                     state = TelephonyManager.SIM_STATE_PERM_DISABLED;
-                } else {
-                    state = TelephonyManager.SIM_STATE_UNKNOWN;
                 }
-            } else if (Intent.SIM_LOCKED_NETWORK.equals(stateExtra)) {
-                state = TelephonyManager.SIM_STATE_NETWORK_LOCKED;
             } else if (Intent.SIM_STATE_CARD_IO_ERROR.equals(stateExtra)) {
                 state = TelephonyManager.SIM_STATE_CARD_IO_ERROR;
-            } else if (Intent.SIM_STATE_LOADED.equals(stateExtra)
+            } else if (Intent.SIM_STATE_CARD_RESTRICTED.equals(stateExtra)) {
+                state = TelephonyManager.SIM_STATE_CARD_RESTRICTED;
+            } else if (Intent.SIM_STATE_NOT_READY.equals(stateExtra)) {
+                state = TelephonyManager.SIM_STATE_NOT_READY;
+            } else if (Intent.SIM_STATE_READY.equals(stateExtra)
+                    || Intent.SIM_STATE_LOADED.equals(stateExtra)
                     || Intent.SIM_STATE_IMSI.equals(stateExtra)) {
-                // This is required because telephony doesn't return to "READY" after
+                // Mapping SIM_STATE_LOADED and SIM_STATE_IMSI to SIM_STATE_READY is required
+                // because telephony doesn't return to "READY" after
                 // these state transitions. See bug 7197471.
                 state = TelephonyManager.SIM_STATE_READY;
-            } else {
-                state = TelephonyManager.SIM_STATE_UNKNOWN;
             }
             return new SimData(state, slotId, subId);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index f3403f7..951d077 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -266,7 +266,7 @@
     /** Flag meant to guard the talkback fix for the KeyguardIndicationTextView */
     // TODO(b/286563884): Tracking bug
     @JvmField
-    val KEYGUARD_TALKBACK_FIX = unreleasedFlag(238, "keyguard_talkback_fix")
+    val KEYGUARD_TALKBACK_FIX = releasedFlag(238, "keyguard_talkback_fix")
 
     // 300 - power menu
     // TODO(b/254512600): Tracking Bug
@@ -740,6 +740,12 @@
     val ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD =
         releasedFlag(2900, "zj_285570694_lockscreen_transition_from_aod")
 
+    // 3000 - dream
+    // TODO(b/285059790) : Tracking Bug
+    @JvmField
+    val LOCKSCREEN_WALLPAPER_DREAM_ENABLED =
+        unreleasedFlag(3000, name = "enable_lockscreen_wallpaper_dream")
+
     // TODO(b/283084712): Tracking Bug
     @JvmField
     val IMPROVED_HUN_ANIMATIONS = unreleasedFlag(283084712, "improved_hun_animations")
@@ -748,4 +754,15 @@
     @JvmField
     val BIGPICTURE_NOTIFICATION_LAZY_LOADING =
             unreleasedFlag(283447257, "bigpicture_notification_lazy_loading")
+
+    // TODO(b/283740863): Tracking Bug
+    @JvmField
+    val ENABLE_NEW_PRIVACY_DIALOG =
+            unreleasedFlag(283740863, "enable_new_privacy_dialog", teamfood = false)
+
+    // 2900 - CentralSurfaces-related flags
+
+    // TODO(b/285174336): Tracking Bug
+    @JvmField
+    val USE_REPOS_FOR_BOUNCER_SHOWING = unreleasedFlag(2900, "use_repos_for_bouncer_showing")
 }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 2807107..76322ad 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -249,6 +249,7 @@
     private int mDialogPressDelay = DIALOG_PRESS_DELAY; // ms
     protected Handler mMainHandler;
     private int mSmallestScreenWidthDp;
+    private int mOrientation;
     private final Optional<CentralSurfaces> mCentralSurfacesOptional;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final DialogLaunchAnimator mDialogLaunchAnimator;
@@ -391,6 +392,7 @@
         mRingerModeTracker = ringerModeTracker;
         mMainHandler = handler;
         mSmallestScreenWidthDp = resources.getConfiguration().smallestScreenWidthDp;
+        mOrientation = resources.getConfiguration().orientation;
         mCentralSurfacesOptional = centralSurfacesOptional;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mDialogLaunchAnimator = dialogLaunchAnimator;
@@ -744,8 +746,10 @@
     @Override
     public void onConfigChanged(Configuration newConfig) {
         if (mDialog != null && mDialog.isShowing()
-                && (newConfig.smallestScreenWidthDp != mSmallestScreenWidthDp)) {
+                && (newConfig.smallestScreenWidthDp != mSmallestScreenWidthDp
+                || newConfig.orientation != mOrientation)) {
             mSmallestScreenWidthDp = newConfig.smallestScreenWidthDp;
+            mOrientation = newConfig.orientation;
             mDialog.refreshDialog();
         }
     }
@@ -2303,6 +2307,8 @@
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
+            getWindow().setTitle(getContext().getString(
+                    com.android.systemui.R.string.accessibility_quick_settings_power_menu));
             initializeLayout();
             mWindowDimAmount = getWindow().getAttributes().dimAmount;
             getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index a2c940b..e6053fb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -80,6 +80,8 @@
 import com.android.wm.shell.util.TransitionUtil;
 
 import java.util.ArrayList;
+import java.util.Map;
+import java.util.WeakHashMap;
 
 import javax.inject.Inject;
 
@@ -192,7 +194,8 @@
             private final CounterRotator mCounterRotator = new CounterRotator();
 
             @GuardedBy("mLeashMap")
-            private IRemoteTransitionFinishedCallback mFinishCallback = null;
+            private final Map<IBinder, IRemoteTransitionFinishedCallback> mFinishCallbacks =
+                    new WeakHashMap<>();
 
             @Override
             public void startAnimation(IBinder transition, TransitionInfo info,
@@ -206,7 +209,7 @@
                 synchronized (mLeashMap) {
                     apps = wrap(info, false /* wallpapers */, t, mLeashMap, mCounterRotator);
                     wallpapers = wrap(info, true /* wallpapers */, t, mLeashMap, mCounterRotator);
-                    mFinishCallback = finishCallback;
+                    mFinishCallbacks.put(transition, finishCallback);
                 }
 
                 // Set alpha back to 1 for the independent changes because we will be animating
@@ -229,7 +232,7 @@
                             @Override
                             public void onAnimationFinished() throws RemoteException {
                                 Slog.d(TAG, "Finish IRemoteAnimationRunner.");
-                                finish();
+                                finish(transition);
                             }
                         });
             }
@@ -246,7 +249,7 @@
 
                 try {
                     runner.onAnimationCancelled();
-                    finish();
+                    finish(currentTransition);
                 } catch (RemoteException e) {
                     // nothing, we'll just let it finish on its own I guess.
                 }
@@ -260,7 +263,7 @@
                 }
             }
 
-            private void finish() throws RemoteException {
+            private void finish(IBinder transition) throws RemoteException {
                 IRemoteTransitionFinishedCallback finishCallback = null;
                 SurfaceControl.Transaction finishTransaction = null;
 
@@ -271,8 +274,7 @@
                         mCounterRotator.cleanUp(finishTransaction);
                     }
                     mLeashMap.clear();
-                    finishCallback = mFinishCallback;
-                    mFinishCallback = null;
+                    finishCallback = mFinishCallbacks.remove(transition);
                 }
 
                 if (finishCallback != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 97244c8..bc41ab31 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -33,6 +33,7 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE;
 import static com.android.systemui.DejankUtils.whitelistIpcs;
 import static com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel.DREAMING_ANIMATION_DURATION_MS;
@@ -136,6 +137,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
+import com.android.systemui.flags.SystemPropertiesHelper;
 import com.android.systemui.keyguard.dagger.KeyguardModule;
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
 import com.android.systemui.log.SessionTracker;
@@ -166,6 +168,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 
@@ -279,6 +282,8 @@
      * keyguard to show even if it is disabled for the current user.
      */
     public static final String OPTION_FORCE_SHOW = "force_show";
+    public static final String SYS_BOOT_REASON_PROP = "sys.boot.reason.last";
+    public static final String REBOOT_MAINLINE_UPDATE = "reboot,mainline_update";
     private final DreamOverlayStateController mDreamOverlayStateController;
 
     /** The stream type that the lock sounds are tied to. */
@@ -314,6 +319,7 @@
 
     /** UserSwitcherController for creating guest user on boot complete */
     private final UserSwitcherController mUserSwitcherController;
+    private SystemPropertiesHelper mSystemPropertiesHelper;
 
     /**
      * Used to keep the device awake while to ensure the keyguard finishes opening before
@@ -845,9 +851,16 @@
                     strongAuthTracker.isNonStrongBiometricAllowedAfterIdleTimeout(currentUser);
 
             if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) {
-                return KeyguardSecurityView.PROMPT_REASON_RESTART;
+                String reasonForReboot = mSystemPropertiesHelper.get(SYS_BOOT_REASON_PROP);
+                if (Objects.equals(reasonForReboot, REBOOT_MAINLINE_UPDATE)) {
+                    return KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE;
+                } else {
+                    return  KeyguardSecurityView.PROMPT_REASON_RESTART;
+                }
             } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) != 0) {
                 return KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
+            } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN) != 0) {
+                return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
             } else if ((strongAuth & STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) != 0) {
                 return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
             } else if (trustAgentsEnabled
@@ -1240,7 +1253,8 @@
         @Override
         public void onPrimaryBouncerShowingChanged() {
             synchronized (KeyguardViewMediator.this) {
-                if (mKeyguardStateController.isPrimaryBouncerShowing()) {
+                if (mKeyguardStateController.isPrimaryBouncerShowing()
+                        && !mKeyguardStateController.isKeyguardGoingAway()) {
                     mPendingPinLock = false;
                 }
                 adjustStatusBarLocked(mKeyguardStateController.isPrimaryBouncerShowing(), false);
@@ -1301,7 +1315,8 @@
             Lazy<ScrimController> scrimControllerLazy,
             FeatureFlags featureFlags,
             @Main CoroutineDispatcher mainDispatcher,
-            Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel) {
+            Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel,
+            SystemPropertiesHelper systemPropertiesHelper) {
         mContext = context;
         mUserTracker = userTracker;
         mFalsingCollector = falsingCollector;
@@ -1315,6 +1330,7 @@
         mPM = powerManager;
         mTrustManager = trustManager;
         mUserSwitcherController = userSwitcherController;
+        mSystemPropertiesHelper = systemPropertiesHelper;
         mStatusBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
         mKeyguardDisplayManager = keyguardDisplayManager;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactory.kt b/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactory.kt
index 4085dab..11bc88a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactory.kt
@@ -36,43 +36,9 @@
 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED
 import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST
 import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.R.string.bouncer_face_not_recognized
 import com.android.systemui.R.string.keyguard_enter_password
 import com.android.systemui.R.string.keyguard_enter_pattern
 import com.android.systemui.R.string.keyguard_enter_pin
-import com.android.systemui.R.string.kg_bio_too_many_attempts_password
-import com.android.systemui.R.string.kg_bio_too_many_attempts_pattern
-import com.android.systemui.R.string.kg_bio_too_many_attempts_pin
-import com.android.systemui.R.string.kg_bio_try_again_or_password
-import com.android.systemui.R.string.kg_bio_try_again_or_pattern
-import com.android.systemui.R.string.kg_bio_try_again_or_pin
-import com.android.systemui.R.string.kg_face_locked_out
-import com.android.systemui.R.string.kg_fp_locked_out
-import com.android.systemui.R.string.kg_fp_not_recognized
-import com.android.systemui.R.string.kg_primary_auth_locked_out_password
-import com.android.systemui.R.string.kg_primary_auth_locked_out_pattern
-import com.android.systemui.R.string.kg_primary_auth_locked_out_pin
-import com.android.systemui.R.string.kg_prompt_after_dpm_lock
-import com.android.systemui.R.string.kg_prompt_after_user_lockdown_password
-import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pattern
-import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pin
-import com.android.systemui.R.string.kg_prompt_auth_timeout
-import com.android.systemui.R.string.kg_prompt_password_auth_timeout
-import com.android.systemui.R.string.kg_prompt_pattern_auth_timeout
-import com.android.systemui.R.string.kg_prompt_pin_auth_timeout
-import com.android.systemui.R.string.kg_prompt_reason_restart_password
-import com.android.systemui.R.string.kg_prompt_reason_restart_pattern
-import com.android.systemui.R.string.kg_prompt_reason_restart_pin
-import com.android.systemui.R.string.kg_prompt_unattended_update
-import com.android.systemui.R.string.kg_too_many_failed_attempts_countdown
-import com.android.systemui.R.string.kg_trust_agent_disabled
-import com.android.systemui.R.string.kg_unlock_with_password_or_fp
-import com.android.systemui.R.string.kg_unlock_with_pattern_or_fp
-import com.android.systemui.R.string.kg_unlock_with_pin_or_fp
-import com.android.systemui.R.string.kg_wrong_input_try_fp_suggestion
-import com.android.systemui.R.string.kg_wrong_password_try_again
-import com.android.systemui.R.string.kg_wrong_pattern_try_again
-import com.android.systemui.R.string.kg_wrong_pin_try_again
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel
 import com.android.systemui.keyguard.bouncer.shared.model.Message
@@ -186,175 +152,171 @@
 
 private fun defaultMessageWithFingerprint(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, 0)
-        SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, 0)
-        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, 0)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun incorrectSecurityInput(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, 0)
-        SecurityMode.Password -> Pair(kg_wrong_password_try_again, 0)
-        SecurityMode.PIN -> Pair(kg_wrong_pin_try_again, 0)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun incorrectSecurityInputWithFingerprint(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, kg_wrong_input_try_fp_suggestion)
-        SecurityMode.Password -> Pair(kg_wrong_password_try_again, kg_wrong_input_try_fp_suggestion)
-        SecurityMode.PIN -> Pair(kg_wrong_pin_try_again, kg_wrong_input_try_fp_suggestion)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun incorrectFingerprintInput(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pattern)
-        SecurityMode.Password -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_password)
-        SecurityMode.PIN -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pin)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun incorrectFaceInput(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pattern)
-        SecurityMode.Password -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_password)
-        SecurityMode.PIN -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pin)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun incorrectFaceInputWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, bouncer_face_not_recognized)
-        SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, bouncer_face_not_recognized)
-        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, bouncer_face_not_recognized)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun biometricLockout(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_bio_too_many_attempts_pattern)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_bio_too_many_attempts_password)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_bio_too_many_attempts_pin)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun authRequiredAfterReboot(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_reason_restart_pattern)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_reason_restart_password)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_reason_restart_pin)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun authRequiredAfterAdminLockdown(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_dpm_lock)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_after_dpm_lock)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun authRequiredAfterUserLockdown(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_user_lockdown_pattern)
-        SecurityMode.Password ->
-            Pair(keyguard_enter_password, kg_prompt_after_user_lockdown_password)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_user_lockdown_pin)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun authRequiredForUnattendedUpdate(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_unattended_update)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_unattended_update)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_unattended_update)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun authRequiredAfterPrimaryAuthTimeout(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_pattern_auth_timeout)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_password_auth_timeout)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_pin_auth_timeout)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun nonStrongAuthTimeout(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_auth_timeout)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_auth_timeout)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_auth_timeout)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun nonStrongAuthTimeoutWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_prompt_auth_timeout)
-        SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_prompt_auth_timeout)
-        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_prompt_auth_timeout)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun faceUnlockUnavailable(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_face_locked_out)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_face_locked_out)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_face_locked_out)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun fingerprintUnlockUnavailable(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_fp_locked_out)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_fp_locked_out)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_fp_locked_out)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun trustAgentDisabled(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_trust_agent_disabled)
-        SecurityMode.Password -> Pair(keyguard_enter_password, kg_trust_agent_disabled)
-        SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_trust_agent_disabled)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun trustAgentDisabledWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_trust_agent_disabled)
-        SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_trust_agent_disabled)
-        SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_trust_agent_disabled)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
 
 private fun primaryAuthLockedOut(securityMode: SecurityMode): Pair<Int, Int> {
     return when (securityMode) {
-        SecurityMode.Pattern ->
-            Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pattern)
-        SecurityMode.Password ->
-            Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_password)
-        SecurityMode.PIN ->
-            Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pin)
+        SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0)
+        SecurityMode.Password -> Pair(keyguard_enter_password, 0)
+        SecurityMode.PIN -> Pair(keyguard_enter_pin, 0)
         else -> Pair(0, 0)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index ab79c80..1f121e9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -42,6 +42,7 @@
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.SystemPropertiesHelper;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -134,7 +135,8 @@
             Lazy<ScrimController> scrimControllerLazy,
             FeatureFlags featureFlags,
             @Main CoroutineDispatcher mainDispatcher,
-            Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel) {
+            Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel,
+            SystemPropertiesHelper systemPropertiesHelper) {
         return new KeyguardViewMediator(
                 context,
                 uiEventLogger,
@@ -170,7 +172,8 @@
                 scrimControllerLazy,
                 featureFlags,
                 mainDispatcher,
-                dreamingToLockscreenTransitionViewModel);
+                dreamingToLockscreenTransitionViewModel,
+                systemPropertiesHelper);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index b96ca7a..3b32313e 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -224,7 +224,6 @@
                         return LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION;
                     }
                 });
-        controller.overrideIconTintForNavMode(true);
 
         return controller;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 1712490..d511d8a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -114,11 +114,18 @@
         mQs = qs;
     }
 
+    private void reloadAdapterTileHeight(@Nullable RecyclerView.Adapter adapter) {
+        if (adapter instanceof TileAdapter) {
+            ((TileAdapter) adapter).reloadTileHeight();
+        }
+    }
+
     /** Animate and show QSCustomizer panel.
      * @param x,y Location on screen of {@code edit} button to determine center of animation.
      */
     void show(int x, int y, TileAdapter tileAdapter) {
         if (!isShown) {
+            reloadAdapterTileHeight(tileAdapter);
             mRecyclerView.getLayoutManager().scrollToPosition(0);
             int[] containerLocation = findViewById(R.id.customize_container).getLocationOnScreen();
             mX = x - containerLocation[0];
@@ -136,6 +143,7 @@
 
     void showImmediately() {
         if (!isShown) {
+            reloadAdapterTileHeight(mRecyclerView.getAdapter());
             mRecyclerView.getLayoutManager().scrollToPosition(0);
             setVisibility(VISIBLE);
             mClipper.cancelAnimator();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 6a05684..596475e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -43,9 +43,11 @@
 import androidx.recyclerview.widget.RecyclerView.ViewHolder;
 
 import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSEditEvent;
 import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.TileLayout;
 import com.android.systemui.qs.customize.TileAdapter.Holder;
 import com.android.systemui.qs.customize.TileQueryHelper.TileInfo;
 import com.android.systemui.qs.customize.TileQueryHelper.TileStateListener;
@@ -114,6 +116,9 @@
     private RecyclerView mRecyclerView;
     private int mNumColumns;
 
+    private TextView mTempTextView;
+    private int mMinTileViewHeight;
+
     @Inject
     public TileAdapter(
             @QSThemedContext Context context,
@@ -129,6 +134,8 @@
         mNumColumns = context.getResources().getInteger(NUM_COLUMNS_ID);
         mAccessibilityDelegate = new TileAdapterDelegate();
         mSizeLookup.setSpanIndexCacheEnabled(true);
+        mTempTextView = new TextView(context);
+        mMinTileViewHeight = context.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
     }
 
     @Override
@@ -318,6 +325,10 @@
 
     @Override
     public void onBindViewHolder(final Holder holder, int position) {
+        if (holder.mTileView != null) {
+            holder.mTileView.setMinimumHeight(mMinTileViewHeight);
+        }
+
         if (holder.getItemViewType() == TYPE_HEADER) {
             setSelectableForHeaders(holder.itemView);
             return;
@@ -860,4 +871,19 @@
                 - buttonMinWidth
                 - res.getDimensionPixelSize(R.dimen.qs_tile_margin_top_bottom);
     }
+
+    /**
+     * Re-estimate the tile view height based under current font scaling. Like
+     * {@link TileLayout#estimateCellHeight()}, the tile view height would be estimated with 2
+     * labels as general case.
+     */
+    public void reloadTileHeight() {
+        final int minHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
+        FontSizeUtils.updateFontSize(mTempTextView, R.dimen.qs_tile_text_size);
+        int unspecifiedSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
+        mTempTextView.measure(unspecifiedSpec, unspecifiedSpec);
+        int padding = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_padding);
+        int estimatedTileViewHeight = mTempTextView.getMeasuredHeight() * 2 + padding * 2;
+        mMinTileViewHeight = Math.max(minHeight, estimatedTileViewHeight);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index d2e94d6..776a90d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -4813,7 +4813,9 @@
 
             if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && mQsController.handleTouch(
                     event, isFullyCollapsed(), isShadeOrQsHeightAnimationRunning())) {
-                mShadeLog.logMotionEvent(event, "onTouch: handleQsTouch handled event");
+                if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
+                    mShadeLog.logMotionEvent(event, "onTouch: handleQsTouch handled event");
+                }
                 return true;
             }
             if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
@@ -4827,7 +4829,6 @@
             }
 
             handled |= handleTouch(event);
-            mShadeLog.logOnTouchEventLastReturn(event, !mDozing, handled);
             return !mDozing || handled;
         }
 
@@ -5010,7 +5011,6 @@
                     }
                     break;
             }
-            mShadeLog.logHandleTouchLastReturn(event, !mGestureWaitForTouchSlop, mTracking);
             return !mGestureWaitForTouchSlop || mTracking;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index 6480164..7d66a0b 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -1186,7 +1186,6 @@
                         mClippingAnimationEndBounds.left, fraction);
                 int animTop = (int) MathUtils.lerp(startTop,
                         mClippingAnimationEndBounds.top, fraction);
-                logClippingTopBound("interpolated top bound", top);
                 int animRight = (int) MathUtils.lerp(startRight,
                         mClippingAnimationEndBounds.right, fraction);
                 int animBottom = (int) MathUtils.lerp(startBottom,
@@ -1216,7 +1215,8 @@
         if (mIsFullWidth) {
             clipStatusView = qsVisible;
             float screenCornerRadius =
-                    mRecordingController.isRecording() || mCastController.hasConnectedCastDevice()
+                    !mSplitShadeEnabled || mRecordingController.isRecording()
+                            || mCastController.hasConnectedCastDevice()
                             ? 0 : mScreenCornerRadius;
             radius = (int) MathUtils.lerp(screenCornerRadius, mScrimCornerRadius,
                     Math.min(top / (float) mScrimCornerRadius, 1f));
@@ -1337,8 +1337,6 @@
             // the screen without clipping.
             return -mAmbientState.getStackTopMargin();
         } else {
-            logNotificationsClippingTopBound(qsTop,
-                    mNotificationStackScrollLayoutController.getTop());
             return qsTop - mNotificationStackScrollLayoutController.getTop();
         }
     }
@@ -1380,25 +1378,21 @@
                     keyguardNotificationStaticPadding, maxQsPadding) : maxQsPadding;
             topPadding = (int) MathUtils.lerp((float) getMinExpansionHeight(),
                     (float) max, expandedFraction);
-            logNotificationsTopPadding("keyguard and expandImmediate", topPadding);
             return topPadding;
         } else if (isSizeChangeAnimationRunning()) {
             topPadding = Math.max((int) mSizeChangeAnimator.getAnimatedValue(),
                     keyguardNotificationStaticPadding);
-            logNotificationsTopPadding("size change animation running", topPadding);
             return topPadding;
         } else if (keyguardShowing) {
             // We can only do the smoother transition on Keyguard when we also are not collapsing
             // from a scrolled quick settings.
             topPadding = MathUtils.lerp((float) keyguardNotificationStaticPadding,
                     (float) (getMaxExpansionHeight()), computeExpansionFraction());
-            logNotificationsTopPadding("keyguard", topPadding);
             return topPadding;
         } else {
             topPadding = Math.max(mQsFrameTranslateController.getNotificationsTopPadding(
                     mExpansionHeight, mNotificationStackScrollLayoutController),
                     mQuickQsHeaderHeight);
-            logNotificationsTopPadding("default case", topPadding);
             return topPadding;
         }
     }
@@ -1446,38 +1440,6 @@
                         - mAmbientState.getScrollY());
     }
 
-    /** TODO(b/273591201): remove after bug resolved */
-    private void logNotificationsTopPadding(String message, float rawPadding) {
-        int padding =  ((int) rawPadding / 10) * 10;
-        if (mBarState != KEYGUARD && padding != mLastNotificationsTopPadding && !mExpanded) {
-            mLastNotificationsTopPadding = padding;
-            mShadeLog.logNotificationsTopPadding(message, padding);
-        }
-    }
-
-    /** TODO(b/273591201): remove after bug resolved */
-    private void logClippingTopBound(String message, int top) {
-        top = (top / 10) * 10;
-        if (mBarState != KEYGUARD && mShadeExpandedFraction == 1
-                && top != mLastClippingTopBound && !mExpanded) {
-            mLastClippingTopBound = top;
-            mShadeLog.logClippingTopBound(message, top);
-        }
-    }
-
-    /** TODO(b/273591201): remove after bug resolved */
-    private void logNotificationsClippingTopBound(int top, int nsslTop) {
-        top = (top / 10) * 10;
-        nsslTop = (nsslTop / 10) * 10;
-        if (mBarState == SHADE && mShadeExpandedFraction == 1
-                && (top != mLastNotificationsClippingTopBound
-                || nsslTop != mLastNotificationsClippingTopBoundNssl) && !mExpanded) {
-            mLastNotificationsClippingTopBound = top;
-            mLastNotificationsClippingTopBoundNssl = nsslTop;
-            mShadeLog.logNotificationsClippingTopBound(top, nsslTop);
-        }
-    }
-
     private int calculateTopClippingBound(int qsPanelBottomY) {
         int top;
         if (mSplitShadeEnabled) {
@@ -1487,7 +1449,6 @@
                 // If we're transitioning, let's use the actual value. The else case
                 // can be wrong during transitions when waiting for the keyguard to unlock
                 top = mTransitionToFullShadePosition;
-                logClippingTopBound("set while transitioning to full shade", top);
             } else {
                 final float notificationTop = getEdgePosition();
                 if (mBarState == KEYGUARD) {
@@ -1496,10 +1457,8 @@
                         // this should go away once we unify the stackY position and don't have
                         // to do this min anymore below.
                         top = qsPanelBottomY;
-                        logClippingTopBound("bypassing keyguard", top);
                     } else {
                         top = (int) Math.min(qsPanelBottomY, notificationTop);
-                        logClippingTopBound("keyguard default case", top);
                     }
                 } else {
                     top = (int) notificationTop;
@@ -1507,14 +1466,12 @@
             }
             // TODO (b/265193930): remove dependency on NPVC
             top += mPanelViewControllerLazy.get().getOverStretchAmount();
-            logClippingTopBound("including overstretch", top);
             // Correction for instant expansion caused by HUN pull down/
             float minFraction = mPanelViewControllerLazy.get().getMinFraction();
             if (minFraction > 0f && minFraction < 1f) {
                 float realFraction = (mShadeExpandedFraction
                         - minFraction) / (1f - minFraction);
                 top *= MathUtils.saturate(realFraction / minFraction);
-                logClippingTopBound("after adjusted fraction", top);
             }
         }
         return top;
@@ -1654,15 +1611,11 @@
         // as sometimes the qsExpansionFraction can be a tiny value instead of 0 when in QQS.
         if (!mSplitShadeEnabled && !mLastShadeFlingWasExpanding
                 && computeExpansionFraction() <= 0.01 && mShadeExpandedFraction < 1.0) {
-            mShadeLog.logMotionEvent(event,
-                    "handleQsTouch: shade touched while shade collapsing, QS tracking disabled");
             mTracking = false;
         }
         if (!isExpandImmediate() && mTracking) {
             onTouch(event);
             if (!mConflictingExpansionGesture && !mSplitShadeEnabled) {
-                mShadeLog.logMotionEvent(event,
-                        "handleQsTouch: not immediate expand or conflicting gesture");
                 return true;
             }
         }
@@ -1756,7 +1709,6 @@
                 break;
 
             case MotionEvent.ACTION_MOVE:
-                mShadeLog.logMotionEvent(event, "onQsTouch: move action, setting QS expansion");
                 setExpansionHeight(h + mInitialHeightOnTouch);
                 // TODO (b/265193930): remove dependency on NPVC
                 if (h >= mPanelViewControllerLazy.get().getFalsingThreshold()) {
@@ -1844,17 +1796,14 @@
                 final float h = y - mInitialTouchY;
                 trackMovement(event);
                 if (mTracking) {
-
                     // Already tracking because onOverscrolled was called. We need to update here
                     // so we don't stop for a frame until the next touch event gets handled in
                     // onTouchEvent.
                     setExpansionHeight(h + mInitialHeightOnTouch);
                     trackMovement(event);
                     return true;
-                } else {
-                    mShadeLog.logMotionEvent(event,
-                            "onQsIntercept: move ignored because qs tracking disabled");
                 }
+
                 // TODO (b/265193930): remove dependency on NPVC
                 float touchSlop = event.getClassification()
                         == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE
@@ -1878,7 +1827,7 @@
                 } else {
                     mShadeLog.logQsTrackingNotStarted(mInitialTouchY, y, h, touchSlop,
                             getExpanded(), mPanelViewControllerLazy.get().isKeyguardShowing(),
-                            isExpansionEnabled());
+                            isExpansionEnabled(), event.getDownTime());
                 }
                 break;
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
index 2b772e3..2da8d5f4 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
@@ -54,7 +54,8 @@
         touchSlop: Float,
         qsExpanded: Boolean,
         keyguardShowing: Boolean,
-        qsExpansionEnabled: Boolean
+        qsExpansionEnabled: Boolean,
+        downTime: Long
     ) {
         buffer.log(
             TAG,
@@ -67,10 +68,11 @@
                 bool1 = qsExpanded
                 bool2 = keyguardShowing
                 bool3 = qsExpansionEnabled
+                str1 = downTime.toString()
             },
             {
-                "QsTrackingNotStarted: initTouchY=$int1,y=$int2,h=$long1,slop=$double1,qsExpanded" +
-                    "=$bool1,keyguardShowing=$bool2,qsExpansion=$bool3"
+                "QsTrackingNotStarted: downTime=$str1,initTouchY=$int1,y=$int2,h=$long1," +
+                        "slop=$double1,qsExpanded=$bool1,keyguardShowing=$bool2,qsExpansion=$bool3"
             }
         )
     }
@@ -306,91 +308,6 @@
         )
     }
 
-    fun logNotificationsTopPadding(message: String, padding: Int) {
-        buffer.log(
-            TAG,
-            LogLevel.VERBOSE,
-            {
-                str1 = message
-                int1 = padding
-            },
-            { "QSC NotificationsTopPadding $str1: $int1"}
-        )
-    }
-
-    fun logClippingTopBound(message: String, top: Int) {
-        buffer.log(
-            TAG,
-            LogLevel.VERBOSE,
-            {
-                str1 = message
-                int1 = top
-            },
-            { "QSC ClippingTopBound $str1: $int1" }
-        )
-    }
-
-    fun logNotificationsClippingTopBound(top: Int, nsslTop: Int) {
-        buffer.log(
-            TAG,
-            LogLevel.VERBOSE,
-            {
-                int1 = top
-                int2 = nsslTop
-            },
-            { "QSC NotificationsClippingTopBound set to $int1 - $int2" }
-        )
-    }
-
-    fun logOnTouchEventLastReturn(
-        event: MotionEvent,
-        dozing: Boolean,
-        handled: Boolean,
-    ) {
-        buffer.log(
-            TAG,
-            LogLevel.VERBOSE,
-            {
-                bool1 = dozing
-                bool2 = handled
-                long1 = event.eventTime
-                long2 = event.downTime
-                int1 = event.action
-                int2 = event.classification
-                double1 = event.y.toDouble()
-            },
-            {
-                "NPVC onTouchEvent last return: !mDozing: $bool1 || handled: $bool2 " +
-                        "\neventTime=$long1,downTime=$long2,y=$double1,action=$int1,class=$int2"
-            }
-        )
-    }
-
-    fun logHandleTouchLastReturn(
-        event: MotionEvent,
-        gestureWaitForTouchSlop: Boolean,
-        tracking: Boolean,
-    ) {
-        buffer.log(
-            TAG,
-            LogLevel.VERBOSE,
-            {
-                bool1 = gestureWaitForTouchSlop
-                bool2 = tracking
-                long1 = event.eventTime
-                long2 = event.downTime
-                int1 = event.action
-                int2 = event.classification
-                double1 = event.y.toDouble()
-            },
-            {
-                "NPVC handleTouch last return: !mGestureWaitForTouchSlop: $bool1 " +
-                        "|| mTracking: $bool2 " +
-                        "\neventTime=$long1,downTime=$long2,y=$double1,action=$int1,class=$int2"
-            }
-        )
-    }
-
     fun logUpdateNotificationPanelTouchState(
         disabled: Boolean,
         isGoingToSleep: Boolean,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
index fc1e87a..ad49b26 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
@@ -198,6 +198,11 @@
         return mSlotIndexResolver.getSlotIndex(subscriptionId);
     }
 
+    @VisibleForTesting
+    protected int getShadeCarrierVisibility(int index) {
+        return mCarrierGroups[index].getVisibility();
+    }
+
     /**
      * Sets a {@link OnSingleCarrierChangedListener}.
      *
@@ -307,11 +312,13 @@
                                         + info.subscriptionIds[i]);
                         continue;
                     }
-                    mInfos[slot] = mInfos[slot].changeVisibility(true);
-                    slotSeen[slot] = true;
-                    mCarrierGroups[slot].setCarrierText(
-                            info.listOfCarriers[i].toString().trim());
-                    mCarrierGroups[slot].setVisibility(View.VISIBLE);
+                    String carrierText = info.listOfCarriers[i].toString().trim();
+                    if (!TextUtils.isEmpty(carrierText)) {
+                        mInfos[slot] = mInfos[slot].changeVisibility(true);
+                        slotSeen[slot] = true;
+                        mCarrierGroups[slot].setCarrierText(carrierText);
+                        mCarrierGroups[slot].setVisibility(View.VISIBLE);
+                    }
                 }
                 for (int i = 0; i < SIM_SLOTS; i++) {
                     if (!slotSeen[i]) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
index 731ec80..d47fe20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
@@ -63,10 +63,27 @@
      *      - has a media session associated with it
      *      - has messaging style
      *
-     * A GroupEntry is considered high priority if its representativeEntry (summary) or children are
-     * high priority
+     * A GroupEntry is considered high priority if its representativeEntry (summary) or any of its
+     * children are high priority.
      */
     public boolean isHighPriority(@Nullable ListEntry entry) {
+        return isHighPriority(entry, /* allowImplicit = */ true);
+    }
+
+    /**
+     * @return true if the ListEntry is explicitly high priority, else false
+     *
+     * A NotificationEntry is considered explicitly high priority if has importance greater than or
+     * equal to IMPORTANCE_DEFAULT.
+     *
+     * A GroupEntry is considered explicitly high priority if its representativeEntry (summary) or
+     * any of its children are explicitly high priority.
+     */
+    public boolean isExplicitlyHighPriority(@Nullable ListEntry entry) {
+        return isHighPriority(entry, /* allowImplicit= */ false);
+    }
+
+    private boolean isHighPriority(@Nullable ListEntry entry, boolean allowImplicit) {
         if (entry == null) {
             return false;
         }
@@ -77,8 +94,8 @@
         }
 
         return notifEntry.getRanking().getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
-                || hasHighPriorityCharacteristics(notifEntry)
-                || hasHighPriorityChild(entry);
+                || (allowImplicit && hasHighPriorityCharacteristics(notifEntry))
+                || hasHighPriorityChild(entry, allowImplicit);
     }
 
     /**
@@ -112,7 +129,7 @@
                                 >= NotificationManager.IMPORTANCE_DEFAULT);
     }
 
-    private boolean hasHighPriorityChild(ListEntry entry) {
+    private boolean hasHighPriorityChild(ListEntry entry, boolean allowImplicit) {
         if (entry instanceof NotificationEntry
                 && !mGroupMembershipManager.isGroupSummary((NotificationEntry) entry)) {
             return false;
@@ -121,7 +138,7 @@
         List<NotificationEntry> children = mGroupMembershipManager.getChildren(entry);
         if (children != null) {
             for (NotificationEntry child : children) {
-                if (child != entry && isHighPriority(child)) {
+                if (child != entry && isHighPriority(child, allowImplicit)) {
                     return true;
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
index 7513aa7..90014c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
@@ -180,8 +180,8 @@
     }
 
     private fun shouldHideIfEntrySilent(entry: ListEntry): Boolean = when {
-        // Show if high priority (not hidden)
-        highPriorityProvider.isHighPriority(entry) -> false
+        // Show if explicitly high priority (not hidden)
+        highPriorityProvider.isExplicitlyHighPriority(entry) -> false
         // Ambient notifications are hidden always from lock screen
         entry.representativeEntry?.isAmbient == true -> true
         // [Now notification is silent]
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 1cd0f08..648ece5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -475,6 +475,13 @@
      */
     private boolean mShouldDelayWakeUpAnimation = false;
 
+    /**
+     * Whether we should delay the AOD->Lockscreen animation.
+     * If false, the animation will start in onStartedWakingUp().
+     * If true, the animation will start in onFinishedWakingUp().
+     */
+    private boolean mShouldDelayLockscreenTransitionFromAod = false;
+
     private final Object mQueueLock = new Object();
 
     private final PulseExpansionHandler mPulseExpansionHandler;
@@ -3242,7 +3249,10 @@
 
                 updateVisibleToUser();
                 updateIsKeyguard();
-                if (!mFeatureFlags.isEnabled(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD)) {
+                mShouldDelayLockscreenTransitionFromAod = mDozeParameters.getAlwaysOn()
+                        && mFeatureFlags.isEnabled(
+                                Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD);
+                if (!mShouldDelayLockscreenTransitionFromAod) {
                     startLockscreenTransitionFromAod();
                 }
             });
@@ -3251,8 +3261,7 @@
 
         /**
          * Private helper for starting the LOCKSCREEN_TRANSITION_FROM_AOD animation - only necessary
-         * so we can start it from either onFinishedWakingUp() or onFinishedWakingUp() depending
-         * on a flag value.
+         * so we can start it from either onFinishedWakingUp() or onFinishedWakingUp().
          */
         private void startLockscreenTransitionFromAod() {
             // stopDozing() starts the LOCKSCREEN_TRANSITION_FROM_AOD animation.
@@ -3273,7 +3282,7 @@
 
         @Override
         public void onFinishedWakingUp() {
-            if (mFeatureFlags.isEnabled(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD)) {
+            if (mShouldDelayLockscreenTransitionFromAod) {
                 mNotificationShadeWindowController.batchApplyWindowLayoutParams(
                         this::startLockscreenTransitionFromAod);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 7bc4fc3..ae70384 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -115,7 +115,6 @@
     };
 
     private final Context mContext;
-    private Boolean mOverrideIconTintForNavMode;
 
     @AssistedInject
     public LightBarTransitionsController(
@@ -276,19 +275,11 @@
     }
 
     /**
-     * Specify an override value to return for {@link #overrideIconTintForNavMode(boolean)}.
-     */
-    public void overrideIconTintForNavMode(boolean overrideValue) {
-        mOverrideIconTintForNavMode = overrideValue;
-    }
-    /**
      * Return whether to use the tint calculated in this class for nav icons.
      */
     public boolean supportsIconTintForNavMode(int navigationMode) {
         // In gesture mode, we already do region sampling to update tint based on content beneath.
-        return mOverrideIconTintForNavMode != null
-                ? mOverrideIconTintForNavMode
-                : !QuickStepContract.isGesturalMode(navigationMode);
+        return !QuickStepContract.isGesturalMode(navigationMode);
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
index 48a8d1b..e7d420b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
@@ -561,6 +561,66 @@
                 captor.getValue().carrierText);
     }
 
+    @Test
+    public void testGetStatusForIccState() {
+        when(mKeyguardUpdateMonitor.isDeviceProvisioned()).thenReturn(false);
+        assertEquals(CarrierTextManager.StatusMode.SimMissingLocked,
+                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_ABSENT));
+        assertEquals(CarrierTextManager.StatusMode.NetworkLocked,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_NETWORK_LOCKED));
+        assertEquals(CarrierTextManager.StatusMode.SimNotReady,
+                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_NOT_READY));
+        assertEquals(CarrierTextManager.StatusMode.SimLocked,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_PIN_REQUIRED));
+        assertEquals(CarrierTextManager.StatusMode.SimPukLocked,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_PUK_REQUIRED));
+        assertEquals(CarrierTextManager.StatusMode.Normal,
+                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_READY));
+        assertEquals(CarrierTextManager.StatusMode.SimMissingLocked,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_PERM_DISABLED));
+        assertEquals(CarrierTextManager.StatusMode.SimUnknown,
+                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_UNKNOWN));
+        assertEquals(CarrierTextManager.StatusMode.SimIoError,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_CARD_IO_ERROR));
+        assertEquals(CarrierTextManager.StatusMode.SimRestricted,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_CARD_RESTRICTED));
+
+        when(mKeyguardUpdateMonitor.isDeviceProvisioned()).thenReturn(true);
+        assertEquals(CarrierTextManager.StatusMode.SimMissing,
+                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_ABSENT));
+        assertEquals(CarrierTextManager.StatusMode.NetworkLocked,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_NETWORK_LOCKED));
+        assertEquals(CarrierTextManager.StatusMode.SimNotReady,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_NOT_READY));
+        assertEquals(CarrierTextManager.StatusMode.SimLocked,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_PIN_REQUIRED));
+        assertEquals(CarrierTextManager.StatusMode.SimPukLocked,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_PUK_REQUIRED));
+        assertEquals(CarrierTextManager.StatusMode.Normal,
+                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_READY));
+        assertEquals(CarrierTextManager.StatusMode.SimPermDisabled,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_PERM_DISABLED));
+        assertEquals(CarrierTextManager.StatusMode.SimUnknown,
+                mCarrierTextManager.getStatusForIccState(TelephonyManager.SIM_STATE_UNKNOWN));
+        assertEquals(CarrierTextManager.StatusMode.SimIoError,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_CARD_IO_ERROR));
+        assertEquals(CarrierTextManager.StatusMode.SimRestricted,
+                mCarrierTextManager.getStatusForIccState(
+                        TelephonyManager.SIM_STATE_CARD_RESTRICTED));
+    }
+
     private Context getContextSpyForStickyBroadcast(Intent returnVal) {
         Context contextSpy = spy(mContext);
         doReturn(returnVal).when(contextSpy).registerReceiver(eq(null), any(IntentFilter.class));
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
index ae3a320..fa32835 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
+import android.os.SystemClock;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.KeyEvent;
@@ -183,4 +184,15 @@
         mKeyguardAbsKeyInputViewController.onResume(KeyguardSecurityView.VIEW_REVEALED);
         verify(mLockPatternUtils).getLockoutAttemptDeadline(anyInt());
     }
+
+    @Test
+    public void testLockedOut_verifyPasswordAndUnlock_doesNotEnableViewInput() {
+        mKeyguardAbsKeyInputViewController.handleAttemptLockout(
+                SystemClock.elapsedRealtime() + 1000);
+        mKeyguardAbsKeyInputViewController.verifyPasswordAndUnlock();
+        verify(mAbsKeyInputView).setPasswordEntryInputEnabled(false);
+        verify(mAbsKeyInputView).setPasswordEntryEnabled(false);
+        verify(mAbsKeyInputView, never()).setPasswordEntryInputEnabled(true);
+        verify(mAbsKeyInputView, never()).setPasswordEntryEnabled(true);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index de306d6..1e675f8 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -167,6 +167,7 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -672,6 +673,130 @@
     }
 
     @Test
+    public void testHandleSimStateChange_Unknown() {
+        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_UNKNOWN);
+        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
+                putPhoneInfo(intent, null, false));
+        mTestableLooper.processAllMessages();
+        Assert.assertEquals(TelephonyManager.SIM_STATE_UNKNOWN,
+                mKeyguardUpdateMonitor.getCachedSimState());
+    }
+
+    @Test
+    public void testHandleSimStateChange_Absent() {
+        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_ABSENT);
+        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
+                putPhoneInfo(intent, null, false));
+        mTestableLooper.processAllMessages();
+        Assert.assertEquals(TelephonyManager.SIM_STATE_ABSENT,
+                mKeyguardUpdateMonitor.getCachedSimState());
+    }
+
+    @Test
+    public void testHandleSimStateChange_CardIOError() {
+        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_CARD_IO_ERROR);
+        intent.putExtra(Intent.EXTRA_SIM_LOCKED_REASON, Intent.SIM_STATE_CARD_IO_ERROR);
+        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
+                putPhoneInfo(intent, null, false));
+        mTestableLooper.processAllMessages();
+        Assert.assertEquals(TelephonyManager.SIM_STATE_CARD_IO_ERROR,
+                mKeyguardUpdateMonitor.getCachedSimState());
+    }
+
+    @Test
+    public void testHandleSimStateChange_CardRestricted() {
+        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_CARD_RESTRICTED);
+        intent.putExtra(Intent.EXTRA_SIM_LOCKED_REASON, Intent.SIM_STATE_CARD_RESTRICTED);
+        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
+                putPhoneInfo(intent, null, false));
+        mTestableLooper.processAllMessages();
+        Assert.assertEquals(TelephonyManager.SIM_STATE_CARD_RESTRICTED,
+                mKeyguardUpdateMonitor.getCachedSimState());
+    }
+
+    @Test
+    public void testHandleSimStateChange_Locked() {
+        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_LOCKED);
+
+        // locked on PIN1
+        intent.putExtra(Intent.EXTRA_SIM_LOCKED_REASON, Intent.SIM_LOCKED_ON_PIN);
+        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
+                putPhoneInfo(intent, null, true));
+        mTestableLooper.processAllMessages();
+        Assert.assertEquals(TelephonyManager.SIM_STATE_PIN_REQUIRED,
+                mKeyguardUpdateMonitor.getCachedSimState());
+
+        // locked on PUK1
+        intent.putExtra(Intent.EXTRA_SIM_LOCKED_REASON, Intent.SIM_LOCKED_ON_PUK);
+        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
+                putPhoneInfo(intent, null, true));
+        mTestableLooper.processAllMessages();
+        Assert.assertEquals(TelephonyManager.SIM_STATE_PUK_REQUIRED,
+                mKeyguardUpdateMonitor.getCachedSimState());
+
+        // locked on network personalization
+        intent.putExtra(Intent.EXTRA_SIM_LOCKED_REASON, Intent.SIM_LOCKED_NETWORK);
+        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
+                putPhoneInfo(intent, null, true));
+        mTestableLooper.processAllMessages();
+        Assert.assertEquals(TelephonyManager.SIM_STATE_NETWORK_LOCKED,
+                mKeyguardUpdateMonitor.getCachedSimState());
+
+        // permanently disabled due to puk fails
+        intent.putExtra(Intent.EXTRA_SIM_LOCKED_REASON, Intent.SIM_ABSENT_ON_PERM_DISABLED);
+        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
+                putPhoneInfo(intent, null, true));
+        mTestableLooper.processAllMessages();
+        Assert.assertEquals(TelephonyManager.SIM_STATE_PERM_DISABLED,
+                mKeyguardUpdateMonitor.getCachedSimState());
+    }
+
+    @Test
+    public void testHandleSimStateChange_NotReady() {
+        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_NOT_READY);
+        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
+                putPhoneInfo(intent, null, false));
+        mTestableLooper.processAllMessages();
+        Assert.assertEquals(TelephonyManager.SIM_STATE_NOT_READY,
+                mKeyguardUpdateMonitor.getCachedSimState());
+    }
+
+    @Test
+    public void testHandleSimStateChange_Ready() {
+        Intent intent = new Intent(Intent.ACTION_SIM_STATE_CHANGED);
+
+        // ICC IMSI is ready in property
+        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_IMSI);
+        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
+                putPhoneInfo(intent, null, false));
+        mTestableLooper.processAllMessages();
+        Assert.assertEquals(TelephonyManager.SIM_STATE_READY,
+                mKeyguardUpdateMonitor.getCachedSimState());
+
+        // ICC is ready to access
+        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_READY);
+        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
+                putPhoneInfo(intent, null, false));
+        mTestableLooper.processAllMessages();
+        Assert.assertEquals(TelephonyManager.SIM_STATE_READY,
+                mKeyguardUpdateMonitor.getCachedSimState());
+
+        // all ICC records, including IMSI, are loaded
+        intent.putExtra(Intent.EXTRA_SIM_STATE, Intent.SIM_STATE_LOADED);
+        mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
+                putPhoneInfo(intent, null, true));
+        mTestableLooper.processAllMessages();
+        Assert.assertEquals(TelephonyManager.SIM_STATE_READY,
+                mKeyguardUpdateMonitor.getCachedSimState());
+    }
+
+    @Test
     public void testTriesToAuthenticateFingerprint_whenKeyguard() {
         mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
         mTestableLooper.processAllMessages();
@@ -3122,6 +3247,7 @@
 
     private class TestableKeyguardUpdateMonitor extends KeyguardUpdateMonitor {
         AtomicBoolean mSimStateChanged = new AtomicBoolean(false);
+        AtomicInteger mCachedSimState = new AtomicInteger(-1);
 
         protected TestableKeyguardUpdateMonitor(Context context) {
             super(context, mUserTracker,
@@ -3144,9 +3270,14 @@
             return mSimStateChanged.getAndSet(false);
         }
 
+        public int getCachedSimState() {
+            return mCachedSimState.getAndSet(-1);
+        }
+
         @Override
         protected void handleSimStateChange(int subId, int slotId, int state) {
             mSimStateChanged.set(true);
+            mCachedSimState.set(state);
             super.handleSimStateChange(subId, slotId, state);
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 1f353e1..c280538 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -21,6 +21,9 @@
 
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+import static com.android.systemui.keyguard.KeyguardViewMediator.REBOOT_MAINLINE_UPDATE;
+import static com.android.systemui.keyguard.KeyguardViewMediator.SYS_BOOT_REASON_PROP;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -71,6 +74,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.flags.Flags;
+import com.android.systemui.flags.SystemPropertiesHelper;
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.navigationbar.NavigationModeController;
@@ -152,6 +156,8 @@
     private @Mock ShadeWindowLogger mShadeWindowLogger;
     private @Captor ArgumentCaptor<KeyguardUpdateMonitorCallback>
             mKeyguardUpdateMonitorCallbackCaptor;
+    private @Captor ArgumentCaptor<KeyguardStateController.Callback>
+            mKeyguardStateControllerCallback;
     private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake();
     private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
 
@@ -160,6 +166,7 @@
     private @Mock CentralSurfaces mCentralSurfaces;
     private @Mock UiEventLogger mUiEventLogger;
     private @Mock SessionTracker mSessionTracker;
+    private @Mock SystemPropertiesHelper mSystemPropertiesHelper;
     private @Mock CoroutineDispatcher mDispatcher;
     private @Mock DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
 
@@ -356,6 +363,59 @@
     }
 
     @Test
+    public void testBouncerPrompt_deviceRestartedDueToMainlineUpdate() {
+        // GIVEN biometrics enrolled
+        when(mUpdateMonitor.isUnlockingWithBiometricsPossible(anyInt())).thenReturn(true);
+
+        // WHEN reboot caused by ota update
+        KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
+                mock(KeyguardUpdateMonitor.StrongAuthTracker.class);
+        when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(strongAuthTracker);
+        when(strongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(false);
+        when(mSystemPropertiesHelper.get(SYS_BOOT_REASON_PROP)).thenReturn(REBOOT_MAINLINE_UPDATE);
+
+        // THEN the bouncer prompt reason should return PROMPT_REASON_RESTART_FOR_OTA
+        assertEquals(KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE,
+                mViewMediator.mViewMediatorCallback.getBouncerPromptReason());
+    }
+
+    @Test
+    public void testBouncerPrompt_afterUserLockDown() {
+        // GIVEN biometrics enrolled
+        when(mUpdateMonitor.isUnlockingWithBiometricsPossible(anyInt())).thenReturn(true);
+
+        // WHEN user has locked down the device
+        KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
+                mock(KeyguardUpdateMonitor.StrongAuthTracker.class);
+        when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(strongAuthTracker);
+        when(strongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
+        when(strongAuthTracker.getStrongAuthForUser(anyInt()))
+                .thenReturn(STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+
+        // THEN the bouncer prompt reason should return PROMPT_REASON_USER_REQUEST
+        assertEquals(KeyguardSecurityView.PROMPT_REASON_USER_REQUEST,
+                mViewMediator.mViewMediatorCallback.getBouncerPromptReason());
+    }
+
+    @Test
+    public void testBouncerPrompt_afterUserLockDown_noBiometricsEnrolled() {
+        // GIVEN biometrics not enrolled
+        when(mUpdateMonitor.isUnlockingWithBiometricsPossible(anyInt())).thenReturn(false);
+
+        // WHEN user has locked down the device
+        KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
+                mock(KeyguardUpdateMonitor.StrongAuthTracker.class);
+        when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(strongAuthTracker);
+        when(strongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
+        when(strongAuthTracker.getStrongAuthForUser(anyInt()))
+                .thenReturn(STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+
+        // THEN the bouncer prompt reason should return the default prompt
+        assertEquals(KeyguardSecurityView.PROMPT_REASON_NONE,
+                mViewMediator.mViewMediatorCallback.getBouncerPromptReason());
+    }
+
+    @Test
     public void testBouncerPrompt_nonStrongIdleTimeout() {
         // GIVEN trust agents enabled and biometrics are enrolled
         when(mUpdateMonitor.isTrustUsuallyManaged(anyInt())).thenReturn(true);
@@ -604,6 +664,33 @@
         );
     }
 
+    @Test
+    @TestableLooper.RunWithLooper(setAsMainLooper = true)
+    public void pendingPinLockOnKeyguardGoingAway_doKeyguardLockedOnKeyguardVisibilityChanged() {
+        // GIVEN SIM_STATE_PIN_REQUIRED
+        mViewMediator.onSystemReady();
+        final KeyguardUpdateMonitorCallback keyguardUpdateMonitorCallback =
+                mViewMediator.mUpdateCallback;
+        keyguardUpdateMonitorCallback.onSimStateChanged(0, 0,
+                TelephonyManager.SIM_STATE_PIN_REQUIRED);
+        TestableLooper.get(this).processAllMessages();
+
+        // ...and then the primary bouncer shows while the keyguard is going away
+        captureKeyguardStateControllerCallback();
+        when(mKeyguardStateController.isPrimaryBouncerShowing()).thenReturn(true);
+        when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true);
+        mKeyguardStateControllerCallback.getValue().onPrimaryBouncerShowingChanged();
+        TestableLooper.get(this).processAllMessages();
+
+        // WHEN keyguard visibility becomes FALSE
+        mViewMediator.setShowingLocked(false);
+        keyguardUpdateMonitorCallback.onKeyguardVisibilityChanged(false);
+        TestableLooper.get(this).processAllMessages();
+
+        // THEN keyguard shows due to the pending SIM PIN lock
+        assertTrue(mViewMediator.isShowingAndNotOccluded());
+    }
+
     private void createAndStartViewMediator() {
         mViewMediator = new KeyguardViewMediator(
                 mContext,
@@ -640,7 +727,8 @@
                 () -> mScrimController,
                 mFeatureFlags,
                 mDispatcher,
-                () -> mDreamingToLockscreenTransitionViewModel);
+                () -> mDreamingToLockscreenTransitionViewModel,
+                mSystemPropertiesHelper);
         mViewMediator.start();
 
         mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null);
@@ -649,4 +737,8 @@
     private void captureKeyguardUpdateMonitorCallback() {
         verify(mUpdateMonitor).registerCallback(mKeyguardUpdateMonitorCallbackCaptor.capture());
     }
+
+    private void captureKeyguardStateControllerCallback() {
+        verify(mKeyguardStateController).addCallback(mKeyguardStateControllerCallback.capture());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactoryTest.kt
index 9e79849..0ef77e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactoryTest.kt
@@ -34,6 +34,7 @@
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
@@ -42,6 +43,7 @@
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@Ignore("b/236891644")
 class BouncerMessageFactoryTest : SysuiTestCase() {
     private lateinit var underTest: BouncerMessageFactory
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepositoryTest.kt
index 1277fc0..a729de5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepositoryTest.kt
@@ -61,6 +61,7 @@
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentCaptor
@@ -73,6 +74,7 @@
 @SmallTest
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @RunWith(AndroidJUnit4::class)
+@Ignore("b/236891644")
 class BouncerMessageRepositoryTest : SysuiTestCase() {
 
     @Mock private lateinit var updateMonitor: KeyguardUpdateMonitor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
index b0af310..3a87680 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
@@ -42,6 +42,7 @@
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.eq
@@ -53,6 +54,7 @@
 @SmallTest
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @RunWith(AndroidJUnit4::class)
+@Ignore("b/236891644")
 class BouncerMessageInteractorTest : SysuiTestCase() {
 
     @Mock private lateinit var securityModel: KeyguardSecurityModel
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java
index 57ae621..31bfa3fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java
@@ -66,6 +66,11 @@
 @SmallTest
 public class ShadeCarrierGroupControllerTest extends LeakCheckedTest {
 
+    private static final String SINGLE_CARRIER_TEXT = "singleCarrierText";
+    private static final String MULTI_CARRIER_TEXT = "multiCarrierText";
+    private static final String FIRST_CARRIER_NAME = "carrier1";
+    private static final String SECOND_CARRIER_NAME = "carrier2";
+
     private ShadeCarrierGroupController mShadeCarrierGroupController;
     private SignalCallback mSignalCallback;
     private CarrierTextManager.CarrierTextCallback mCallback;
@@ -148,8 +153,8 @@
         // listOfCarriers length 1, subscriptionIds length 1, anySims false
         CarrierTextManager.CarrierTextCallbackInfo
                 c1 = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{""},
+                SINGLE_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME},
                 false,
                 new int[]{0});
         mCallback.updateCarrierInfo(c1);
@@ -157,8 +162,8 @@
         // listOfCarriers length 1, subscriptionIds length 1, anySims true
         CarrierTextManager.CarrierTextCallbackInfo
                 c2 = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{""},
+                SINGLE_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME},
                 true,
                 new int[]{0});
         mCallback.updateCarrierInfo(c2);
@@ -166,8 +171,8 @@
         // listOfCarriers length 2, subscriptionIds length 2, anySims false
         CarrierTextManager.CarrierTextCallbackInfo
                 c3 = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{"", ""},
+                MULTI_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME},
                 false,
                 new int[]{0, 1});
         mCallback.updateCarrierInfo(c3);
@@ -175,8 +180,8 @@
         // listOfCarriers length 2, subscriptionIds length 2, anySims true
         CarrierTextManager.CarrierTextCallbackInfo
                 c4 = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{"", ""},
+                MULTI_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME},
                 true,
                 new int[]{0, 1});
         mCallback.updateCarrierInfo(c4);
@@ -189,8 +194,8 @@
         // listOfCarriers length 2, subscriptionIds length 1, anySims false
         CarrierTextManager.CarrierTextCallbackInfo
                 c1 = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{"", ""},
+                MULTI_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME},
                 false,
                 new int[]{0});
         mCallback.updateCarrierInfo(c1);
@@ -198,8 +203,8 @@
         // listOfCarriers length 2, subscriptionIds length 1, anySims true
         CarrierTextManager.CarrierTextCallbackInfo
                 c2 = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{"", ""},
+                MULTI_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME},
                 true,
                 new int[]{0});
         mCallback.updateCarrierInfo(c2);
@@ -207,8 +212,8 @@
         // listOfCarriers length 1, subscriptionIds length 2, anySims false
         CarrierTextManager.CarrierTextCallbackInfo
                 c3 = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{""},
+                SINGLE_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME},
                 false,
                 new int[]{0, 1});
         mCallback.updateCarrierInfo(c3);
@@ -216,8 +221,8 @@
         // listOfCarriers length 1, subscriptionIds length 2, anySims true
         CarrierTextManager.CarrierTextCallbackInfo
                 c4 = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{""},
+                SINGLE_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME},
                 true,
                 new int[]{0, 1});
         mCallback.updateCarrierInfo(c4);
@@ -230,8 +235,8 @@
 
         CarrierTextManager.CarrierTextCallbackInfo
                 c4 = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{"", ""},
+                MULTI_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME},
                 true,
                 new int[]{0, 1});
         mCallback.updateCarrierInfo(c4);
@@ -264,6 +269,20 @@
     }
 
     @Test
+    public void testVisibleView_airplaneMode_WFCOn() {
+        CarrierTextManager.CarrierTextCallbackInfo
+                info = new CarrierTextManager.CarrierTextCallbackInfo(
+                "",
+                new CharSequence[]{FIRST_CARRIER_NAME, ""},
+                true,
+                new int[]{0, 1},
+                false /* airplaneMode */);
+        mCallback.updateCarrierInfo(info);
+        mTestableLooper.processAllMessages();
+        assertEquals(View.VISIBLE, mShadeCarrierGroupController.getShadeCarrierVisibility(0));
+    }
+
+    @Test
     public void testListenerNotCalledOnRegistreation() {
         mShadeCarrierGroupController
                 .setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener);
@@ -276,8 +295,8 @@
         // Only one element in the info
         CarrierTextManager.CarrierTextCallbackInfo
                 info = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{""},
+                SINGLE_CARRIER_TEXT,
+                new CharSequence[]{SINGLE_CARRIER_TEXT},
                 true,
                 new int[]{0},
                 false /* airplaneMode */);
@@ -295,8 +314,8 @@
         // More than one element in the info
         CarrierTextManager.CarrierTextCallbackInfo
                 info = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{"", ""},
+                MULTI_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME},
                 true,
                 new int[]{0, 1},
                 false /* airplaneMode */);
@@ -313,16 +332,16 @@
     public void testSingleMultiCarrierSwitch() {
         CarrierTextManager.CarrierTextCallbackInfo
                 singleCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{""},
+                SINGLE_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME},
                 true,
                 new int[]{0},
                 false /* airplaneMode */);
 
         CarrierTextManager.CarrierTextCallbackInfo
                 multiCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{"", ""},
+                MULTI_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME},
                 true,
                 new int[]{0, 1},
                 false /* airplaneMode */);
@@ -347,8 +366,8 @@
     public void testNoCallbackIfSingleCarrierDoesntChange() {
         CarrierTextManager.CarrierTextCallbackInfo
                 singleCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{""},
+                SINGLE_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME},
                 true,
                 new int[]{0},
                 false /* airplaneMode */);
@@ -369,8 +388,8 @@
     public void testNoCallbackIfMultiCarrierDoesntChange() {
         CarrierTextManager.CarrierTextCallbackInfo
                 multiCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo(
-                "",
-                new CharSequence[]{"", ""},
+                MULTI_CARRIER_TEXT,
+                new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME},
                 true,
                 new int[]{0, 1},
                 false /* airplaneMode */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
index ac66ad9..2d044fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
@@ -92,8 +92,9 @@
                 .getPeopleNotificationType(entry))
                 .thenReturn(TYPE_PERSON);
 
-        // THEN it has high priority
+        // THEN it has high priority BUT it has low explicit priority.
         assertTrue(mHighPriorityProvider.isHighPriority(entry));
+        assertFalse(mHighPriorityProvider.isExplicitlyHighPriority(entry));
     }
 
     @Test
@@ -115,7 +116,7 @@
 
     @Test
     public void lowImportanceConversation() {
-        // GIVEN notification is high importance and is a people notification
+        // GIVEN notification is low importance and is a people notification
         final Notification notification = new Notification.Builder(mContext, "test")
                 .build();
         final NotificationEntry entry = new NotificationEntryBuilder()
@@ -162,8 +163,9 @@
                 .getPeopleNotificationType(entry))
                 .thenReturn(TYPE_NON_PERSON);
 
-        // THEN it has high priority
+        // THEN it has high priority but low explicit priority
         assertTrue(mHighPriorityProvider.isHighPriority(entry));
+        assertFalse(mHighPriorityProvider.isExplicitlyHighPriority(entry));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
index 6bd3f7a..8f39ee6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
@@ -257,7 +257,7 @@
                 .setImportance(IMPORTANCE_LOW)
                 .setParent(parent)
                 .build();
-        when(mHighPriorityProvider.isHighPriority(any())).thenReturn(false);
+        when(mHighPriorityProvider.isExplicitlyHighPriority(any())).thenReturn(false);
         assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
     }
 
@@ -270,7 +270,7 @@
                 .setUser(new UserHandle(NOTIF_USER_ID))
                 .setImportance(IMPORTANCE_LOW)
                 .build();
-        when(mHighPriorityProvider.isHighPriority(any())).thenReturn(false);
+        when(mHighPriorityProvider.isExplicitlyHighPriority(any())).thenReturn(false);
         assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
     }
 
@@ -292,7 +292,7 @@
                 .setImportance(IMPORTANCE_LOW)
                 .setParent(parent)
                 .build();
-        when(mHighPriorityProvider.isHighPriority(any())).thenReturn(false);
+        when(mHighPriorityProvider.isExplicitlyHighPriority(any())).thenReturn(false);
         assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
     }
 
@@ -309,7 +309,7 @@
         mEntry = new NotificationEntryBuilder()
                 .setImportance(IMPORTANCE_LOW)
                 .build();
-        when(mHighPriorityProvider.isHighPriority(any())).thenReturn(false);
+        when(mHighPriorityProvider.isExplicitlyHighPriority(any())).thenReturn(false);
 
         // THEN filter out the entry
         assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
@@ -328,7 +328,7 @@
         mEntry = new NotificationEntryBuilder()
                 .setImportance(IMPORTANCE_LOW)
                 .build();
-        when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false);
+        when(mHighPriorityProvider.isExplicitlyHighPriority(mEntry)).thenReturn(false);
 
         // THEN do not filter out the entry
         assertFalse(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
@@ -345,7 +345,7 @@
                 .setUser(new UserHandle(NOTIF_USER_ID))
                 .setImportance(IMPORTANCE_LOW)
                 .build();
-        when(mHighPriorityProvider.isHighPriority(any())).thenReturn(false);
+        when(mHighPriorityProvider.isExplicitlyHighPriority(any())).thenReturn(false);
 
         // WhHEN the show silent notifs on lockscreen setting is unset
         assertNull(mFakeSettings.getString(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS));
@@ -460,13 +460,33 @@
                 .setKey(mEntry.getKey())
                 .setImportance(IMPORTANCE_MIN)
                 .build());
-        when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false);
+        when(mHighPriorityProvider.isExplicitlyHighPriority(mEntry)).thenReturn(false);
 
         // THEN filter out the entry
         assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
     }
 
     @Test
+    public void highPriorityCharacteristicsIgnored() {
+        // GIVEN an 'unfiltered-keyguard-showing' state with silent notifications hidden
+        setupUnfilteredState(mEntry);
+        mFakeSettings.putBool(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, true);
+        mFakeSettings.putBool(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, false);
+
+        // WHEN the notification doesn't exceed the threshold to show on the lockscreen, but does
+        // have the "high priority characteristics" that would promote it to high priority
+        mEntry.setRanking(new RankingBuilder()
+                .setKey(mEntry.getKey())
+                .setImportance(IMPORTANCE_MIN)
+                .build());
+        when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(true);
+        when(mHighPriorityProvider.isExplicitlyHighPriority(mEntry)).thenReturn(false);
+
+        // THEN filter out the entry anyway, because the user explicitly asked us to hide it
+        assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
+    }
+
+    @Test
     public void notificationVisibilityPublic() {
         // GIVEN a VISIBILITY_PUBLIC notification
         NotificationEntryBuilder entryBuilder = new NotificationEntryBuilder()
@@ -538,14 +558,14 @@
 
         // WHEN its parent does exceed threshold tot show on the lockscreen
         mFakeSettings.putBool(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, false);
-        when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(true);
+        when(mHighPriorityProvider.isExplicitlyHighPriority(parent)).thenReturn(true);
 
         // THEN filter out the entry regardless of parent
         assertTrue(
                 mKeyguardNotificationVisibilityProvider.shouldHideNotification(entryWithParent));
 
         // WHEN its parent doesn't exceed threshold to show on lockscreen
-        when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(false);
+        when(mHighPriorityProvider.isExplicitlyHighPriority(parent)).thenReturn(false);
         modifyEntry(parent.getSummary(), builder -> builder
                 .setImportance(IMPORTANCE_MIN)
                 .done());
@@ -591,7 +611,7 @@
         // notification doesn't have a summary
 
         // notification is high priority, so it shouldn't be filtered
-        when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(true);
+        when(mHighPriorityProvider.isExplicitlyHighPriority(mEntry)).thenReturn(true);
     }
 
     @SysUISingleton
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 85b1ec1..40e7e8d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -61,7 +61,6 @@
 import android.view.WindowInsetsAnimation;
 import android.widget.TextView;
 
-import androidx.test.annotation.UiThreadTest;
 import androidx.test.filters.SmallTest;
 
 import com.android.keyguard.BouncerPanelExpansionCalculator;
@@ -84,12 +83,11 @@
 import com.android.systemui.statusbar.notification.row.FooterView;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 
 import org.junit.Assert;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -103,7 +101,6 @@
 /**
  * Tests for {@link NotificationStackScrollLayout}.
  */
-@Ignore("b/255552856")
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
@@ -113,7 +110,6 @@
     private NotificationStackScrollLayout mStackScrollerInternal;  // See explanation below
     private AmbientState mAmbientState;
     private TestableResources mTestableResources;
-
     @Rule public MockitoRule mockito = MockitoJUnit.rule();
     @Mock private CentralSurfaces mCentralSurfaces;
     @Mock private SysuiStatusBarStateController mBarState;
@@ -128,7 +124,7 @@
     @Mock private NotificationSection mNotificationSection;
     @Mock private NotificationSwipeHelper mNotificationSwipeHelper;
     @Mock private NotificationStackScrollLayoutController mStackScrollLayoutController;
-    @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+    @Mock private ScreenOffAnimationController mScreenOffAnimationController;
     @Mock private NotificationShelf mNotificationShelf;
     @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
     @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@@ -136,7 +132,6 @@
     @Mock private FeatureFlags mFeatureFlags;
 
     @Before
-    @UiThreadTest
     public void setUp() throws Exception {
         allowTestableLooperAsMainThread();
         mTestableResources = mContext.getOrCreateTestableResources();
@@ -162,7 +157,7 @@
         mDependency.injectTestDependency(AmbientState.class, mAmbientState);
         mDependency.injectTestDependency(NotificationShelf.class, mNotificationShelf);
         mDependency.injectTestDependency(
-                UnlockedScreenOffAnimationController.class, mUnlockedScreenOffAnimationController);
+                ScreenOffAnimationController.class, mScreenOffAnimationController);
 
         NotificationShelfController notificationShelfController =
                 mock(NotificationShelfController.class);
@@ -364,7 +359,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testSetExpandedHeight_listenerReceivedCallbacks() {
         final float expectedHeight = 0f;
 
@@ -375,20 +369,6 @@
     }
 
     @Test
-    public void testAppearFractionCalculation() {
-        // appear start position
-        when(mNotificationShelf.getIntrinsicHeight()).thenReturn(100);
-        // because it's the same as shelf height, appear start position equals shelf height
-        mStackScroller.mStatusBarHeight = 100;
-        // appear end position
-        when(mEmptyShadeView.getHeight()).thenReturn(200);
-
-        assertEquals(0f, mStackScroller.calculateAppearFraction(100));
-        assertEquals(1f, mStackScroller.calculateAppearFraction(200));
-        assertEquals(0.5f, mStackScroller.calculateAppearFraction(150));
-    }
-
-    @Test
     public void testAppearFractionCalculationIsNotNegativeWhenShelfBecomesSmaller() {
         // this situation might occur if status bar height is defined in pixels while shelf height
         // in dp and screen density changes - appear start position
@@ -405,7 +385,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testSetExpandedHeight_withSplitShade_doesntInterpolateStackHeight() {
         mTestableResources
                 .addOverride(R.bool.config_use_split_notification_shade, /* value= */ true);
@@ -590,6 +569,7 @@
 
     @Test
     public void testReInflatesFooterViews() {
+        when(mEmptyShadeView.getTextResource()).thenReturn(R.string.empty_shade_text);
         clearInvocations(mStackScroller);
         mStackScroller.reinflateViews();
         verify(mStackScroller).setFooterView(any());
@@ -597,21 +577,18 @@
     }
 
     @Test
-    @UiThreadTest
     public void testSetIsBeingDraggedResetsExposedMenu() {
         mStackScroller.setIsBeingDragged(true);
         verify(mNotificationSwipeHelper).resetExposedMenuView(true, true);
     }
 
     @Test
-    @UiThreadTest
     public void testPanelTrackingStartResetsExposedMenu() {
         mStackScroller.onPanelTrackingStarted();
         verify(mNotificationSwipeHelper).resetExposedMenuView(true, true);
     }
 
     @Test
-    @UiThreadTest
     public void testDarkModeResetsExposedMenu() {
         mStackScroller.setHideAmount(0.1f, 0.1f);
         verify(mNotificationSwipeHelper).resetExposedMenuView(true, true);
@@ -916,7 +893,7 @@
         mStackScroller.setHasFilteredOutSeenNotifications(true);
         mStackScroller.updateEmptyShadeView(true, false);
 
-        verify(mEmptyShadeView).setFooterText(not(0));
+        verify(mEmptyShadeView).setFooterText(not(eq(0)));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 8062272..7702630 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -350,7 +350,9 @@
         // For the Shade to animate during the Back gesture, we must enable the animation flag.
         mFeatureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true);
         mFeatureFlags.set(Flags.LIGHT_REVEAL_MIGRATION, true);
+        // Turn AOD on and toggle feature flag for jank fixes
         mFeatureFlags.set(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD, true);
+        when(mDozeParameters.getAlwaysOn()).thenReturn(true);
 
         IThermalService thermalService = mock(IThermalService.class);
         mPowerManager = new PowerManager(mContext, mPowerManagerService, thermalService,
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index ac77043..82af382 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -46,6 +46,7 @@
 import com.android.server.utils.Slogf;
 
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -319,6 +320,13 @@
         return context.createDisplayContext(display);
     }
 
+    static <T> @Nullable T weakDeref(WeakReference<T> weakRef, String tag, String prefix) {
+        T deref = weakRef.get();
+        if (deref == null) {
+            Slog.wtf(tag, prefix + "fail to deref " + weakRef);
+        }
+        return deref;
+    }
 
     private interface ViewNodeFilter {
         boolean matches(ViewNode node);
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFieldClassificationService.java b/services/autofill/java/com/android/server/autofill/RemoteFieldClassificationService.java
index ea31074..bcca006 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFieldClassificationService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFieldClassificationService.java
@@ -44,6 +44,8 @@
 import com.android.internal.infra.AbstractRemoteService;
 import com.android.internal.infra.ServiceConnector;
 
+import java.lang.ref.WeakReference;
+
 /**
  * Class responsible for connection with the Remote {@link FieldClassificationService}.
  * This class is instantiated when {@link AutofillManagerServiceImpl} is established.
@@ -133,7 +135,8 @@
     }
 
     public void onFieldClassificationRequest(@NonNull FieldClassificationRequest request,
-            FieldClassificationServiceCallbacks fieldClassificationServiceCallbacks) {
+            WeakReference<FieldClassificationServiceCallbacks>
+                fieldClassificationServiceCallbacksWeakRef) {
         final long startTime = SystemClock.elapsedRealtime();
         if (sVerbose) {
             Slog.v(TAG, "onFieldClassificationRequest request:" + request);
@@ -170,6 +173,15 @@
                                                 Slog.d(TAG, "onSuccess " + msg);
                                             }
                                         }
+                                        FieldClassificationServiceCallbacks
+                                                fieldClassificationServiceCallbacks =
+                                                        Helper.weakDeref(
+                                                                fieldClassificationServiceCallbacksWeakRef,
+                                                                TAG, "onSuccess "
+                                                        );
+                                        if (fieldClassificationServiceCallbacks == null) {
+                                            return;
+                                        }
                                         fieldClassificationServiceCallbacks
                                                 .onClassificationRequestSuccess(response);
                                     }
@@ -180,6 +192,15 @@
                                         if (sDebug) {
                                             Slog.d(TAG, "onFailure");
                                         }
+                                        FieldClassificationServiceCallbacks
+                                                fieldClassificationServiceCallbacks =
+                                                        Helper.weakDeref(
+                                                                fieldClassificationServiceCallbacksWeakRef,
+                                                                TAG, "onFailure "
+                                                        );
+                                        if (fieldClassificationServiceCallbacks == null) {
+                                            return;
+                                        }
                                         fieldClassificationServiceCallbacks
                                                 .onClassificationRequestFailure(0, null);
                                     }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 0c3f866..fb26f42 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -850,8 +850,12 @@
             RemoteFieldClassificationService remoteFieldClassificationService =
                     mService.getRemoteFieldClassificationServiceLocked();
             if (remoteFieldClassificationService != null) {
+                WeakReference<RemoteFieldClassificationService.FieldClassificationServiceCallbacks>
+                        fieldClassificationServiceCallbacksWeakRef =
+                                new WeakReference<>(Session.this);
                 remoteFieldClassificationService.onFieldClassificationRequest(
-                        mClassificationState.mPendingFieldClassificationRequest, Session.this);
+                        mClassificationState.mPendingFieldClassificationRequest,
+                                fieldClassificationServiceCallbacksWeakRef);
             }
             mClassificationState.onFieldClassificationRequestSent();
         }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index fc84e13..c1239d5 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -406,6 +406,8 @@
     // allowlisted packageName.
     ArraySet<String> mAllowListWhileInUsePermissionInFgs = new ArraySet<>();
 
+    String mCachedDeviceProvisioningPackage;
+
     // TODO: remove this after feature development is done
     private static final SimpleDateFormat DATE_FORMATTER =
             new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@@ -480,7 +482,8 @@
                 // (REASON_ALARM_MANAGER_ALARM_CLOCK), allow it to continue and do not stop it,
                 // even the app is background-restricted.
                 if (r.isForeground
-                        && r.mAllowStartForegroundAtEntering != REASON_ALARM_MANAGER_ALARM_CLOCK) {
+                        && r.mAllowStartForegroundAtEntering != REASON_ALARM_MANAGER_ALARM_CLOCK
+                        && !isDeviceProvisioningPackage(r.packageName)) {
                     toStop.add(r);
                 }
             }
@@ -880,7 +883,8 @@
         boolean forcedStandby = false;
         if (bgLaunch
                 && appRestrictedAnyInBackground(appUid, appPackageName)
-                && !isTempAllowedByAlarmClock(appUid)) {
+                && !isTempAllowedByAlarmClock(appUid)
+                && !isDeviceProvisioningPackage(appPackageName)) {
             if (DEBUG_FOREGROUND_SERVICE) {
                 Slog.d(TAG, "Forcing bg-only service start only for " + r.shortInstanceName
                         + " : bgLaunch=" + bgLaunch + " callerFg=" + callerFg);
@@ -1926,6 +1930,9 @@
      */
     private boolean isForegroundServiceAllowedInBackgroundRestricted(ProcessRecord app) {
         final ProcessStateRecord state = app.mState;
+        if (isDeviceProvisioningPackage(app.info.packageName)) {
+            return true;
+        }
         if (!state.isBackgroundRestricted()
                 || state.getSetProcState() <= ActivityManager.PROCESS_STATE_BOUND_TOP) {
             return true;
@@ -8404,4 +8411,13 @@
         }
         return results;
     }
+
+    private boolean isDeviceProvisioningPackage(String packageName) {
+        if (mCachedDeviceProvisioningPackage == null) {
+            mCachedDeviceProvisioningPackage = mAm.mContext.getResources().getString(
+                    com.android.internal.R.string.config_deviceProvisioningPackage);
+        }
+        return mCachedDeviceProvisioningPackage != null
+                && mCachedDeviceProvisioningPackage.equals(packageName);
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a7db663..476e1b4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17311,6 +17311,12 @@
         }
     }
 
+    void onProcessFreezableChangedLocked(ProcessRecord app) {
+        if (mEnableModernQueue) {
+            mBroadcastQueues[0].onProcessFreezableChangedLocked(app);
+        }
+    }
+
     @VisibleForTesting
     public final class LocalService extends ActivityManagerInternal
             implements ActivityManagerLocal {
@@ -19022,25 +19028,27 @@
         // too quickly in parallel below
         pingCount.incrementAndGet();
 
-        synchronized (mProcLock) {
-            final ArrayMap<String, SparseArray<ProcessRecord>> pmap =
-                    mProcessList.getProcessNamesLOSP().getMap();
-            final int numProc = pmap.size();
-            for (int iProc = 0; iProc < numProc; iProc++) {
-                final SparseArray<ProcessRecord> apps = pmap.valueAt(iProc);
-                for (int iApp = 0, numApps = apps.size(); iApp < numApps; iApp++) {
-                    final ProcessRecord app = apps.valueAt(iApp);
-                    final IApplicationThread thread = app.getOnewayThread();
-                    if (thread != null) {
-                        mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(app,
-                                CachedAppOptimizer.UNFREEZE_REASON_PING);
-                        pingCount.incrementAndGet();
-                        try {
-                            thread.schedulePing(pongCallback);
-                        } catch (RemoteException ignored) {
-                            // When we failed to ping remote process, pretend as
-                            // if we received the expected pong
-                            pongCallback.sendResult(null);
+        synchronized (ActivityManagerService.this) {
+            synchronized (mProcLock) {
+                final ArrayMap<String, SparseArray<ProcessRecord>> pmap =
+                        mProcessList.getProcessNamesLOSP().getMap();
+                final int numProc = pmap.size();
+                for (int iProc = 0; iProc < numProc; iProc++) {
+                    final SparseArray<ProcessRecord> apps = pmap.valueAt(iProc);
+                    for (int iApp = 0, numApps = apps.size(); iApp < numApps; iApp++) {
+                        final ProcessRecord app = apps.valueAt(iApp);
+                        final IApplicationThread thread = app.getOnewayThread();
+                        if (thread != null) {
+                            mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(app,
+                                    CachedAppOptimizer.UNFREEZE_REASON_PING);
+                            pingCount.incrementAndGet();
+                            try {
+                                thread.schedulePing(pongCallback);
+                            } catch (RemoteException ignored) {
+                                // When we failed to ping remote process, pretend as
+                                // if we received the expected pong
+                                pongCallback.sendResult(null);
+                            }
                         }
                     }
                 }
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index a80ad59..58f62b6 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -208,7 +208,7 @@
     private boolean mLastDeferredStates;
 
     private boolean mUidForeground;
-    private boolean mUidCached;
+    private boolean mProcessFreezable;
     private boolean mProcessInstrumented;
     private boolean mProcessPersistent;
 
@@ -440,7 +440,7 @@
      */
     @CheckResult
     public boolean setProcessAndUidState(@Nullable ProcessRecord app, boolean uidForeground,
-            boolean uidCached) {
+            boolean processFreezable) {
         this.app = app;
 
         // Since we may have just changed our PID, invalidate cached strings
@@ -449,13 +449,13 @@
 
         boolean didSomething = false;
         if (app != null) {
-            didSomething |= setUidCached(uidCached);
             didSomething |= setUidForeground(uidForeground);
+            didSomething |= setProcessFreezable(processFreezable);
             didSomething |= setProcessInstrumented(app.getActiveInstrumentation() != null);
             didSomething |= setProcessPersistent(app.isPersistent());
         } else {
-            didSomething |= setUidCached(uidCached);
             didSomething |= setUidForeground(false);
+            didSomething |= setProcessFreezable(false);
             didSomething |= setProcessInstrumented(false);
             didSomething |= setProcessPersistent(false);
         }
@@ -479,13 +479,13 @@
     }
 
     /**
-     * Update if this process is in the "cached" state, typically signaling that
+     * Update if this process is in the "freezable" state, typically signaling that
      * broadcast dispatch should be paused or delayed.
      */
     @CheckResult
-    private boolean setUidCached(boolean uidCached) {
-        if (mUidCached != uidCached) {
-            mUidCached = uidCached;
+    private boolean setProcessFreezable(boolean freezable) {
+        if (mProcessFreezable != freezable) {
+            mProcessFreezable = freezable;
             invalidateRunnableAt();
             return true;
         } else {
@@ -1150,7 +1150,7 @@
             } else if (mCountManifest > 0) {
                 mRunnableAt = runnableAt;
                 mRunnableAtReason = REASON_CONTAINS_MANIFEST;
-            } else if (mUidCached) {
+            } else if (mProcessFreezable) {
                 if (r.deferUntilActive) {
                     // All enqueued broadcasts are deferrable, defer
                     if (mCountDeferred == mCountEnqueued) {
@@ -1220,7 +1220,7 @@
         // When all we have pending is deferred broadcasts, and we're cached,
         // then we want everything to be marked deferred
         final boolean wantDeferredStates = (mCountDeferred > 0)
-                && (mCountDeferred == mCountEnqueued) && mUidCached;
+                && (mCountDeferred == mCountEnqueued) && mProcessFreezable;
 
         if (mLastDeferredStates != wantDeferredStates) {
             mLastDeferredStates = wantDeferredStates;
@@ -1407,9 +1407,9 @@
         if (mUidForeground) {
             sb.append("FG");
         }
-        if (mUidCached) {
+        if (mProcessFreezable) {
             if (sb.length() > 0) sb.append("|");
-            sb.append("CACHED");
+            sb.append("FRZ");
         }
         if (mProcessInstrumented) {
             if (sb.length() > 0) sb.append("|");
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index e38a2ee..c1f1dfd 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -174,6 +174,13 @@
     public abstract void onApplicationCleanupLocked(@NonNull ProcessRecord app);
 
     /**
+     * Signal from OS internals that the given process is in a freezable state and will be
+     * frozen soon after.
+     */
+    @GuardedBy("mService")
+    public abstract void onProcessFreezableChangedLocked(@NonNull ProcessRecord app);
+
+    /**
      * Signal from OS internals that the given package (or some subset of that
      * package) has been disabled or uninstalled, and that any pending
      * broadcasts should be cleaned up.
diff --git a/services/core/java/com/android/server/am/BroadcastQueueImpl.java b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
index f13dc89..127c5b3 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
@@ -466,6 +466,10 @@
         skipCurrentOrPendingReceiverLocked(app);
     }
 
+    public void onProcessFreezableChangedLocked(ProcessRecord app) {
+        // Not supported; ignore
+    }
+
     public boolean sendPendingBroadcastsLocked(ProcessRecord app)
             throws BroadcastDeliveryFailedException {
         boolean didSomething = false;
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 33e21f1..f420619 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -232,16 +232,6 @@
     @GuardedBy("mService")
     private final SparseBooleanArray mUidForeground = new SparseBooleanArray();
 
-    /**
-     * Map from UID to its last known "cached" state.
-     * <p>
-     * We manually maintain this data structure since the lifecycle of
-     * {@link ProcessRecord} and {@link BroadcastProcessQueue} can be
-     * mismatched.
-     */
-    @GuardedBy("mService")
-    private final SparseBooleanArray mUidCached = new SparseBooleanArray();
-
     private final BroadcastConstants mConstants;
     private final BroadcastConstants mFgConstants;
     private final BroadcastConstants mBgConstants;
@@ -258,6 +248,7 @@
     private static final int MSG_BG_ACTIVITY_START_TIMEOUT = 4;
     private static final int MSG_CHECK_HEALTH = 5;
     private static final int MSG_CHECK_PENDING_COLD_START_VALIDITY = 6;
+    private static final int MSG_PROCESS_FREEZABLE_CHANGED = 7;
 
     private void enqueueUpdateRunningList() {
         mLocalHandler.removeMessages(MSG_UPDATE_RUNNING_LIST);
@@ -298,6 +289,12 @@
                 checkPendingColdStartValidity();
                 return true;
             }
+            case MSG_PROCESS_FREEZABLE_CHANGED: {
+                synchronized (mService) {
+                    refreshProcessQueueLocked((ProcessRecord) msg.obj);
+                }
+                return true;
+            }
         }
         return false;
     };
@@ -673,6 +670,12 @@
     }
 
     @Override
+    public void onProcessFreezableChangedLocked(@NonNull ProcessRecord app) {
+        mLocalHandler.removeMessages(MSG_PROCESS_FREEZABLE_CHANGED, app);
+        mLocalHandler.sendMessage(mHandler.obtainMessage(MSG_PROCESS_FREEZABLE_CHANGED, app));
+    }
+
+    @Override
     public int getPreferredSchedulingGroupLocked(@NonNull ProcessRecord app) {
         final BroadcastProcessQueue queue = getProcessQueue(app);
         if ((queue != null) && getRunningIndexOf(queue) >= 0) {
@@ -1465,7 +1468,6 @@
             };
             broadcastPredicate = BROADCAST_PREDICATE_ANY;
 
-            cleanupUserStateLocked(mUidCached, userId);
             cleanupUserStateLocked(mUidForeground, userId);
         }
         return forEachMatchingBroadcast(queuePredicate, broadcastPredicate,
@@ -1608,19 +1610,7 @@
                     refreshProcessQueuesLocked(uid);
                 }
             }
-
-            @Override
-            public void onUidCachedChanged(int uid, boolean cached) {
-                synchronized (mService) {
-                    if (cached) {
-                        mUidCached.put(uid, true);
-                    } else {
-                        mUidCached.delete(uid);
-                    }
-                    refreshProcessQueuesLocked(uid);
-                }
-            }
-        }, ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_CACHED,
+        }, ActivityManager.UID_OBSERVER_PROCSTATE,
                 ActivityManager.PROCESS_STATE_TOP, "android");
 
         // Kick off periodic health checks
@@ -1810,10 +1800,9 @@
             // warm via this operation, we're going to immediately promote it to
             // be running, and any side effect of this operation will then apply
             // after it's finished and is returned to the runnable list.
-            queue.setProcessAndUidState(
-                    mService.getProcessRecordLocked(queue.processName, queue.uid),
-                    mUidForeground.get(queue.uid, false),
-                    mUidCached.get(queue.uid, false));
+            final ProcessRecord app = mService.getProcessRecordLocked(queue.processName, queue.uid);
+            queue.setProcessAndUidState(app, mUidForeground.get(queue.uid, false),
+                    isProcessFreezable(app));
         }
     }
 
@@ -1825,11 +1814,21 @@
     private void setQueueProcess(@NonNull BroadcastProcessQueue queue,
             @Nullable ProcessRecord app) {
         if (queue.setProcessAndUidState(app, mUidForeground.get(queue.uid, false),
-                mUidCached.get(queue.uid, false))) {
+                isProcessFreezable(app))) {
             updateRunnableList(queue);
         }
     }
 
+    @GuardedBy("mService")
+    private boolean isProcessFreezable(@Nullable ProcessRecord app) {
+        if (app == null) {
+            return false;
+        }
+        synchronized (mService.mProcLock) {
+            return app.mOptRecord.isPendingFreeze() || app.mOptRecord.isFrozen();
+        }
+    }
+
     /**
      * Refresh the process queues with the latest process state so that runnableAt
      * can be updated.
@@ -1847,6 +1846,20 @@
     }
 
     /**
+     * Refresh the process queue corresponding to {@code app} with the latest process state
+     * so that runnableAt can be updated.
+     */
+    @GuardedBy("mService")
+    private void refreshProcessQueueLocked(@NonNull ProcessRecord app) {
+        final BroadcastProcessQueue queue = getProcessQueue(app.processName, app.uid);
+        if (queue == null || queue.app == null || queue.app.getPid() != app.getPid()) {
+            return;
+        }
+        setQueueProcess(queue, queue.app);
+        enqueueUpdateRunningList();
+    }
+
+    /**
      * Inform other parts of OS that the given broadcast queue has started
      * running, typically for internal bookkeeping.
      */
@@ -2172,12 +2185,6 @@
         ipw.decreaseIndent();
         ipw.println();
 
-        ipw.println("Cached UIDs:");
-        ipw.increaseIndent();
-        ipw.println(mUidCached);
-        ipw.decreaseIndent();
-        ipw.println();
-
         ipw.println("Foreground UIDs:");
         ipw.increaseIndent();
         ipw.println(mUidForeground);
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 7773190..e588a9e 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -123,7 +123,14 @@
             "freeze_debounce_timeout";
     @VisibleForTesting static final String KEY_FREEZER_EXEMPT_INST_PKG =
             "freeze_exempt_inst_pkg";
-
+    @VisibleForTesting static final String KEY_FREEZER_BINDER_ENABLED =
+            "freeze_binder_enabled";
+    @VisibleForTesting static final String KEY_FREEZER_BINDER_DIVISOR =
+            "freeze_binder_divisor";
+    @VisibleForTesting static final String KEY_FREEZER_BINDER_OFFSET =
+            "freeze_binder_offset";
+    @VisibleForTesting static final String KEY_FREEZER_BINDER_THRESHOLD =
+            "freeze_binder_threshold";
 
     static final int UNFREEZE_REASON_NONE =
             FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_NONE;
@@ -237,8 +244,8 @@
     @VisibleForTesting static final boolean ENABLE_FILE_COMPACT = false;
 
     // Defaults for phenotype flags.
-    @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = true;
-    @VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = true;
+    @VisibleForTesting static final boolean DEFAULT_USE_COMPACTION = true;
+    @VisibleForTesting static final boolean DEFAULT_USE_FREEZER = true;
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_1 = 5_000;
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000;
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_3 = 500;
@@ -257,7 +264,11 @@
     @VisibleForTesting static final String DEFAULT_COMPACT_PROC_STATE_THROTTLE =
             String.valueOf(ActivityManager.PROCESS_STATE_RECEIVER);
     @VisibleForTesting static final long DEFAULT_FREEZER_DEBOUNCE_TIMEOUT = 10_000L;
-    @VisibleForTesting static final Boolean DEFAULT_FREEZER_EXEMPT_INST_PKG = true;
+    @VisibleForTesting static final boolean DEFAULT_FREEZER_EXEMPT_INST_PKG = true;
+    @VisibleForTesting static final boolean DEFAULT_FREEZER_BINDER_ENABLED = true;
+    @VisibleForTesting static final long DEFAULT_FREEZER_BINDER_DIVISOR = 4;
+    @VisibleForTesting static final int DEFAULT_FREEZER_BINDER_OFFSET = 500;
+    @VisibleForTesting static final long DEFAULT_FREEZER_BINDER_THRESHOLD = 1_000;
 
     @VisibleForTesting static final Uri CACHED_APP_FREEZER_ENABLED_URI = Settings.Global.getUriFor(
                 Settings.Global.CACHED_APPS_FREEZER_ENABLED);
@@ -393,6 +404,11 @@
                                 updateFreezerDebounceTimeout();
                             } else if (KEY_FREEZER_EXEMPT_INST_PKG.equals(name)) {
                                 updateFreezerExemptInstPkg();
+                            } else if (KEY_FREEZER_BINDER_ENABLED.equals(name)
+                                    || KEY_FREEZER_BINDER_DIVISOR.equals(name)
+                                    || KEY_FREEZER_BINDER_THRESHOLD.equals(name)
+                                    || KEY_FREEZER_BINDER_OFFSET.equals(name)) {
+                                updateFreezerBinderState();
                             }
                         }
                     }
@@ -455,6 +471,16 @@
     @GuardedBy("mPhenotypeFlagLock")
     @VisibleForTesting final Set<Integer> mProcStateThrottle;
 
+    @GuardedBy("mPhenotypeFlagLock")
+    @VisibleForTesting volatile boolean mFreezerBinderEnabled = DEFAULT_FREEZER_BINDER_ENABLED;
+    @GuardedBy("mPhenotypeFlagLock")
+    @VisibleForTesting volatile long mFreezerBinderDivisor = DEFAULT_FREEZER_BINDER_DIVISOR;
+    @GuardedBy("mPhenotypeFlagLock")
+    @VisibleForTesting volatile int mFreezerBinderOffset = DEFAULT_FREEZER_BINDER_OFFSET;
+    @GuardedBy("mPhenotypeFlagLock")
+    @VisibleForTesting volatile long mFreezerBinderThreshold = DEFAULT_FREEZER_BINDER_THRESHOLD;
+
+
     // Handler on which compaction runs.
     @VisibleForTesting
     Handler mCompactionHandler;
@@ -759,6 +785,10 @@
             pw.println("  " + KEY_FREEZER_STATSD_SAMPLE_RATE + "=" + mFreezerStatsdSampleRate);
             pw.println("  " + KEY_FREEZER_DEBOUNCE_TIMEOUT + "=" + mFreezerDebounceTimeout);
             pw.println("  " + KEY_FREEZER_EXEMPT_INST_PKG + "=" + mFreezerExemptInstPkg);
+            pw.println("  " + KEY_FREEZER_BINDER_ENABLED + "=" + mFreezerBinderEnabled);
+            pw.println("  " + KEY_FREEZER_BINDER_THRESHOLD + "=" + mFreezerBinderThreshold);
+            pw.println("  " + KEY_FREEZER_BINDER_DIVISOR + "=" + mFreezerBinderDivisor);
+            pw.println("  " + KEY_FREEZER_BINDER_OFFSET + "=" + mFreezerBinderOffset);
             synchronized (mProcLock) {
                 int size = mFrozenProcesses.size();
                 pw.println("  Apps frozen: " + size);
@@ -1264,6 +1294,26 @@
         Slog.d(TAG_AM, "Freezer exemption set to " + mFreezerExemptInstPkg);
     }
 
+    @GuardedBy("mPhenotypeFlagLock")
+    private void updateFreezerBinderState() {
+        mFreezerBinderEnabled = DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
+                KEY_FREEZER_BINDER_ENABLED, DEFAULT_FREEZER_BINDER_ENABLED);
+        mFreezerBinderDivisor = DeviceConfig.getLong(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
+                KEY_FREEZER_BINDER_DIVISOR, DEFAULT_FREEZER_BINDER_DIVISOR);
+        mFreezerBinderOffset = DeviceConfig.getInt(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
+                KEY_FREEZER_BINDER_OFFSET, DEFAULT_FREEZER_BINDER_OFFSET);
+        mFreezerBinderThreshold = DeviceConfig.getLong(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
+                KEY_FREEZER_BINDER_THRESHOLD, DEFAULT_FREEZER_BINDER_THRESHOLD);
+        Slog.d(TAG_AM, "Freezer binder state set to enabled=" + mFreezerBinderEnabled
+                + ", divisor=" + mFreezerBinderDivisor
+                + ", offset=" + mFreezerBinderOffset
+                + ", threshold=" + mFreezerBinderThreshold);
+    }
+
     private boolean parseProcStateThrottle(String procStateThrottleString) {
         String[] procStates = TextUtils.split(procStateThrottleString, ",");
         mProcStateThrottle.clear();
@@ -1352,6 +1402,8 @@
                 }
             }
         }
+        reportProcessFreezableChangedLocked(app);
+        app.mOptRecord.setLastUsedTimeout(delayMillis);
         mFreezeHandler.sendMessageDelayed(
                 mFreezeHandler.obtainMessage(SET_FROZEN_PROCESS_MSG, DO_FREEZE, 0, app),
                 delayMillis);
@@ -1389,6 +1441,7 @@
             uidRec.setFrozen(false);
             postUidFrozenMessage(uidRec.getUid(), false);
         }
+        reportProcessFreezableChangedLocked(app);
 
         opt.setFreezerOverride(false);
         if (pid == 0 || !opt.isFrozen()) {
@@ -1525,10 +1578,14 @@
                 opt.setPendingFreeze(false);
             }
 
-            UidRecord uidRec = app.getUidRecord();
-            if (uidRec != null && uidRec.isFrozen()) {
-                uidRec.setFrozen(false);
-                postUidFrozenMessage(uidRec.getUid(), false);
+            final UidRecord uidRec = app.getUidRecord();
+            if (uidRec != null) {
+                final boolean isFrozen = uidRec.getNumOfProcs() > 1
+                        && uidRec.areAllProcessesFrozen(app);
+                if (isFrozen != uidRec.isFrozen()) {
+                    uidRec.setFrozen(isFrozen);
+                    postUidFrozenMessage(uidRec.getUid(), isFrozen);
+                }
             }
 
             mFrozenProcesses.delete(app.getPid());
@@ -2066,6 +2123,11 @@
                 0, uidObj));
     }
 
+    @GuardedBy("mAm")
+    private void reportProcessFreezableChangedLocked(ProcessRecord app) {
+        mAm.onProcessFreezableChangedLocked(app);
+    }
+
     private final class FreezeHandler extends Handler implements
             ProcLocksReader.ProcLocksReaderCallback {
         private FreezeHandler() {
@@ -2075,7 +2137,7 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case SET_FROZEN_PROCESS_MSG:
+                case SET_FROZEN_PROCESS_MSG: {
                     ProcessRecord proc = (ProcessRecord) msg.obj;
                     synchronized (mAm) {
                         freezeProcess(proc);
@@ -2085,8 +2147,8 @@
                         removeMessages(DEADLOCK_WATCHDOG_MSG);
                         sendEmptyMessageDelayed(DEADLOCK_WATCHDOG_MSG, FREEZE_DEADLOCK_TIMEOUT_MS);
                     }
-                    break;
-                case REPORT_UNFREEZE_MSG:
+                } break;
+                case REPORT_UNFREEZE_MSG: {
                     int pid = msg.arg1;
                     int frozenDuration = msg.arg2;
                     Pair<String, Integer> obj = (Pair<String, Integer>) msg.obj;
@@ -2094,13 +2156,13 @@
                     int reason = obj.second;
 
                     reportUnfreeze(pid, frozenDuration, processName, reason);
-                    break;
-                case UID_FROZEN_STATE_CHANGED_MSG:
+                } break;
+                case UID_FROZEN_STATE_CHANGED_MSG: {
                     final boolean frozen = (msg.arg1 == 1);
                     final int uid = (int) msg.obj;
                     reportOneUidFrozenStateChanged(uid, frozen);
-                    break;
-                case DEADLOCK_WATCHDOG_MSG:
+                } break;
+                case DEADLOCK_WATCHDOG_MSG: {
                     try {
                         // post-check to prevent deadlock
                         if (DEBUG_FREEZER) {
@@ -2110,19 +2172,61 @@
                     } catch (IOException e) {
                         Slog.w(TAG_AM, "Unable to check file locks");
                     }
-                    break;
+                } break;
                 default:
                     return;
             }
         }
 
         @GuardedBy({"mAm", "mProcLock"})
-        private void rescheduleFreeze(final ProcessRecord proc, final String reason,
-                @UnfreezeReason int reasonCode) {
+        private void handleBinderFreezerFailure(final ProcessRecord proc, final String reason) {
+            if (!mFreezerBinderEnabled) {
+                // Just reschedule indefinitely.
+                unfreezeAppLSP(proc, UNFREEZE_REASON_BINDER_TXNS);
+                freezeAppAsyncLSP(proc);
+                return;
+            }
+            /*
+             * This handles the case where a process couldn't be frozen due to pending binder
+             * transactions. In order to prevent apps from avoiding the freezer by spamming binder
+             * transactions, there is an exponential decrease in freezer retry times plus a random
+             * offset per attempt to avoid phase issues. Once the last-attempted timeout is below a
+             * threshold, we assume that the app is spamming binder calls and can never be frozen,
+             * and we will then crash the app.
+             */
+            if (proc.mOptRecord.getLastUsedTimeout() <= mFreezerBinderThreshold) {
+                // We've given the app plenty of chances, assume broken. Time to die.
+                Slog.d(TAG_AM, "Kill app due to repeated failure to freeze binder: "
+                        + proc.getPid() + " " + proc.processName);
+                mAm.mHandler.post(() -> {
+                    synchronized (mAm) {
+                        // Crash regardless of procstate in case the app has found another way
+                        // to abuse oom_adj
+                        if (proc.getThread() == null) {
+                            return;
+                        }
+                        proc.killLocked("excessive binder traffic during cached",
+                                ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
+                                ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU,
+                                true);
+                    }
+                });
+                return;
+            }
+
+            long timeout = proc.mOptRecord.getLastUsedTimeout() / mFreezerBinderDivisor;
+            // range is [-mFreezerBinderOffset, +mFreezerBinderOffset]
+            int offset = mRandom.nextInt(mFreezerBinderOffset * 2) - mFreezerBinderOffset;
+            timeout = Math.max(timeout + offset, mFreezerBinderThreshold);
+
             Slog.d(TAG_AM, "Reschedule freeze for process " + proc.getPid()
-                    + " " + proc.processName + " (" + reason + ")");
-            unfreezeAppLSP(proc, reasonCode);
-            freezeAppAsyncLSP(proc);
+                    + " " + proc.processName + " (" + reason  + "), timeout=" + timeout);
+            Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, ATRACE_FREEZER_TRACK,
+                    "Reschedule freeze " + proc.processName + ":" + proc.getPid()
+                    + " timeout=" + timeout + ", reason=" + reason);
+
+            unfreezeAppLSP(proc, UNFREEZE_REASON_BINDER_TXNS);
+            freezeAppAsyncLSP(proc, timeout);
         }
 
         /**
@@ -2169,7 +2273,7 @@
                 // transactions that might be pending.
                 try {
                     if (freezeBinder(pid, true, FREEZE_BINDER_TIMEOUT_MS) != 0) {
-                        rescheduleFreeze(proc, "outstanding txns", UNFREEZE_REASON_BINDER_TXNS);
+                        handleBinderFreezerFailure(proc, "outstanding txns");
                         return;
                     }
                 } catch (RuntimeException e) {
@@ -2230,7 +2334,7 @@
 
                 if ((freezeInfo & TXNS_PENDING_WHILE_FROZEN) != 0) {
                     synchronized (mProcLock) {
-                        rescheduleFreeze(proc, "new pending txns", UNFREEZE_REASON_BINDER_TXNS);
+                        handleBinderFreezerFailure(proc, "new pending txns");
                     }
                     return;
                 }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 764bbe8..f21ad22 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1009,7 +1009,6 @@
             mCacheOomRanker.reRankLruCachedAppsLSP(mProcessList.getLruProcessesLSP(),
                     mProcessList.getLruProcessServiceStartLOSP());
         }
-        assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP());
 
         if (computeClients) { // There won't be cycles if we didn't compute clients above.
             // Cycle strategy:
@@ -1034,7 +1033,7 @@
                     ProcessRecord app = activeProcesses.get(i);
                     final ProcessStateRecord state = app.mState;
                     if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) {
-                        if (computeOomAdjLSP(app, state.getCurRawAdj(), topApp, true, now,
+                        if (computeOomAdjLSP(app, UNKNOWN_ADJ, topApp, true, now,
                                 true, true)) {
                             retryCycles = true;
                         }
@@ -1044,6 +1043,8 @@
         }
         mProcessesInCycle.clear();
 
+        assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP());
+
         mNumNonCachedProcs = 0;
         mNumCachedHiddenProcs = 0;
 
diff --git a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
index ffe5a6e..f5c5ea8 100644
--- a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
+++ b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
@@ -127,6 +127,12 @@
     @GuardedBy("mProcLock")
     private @UptimeMillisLong long mEarliestFreezableTimeMillis;
 
+    /**
+     * This is the most recently used timeout for freezing the app in millis
+     */
+    @GuardedBy("mProcLock")
+    private long mLastUsedTimeout;
+
     @GuardedBy("mProcLock")
     long getLastCompactTime() {
         return mLastCompactTime;
@@ -282,6 +288,16 @@
     }
 
     @GuardedBy("mProcLock")
+    long getLastUsedTimeout() {
+        return mLastUsedTimeout;
+    }
+
+    @GuardedBy("mProcLock")
+    void setLastUsedTimeout(long lastUsedTimeout) {
+        mLastUsedTimeout = lastUsedTimeout;
+    }
+
+    @GuardedBy("mProcLock")
     boolean isFreezeExempt() {
         return mFreezeExempt;
     }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 267d246..f814c3b 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1197,6 +1197,9 @@
                         "Killing " + toShortString() + " (adj " + mState.getSetAdj()
                         + "): " + reason, info.uid);
             }
+            // Since the process is getting killed, reset the freezable related state.
+            mOptRecord.setPendingFreeze(false);
+            mOptRecord.setFrozen(false);
             if (mPid > 0) {
                 mService.mProcessList.noteAppKill(this, reasonCode, subReason, description);
                 EventLog.writeEvent(EventLogTags.AM_KILL,
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index 993088e..4329afc 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -345,21 +345,32 @@
     }
 
     /**
+     * Check whether all processes in the Uid are frozen.
+     *
+     * @param excluding Skip this process record during the check.
      * @return true if all processes in the Uid are frozen, false otherwise.
      */
     @GuardedBy(anyOf = {"mService", "mProcLock"})
-    public boolean areAllProcessesFrozen() {
+    public boolean areAllProcessesFrozen(ProcessRecord excluding) {
         for (int i = mProcRecords.size() - 1; i >= 0; i--) {
             final ProcessRecord app = mProcRecords.valueAt(i);
             final ProcessCachedOptimizerRecord opt = app.mOptRecord;
 
-            if (!opt.isFrozen()) {
+            if (excluding != app && !opt.isFrozen()) {
                 return false;
             }
         }
         return true;
     }
 
+    /**
+     * @return true if all processes in the Uid are frozen, false otherwise.
+     */
+    @GuardedBy(anyOf = {"mService", "mProcLock"})
+    public boolean areAllProcessesFrozen() {
+        return areAllProcessesFrozen(null);
+    }
+
     @GuardedBy(anyOf = {"mService", "mProcLock"})
     public void setFrozen(boolean frozen) {
         mUidIsFrozen = frozen;
diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
index 4e7865c..2d74564 100644
--- a/services/core/java/com/android/server/am/UserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -88,8 +88,6 @@
     UserSwitchingDialog(Context context, UserInfo oldUser, UserInfo newUser,
             String switchingFromSystemUserMessage, String switchingToSystemUserMessage,
             WindowManagerService windowManager) {
-        // TODO(b/278857848): Make full screen user switcher cover top part of the screen as well.
-        //                    This problem is seen only on phones, it works fine on tablets.
         super(context, R.style.Theme_Material_NoActionBar_Fullscreen);
 
         mContext = context;
@@ -112,9 +110,12 @@
         final WindowManager.LayoutParams attrs = window.getAttributes();
         attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR |
                 WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+        attrs.layoutInDisplayCutoutMode =
+                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         window.setAttributes(attrs);
         window.setBackgroundDrawableResource(android.R.color.transparent);
         window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+        window.setDecorFitsSystemWindows(false);
     }
 
     void inflateContent() {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index ec85d57..0c7f11f 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -1199,11 +1199,16 @@
                     AudioDeviceInfo device = Stream.of(connectedDevices)
                             .filter(d -> d.getInternalType() == ada.getInternalType())
                             .filter(d -> (!AudioSystem.isBluetoothDevice(d.getInternalType())
-                                            || (d.getAddress() == ada.getAddress())))
+                                            || (d.getAddress().equals(ada.getAddress()))))
                             .findFirst()
                             .orElse(null);
 
                     if (device == null) {
+                        if (AudioService.DEBUG_DEVICES) {
+                            Slog.i(TAG, "purgeRoles() removing device: " + ada.toString()
+                                    + ", for strategy: " + keyRole.first
+                                    + " and role: " + keyRole.second);
+                        }
                         asi.deviceRoleAction(keyRole.first, keyRole.second, Arrays.asList(ada));
                         itDev.remove();
                     }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index c177c4e..53ed38e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3666,25 +3666,29 @@
      * and aliases before mute change changed and after.
      */
     private void muteAliasStreams(int streamAlias, boolean state) {
-        synchronized (VolumeStreamState.class) {
-            List<Integer> streamsToMute = new ArrayList<>();
-            for (int stream = 0; stream < mStreamStates.length; stream++) {
-                VolumeStreamState vss = mStreamStates[stream];
-                if (streamAlias == mStreamVolumeAlias[stream] && vss.isMutable()) {
-                    if (!(mCameraSoundForced
-                            && (vss.getStreamType()
-                                    == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
-                        boolean changed = vss.mute(state, /* apply= */ false, "muteAliasStreams");
-                        if (changed) {
-                            streamsToMute.add(stream);
+        // Locking mSettingsLock to avoid inversion when calling doMute -> updateVolumeGroupIndex
+        synchronized (mSettingsLock) {
+            synchronized (VolumeStreamState.class) {
+                List<Integer> streamsToMute = new ArrayList<>();
+                for (int stream = 0; stream < mStreamStates.length; stream++) {
+                    VolumeStreamState vss = mStreamStates[stream];
+                    if (streamAlias == mStreamVolumeAlias[stream] && vss.isMutable()) {
+                        if (!(mCameraSoundForced
+                                && (vss.getStreamType()
+                                == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
+                            boolean changed = vss.mute(state, /* apply= */ false,
+                                    "muteAliasStreams");
+                            if (changed) {
+                                streamsToMute.add(stream);
+                            }
                         }
                     }
                 }
+                streamsToMute.forEach(streamToMute -> {
+                    mStreamStates[streamToMute].doMute();
+                    broadcastMuteSetting(streamToMute, state);
+                });
             }
-            streamsToMute.forEach(streamToMute -> {
-                mStreamStates[streamToMute].doMute();
-                broadcastMuteSetting(streamToMute, state);
-            });
         }
     }
 
@@ -3699,18 +3703,22 @@
     // Called after a delay when volume down is pressed while muted
     private void onUnmuteStream(int stream, int flags) {
         boolean wasMuted;
-        synchronized (VolumeStreamState.class) {
-            final VolumeStreamState streamState = mStreamStates[stream];
-            // if unmuting causes a change, it was muted
-            wasMuted = streamState.mute(false, "onUnmuteStream");
+        // Locking mSettingsLock to avoid inversion when calling vss.mute -> vss.doMute ->
+        // vss.updateVolumeGroupIndex
+        synchronized (mSettingsLock) {
+            synchronized (VolumeStreamState.class) {
+                final VolumeStreamState streamState = mStreamStates[stream];
+                // if unmuting causes a change, it was muted
+                wasMuted = streamState.mute(false, "onUnmuteStream");
 
-            final int device = getDeviceForStream(stream);
-            final int index = streamState.getIndex(device);
-            sendVolumeUpdate(stream, index, index, flags, device);
-        }
-        if (stream == AudioSystem.STREAM_MUSIC && wasMuted) {
-            synchronized (mHdmiClientLock) {
-                maybeSendSystemAudioStatusCommand(true);
+                final int device = getDeviceForStream(stream);
+                final int index = streamState.getIndex(device);
+                sendVolumeUpdate(stream, index, index, flags, device);
+            }
+            if (stream == AudioSystem.STREAM_MUSIC && wasMuted) {
+                synchronized (mHdmiClientLock) {
+                    maybeSendSystemAudioStatusCommand(true);
+                }
             }
         }
     }
@@ -7611,7 +7619,11 @@
                 Log.i(TAG, String.format("onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
                         newDevice, AudioSystem.getOutputDeviceName(newDevice)));
             }
-            mStreamStates[AudioSystem.STREAM_MUSIC].mute(false, "onAccessoryPlugMediaUnmute");
+            // Locking mSettingsLock to avoid inversion when calling vss.mute -> vss.doMute ->
+            // vss.updateVolumeGroupIndex
+            synchronized (mSettingsLock) {
+                mStreamStates[AudioSystem.STREAM_MUSIC].mute(false, "onAccessoryPlugMediaUnmute");
+            }
         }
     }
 
@@ -7646,9 +7658,14 @@
                 continue;
             }
         }
-        for (int i = 0; i < sVolumeGroupStates.size(); i++) {
-            final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
-            vgs.applyAllVolumes(/* userSwitch= */ false);
+
+        // need mSettingsLock for vgs.applyAllVolumes -> vss.setIndex which grabs this lock after
+        // VSS.class. Locking order needs to be preserved
+        synchronized (mSettingsLock) {
+            for (int i = 0; i < sVolumeGroupStates.size(); i++) {
+                final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
+                vgs.applyAllVolumes(/* userSwitch= */ false);
+            }
         }
     }
 
@@ -7685,9 +7702,14 @@
         if (DEBUG_VOL) {
             Log.v(TAG, "restoreVolumeGroups");
         }
-        for (int i = 0; i < sVolumeGroupStates.size(); i++) {
-            final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
-            vgs.applyAllVolumes(false/*userSwitch*/);
+
+        // need mSettingsLock for vgs.applyAllVolumes -> vss.setIndex which grabs this lock after
+        // VSS.class. Locking order needs to be preserved
+        synchronized (mSettingsLock) {
+            for (int i = 0; i < sVolumeGroupStates.size(); i++) {
+                final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
+                vgs.applyAllVolumes(false/*userSwitch*/);
+            }
         }
     }
 
@@ -7824,49 +7846,51 @@
         }
 
         public void adjustVolume(int direction, int flags) {
-            synchronized (AudioService.VolumeStreamState.class) {
-                int device = getDeviceForVolume();
-                int previousIndex = getIndex(device);
-                if (isMuteAdjust(direction) && !isMutable()) {
-                    // Non mutable volume group
-                    if (DEBUG_VOL) {
-                        Log.d(TAG, "invalid mute on unmutable volume group " + name());
-                    }
-                    return;
-                }
-                switch (direction) {
-                    case AudioManager.ADJUST_TOGGLE_MUTE: {
-                        // Note: If muted by volume 0, unmute will restore volume 0.
-                        mute(!mIsMuted);
-                        break;
-                    }
-                    case AudioManager.ADJUST_UNMUTE:
-                        // Note: If muted by volume 0, unmute will restore volume 0.
-                        mute(false);
-                        break;
-                    case AudioManager.ADJUST_MUTE:
-                        // May be already muted by setvolume 0, prevent from setting same value
-                        if (previousIndex != 0) {
-                            // bypass persist
-                            mute(true);
+            synchronized (mSettingsLock) {
+                synchronized (AudioService.VolumeStreamState.class) {
+                    int device = getDeviceForVolume();
+                    int previousIndex = getIndex(device);
+                    if (isMuteAdjust(direction) && !isMutable()) {
+                        // Non mutable volume group
+                        if (DEBUG_VOL) {
+                            Log.d(TAG, "invalid mute on unmutable volume group " + name());
                         }
-                        mIsMuted = true;
-                        break;
-                    case AudioManager.ADJUST_RAISE:
-                        // As for stream, RAISE during mute will increment the index
-                        setVolumeIndex(Math.min(previousIndex + 1, mIndexMax),  device, flags);
-                        break;
-                    case AudioManager.ADJUST_LOWER:
-                        // For stream, ADJUST_LOWER on a muted VSS is a no-op
-                        // If we decide to unmute on ADJUST_LOWER, cannot fallback on
-                        // adjustStreamVolume for group associated to legacy stream type
-                        if (isMuted() && previousIndex != 0) {
+                        return;
+                    }
+                    switch (direction) {
+                        case AudioManager.ADJUST_TOGGLE_MUTE: {
+                            // Note: If muted by volume 0, unmute will restore volume 0.
+                            mute(!mIsMuted);
+                            break;
+                        }
+                        case AudioManager.ADJUST_UNMUTE:
+                            // Note: If muted by volume 0, unmute will restore volume 0.
                             mute(false);
-                        } else {
-                            int newIndex = Math.max(previousIndex - 1, mIndexMin);
-                            setVolumeIndex(newIndex, device, flags);
-                        }
-                        break;
+                            break;
+                        case AudioManager.ADJUST_MUTE:
+                            // May be already muted by setvolume 0, prevent from setting same value
+                            if (previousIndex != 0) {
+                                // bypass persist
+                                mute(true);
+                            }
+                            mIsMuted = true;
+                            break;
+                        case AudioManager.ADJUST_RAISE:
+                            // As for stream, RAISE during mute will increment the index
+                            setVolumeIndex(Math.min(previousIndex + 1, mIndexMax),  device, flags);
+                            break;
+                        case AudioManager.ADJUST_LOWER:
+                            // For stream, ADJUST_LOWER on a muted VSS is a no-op
+                            // If we decide to unmute on ADJUST_LOWER, cannot fallback on
+                            // adjustStreamVolume for group associated to legacy stream type
+                            if (isMuted() && previousIndex != 0) {
+                                mute(false);
+                            } else {
+                                int newIndex = Math.max(previousIndex - 1, mIndexMin);
+                                setVolumeIndex(newIndex, device, flags);
+                            }
+                            break;
+                    }
                 }
             }
         }
@@ -7878,11 +7902,13 @@
         }
 
         public void setVolumeIndex(int index, int flags) {
-            synchronized (AudioService.VolumeStreamState.class) {
-                if (mUseFixedVolume) {
-                    return;
+            synchronized (mSettingsLock) {
+                synchronized (AudioService.VolumeStreamState.class) {
+                    if (mUseFixedVolume) {
+                        return;
+                    }
+                    setVolumeIndex(index, getDeviceForVolume(), flags);
                 }
-                setVolumeIndex(index, getDeviceForVolume(), flags);
             }
         }
 
@@ -8689,24 +8715,30 @@
 
         // If associated to volume group, update group cache
         private void updateVolumeGroupIndex(int device, boolean forceMuteState) {
-            synchronized (VolumeStreamState.class) {
-                if (mVolumeGroupState != null) {
-                    int groupIndex = (getIndex(device) + 5) / 10;
-                    if (DEBUG_VOL) {
-                        Log.d(TAG, "updateVolumeGroupIndex for stream " + mStreamType
-                                + ", muted=" + mIsMuted + ", device=" + device + ", index="
-                                + getIndex(device) + ", group " + mVolumeGroupState.name()
-                                + " Muted=" + mVolumeGroupState.isMuted() + ", Index=" + groupIndex
-                                + ", forceMuteState=" + forceMuteState);
-                    }
-                    mVolumeGroupState.updateVolumeIndex(groupIndex, device);
-                    // Only propage mute of stream when applicable
-                    if (isMutable()) {
-                        // For call stream, align mute only when muted, not when index is set to 0
-                        mVolumeGroupState.mute(
-                                forceMuteState ? mIsMuted :
-                                        (groupIndex == 0 && !isCallStream(mStreamType))
-                                                || mIsMuted);
+            // need mSettingsLock when called from setIndex for vgs.mute -> vgs.applyAllVolumes ->
+            // vss.setIndex which grabs this lock after VSS.class. Locking order needs to be
+            // preserved
+            synchronized (mSettingsLock) {
+                synchronized (VolumeStreamState.class) {
+                    if (mVolumeGroupState != null) {
+                        int groupIndex = (getIndex(device) + 5) / 10;
+                        if (DEBUG_VOL) {
+                            Log.d(TAG, "updateVolumeGroupIndex for stream " + mStreamType
+                                    + ", muted=" + mIsMuted + ", device=" + device + ", index="
+                                    + getIndex(device) + ", group " + mVolumeGroupState.name()
+                                    + " Muted=" + mVolumeGroupState.isMuted() + ", Index="
+                                    + groupIndex + ", forceMuteState=" + forceMuteState);
+                        }
+                        mVolumeGroupState.updateVolumeIndex(groupIndex, device);
+                        // Only propage mute of stream when applicable
+                        if (isMutable()) {
+                            // For call stream, align mute only when muted, not when index is set to
+                            // 0
+                            mVolumeGroupState.mute(
+                                    forceMuteState ? mIsMuted :
+                                            (groupIndex == 0 && !isCallStream(mStreamType))
+                                                    || mIsMuted);
+                        }
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index c8a17e5..3560797 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -218,8 +218,8 @@
             if (AudioService.DEBUG_VOL) {
                 AudioService.sVolumeLogger.enqueue(new EventLogger.StringEvent(
                         "setAvrcpAbsoluteVolumeIndex: bailing due to null mA2dp").printLog(TAG));
-                return;
             }
+            return;
         }
         if (!mAvrcpAbsVolSupported) {
             AudioService.sVolumeLogger.enqueue(new EventLogger.StringEvent(
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d29d9c8..488745c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -8718,13 +8718,7 @@
 
         ToastRecord lastToast = mToastQueue.remove(index);
 
-        mWindowManagerInternal.removeWindowToken(lastToast.windowToken, false /* removeWindows */,
-                lastToast.displayId);
-        // We passed 'false' for 'removeWindows' so that the client has time to stop
-        // rendering (as hide above is a one-way message), otherwise we could crash
-        // a client which was actively using a surface made from the token. However
-        // we need to schedule a timeout to make sure the token is eventually killed
-        // one way or another.
+        // We need to schedule a timeout to make sure the token is eventually killed
         scheduleKillTokenTimeout(lastToast);
 
         keepProcessAliveForToastIfNeededLocked(record.pid);
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index abfc1d7..78f1fa6 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -4311,7 +4311,12 @@
         if (Process.isIsolatedUid(uid)
                 && mPermissionManager.getHotwordDetectionServiceProvider() != null
                 && uid == mPermissionManager.getHotwordDetectionServiceProvider().getUid()) {
-            uid = getIsolatedOwner(uid);
+            try {
+                uid = getIsolatedOwner(uid);
+            } catch (IllegalStateException e) {
+                // If the owner uid doesn't exist, just use the current uid
+                Slog.wtf(TAG, "Expected isolated uid " + uid + " to have an owner", e);
+            }
         }
         final int callingUserId = UserHandle.getUserId(callingUid);
         final int appId = UserHandle.getAppId(uid);
@@ -4352,7 +4357,12 @@
             if (Process.isIsolatedUid(uid)
                     && mPermissionManager.getHotwordDetectionServiceProvider() != null
                     && uid == mPermissionManager.getHotwordDetectionServiceProvider().getUid()) {
-                uid = getIsolatedOwner(uid);
+                try {
+                    uid = getIsolatedOwner(uid);
+                } catch (IllegalStateException e) {
+                    // If the owner uid doesn't exist, just use the current uid
+                    Slog.wtf(TAG, "Expected isolated uid " + uid + " to have an owner", e);
+                }
             }
             final int appId = UserHandle.getAppId(uid);
             final Object obj = mSettings.getSettingBase(appId);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 3e81f46..3132c5d 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3272,12 +3272,6 @@
                 Slog.wtf(TAG, "KEYCODE_STYLUS_BUTTON_* should be handled in"
                         + " interceptKeyBeforeQueueing");
                 return key_consumed;
-            case KeyEvent.KEYCODE_MACRO_1:
-            case KeyEvent.KEYCODE_MACRO_2:
-            case KeyEvent.KEYCODE_MACRO_3:
-            case KeyEvent.KEYCODE_MACRO_4:
-                Slog.wtf(TAG, "KEYCODE_MACRO_x should be handled in interceptKeyBeforeQueueing");
-                return key_consumed;
         }
 
         if (isValidGlobalKey(keyCode)
@@ -4427,7 +4421,6 @@
             case KeyEvent.KEYCODE_MACRO_2:
             case KeyEvent.KEYCODE_MACRO_3:
             case KeyEvent.KEYCODE_MACRO_4:
-                // TODO(b/266098478): Add logic to handle KEYCODE_MACROx feature
                 result &= ~ACTION_PASS_TO_USER;
                 break;
         }
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 9e9b344..e31b53c 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -3293,7 +3293,7 @@
         WallpaperData wallpaper;
 
         synchronized (mLock) {
-            Slog.v(TAG, "setWallpaperComponent name=" + name);
+            Slog.v(TAG, "setWallpaperComponent name=" + name + ", which=" + which);
             wallpaper = mWallpaperMap.get(userId);
             if (wallpaper == null) {
                 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
@@ -3324,7 +3324,11 @@
                 wallpaper.mWhich = which;
                 wallpaper.fromForegroundApp = isFromForegroundApp(callingPackage);
                 boolean same = changingToSame(name, wallpaper);
-                if (bindWallpaperComponentLocked(name, false, true, wallpaper, null)) {
+
+                // force rebind when reapplying a system-only wallpaper to system+lock
+                boolean forceRebind = same && mLockWallpaperMap.get(userId) != null
+                        && which == (FLAG_SYSTEM | FLAG_LOCK);
+                if (bindWallpaperComponentLocked(name, forceRebind, true, wallpaper, null)) {
                     if (!same) {
                         wallpaper.primaryColors = null;
                     } else {
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 8660bec..89f044b 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -178,6 +178,10 @@
         mSurfaceAnimatorStarter = surfaceAnimatorStarter;
     }
 
+    WindowContainer<?> getHost() {
+        return mHost;
+    }
+
     private SurfaceControl makeDimLayer() {
         return mHost.makeChildSurface(null)
                 .setParent(mHost.getSurfaceControl())
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index 9f59f5a..f81e5d4 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -790,7 +790,8 @@
 
             // If SystemUI is dragging for recents, we want to reset the dim state so any dim layer
             // on the display level fades out.
-            if (forAllTasks(task -> !task.canAffectSystemUiFlags())) {
+            if (!mTransitionController.isShellTransitionsEnabled()
+                    && forAllTasks(task -> !task.canAffectSystemUiFlags())) {
                 mDimmer.resetDimStates();
             }
 
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index aad1225..3d9edca 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -397,6 +397,28 @@
         return false;
     }
 
+    boolean canApplyDim(@NonNull Task task) {
+        if (mTransientLaunches == null) return true;
+        final Dimmer dimmer = task.getDimmer();
+        final WindowContainer<?> dimmerHost = dimmer != null ? dimmer.getHost() : null;
+        if (dimmerHost == null) return false;
+        if (isInTransientHide(dimmerHost)) {
+            // The layer of dimmer is inside transient-hide task, then allow to dim.
+            return true;
+        }
+        // The dimmer host of a translucent task can be a display, then it is not in transient-hide.
+        for (int i = mTransientLaunches.size() - 1; i >= 0; --i) {
+            // The transient task is usually the task of recents/home activity.
+            final Task transientTask = mTransientLaunches.keyAt(i).getTask();
+            if (transientTask != null && transientTask.canAffectSystemUiFlags()) {
+                // It usually means that the recents animation has moved the transient-hide task
+                // an noticeable distance, then the display level dimmer should not show.
+                return false;
+            }
+        }
+        return true;
+    }
+
     boolean hasTransientLaunch() {
         return mTransientLaunches != null && !mTransientLaunches.isEmpty();
     }
@@ -1224,6 +1246,16 @@
                     mController.mAtm.mRootWindowContainer.getDisplayContent(mRecentsDisplayId);
             dc.getInputMonitor().setActiveRecents(null /* activity */, null /* layer */);
         }
+        if (mTransientLaunches != null) {
+            for (int i = mTransientLaunches.size() - 1; i >= 0; --i) {
+                // Reset the ability of controlling SystemUi which might be changed by
+                // setTransientLaunch or setRecentsAppBehindSystemBars.
+                final Task task = mTransientLaunches.keyAt(i).getTask();
+                if (task != null) {
+                    task.setCanAffectSystemUiFlags(true);
+                }
+            }
+        }
 
         for (int i = 0; i < mTargetDisplays.size(); ++i) {
             final DisplayContent dc = mTargetDisplays.get(i);
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 359b353..a539a48 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -58,6 +58,7 @@
 import com.android.server.FgThread;
 
 import java.util.ArrayList;
+import java.util.function.Consumer;
 import java.util.function.LongConsumer;
 
 /**
@@ -476,6 +477,19 @@
         return false;
     }
 
+    boolean canApplyDim(@Nullable Task task) {
+        if (task == null) {
+            // Always allow non-activity window.
+            return true;
+        }
+        for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
+            if (!mPlayingTransitions.get(i).canApplyDim(task)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     /**
      * During transient-launch, the "behind" app should retain focus during the transition unless
      * something takes focus from it explicitly (eg. by calling ATMS.setFocusedTask or by another
@@ -1314,18 +1328,18 @@
         return transit;
     }
 
-    /** Returns {@code true} if it started collecting, {@code false} if it was queued. */
-    boolean startLegacySyncOrQueue(BLASTSyncEngine.SyncGroup syncGroup, Runnable applySync) {
+    /** Starts the sync set if there is no pending or active syncs, otherwise enqueue the sync. */
+    void startLegacySyncOrQueue(BLASTSyncEngine.SyncGroup syncGroup, Consumer<Boolean> applySync) {
         if (!mQueuedTransitions.isEmpty() || mSyncEngine.hasActiveSync()) {
             // Just add to queue since we already have a queue.
-            mQueuedTransitions.add(new QueuedTransition(syncGroup, (d) -> applySync.run()));
+            mQueuedTransitions.add(new QueuedTransition(syncGroup,
+                    (deferred) -> applySync.accept(true /* deferred */)));
             ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN,
                     "Queueing legacy sync-set: %s", syncGroup.mSyncId);
-            return false;
+            return;
         }
         mSyncEngine.startSyncSet(syncGroup);
-        applySync.run();
-        return true;
+        applySync.accept(false /* deferred */);
     }
 
     interface OnStartCollect {
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 8e85e5b..a2f7ba4 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -232,8 +232,8 @@
                 final BLASTSyncEngine.SyncGroup syncGroup = prepareSyncWithOrganizer(callback);
                 final int syncId = syncGroup.mSyncId;
                 if (mTransitionController.isShellTransitionsEnabled()) {
-                    mTransitionController.startLegacySyncOrQueue(syncGroup, () -> {
-                        applyTransaction(t, syncId, null /*transition*/, caller);
+                    mTransitionController.startLegacySyncOrQueue(syncGroup, (deferred) -> {
+                        applyTransaction(t, syncId, null /* transition */, caller, deferred);
                         setSyncReady(syncId);
                     });
                 } else {
@@ -304,7 +304,8 @@
                             (deferred) -> {
                                 nextTransition.start();
                                 nextTransition.mLogger.mStartWCT = wct;
-                                applyTransaction(wct, -1 /*syncId*/, nextTransition, caller);
+                                applyTransaction(wct, -1 /* syncId */, nextTransition, caller,
+                                        deferred);
                                 if (needsSetReady) {
                                     nextTransition.setAllReady();
                                 }
@@ -456,7 +457,7 @@
                     transition.abort();
                     return;
                 }
-                if (applyTransaction(wct, -1 /* syncId */, transition, caller)
+                if (applyTransaction(wct, -1 /* syncId */, transition, caller, deferred)
                         == TRANSACT_EFFECTS_NONE && transition.mParticipants.isEmpty()) {
                     transition.abort();
                     return;
@@ -476,6 +477,23 @@
         return applyTransaction(t, syncId, transition, caller, null /* finishTransition */);
     }
 
+    private int applyTransaction(@NonNull WindowContainerTransaction t, int syncId,
+            @Nullable Transition transition, @NonNull CallerInfo caller, boolean deferred) {
+        if (deferred) {
+            try {
+                return applyTransaction(t, syncId, transition, caller);
+            } catch (RuntimeException e) {
+                // If the transaction is deferred, the caller could be from TransitionController
+                // #tryStartCollectFromQueue that executes on system's worker thread rather than
+                // binder thread. And the operation in the WCT may be outdated that violates the
+                // current state. So catch the exception to avoid crashing the system.
+                Slog.e(TAG, "Failed to execute deferred applyTransaction", e);
+            }
+            return TRANSACT_EFFECTS_NONE;
+        }
+        return applyTransaction(t, syncId, transition, caller);
+    }
+
     /**
      * @param syncId If non-null, this will be a sync-transaction.
      * @param transition A transition to collect changes into.
@@ -838,13 +856,21 @@
         switch (type) {
             case HIERARCHY_OP_TYPE_REMOVE_TASK: {
                 final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
-                final Task task = wc != null ? wc.asTask() : null;
+                if (wc == null || wc.asTask() == null || !wc.isAttached()) {
+                    Slog.e(TAG, "Attempt to remove invalid task: " + wc);
+                    break;
+                }
+                final Task task = wc.asTask();
                 task.remove(true, "Applying remove task Hierarchy Op");
                 break;
             }
             case HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT: {
                 final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
-                final Task task = wc != null ? wc.asTask() : null;
+                if (wc == null || !wc.isAttached()) {
+                    Slog.e(TAG, "Attempt to set launch root to a detached container: " + wc);
+                    break;
+                }
+                final Task task = wc.asTask();
                 if (task == null) {
                     throw new IllegalArgumentException("Cannot set non-task as launch root: " + wc);
                 } else if (task.getTaskDisplayArea() == null) {
@@ -858,7 +884,11 @@
             }
             case HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT: {
                 final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
-                final Task task = wc != null ? wc.asTask() : null;
+                if (wc == null || !wc.isAttached()) {
+                    Slog.e(TAG, "Attempt to set launch adjacent to a detached container: " + wc);
+                    break;
+                }
+                final Task task = wc.asTask();
                 final boolean clearRoot = hop.getToTop();
                 if (task == null) {
                     throw new IllegalArgumentException("Cannot set non-task as launch root: " + wc);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 9ffca41..cc9ac76 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5120,12 +5120,13 @@
 
     private void applyDims() {
         if (((mAttrs.flags & FLAG_DIM_BEHIND) != 0 || shouldDrawBlurBehind())
-                   && isVisibleNow() && !mHidden) {
+                   && isVisibleNow() && !mHidden && mTransitionController.canApplyDim(getTask())) {
             // Only show the Dimmer when the following is satisfied:
             // 1. The window has the flag FLAG_DIM_BEHIND or blur behind is requested
             // 2. The WindowToken is not hidden so dims aren't shown when the window is exiting.
             // 3. The WS is considered visible according to the isVisible() method
             // 4. The WS is not hidden.
+            // 5. The window is not in a transition or is in a transition that allows to dim.
             mIsDimming = true;
             final float dimAmount = (mAttrs.flags & FLAG_DIM_BEHIND) != 0 ? mAttrs.dimAmount : 0;
             final int blurRadius = shouldDrawBlurBehind() ? mAttrs.getBlurBehindRadius() : 0;
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index f4238f6..3b3e7cd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -410,9 +410,9 @@
                 List.of(makeMockRegisteredReceiver()), false);
         enqueueOrReplaceBroadcast(queue, airplaneRecord, 0);
 
-        queue.setProcessAndUidState(null, false, false);
+        queue.setProcessAndUidState(mProcess, false, false);
         final long notCachedRunnableAt = queue.getRunnableAt();
-        queue.setProcessAndUidState(null, false, true);
+        queue.setProcessAndUidState(mProcess, false, true);
         final long cachedRunnableAt = queue.getRunnableAt();
         assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt);
         assertFalse(queue.isRunnable());
@@ -437,9 +437,9 @@
                 List.of(makeMockRegisteredReceiver()), false);
         enqueueOrReplaceBroadcast(queue, airplaneRecord, 0);
 
-        queue.setProcessAndUidState(null, false, false);
+        queue.setProcessAndUidState(mProcess, false, false);
         final long notCachedRunnableAt = queue.getRunnableAt();
-        queue.setProcessAndUidState(null, false, true);
+        queue.setProcessAndUidState(mProcess, false, true);
         final long cachedRunnableAt = queue.getRunnableAt();
         assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt);
         assertTrue(queue.isRunnable());
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
index e7a94c0..73eb237 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -172,6 +172,7 @@
     BroadcastConstants mConstants;
     private BroadcastSkipPolicy mSkipPolicy;
     private UidObserver mUidObserver;
+    private UidObserver mUidCachedStateObserver;
 
     /**
      * Desired behavior of the next
@@ -317,7 +318,13 @@
         doAnswer((invocation) -> {
             mUidObserver = invocation.getArgument(0);
             return null;
-        }).when(mAms).registerUidObserver(any(), anyInt(), anyInt(), any());
+        }).when(mAms).registerUidObserver(any(), anyInt(),
+                eq(ActivityManager.PROCESS_STATE_TOP), any());
+        doAnswer((invocation) -> {
+            mUidCachedStateObserver = invocation.getArgument(0);
+            return null;
+        }).when(mAms).registerUidObserver(any(), anyInt(),
+                eq(ActivityManager.PROCESS_STATE_LAST_ACTIVITY), any());
 
         mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS);
         mConstants.TIMEOUT = 100;
@@ -414,6 +421,12 @@
                 UserHandle.USER_SYSTEM);
     }
 
+    private ProcessRecord makeActiveProcessRecord(String packageName, String processName)
+            throws Exception {
+        return makeActiveProcessRecord(packageName, processName, ProcessBehavior.NORMAL,
+                UserHandle.USER_SYSTEM);
+    }
+
     private ProcessRecord makeActiveProcessRecord(String packageName,
             ProcessBehavior behavior) throws Exception {
         return makeActiveProcessRecord(packageName, packageName, behavior, UserHandle.USER_SYSTEM);
@@ -616,6 +629,11 @@
                 BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN);
     }
 
+    private void setProcessFreezable(ProcessRecord app, boolean pendingFreeze, boolean frozen) {
+        app.mOptRecord.setPendingFreeze(pendingFreeze);
+        app.mOptRecord.setFrozen(frozen);
+    }
+
     private void assertHealth() {
         if (mImpl == Impl.MODERN) {
             // If this fails, it'll throw a clear reason message
@@ -1762,8 +1780,10 @@
         final ProcessRecord receiverYellowApp = makeActiveProcessRecord(PACKAGE_YELLOW);
         final ProcessRecord receiverOrangeApp = makeActiveProcessRecord(PACKAGE_ORANGE);
 
-        mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_GREEN), true);
-        mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_BLUE), true);
+        setProcessFreezable(receiverGreenApp, true, false);
+        mQueue.onProcessFreezableChangedLocked(receiverGreenApp);
+        setProcessFreezable(receiverBlueApp, false, true);
+        mQueue.onProcessFreezableChangedLocked(receiverBlueApp);
 
         final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK);
         final BroadcastOptions opts = BroadcastOptions.makeBasic()
@@ -1807,12 +1827,14 @@
                 eq(UserHandle.USER_SYSTEM), anyInt(), anyInt(), any());
 
         // Shift blue to be active and confirm that deferred broadcast is delivered
-        mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_BLUE), false);
+        setProcessFreezable(receiverBlueApp, false, false);
+        mQueue.onProcessFreezableChangedLocked(receiverBlueApp);
         waitForIdle();
         verifyScheduleRegisteredReceiver(times(1), receiverBlueApp, timeTick);
 
         // Shift green to be active and confirm that deferred broadcast is delivered
-        mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_GREEN), false);
+        setProcessFreezable(receiverGreenApp, false, false);
+        mQueue.onProcessFreezableChangedLocked(receiverGreenApp);
         waitForIdle();
         verifyScheduleRegisteredReceiver(times(1), receiverGreenApp, timeTick);
     }
@@ -2237,9 +2259,12 @@
         final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE);
         final ProcessRecord receiverYellowApp = makeActiveProcessRecord(PACKAGE_YELLOW);
 
-        mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_GREEN), true);
-        mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_BLUE), true);
-        mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_YELLOW), false);
+        setProcessFreezable(receiverGreenApp, true, true);
+        mQueue.onProcessFreezableChangedLocked(receiverGreenApp);
+        setProcessFreezable(receiverBlueApp, true, false);
+        mQueue.onProcessFreezableChangedLocked(receiverBlueApp);
+        setProcessFreezable(receiverYellowApp, false, false);
+        mQueue.onProcessFreezableChangedLocked(receiverYellowApp);
 
         final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
         final BroadcastOptions opts = BroadcastOptions.makeBasic()
@@ -2262,11 +2287,50 @@
         verifyScheduleRegisteredReceiver(times(1), receiverYellowApp, airplane);
 
         // Shift green to be active and confirm that deferred broadcast is delivered
-        mUidObserver.onUidCachedChanged(getUidForPackage(PACKAGE_GREEN), false);
+        setProcessFreezable(receiverGreenApp, false, false);
+        mQueue.onProcessFreezableChangedLocked(receiverGreenApp);
         waitForIdle();
         verifyScheduleRegisteredReceiver(times(1), receiverGreenApp, airplane);
     }
 
+    /**
+     * Verify broadcasts to a runtime receiver in cached process is deferred even when a different
+     * process in the same package is not cached.
+     */
+    @Test
+    public void testDeferralPolicy_UntilActive_WithMultiProcessUid() throws Exception {
+        // Legacy stack doesn't support deferral
+        Assume.assumeTrue(mImpl == Impl.MODERN);
+
+        final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+        final ProcessRecord receiverGreenApp1 = makeActiveProcessRecord(PACKAGE_GREEN);
+        final ProcessRecord receiverGreenApp2 = makeActiveProcessRecord(PACKAGE_GREEN,
+                PACKAGE_GREEN + "_proc2");
+
+        setProcessFreezable(receiverGreenApp1, true, true);
+        mQueue.onProcessFreezableChangedLocked(receiverGreenApp1);
+
+        final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+        final BroadcastOptions opts = BroadcastOptions.makeBasic()
+                .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
+        enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, opts,
+                List.of(makeRegisteredReceiver(receiverGreenApp1),
+                        makeRegisteredReceiver(receiverGreenApp2))));
+        waitForIdle();
+
+        // 1st process in Green package is ignored since it is in a cached state
+        // but the 2nd process should still receive the broadcast.
+        verifyScheduleRegisteredReceiver(never(), receiverGreenApp1, airplane);
+        verifyScheduleRegisteredReceiver(times(1), receiverGreenApp2, airplane);
+
+        // Shift the 1st process in Green package to be active and confirm that deferred broadcast
+        // is delivered
+        setProcessFreezable(receiverGreenApp1, false, false);
+        mQueue.onProcessFreezableChangedLocked(receiverGreenApp1);
+        waitForIdle();
+        verifyScheduleRegisteredReceiver(times(1), receiverGreenApp1, airplane);
+    }
+
     @Test
     public void testBroadcastDelivery_uidForeground() throws Exception {
         // Legacy stack doesn't support prioritization to foreground app.
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 770f04a..60e2af5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -2512,6 +2512,35 @@
         assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());
     }
 
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testUpdateOomAdj_DoAll_Side_Cycle() {
+        final ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+        final ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+        final ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+                MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+        long now = SystemClock.uptimeMillis();
+        ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class));
+        s.startRequested = true;
+        s.lastActivity = now;
+        s = bindService(app2, app3, null, 0, mock(IBinder.class));
+        s.lastActivity = now;
+        s = bindService(app3, app2, null, 0, mock(IBinder.class));
+        s.lastActivity = now;
+
+        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+        sService.mOomAdjuster.mNumServiceProcs = 3;
+        updateOomAdj(app, app2, app3);
+
+        assertEquals(SERVICE_ADJ, app.mState.getSetAdj());
+        assertTrue(sFirstCachedAdj <= app2.mState.getSetAdj());
+        assertTrue(sFirstCachedAdj <= app3.mState.getSetAdj());
+        assertTrue(CACHED_APP_MAX_ADJ >= app2.mState.getSetAdj());
+        assertTrue(CACHED_APP_MAX_ADJ >= app3.mState.getSetAdj());
+    }
+
     private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
             String packageName, boolean hasShownUi) {
         long now = SystemClock.uptimeMillis();
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index aad373f..aca96ad 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -445,14 +445,14 @@
                         + "    <library \n"
                         + "        name=\"foo\"\n"
                         + "        file=\"" + mFooJar + "\"\n"
-                        + "        on-bootclasspath-before=\"A\"\n"
+                        + "        on-bootclasspath-before=\"Q\"\n"
                         + "        on-bootclasspath-since=\"W\"\n"
                         + "     />\n\n"
                         + " </permissions>";
         parseSharedLibraries(contents);
         assertFooIsOnlySharedLibrary();
         SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
-        assertThat(entry.onBootclasspathBefore).isEqualTo("A");
+        assertThat(entry.onBootclasspathBefore).isEqualTo("Q");
         assertThat(entry.onBootclasspathSince).isEqualTo("W");
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 1126726..ed0c8ef 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1452,6 +1452,11 @@
             }
         });
         assertTrue(activity1.isVisible());
+        doReturn(false).when(task1).isTranslucent(null);
+        assertTrue(controller.canApplyDim(task1));
+        doReturn(true).when(task1).isTranslucent(null);
+        assertFalse(controller.canApplyDim(task1));
+
         controller.finishTransition(closeTransition);
         assertTrue(wasInFinishingTransition[0]);
         assertNull(controller.mFinishingTransition);
@@ -2191,8 +2196,11 @@
 
         BLASTSyncEngine.SyncGroup legacySync = mSyncEngine.prepareSyncSet(
                 mock(BLASTSyncEngine.TransactionReadyListener.class), "test");
-        final boolean[] applyLegacy = new boolean[]{false};
-        controller.startLegacySyncOrQueue(legacySync, () -> applyLegacy[0] = true);
+        final boolean[] applyLegacy = new boolean[2];
+        controller.startLegacySyncOrQueue(legacySync, (deferred) -> {
+            applyLegacy[0] = true;
+            applyLegacy[1] = deferred;
+        });
         assertFalse(applyLegacy[0]);
         waitUntilHandlersIdle();
 
@@ -2208,6 +2216,7 @@
         assertTrue(transitA.isPlaying());
         // legacy sync should start now
         assertTrue(applyLegacy[0]);
+        assertTrue(applyLegacy[1]);
         // transitB must wait
         assertTrue(transitB.isPending());
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
index 122a6cb..537238b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.server.wm.flicker.ime
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.Rotation
@@ -104,7 +103,6 @@
     @Presubmit
     @Test
     @PlatinumTest(focusArea = "ime")
-    @IwTest(focusArea = "ime")
     override fun cujCompleted() {
         super.cujCompleted()
         imeLayerBecomesInvisible()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
index 5aa4382..8d80759 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.server.wm.flicker.ime
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.traces.component.ComponentNameMatcher
@@ -105,7 +104,6 @@
     @Presubmit
     @Test
     @PlatinumTest(focusArea = "ime")
-    @IwTest(focusArea = "ime")
     override fun cujCompleted() {
         super.cujCompleted()
         imeLayerBecomesInvisible()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
index 6731089..1526295 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
@@ -17,7 +17,6 @@
 package com.android.server.wm.flicker.ime
 
 import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.Rotation
@@ -73,7 +72,6 @@
     @Presubmit
     @Test
     @PlatinumTest(focusArea = "ime")
-    @IwTest(focusArea = "ime")
     override fun cujCompleted() {
         runAndIgnoreAssumptionViolation { entireScreenCovered() }
         runAndIgnoreAssumptionViolation { statusBarLayerIsVisibleAtStartAndEnd() }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
index c70e3cb..827110d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.server.wm.flicker.ime
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.Rotation
@@ -54,7 +53,6 @@
     @Presubmit
     @Test
     @PlatinumTest(focusArea = "ime")
-    @IwTest(focusArea = "ime")
     override fun cujCompleted() {
         super.cujCompleted()
         imeWindowBecomesVisible()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index 7fbcfec..ef75c61 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.server.wm.flicker.rotation
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.traces.component.ComponentNameMatcher
@@ -131,7 +130,6 @@
 
     @Test
     @PlatinumTest(focusArea = "framework")
-    @IwTest(focusArea = "framework")
     override fun cujCompleted() {
         super.cujCompleted()
         focusChanges()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index 44ae14a..f654bdd4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.server.wm.flicker.rotation
 
-import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.PlatinumTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.ScenarioBuilder
@@ -215,7 +214,6 @@
 
     @Test
     @PlatinumTest(focusArea = "framework")
-    @IwTest(focusArea = "framework")
     override fun cujCompleted() {
         appWindowFullScreen()
         appWindowSeamlessRotation()
diff --git a/tests/UiBench/Android.bp b/tests/UiBench/Android.bp
index 0d2f2ef..90e61c5 100644
--- a/tests/UiBench/Android.bp
+++ b/tests/UiBench/Android.bp
@@ -24,5 +24,6 @@
         "androidx.recyclerview_recyclerview",
         "androidx.leanback_leanback",
     ],
+    certificate: "platform",
     test_suites: ["device-tests"],
 }
diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml
index 4fc6ec7..47211c5 100644
--- a/tests/UiBench/AndroidManifest.xml
+++ b/tests/UiBench/AndroidManifest.xml
@@ -18,6 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      package="com.android.test.uibench">
+    <uses-permission android:name="android.permission.INJECT_EVENTS" />
 
     <application android:allowBackup="false"
          android:theme="@style/Theme.AppCompat.Light.DarkActionBar"