Merge "Fix flaky ScheduleCalendarTest"
diff --git a/Android.bp b/Android.bp
index e9fb93e..4d2e5e1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1251,6 +1251,9 @@
     local_sourcepaths: frameworks_base_subdirs,
     installable: false,
     metalava_enabled: true,
+    metalava_annotations_enabled: true,
+    metalava_previous_api: ":public-api-for-metalava-annotations",
+    metalava_merge_annotations_dir: "tools/metalava/manual",
 }
 
 droiddoc {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 950070e..a58db64 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2206,10 +2206,10 @@
                             com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
                     if (val != null) {
                         if (val.type == TypedValue.TYPE_STRING && val.string != null) {
-                            targetCode = minCode = val.string.toString();
+                            minCode = val.string.toString();
                         } else {
                             // If it's not a string, it's an integer.
-                            targetVers = minVers = val.data;
+                            minVers = val.data;
                         }
                     }
 
@@ -2225,6 +2225,9 @@
                             // If it's not a string, it's an integer.
                             targetVers = val.data;
                         }
+                    } else {
+                        targetVers = minVers;
+                        targetCode = minCode;
                     }
 
                     sa.recycle();
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 87c64cd..32c6898 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2365,13 +2365,25 @@
      * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, is defined relative to the active array rectangle given in
      * this field, with <code>(0, 0)</code> being the top-left of this rectangle.</p>
      * <p>The active array may be smaller than the full pixel array, since the full array may
-     * include black calibration pixels or other inactive regions, and geometric correction
-     * resulting in scaling or cropping may have been applied.</p>
+     * include black calibration pixels or other inactive regions.</p>
+     * <p>For devices that do not support {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the active
+     * array must be the same as {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.</p>
+     * <p>For devices that support {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the active array must
+     * be enclosed by {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. The difference between
+     * pre-correction active array and active array accounts for scaling or cropping caused
+     * by lens geometric distortion correction.</p>
+     * <p>In general, application should always refer to active array size for controls like
+     * metering regions or crop region. Two exceptions are when the application is dealing with
+     * RAW image buffers (RAW_SENSOR, RAW10, RAW12 etc), or when application explicitly set
+     * {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} to OFF. In these cases, application should refer
+     * to {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.</p>
      * <p><b>Units</b>: Pixel coordinates on the image sensor</p>
      * <p>This key is available on all devices.</p>
      *
+     * @see CaptureRequest#DISTORTION_CORRECTION_MODE
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<android.graphics.Rect> SENSOR_INFO_ACTIVE_ARRAY_SIZE =
@@ -2616,9 +2628,9 @@
      * <ol>
      * <li>{@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion}.</li>
      * </ol>
-     * <p>If all of the geometric distortion fields are no-ops, this rectangle will be the same
-     * as the post-distortion-corrected rectangle given in
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
+     * <p>If the camera device doesn't support geometric distortion correction, or all of the
+     * geometric distortion fields are no-ops, this rectangle will be the same as the
+     * post-distortion-corrected rectangle given in {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
      * <p>This rectangle is defined relative to the full pixel array; (0,0) is the top-left of
      * the full pixel array, and the size of the full pixel array is given by
      * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}.</p>
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 411a97e..aca77a5 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1269,11 +1269,26 @@
      * Otherwise will always be present.</p>
      * <p>The maximum number of regions supported by the device is determined by the value
      * of {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AE android.control.maxRegionsAe}.</p>
-     * <p>The coordinate system is based on the active pixel array,
-     * with (0,0) being the top-left pixel in the active pixel array, and
+     * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0,0) being
+     * the top-left pixel in the active pixel array, and
      * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
-     * bottom-right pixel in the active pixel array.</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+     * active pixel array.</p>
+     * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system depends on the mode being set.
+     * When the distortion correction mode is OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array, and
+     * ({@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.width - 1,
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.height - 1) being the bottom-right
+     * pixel in the pre-correction active pixel array.
+     * When the distortion correction mode is not OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the active array, and
+     * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+     * active pixel array.</p>
      * <p>The weight must be within <code>[0, 1000]</code>, and represents a weight
      * for every pixel in the area. This means that a large metering area
      * with the same weight as a smaller area will have more effect in
@@ -1289,15 +1304,20 @@
      * region and output only the intersection rectangle as the metering region in the result
      * metadata.  If the region is entirely outside the crop region, it will be ignored and
      * not reported in the result metadata.</p>
-     * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
+     * distortion correction capability and mode</p>
      * <p><b>Range of valid values:</b><br>
      * Coordinates must be between <code>[(0,0), (width, height))</code> of
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+     * depending on distortion correction capability and mode</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AE
+     * @see CaptureRequest#DISTORTION_CORRECTION_MODE
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AE_REGIONS =
@@ -1443,11 +1463,26 @@
      * Otherwise will always be present.</p>
      * <p>The maximum number of focus areas supported by the device is determined by the value
      * of {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AF android.control.maxRegionsAf}.</p>
-     * <p>The coordinate system is based on the active pixel array,
-     * with (0,0) being the top-left pixel in the active pixel array, and
+     * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0,0) being
+     * the top-left pixel in the active pixel array, and
      * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
-     * bottom-right pixel in the active pixel array.</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+     * active pixel array.</p>
+     * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system depends on the mode being set.
+     * When the distortion correction mode is OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array, and
+     * ({@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.width - 1,
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.height - 1) being the bottom-right
+     * pixel in the pre-correction active pixel array.
+     * When the distortion correction mode is not OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the active array, and
+     * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+     * active pixel array.</p>
      * <p>The weight must be within <code>[0, 1000]</code>, and represents a weight
      * for every pixel in the area. This means that a large metering area
      * with the same weight as a smaller area will have more effect in
@@ -1464,15 +1499,20 @@
      * region and output only the intersection rectangle as the metering region in the result
      * metadata. If the region is entirely outside the crop region, it will be ignored and
      * not reported in the result metadata.</p>
-     * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
+     * distortion correction capability and mode</p>
      * <p><b>Range of valid values:</b><br>
      * Coordinates must be between <code>[(0,0), (width, height))</code> of
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+     * depending on distortion correction capability and mode</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AF
+     * @see CaptureRequest#DISTORTION_CORRECTION_MODE
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AF_REGIONS =
@@ -1612,11 +1652,26 @@
      * Otherwise will always be present.</p>
      * <p>The maximum number of regions supported by the device is determined by the value
      * of {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AWB android.control.maxRegionsAwb}.</p>
-     * <p>The coordinate system is based on the active pixel array,
-     * with (0,0) being the top-left pixel in the active pixel array, and
+     * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0,0) being
+     * the top-left pixel in the active pixel array, and
      * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
-     * bottom-right pixel in the active pixel array.</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+     * active pixel array.</p>
+     * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system depends on the mode being set.
+     * When the distortion correction mode is OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array, and
+     * ({@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.width - 1,
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.height - 1) being the bottom-right
+     * pixel in the pre-correction active pixel array.
+     * When the distortion correction mode is not OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the active array, and
+     * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+     * active pixel array.</p>
      * <p>The weight must range from 0 to 1000, and represents a weight
      * for every pixel in the area. This means that a large metering area
      * with the same weight as a smaller area will have more effect in
@@ -1632,15 +1687,20 @@
      * region and output only the intersection rectangle as the metering region in the result
      * metadata.  If the region is entirely outside the crop region, it will be ignored and
      * not reported in the result metadata.</p>
-     * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
+     * distortion correction capability and mode</p>
      * <p><b>Range of valid values:</b><br>
      * Coordinates must be between <code>[(0,0), (width, height))</code> of
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+     * depending on distortion correction capability and mode</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AWB
+     * @see CaptureRequest#DISTORTION_CORRECTION_MODE
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AWB_REGIONS =
@@ -2433,9 +2493,17 @@
     /**
      * <p>The desired region of the sensor to read out for this capture.</p>
      * <p>This control can be used to implement digital zoom.</p>
-     * <p>The crop region coordinate system is based off
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being the
-     * top-left corner of the sensor active array.</p>
+     * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being
+     * the top-left pixel of the active array.</p>
+     * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system depends on the mode being set.
+     * When the distortion correction mode is OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array.
+     * When the distortion correction mode is not OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the active array.</p>
      * <p>Output streams use this rectangle to produce their output,
      * cropping to a smaller region if necessary to maintain the
      * stream's aspect ratio, then scaling the sensor input to
@@ -2454,20 +2522,30 @@
      * outputs will crop horizontally (pillarbox), and 16:9
      * streams will match exactly. These additional crops will
      * be centered within the crop region.</p>
-     * <p>The width and height of the crop region cannot
-     * be set to be smaller than
+     * <p>If the coordinate system is android.sensor.info.activeArraysSize, the width and height
+     * of the crop region cannot be set to be smaller than
      * <code>floor( activeArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code> and
      * <code>floor( activeArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>, respectively.</p>
+     * <p>If the coordinate system is {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, the width
+     * and height of the crop region cannot be set to be smaller than
+     * <code>floor( preCorrectionActiveArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>
+     * and
+     * <code>floor( preCorrectionActiveArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>,
+     * respectively.</p>
      * <p>The camera device may adjust the crop region to account
      * for rounding and other hardware requirements; the final
      * crop region used will be included in the output capture
      * result.</p>
      * <p><b>Units</b>: Pixel coordinates relative to
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on distortion correction
+     * capability and mode</p>
      * <p>This key is available on all devices.</p>
      *
+     * @see CaptureRequest#DISTORTION_CORRECTION_MODE
      * @see CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<android.graphics.Rect> SCALER_CROP_REGION =
@@ -3186,15 +3264,14 @@
      * any correction at all would slow down capture rate.  Every output stream will have a
      * similar amount of enhancement applied.</p>
      * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
-     * applied to any RAW output.  Metadata coordinates such as face rectangles or metering
+     * applied to any RAW output. Metadata coordinates such as face rectangles or metering
      * regions are also not affected by correction.</p>
-     * <p>Applications enabling distortion correction need to pay extra attention when converting
-     * image coordinates between corrected output buffers and the sensor array. For example, if
-     * the app supports tap-to-focus and enables correction, it then has to apply the distortion
-     * model described in {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} to the image buffer tap coordinates to properly
-     * calculate the tap position on the sensor active array to be used with
-     * {@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}. The same applies in reverse to detected face rectangles if
-     * they need to be drawn on top of the corrected output buffers.</p>
+     * <p>This control will be on by default on devices that support this control. Applications
+     * disabling distortion correction need to pay extra attention with the coordinate system of
+     * metering regions, crop region, and face rectangles. When distortion correction is OFF,
+     * metadata coordinates follow the coordinate system of
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. When distortion is not OFF, metadata
+     * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li>
@@ -3205,9 +3282,10 @@
      * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
-     * @see CaptureRequest#CONTROL_AF_REGIONS
      * @see CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES
      * @see CameraCharacteristics#LENS_DISTORTION
+     * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      * @see #DISTORTION_CORRECTION_MODE_OFF
      * @see #DISTORTION_CORRECTION_MODE_FAST
      * @see #DISTORTION_CORRECTION_MODE_HIGH_QUALITY
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 361d83d..d003f9a 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -730,11 +730,26 @@
      * Otherwise will always be present.</p>
      * <p>The maximum number of regions supported by the device is determined by the value
      * of {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AE android.control.maxRegionsAe}.</p>
-     * <p>The coordinate system is based on the active pixel array,
-     * with (0,0) being the top-left pixel in the active pixel array, and
+     * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0,0) being
+     * the top-left pixel in the active pixel array, and
      * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
-     * bottom-right pixel in the active pixel array.</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+     * active pixel array.</p>
+     * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system depends on the mode being set.
+     * When the distortion correction mode is OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array, and
+     * ({@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.width - 1,
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.height - 1) being the bottom-right
+     * pixel in the pre-correction active pixel array.
+     * When the distortion correction mode is not OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the active array, and
+     * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+     * active pixel array.</p>
      * <p>The weight must be within <code>[0, 1000]</code>, and represents a weight
      * for every pixel in the area. This means that a large metering area
      * with the same weight as a smaller area will have more effect in
@@ -750,15 +765,20 @@
      * region and output only the intersection rectangle as the metering region in the result
      * metadata.  If the region is entirely outside the crop region, it will be ignored and
      * not reported in the result metadata.</p>
-     * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
+     * distortion correction capability and mode</p>
      * <p><b>Range of valid values:</b><br>
      * Coordinates must be between <code>[(0,0), (width, height))</code> of
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+     * depending on distortion correction capability and mode</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AE
+     * @see CaptureRequest#DISTORTION_CORRECTION_MODE
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AE_REGIONS =
@@ -1152,11 +1172,26 @@
      * Otherwise will always be present.</p>
      * <p>The maximum number of focus areas supported by the device is determined by the value
      * of {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AF android.control.maxRegionsAf}.</p>
-     * <p>The coordinate system is based on the active pixel array,
-     * with (0,0) being the top-left pixel in the active pixel array, and
+     * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0,0) being
+     * the top-left pixel in the active pixel array, and
      * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
-     * bottom-right pixel in the active pixel array.</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+     * active pixel array.</p>
+     * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system depends on the mode being set.
+     * When the distortion correction mode is OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array, and
+     * ({@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.width - 1,
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.height - 1) being the bottom-right
+     * pixel in the pre-correction active pixel array.
+     * When the distortion correction mode is not OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the active array, and
+     * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+     * active pixel array.</p>
      * <p>The weight must be within <code>[0, 1000]</code>, and represents a weight
      * for every pixel in the area. This means that a large metering area
      * with the same weight as a smaller area will have more effect in
@@ -1173,15 +1208,20 @@
      * region and output only the intersection rectangle as the metering region in the result
      * metadata. If the region is entirely outside the crop region, it will be ignored and
      * not reported in the result metadata.</p>
-     * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
+     * distortion correction capability and mode</p>
      * <p><b>Range of valid values:</b><br>
      * Coordinates must be between <code>[(0,0), (width, height))</code> of
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+     * depending on distortion correction capability and mode</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AF
+     * @see CaptureRequest#DISTORTION_CORRECTION_MODE
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AF_REGIONS =
@@ -1730,11 +1770,26 @@
      * Otherwise will always be present.</p>
      * <p>The maximum number of regions supported by the device is determined by the value
      * of {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AWB android.control.maxRegionsAwb}.</p>
-     * <p>The coordinate system is based on the active pixel array,
-     * with (0,0) being the top-left pixel in the active pixel array, and
+     * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0,0) being
+     * the top-left pixel in the active pixel array, and
      * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
-     * bottom-right pixel in the active pixel array.</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+     * active pixel array.</p>
+     * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system depends on the mode being set.
+     * When the distortion correction mode is OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array, and
+     * ({@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.width - 1,
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.height - 1) being the bottom-right
+     * pixel in the pre-correction active pixel array.
+     * When the distortion correction mode is not OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the active array, and
+     * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+     * active pixel array.</p>
      * <p>The weight must range from 0 to 1000, and represents a weight
      * for every pixel in the area. This means that a large metering area
      * with the same weight as a smaller area will have more effect in
@@ -1750,15 +1805,20 @@
      * region and output only the intersection rectangle as the metering region in the result
      * metadata.  If the region is entirely outside the crop region, it will be ignored and
      * not reported in the result metadata.</p>
-     * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
+     * distortion correction capability and mode</p>
      * <p><b>Range of valid values:</b><br>
      * Coordinates must be between <code>[(0,0), (width, height))</code> of
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+     * depending on distortion correction capability and mode</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AWB
+     * @see CaptureRequest#DISTORTION_CORRECTION_MODE
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AWB_REGIONS =
@@ -3099,9 +3159,17 @@
     /**
      * <p>The desired region of the sensor to read out for this capture.</p>
      * <p>This control can be used to implement digital zoom.</p>
-     * <p>The crop region coordinate system is based off
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being the
-     * top-left corner of the sensor active array.</p>
+     * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being
+     * the top-left pixel of the active array.</p>
+     * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system depends on the mode being set.
+     * When the distortion correction mode is OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array.
+     * When the distortion correction mode is not OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the active array.</p>
      * <p>Output streams use this rectangle to produce their output,
      * cropping to a smaller region if necessary to maintain the
      * stream's aspect ratio, then scaling the sensor input to
@@ -3120,20 +3188,30 @@
      * outputs will crop horizontally (pillarbox), and 16:9
      * streams will match exactly. These additional crops will
      * be centered within the crop region.</p>
-     * <p>The width and height of the crop region cannot
-     * be set to be smaller than
+     * <p>If the coordinate system is android.sensor.info.activeArraysSize, the width and height
+     * of the crop region cannot be set to be smaller than
      * <code>floor( activeArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code> and
      * <code>floor( activeArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>, respectively.</p>
+     * <p>If the coordinate system is {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, the width
+     * and height of the crop region cannot be set to be smaller than
+     * <code>floor( preCorrectionActiveArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>
+     * and
+     * <code>floor( preCorrectionActiveArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>,
+     * respectively.</p>
      * <p>The camera device may adjust the crop region to account
      * for rounding and other hardware requirements; the final
      * crop region used will be included in the output capture
      * result.</p>
      * <p><b>Units</b>: Pixel coordinates relative to
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on distortion correction
+     * capability and mode</p>
      * <p>This key is available on all devices.</p>
      *
+     * @see CaptureRequest#DISTORTION_CORRECTION_MODE
      * @see CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      */
     @PublicKey
     public static final Key<android.graphics.Rect> SCALER_CROP_REGION =
@@ -3624,12 +3702,23 @@
     /**
      * <p>List of landmarks for detected
      * faces.</p>
-     * <p>The coordinate system is that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+     * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being
+     * the top-left pixel of the active array.</p>
+     * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system depends on the mode being set.
+     * When the distortion correction mode is OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array.
+     * When the distortion correction mode is not OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
      * <code>(0, 0)</code> being the top-left pixel of the active array.</p>
      * <p>Only available if {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} == FULL
      * This key is available on all devices.</p>
      *
+     * @see CaptureRequest#DISTORTION_CORRECTION_MODE
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      * @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
      * @hide
      */
@@ -3639,12 +3728,23 @@
     /**
      * <p>List of the bounding rectangles for detected
      * faces.</p>
-     * <p>The coordinate system is that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+     * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being
+     * the top-left pixel of the active array.</p>
+     * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+     * system depends on the mode being set.
+     * When the distortion correction mode is OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+     * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array.
+     * When the distortion correction mode is not OFF, the coordinate system follows
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
      * <code>(0, 0)</code> being the top-left pixel of the active array.</p>
      * <p>Only available if {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} != OFF
      * This key is available on all devices.</p>
      *
+     * @see CaptureRequest#DISTORTION_CORRECTION_MODE
      * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      * @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
      * @hide
      */
@@ -4478,15 +4578,14 @@
      * any correction at all would slow down capture rate.  Every output stream will have a
      * similar amount of enhancement applied.</p>
      * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
-     * applied to any RAW output.  Metadata coordinates such as face rectangles or metering
+     * applied to any RAW output. Metadata coordinates such as face rectangles or metering
      * regions are also not affected by correction.</p>
-     * <p>Applications enabling distortion correction need to pay extra attention when converting
-     * image coordinates between corrected output buffers and the sensor array. For example, if
-     * the app supports tap-to-focus and enables correction, it then has to apply the distortion
-     * model described in {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} to the image buffer tap coordinates to properly
-     * calculate the tap position on the sensor active array to be used with
-     * {@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}. The same applies in reverse to detected face rectangles if
-     * they need to be drawn on top of the corrected output buffers.</p>
+     * <p>This control will be on by default on devices that support this control. Applications
+     * disabling distortion correction need to pay extra attention with the coordinate system of
+     * metering regions, crop region, and face rectangles. When distortion correction is OFF,
+     * metadata coordinates follow the coordinate system of
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. When distortion is not OFF, metadata
+     * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li>
@@ -4497,9 +4596,10 @@
      * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
-     * @see CaptureRequest#CONTROL_AF_REGIONS
      * @see CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES
      * @see CameraCharacteristics#LENS_DISTORTION
+     * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
      * @see #DISTORTION_CORRECTION_MODE_OFF
      * @see #DISTORTION_CORRECTION_MODE_FAST
      * @see #DISTORTION_CORRECTION_MODE_HIGH_QUALITY
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index e989e1a..8f28102 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1435,7 +1435,9 @@
         // set the EXTRA_AUTHENTICATION_RESULT extra, but it could cause weird results if the
         // service set the extra and returned RESULT_CANCELED...
 
-        if (sDebug) Log.d(TAG, "onAuthenticationResult(): d=" + data);
+        if (sDebug) {
+            Log.d(TAG, "onAuthenticationResult(): id= " + authenticationId + ", data=" + data);
+        }
 
         synchronized (mLock) {
             if (!isActiveLocked()) {
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 1b816fe..c195a8e 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -142,7 +142,7 @@
             LOG_ALWAYS_FATAL_IF(!mProjectedDisplayList->mProjectedOutline);
             const bool shouldClip = mProjectedDisplayList->mProjectedOutline->getPath();
             SkAutoCanvasRestore acr2(canvas, shouldClip);
-            canvas->setMatrix(mProjectedDisplayList->mProjectedReceiverParentMatrix);
+            canvas->setMatrix(mProjectedDisplayList->mParentMatrix);
             if (shouldClip) {
                 clipOutline(*mProjectedDisplayList->mProjectedOutline, canvas, nullptr);
             }
@@ -200,9 +200,7 @@
         setViewProperties(properties, canvas, &alphaMultiplier);
     }
     SkiaDisplayList* displayList = (SkiaDisplayList*)mRenderNode->getDisplayList();
-    if (displayList->containsProjectionReceiver()) {
-        displayList->mProjectedReceiverParentMatrix = canvas->getTotalMatrix();
-    }
+    displayList->mParentMatrix = canvas->getTotalMatrix();
 
     // TODO should we let the bound of the drawable do this for us?
     const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index 6292a6c..dba97fe 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -55,6 +55,11 @@
         if (casterZ >= -NON_ZERO_EPSILON) {  // draw only children with negative Z
             return;
         }
+        SkAutoCanvasRestore acr(canvas, true);
+        // Since we're drawing out of recording order, the child's matrix needs to be applied to the
+        // canvas. In in-order drawing, the canvas already has the child's matrix applied.
+        canvas->setMatrix(mDisplayList->mParentMatrix);
+        canvas->concat(childNode->getRecordedMatrix());
         childNode->forceDraw(canvas);
         drawIndex++;
     }
@@ -102,6 +107,11 @@
 
         RenderNodeDrawable* childNode = zChildren[drawIndex];
         SkASSERT(childNode);
+        SkAutoCanvasRestore acr(canvas, true);
+        // Since we're drawing out of recording order, the child's matrix needs to be applied to the
+        // canvas. In in-order drawing, the canvas already has the child's matrix applied.
+        canvas->setMatrix(mStartBarrier->mDisplayList->mParentMatrix);
+        canvas->concat(childNode->getRecordedMatrix());
         childNode->forceDraw(canvas);
 
         drawIndex++;
@@ -153,10 +163,15 @@
     }
 
     SkAutoCanvasRestore acr(canvas, true);
+    // Since we're drawing out of recording order, the child's matrix needs to be applied to the
+    // canvas. In in-order drawing, the canvas already has the child's matrix applied.
+    canvas->setMatrix(mStartBarrier->mDisplayList->mParentMatrix);
 
     SkMatrix shadowMatrix;
-    mat4 hwuiMatrix;
+    mat4 hwuiMatrix(caster->getRecordedMatrix());
     // TODO we don't pass the optional boolean to treat it as a 4x4 matrix
+    // applyViewPropertyTransforms gets the same matrix, which render nodes apply with
+    // RenderNodeDrawable::setViewProperties as a part if their draw.
     caster->getRenderNode()->applyViewPropertyTransforms(hwuiMatrix);
     hwuiMatrix.copyTo(shadowMatrix);
     canvas->concat(shadowMatrix);
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 58b9242..6eff589 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -173,12 +173,12 @@
     // node is drawn.
     const Outline* mProjectedOutline = nullptr;
 
-    // mProjectedReceiverParentMatrix is valid when render node tree is traversed during the draw
-    // pass. Render nodes that have a child receiver node, will store their matrix in
-    // mProjectedReceiverParentMatrix. Child receiver node will set the matrix and then clip with
-    // the
-    // outline of their parent.
-    SkMatrix mProjectedReceiverParentMatrix;
+    // mParentMatrix is set and valid when render node tree is traversed during the draw
+    // pass. Render nodes, which draw in a order different than recording order (e.g. nodes with a
+    // child receiver node or Z elevation), can use mParentMatrix to calculate the final transform
+    // without replaying the matrix transform OPs from the display list.
+    // Child receiver node will set the matrix and then clip with the outline of their parent.
+    SkMatrix mParentMatrix;
 };
 
 };  // namespace skiapipeline
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 15c0ab1..eb67e6c 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -1094,7 +1094,7 @@
     class ShadowTestCanvas : public SkCanvas {
     public:
         ShadowTestCanvas(int width, int height) : SkCanvas(width, height) {}
-        int getIndex() { return mDrawCounter; }
+        int getDrawCounter() { return mDrawCounter; }
 
         virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
             // expect to draw 2 RenderNodeDrawable, 1 StartReorderBarrierDrawable,
@@ -1109,17 +1109,36 @@
             EXPECT_EQ(dy, TRANSLATE_Y);
         }
 
-        virtual void didConcat(const SkMatrix& matrix) override {
-            // This function is invoked by EndReorderBarrierDrawable::drawShadow to apply shadow
-            // matrix.
+        virtual void didSetMatrix(const SkMatrix& matrix) override {
             mDrawCounter++;
-            EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X, CASTER_Y), matrix);
-            EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X + TRANSLATE_X, CASTER_Y + TRANSLATE_Y),
-                      getTotalMatrix());
+            // First invocation is EndReorderBarrierDrawable::drawShadow to apply shadow matrix.
+            // Second invocation is preparing the matrix for an elevated RenderNodeDrawable.
+            EXPECT_TRUE(matrix.isIdentity());
+            EXPECT_TRUE(getTotalMatrix().isIdentity());
+        }
+
+        virtual void didConcat(const SkMatrix& matrix) override {
+            mDrawCounter++;
+            if (mFirstDidConcat) {
+                // First invocation is EndReorderBarrierDrawable::drawShadow to apply shadow matrix.
+                mFirstDidConcat = false;
+                EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X + TRANSLATE_X, CASTER_Y + TRANSLATE_Y),
+                          matrix);
+                EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X + TRANSLATE_X, CASTER_Y + TRANSLATE_Y),
+                          getTotalMatrix());
+            } else {
+                // Second invocation is preparing the matrix for an elevated RenderNodeDrawable.
+                EXPECT_EQ(SkMatrix::MakeTrans(TRANSLATE_X, TRANSLATE_Y),
+                          matrix);
+                EXPECT_EQ(SkMatrix::MakeTrans(TRANSLATE_X, TRANSLATE_Y),
+                          getTotalMatrix());
+            }
         }
 
     protected:
         int mDrawCounter = 0;
+    private:
+        bool mFirstDidConcat = true;
     };
 
     auto parent = TestUtils::createSkiaNode(
@@ -1143,7 +1162,7 @@
     ShadowTestCanvas canvas(CANVAS_WIDTH, CANVAS_HEIGHT);
     RenderNodeDrawable drawable(parent.get(), &canvas, false);
     canvas.drawDrawable(&drawable);
-    EXPECT_EQ(6, canvas.getIndex());
+    EXPECT_EQ(9, canvas.getDrawCounter());
 }
 
 // Draw a vector drawable twice but with different bounds and verify correct bounds are used.
diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
index 8473c06..a18600a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
@@ -40,9 +40,6 @@
 public class AccessibilityUtils {
     public static final char ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR = ':';
 
-    final static TextUtils.SimpleStringSplitter sStringColonSplitter =
-            new TextUtils.SimpleStringSplitter(ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR);
-
     /**
      * @return the set of enabled accessibility services. If there are no services,
      * it returns the unmodifiable {@link Collections#emptySet()}.
@@ -72,16 +69,16 @@
         final String enabledServicesSetting = Settings.Secure.getStringForUser(
                 context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
                 userId);
-        if (enabledServicesSetting == null) {
+        if (TextUtils.isEmpty(enabledServicesSetting)) {
             return Collections.emptySet();
         }
 
         final Set<ComponentName> enabledServices = new HashSet<>();
-        final TextUtils.SimpleStringSplitter colonSplitter = sStringColonSplitter;
+        final TextUtils.StringSplitter colonSplitter =
+                new TextUtils.SimpleStringSplitter(ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR);
         colonSplitter.setString(enabledServicesSetting);
 
-        while (colonSplitter.hasNext()) {
-            final String componentNameString = colonSplitter.next();
+        for (String componentNameString : colonSplitter) {
             final ComponentName enabledService = ComponentName.unflattenFromString(
                     componentNameString);
             if (enabledService != null) {
@@ -168,8 +165,7 @@
      * an OEM-configurable default if the setting has never been set.
      *
      * @param context A valid context
-     * @param userId The user whose settings should be checked
-     *
+     * @param userId  The user whose settings should be checked
      * @return The component name, flattened to a string, of the target service.
      */
     public static String getShortcutTargetServiceComponentNameString(
@@ -187,9 +183,9 @@
      * Check if the accessibility shortcut is enabled for a user
      *
      * @param context A valid context
-     * @param userId The user of interest
+     * @param userId  The user of interest
      * @return {@code true} if the shortcut is enabled for the user. {@code false} otherwise.
-     *         Note that the shortcut may be enabled, but no action associated with it.
+     * Note that the shortcut may be enabled, but no action associated with it.
      */
     public static boolean isShortcutEnabled(Context context, int userId) {
         return Settings.Secure.getIntForUser(context.getContentResolver(),
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 0f0e4e57..3549abc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -34,7 +34,6 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
-import android.widget.RemoteViews;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -96,11 +95,7 @@
     /**
      * The key used to get the category from metadata of activities of action
      * {@link #EXTRA_SETTINGS_ACTION}
-     * The value must be one of:
-     * <li>com.android.settings.category.wireless</li>
-     * <li>com.android.settings.category.device</li>
-     * <li>com.android.settings.category.personal</li>
-     * <li>com.android.settings.category.system</li>
+     * The value must be from {@link CategoryKey}.
      */
     private static final String EXTRA_CATEGORY_KEY = "com.android.settings.category";
 
@@ -171,17 +166,6 @@
     public static final String META_DATA_PREFERENCE_SUMMARY_URI =
             "com.android.settings.summary_uri";
 
-    /**
-     * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the
-     * custom view which should be displayed for the preference. The custom view will be inflated
-     * as a remote view.
-     *
-     * This also can be used with {@link #META_DATA_PREFERENCE_SUMMARY_URI}, by setting the id
-     * of the summary TextView to '@android:id/summary'.
-     */
-    public static final String META_DATA_PREFERENCE_CUSTOM_VIEW =
-            "com.android.settings.custom_view";
-
     public static final String SETTING_PKG = "com.android.settings";
 
     /**
@@ -442,11 +426,6 @@
                             keyHint = metaData.getString(META_DATA_PREFERENCE_KEYHINT);
                         }
                     }
-                    if (metaData.containsKey(META_DATA_PREFERENCE_CUSTOM_VIEW)) {
-                        int layoutId = metaData.getInt(META_DATA_PREFERENCE_CUSTOM_VIEW);
-                        tile.remoteViews = new RemoteViews(applicationInfo.packageName, layoutId);
-                        updateSummaryAndTitle(context, providerMap, tile);
-                    }
                 }
             } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
                 if (DEBUG) Log.d(LOG_TAG, "Couldn't find info", e);
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionCategory.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionCategory.java
deleted file mode 100644
index 19e556a..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionCategory.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.suggestions;
-
-public class SuggestionCategory {
-    public String category;
-    public String pkg;
-    public boolean multiple;
-    public boolean exclusive;
-    public long exclusiveExpireDaysInMillis;
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionList.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionList.java
deleted file mode 100644
index a890920..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionList.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.suggestions;
-
-import android.content.Intent;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-
-import com.android.settingslib.drawer.Tile;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-public class SuggestionList {
-    // Category -> list of suggestion map
-    private final Map<SuggestionCategory, List<Tile>> mSuggestions;
-
-    // A flatten list of all suggestions.
-    private List<Tile> mSuggestionList;
-
-    public SuggestionList() {
-        mSuggestions = new ArrayMap<>();
-    }
-
-    public void addSuggestions(SuggestionCategory category, List<Tile> suggestions) {
-        mSuggestions.put(category, suggestions);
-    }
-
-    public List<Tile> getSuggestions() {
-        if (mSuggestionList != null) {
-            return mSuggestionList;
-        }
-        mSuggestionList = new ArrayList<>();
-        for (List<Tile> suggestions : mSuggestions.values()) {
-            mSuggestionList.addAll(suggestions);
-        }
-        dedupeSuggestions(mSuggestionList);
-        return mSuggestionList;
-    }
-
-    public boolean isExclusiveSuggestionCategory() {
-        if (mSuggestions.size() != 1) {
-            // If there is no category, or more than 1 category, it's not exclusive by definition.
-            return false;
-        }
-        for (SuggestionCategory category : mSuggestions.keySet()) {
-            if (category.exclusive) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Filter suggestions list so they are all unique.
-     */
-    private void dedupeSuggestions(List<Tile> suggestions) {
-        final Set<String> intents = new ArraySet<>();
-        for (int i = suggestions.size() - 1; i >= 0; i--) {
-            final Tile suggestion = suggestions.get(i);
-            final String intentUri = suggestion.intent.toUri(Intent.URI_INTENT_SCHEME);
-            if (intents.contains(intentUri)) {
-                suggestions.remove(i);
-            } else {
-                intents.add(intentUri);
-            }
-        }
-    }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
deleted file mode 100644
index 8705c98..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settingslib.suggestions;
-
-import android.Manifest;
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.annotation.RequiresPermission;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.content.res.Resources;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import androidx.annotation.VisibleForTesting;
-import android.text.TextUtils;
-import android.text.format.DateUtils;
-import android.util.ArrayMap;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Pair;
-import android.util.Xml;
-import android.view.InflateException;
-
-import com.android.settingslib.drawer.Tile;
-import com.android.settingslib.drawer.TileUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-public class SuggestionParser {
-
-    private static final String TAG = "SuggestionParser";
-
-    // If defined, only returns this suggestion if the feature is supported.
-    public static final String META_DATA_REQUIRE_FEATURE = "com.android.settings.require_feature";
-
-    // If defined, only display this optional step if an account of that type exists.
-    private static final String META_DATA_REQUIRE_ACCOUNT = "com.android.settings.require_account";
-
-    // If defined and not true, do not should optional step.
-    private static final String META_DATA_IS_SUPPORTED = "com.android.settings.is_supported";
-
-    // If defined, only display this optional step if the current user is of that type.
-    private static final String META_DATA_REQUIRE_USER_TYPE =
-            "com.android.settings.require_user_type";
-
-    // If defined, only display this optional step if a connection is available.
-    private static final String META_DATA_IS_CONNECTION_REQUIRED =
-            "com.android.settings.require_connection";
-
-    // The valid values that setup wizard recognizes for differentiating user types.
-    private static final String META_DATA_PRIMARY_USER_TYPE_VALUE = "primary";
-    private static final String META_DATA_ADMIN_USER_TYPE_VALUE = "admin";
-    private static final String META_DATA_GUEST_USER_TYPE_VALUE = "guest";
-    private static final String META_DATA_RESTRICTED_USER_TYPE_VALUE = "restricted";
-
-    /**
-     * Allows suggestions to appear after a certain number of days, and to re-appear if dismissed.
-     * For instance:
-     * 0,10
-     * Will appear immediately, but if the user removes it, it will come back after 10 days.
-     *
-     * Another example:
-     * 10,30
-     * Will only show up after 10 days, and then again after 30.
-     */
-    public static final String META_DATA_DISMISS_CONTROL = "com.android.settings.dismiss";
-
-    // Shared prefs keys for storing dismissed state.
-    // Index into current dismissed state.
-    public static final String SETUP_TIME = "_setup_time";
-    private static final String IS_DISMISSED = "_is_dismissed";
-
-    // Default dismiss control for smart suggestions.
-    private static final String DEFAULT_SMART_DISMISS_CONTROL = "0";
-
-    private final Context mContext;
-    private final List<SuggestionCategory> mSuggestionList;
-    private final ArrayMap<Pair<String, String>, Tile> mAddCache = new ArrayMap<>();
-    private final SharedPreferences mSharedPrefs;
-    private final String mDefaultDismissControl;
-
-    public SuggestionParser(Context context, SharedPreferences sharedPrefs, int orderXml,
-            String defaultDismissControl) {
-        this(
-                context,
-                sharedPrefs,
-                (List<SuggestionCategory>) new SuggestionOrderInflater(context).parse(orderXml),
-                defaultDismissControl);
-    }
-
-    public SuggestionParser(Context context, SharedPreferences sharedPrefs, int orderXml) {
-        this(context, sharedPrefs, orderXml, DEFAULT_SMART_DISMISS_CONTROL);
-    }
-
-    @VisibleForTesting
-    public SuggestionParser(
-            Context context,
-            SharedPreferences sharedPrefs,
-            List<SuggestionCategory> suggestionList,
-            String defaultDismissControl) {
-        mContext = context;
-        mSuggestionList = suggestionList;
-        mSharedPrefs = sharedPrefs;
-        mDefaultDismissControl = defaultDismissControl;
-    }
-
-    public SuggestionList getSuggestions(boolean isSmartSuggestionEnabled) {
-        final SuggestionList suggestionList = new SuggestionList();
-        final int N = mSuggestionList.size();
-        for (int i = 0; i < N; i++) {
-            final SuggestionCategory category = mSuggestionList.get(i);
-            if (category.exclusive && !isExclusiveCategoryExpired(category)) {
-                // If suggestions from an exclusive category are present, parsing is stopped
-                // and only suggestions from that category are displayed. Note that subsequent
-                // exclusive categories are also ignored.
-                final List<Tile> exclusiveSuggestions = new ArrayList<>();
-
-                // Read suggestion and force isSmartSuggestion to be false so the rule defined
-                // from each suggestion itself is used.
-                readSuggestions(category, exclusiveSuggestions, false /* isSmartSuggestion */);
-                if (!exclusiveSuggestions.isEmpty()) {
-                    final SuggestionList exclusiveList = new SuggestionList();
-                    exclusiveList.addSuggestions(category, exclusiveSuggestions);
-                    return exclusiveList;
-                }
-            } else {
-                // Either the category is not exclusive, or the exclusiveness expired so we should
-                // treat it as a normal category.
-                final List<Tile> suggestions = new ArrayList<>();
-                readSuggestions(category, suggestions, isSmartSuggestionEnabled);
-                suggestionList.addSuggestions(category, suggestions);
-            }
-        }
-        return suggestionList;
-    }
-
-    /**
-     * Dismisses a suggestion, returns true if the suggestion has no more dismisses left and should
-     * be disabled.
-     */
-    public boolean dismissSuggestion(Tile suggestion) {
-        final String keyBase = suggestion.intent.getComponent().flattenToShortString();
-        mSharedPrefs.edit()
-                .putBoolean(keyBase + IS_DISMISSED, true)
-                .commit();
-        return true;
-    }
-
-    @VisibleForTesting
-    public void filterSuggestions(
-            List<Tile> suggestions, int countBefore, boolean isSmartSuggestionEnabled) {
-        for (int i = countBefore; i < suggestions.size(); i++) {
-            if (!isAvailable(suggestions.get(i)) ||
-                    !isSupported(suggestions.get(i)) ||
-                    !satisifesRequiredUserType(suggestions.get(i)) ||
-                    !satisfiesRequiredAccount(suggestions.get(i)) ||
-                    !satisfiesConnectivity(suggestions.get(i)) ||
-                    isDismissed(suggestions.get(i), isSmartSuggestionEnabled)) {
-                suggestions.remove(i--);
-            }
-        }
-    }
-
-    @VisibleForTesting
-    void readSuggestions(
-            SuggestionCategory category, List<Tile> suggestions, boolean isSmartSuggestionEnabled) {
-        int countBefore = suggestions.size();
-        Intent intent = new Intent(Intent.ACTION_MAIN);
-        intent.addCategory(category.category);
-        if (category.pkg != null) {
-            intent.setPackage(category.pkg);
-        }
-        TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent,
-                mAddCache, null, suggestions, true, false, false, true /* shouldUpdateTiles */);
-        filterSuggestions(suggestions, countBefore, isSmartSuggestionEnabled);
-        if (!category.multiple && suggestions.size() > (countBefore + 1)) {
-            // If there are too many, remove them all and only re-add the one with the highest
-            // priority.
-            Tile item = suggestions.remove(suggestions.size() - 1);
-            while (suggestions.size() > countBefore) {
-                Tile last = suggestions.remove(suggestions.size() - 1);
-                if (last.priority > item.priority) {
-                    item = last;
-                }
-            }
-            // If category is marked as done, do not add any item.
-            if (!isCategoryDone(category.category)) {
-                suggestions.add(item);
-            }
-        }
-    }
-
-    private boolean isAvailable(Tile suggestion) {
-        final String featuresRequired = suggestion.metaData.getString(META_DATA_REQUIRE_FEATURE);
-        if (featuresRequired != null) {
-            for (String feature : featuresRequired.split(",")) {
-                if (TextUtils.isEmpty(feature)) {
-                    Log.w(TAG, "Found empty substring when parsing required features: "
-                            + featuresRequired);
-                } else if (!mContext.getPackageManager().hasSystemFeature(feature)) {
-                    Log.i(TAG, suggestion.title + " requires unavailable feature " + feature);
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    @RequiresPermission(Manifest.permission.MANAGE_USERS)
-    private boolean satisifesRequiredUserType(Tile suggestion) {
-        final String requiredUser = suggestion.metaData.getString(META_DATA_REQUIRE_USER_TYPE);
-        if (requiredUser != null) {
-            final UserManager userManager = mContext.getSystemService(UserManager.class);
-            UserInfo userInfo = userManager.getUserInfo(UserHandle.myUserId());
-            for (String userType : requiredUser.split("\\|")) {
-                final boolean primaryUserCondtionMet = userInfo.isPrimary()
-                        && META_DATA_PRIMARY_USER_TYPE_VALUE.equals(userType);
-                final boolean adminUserConditionMet = userInfo.isAdmin()
-                        && META_DATA_ADMIN_USER_TYPE_VALUE.equals(userType);
-                final boolean guestUserCondtionMet = userInfo.isGuest()
-                        && META_DATA_GUEST_USER_TYPE_VALUE.equals(userType);
-                final boolean restrictedUserCondtionMet = userInfo.isRestricted()
-                        && META_DATA_RESTRICTED_USER_TYPE_VALUE.equals(userType);
-                if (primaryUserCondtionMet || adminUserConditionMet || guestUserCondtionMet
-                        || restrictedUserCondtionMet) {
-                    return true;
-                }
-            }
-            Log.i(TAG, suggestion.title + " requires user type " + requiredUser);
-            return false;
-        }
-        return true;
-    }
-
-    public boolean satisfiesRequiredAccount(Tile suggestion) {
-        final String requiredAccountType = suggestion.metaData.getString(META_DATA_REQUIRE_ACCOUNT);
-        if (requiredAccountType == null) {
-            return true;
-        }
-        AccountManager accountManager = mContext.getSystemService(AccountManager.class);
-        Account[] accounts = accountManager.getAccountsByType(requiredAccountType);
-        boolean satisfiesRequiredAccount = accounts.length > 0;
-        if (!satisfiesRequiredAccount) {
-            Log.i(TAG, suggestion.title + " requires unavailable account type "
-                    + requiredAccountType);
-        }
-        return satisfiesRequiredAccount;
-    }
-
-    public boolean isSupported(Tile suggestion) {
-        final int isSupportedResource = suggestion.metaData.getInt(META_DATA_IS_SUPPORTED);
-        try {
-            if (suggestion.intent == null) {
-                return false;
-            }
-            final Resources res = mContext.getPackageManager().getResourcesForActivity(
-                    suggestion.intent.getComponent());
-            boolean isSupported =
-                    isSupportedResource != 0 ? res.getBoolean(isSupportedResource) : true;
-            if (!isSupported) {
-                Log.i(TAG, suggestion.title + " requires unsupported resource "
-                        + isSupportedResource);
-            }
-            return isSupported;
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.w(TAG, "Cannot find resources for " + suggestion.intent.getComponent());
-            return false;
-        } catch (Resources.NotFoundException e) {
-            Log.w(TAG, "Cannot find resources for " + suggestion.intent.getComponent(), e);
-            return false;
-        }
-    }
-
-    private boolean satisfiesConnectivity(Tile suggestion) {
-        final boolean isConnectionRequired =
-                suggestion.metaData.getBoolean(META_DATA_IS_CONNECTION_REQUIRED);
-        if (!isConnectionRequired) {
-            return true;
-        }
-        ConnectivityManager cm =
-                (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-        NetworkInfo netInfo = cm.getActiveNetworkInfo();
-        boolean satisfiesConnectivity = netInfo != null && netInfo.isConnectedOrConnecting();
-        if (!satisfiesConnectivity) {
-            Log.i(TAG, suggestion.title + " is missing required connection.");
-        }
-        return satisfiesConnectivity;
-    }
-
-    public boolean isCategoryDone(String category) {
-        String name = Settings.Secure.COMPLETED_CATEGORY_PREFIX + category;
-        return Settings.Secure.getInt(mContext.getContentResolver(), name, 0) != 0;
-    }
-
-    public void markCategoryDone(String category) {
-        String name = Settings.Secure.COMPLETED_CATEGORY_PREFIX + category;
-        Settings.Secure.putInt(mContext.getContentResolver(), name, 1);
-    }
-
-    /**
-     * Whether or not the category's exclusiveness has expired.
-     */
-    private boolean isExclusiveCategoryExpired(SuggestionCategory category) {
-        final String keySetupTime = category.category + SETUP_TIME;
-        final long currentTime = System.currentTimeMillis();
-        if (!mSharedPrefs.contains(keySetupTime)) {
-            mSharedPrefs.edit()
-                    .putLong(keySetupTime, currentTime)
-                    .commit();
-        }
-        if (category.exclusiveExpireDaysInMillis < 0) {
-            // negative means never expires
-            return false;
-        }
-        final long setupTime = mSharedPrefs.getLong(keySetupTime, 0);
-        final long elapsedTime = currentTime - setupTime;
-        Log.d(TAG, "Day " + elapsedTime / DateUtils.DAY_IN_MILLIS + " for " + category.category);
-        return elapsedTime > category.exclusiveExpireDaysInMillis;
-    }
-
-    @VisibleForTesting
-    boolean isDismissed(Tile suggestion, boolean isSmartSuggestionEnabled) {
-        String dismissControl = getDismissControl(suggestion, isSmartSuggestionEnabled);
-        String keyBase = suggestion.intent.getComponent().flattenToShortString();
-        if (!mSharedPrefs.contains(keyBase + SETUP_TIME)) {
-            mSharedPrefs.edit()
-                    .putLong(keyBase + SETUP_TIME, System.currentTimeMillis())
-                    .commit();
-        }
-        // Check if it's already manually dismissed
-        final boolean isDismissed = mSharedPrefs.getBoolean(keyBase + IS_DISMISSED, false);
-        if (isDismissed) {
-            return true;
-        }
-        if (dismissControl == null) {
-            return false;
-        }
-        // Parse when suggestion should first appear. return true to artificially hide suggestion
-        // before then.
-        int firstAppearDay = parseDismissString(dismissControl);
-        long firstAppearDayInMs = getEndTime(mSharedPrefs.getLong(keyBase + SETUP_TIME, 0),
-                firstAppearDay);
-        if (System.currentTimeMillis() >= firstAppearDayInMs) {
-            // Dismiss timeout has passed, undismiss it.
-            mSharedPrefs.edit()
-                    .putBoolean(keyBase + IS_DISMISSED, false)
-                    .commit();
-            return false;
-        }
-        return true;
-    }
-
-    private long getEndTime(long startTime, int daysDelay) {
-        long days = daysDelay * DateUtils.DAY_IN_MILLIS;
-        return startTime + days;
-    }
-
-    /**
-     * Parse the first int from a string formatted as "0,1,2..."
-     * The value means suggestion should first appear on Day X.
-     */
-    private int parseDismissString(String dismissControl) {
-        final String[] dismissStrs = dismissControl.split(",");
-        return Integer.parseInt(dismissStrs[0]);
-    }
-
-    private String getDismissControl(Tile suggestion, boolean isSmartSuggestionEnabled) {
-        if (isSmartSuggestionEnabled) {
-            return mDefaultDismissControl;
-        } else {
-            return suggestion.metaData.getString(META_DATA_DISMISS_CONTROL);
-        }
-    }
-
-    private static class SuggestionOrderInflater {
-        private static final String TAG_LIST = "optional-steps";
-        private static final String TAG_ITEM = "step";
-
-        private static final String ATTR_CATEGORY = "category";
-        private static final String ATTR_PACKAGE = "package";
-        private static final String ATTR_MULTIPLE = "multiple";
-        private static final String ATTR_EXCLUSIVE = "exclusive";
-        private static final String ATTR_EXCLUSIVE_EXPIRE_DAYS = "exclusiveExpireDays";
-
-        private final Context mContext;
-
-        public SuggestionOrderInflater(Context context) {
-            mContext = context;
-        }
-
-        public Object parse(int resource) {
-            XmlPullParser parser = mContext.getResources().getXml(resource);
-            final AttributeSet attrs = Xml.asAttributeSet(parser);
-            try {
-                // Look for the root node.
-                int type;
-                do {
-                    type = parser.next();
-                } while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT);
-
-                if (type != XmlPullParser.START_TAG) {
-                    throw new InflateException(parser.getPositionDescription()
-                            + ": No start tag found!");
-                }
-
-                // Temp is the root that was found in the xml
-                Object xmlRoot = onCreateItem(parser.getName(), attrs);
-
-                // Inflate all children under temp
-                rParse(parser, xmlRoot, attrs);
-                return xmlRoot;
-            } catch (XmlPullParserException | IOException e) {
-                Log.w(TAG, "Problem parser resource " + resource, e);
-                return null;
-            }
-        }
-
-        /**
-         * Recursive method used to descend down the xml hierarchy and instantiate
-         * items, instantiate their children.
-         */
-        private void rParse(XmlPullParser parser, Object parent, final AttributeSet attrs)
-                throws XmlPullParserException, IOException {
-            final int depth = parser.getDepth();
-
-            int type;
-            while (((type = parser.next()) != XmlPullParser.END_TAG ||
-                    parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
-                if (type != XmlPullParser.START_TAG) {
-                    continue;
-                }
-
-                final String name = parser.getName();
-
-                Object item = onCreateItem(name, attrs);
-                onAddChildItem(parent, item);
-                rParse(parser, item, attrs);
-            }
-        }
-
-        protected void onAddChildItem(Object parent, Object child) {
-            if (parent instanceof List<?> && child instanceof SuggestionCategory) {
-                ((List<SuggestionCategory>) parent).add((SuggestionCategory) child);
-            } else {
-                throw new IllegalArgumentException("Parent was not a list");
-            }
-        }
-
-        protected Object onCreateItem(String name, AttributeSet attrs) {
-            if (name.equals(TAG_LIST)) {
-                return new ArrayList<SuggestionCategory>();
-            } else if (name.equals(TAG_ITEM)) {
-                SuggestionCategory category = new SuggestionCategory();
-                category.category = attrs.getAttributeValue(null, ATTR_CATEGORY);
-                category.pkg = attrs.getAttributeValue(null, ATTR_PACKAGE);
-                String multiple = attrs.getAttributeValue(null, ATTR_MULTIPLE);
-                category.multiple = !TextUtils.isEmpty(multiple) && Boolean.parseBoolean(multiple);
-                String exclusive = attrs.getAttributeValue(null, ATTR_EXCLUSIVE);
-                category.exclusive =
-                        !TextUtils.isEmpty(exclusive) && Boolean.parseBoolean(exclusive);
-                String expireDaysAttr = attrs.getAttributeValue(null,
-                        ATTR_EXCLUSIVE_EXPIRE_DAYS);
-                long expireDays = !TextUtils.isEmpty(expireDaysAttr)
-                        ? Integer.parseInt(expireDaysAttr)
-                        : -1;
-                category.exclusiveExpireDaysInMillis = DateUtils.DAY_IN_MILLIS * expireDays;
-                return category;
-            } else {
-                throw new IllegalArgumentException("Unknown item " + name);
-            }
-        }
-    }
-}
-
diff --git a/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml b/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml
deleted file mode 100644
index f02ac15..0000000
--- a/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
--->
-
-<optional-steps>
-    <step category="com.android.settings.suggested.category.DEFERRED_SETUP"
-        exclusive="true" />
-    <step category="com.android.settings.suggested.category.LOCK_SCREEN" />
-    <step category="com.android.settings.suggested.category.TRUST_AGENT" />
-    <step category="com.android.settings.suggested.category.EMAIL" />
-    <step category="com.android.settings.suggested.category.PARTNER_ACCOUNT"
-        multiple="true" />
-    <step category="com.android.settings.suggested.category.GESTURE" />
-    <step category="com.android.settings.suggested.category.HOTWORD" />
-    <step category="com.android.settings.suggested.category.DEFAULT"
-        multiple="true" />
-    <step category="com.android.settings.suggested.category.SETTINGS_ONLY"
-        multiple="true" />
-</optional-steps>
diff --git a/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
deleted file mode 100644
index 14b0d59..0000000
--- a/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
- */
-public class BluetoothCodecConfig {
-    public boolean isMandatoryCodec() { return true; }
-    public String getCodecName() { return null; }
-    public int getCodecType() { return -1; }
-}
diff --git a/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecStatus.java b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecStatus.java
deleted file mode 100644
index 919ec3f..0000000
--- a/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecStatus.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
- */
-public class BluetoothCodecStatus {
-    public BluetoothCodecConfig getCodecConfig() { return null; }
-    public BluetoothCodecConfig[] getCodecsSelectableCapabilities() { return null; }
-}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/accessibility/AccessibilityUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/accessibility/AccessibilityUtilsTest.java
new file mode 100644
index 0000000..152d024
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/accessibility/AccessibilityUtilsTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class AccessibilityUtilsTest {
+
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+    }
+
+    @Test
+    public void getEnabledServicesFromSettings_noService_emptyResult() {
+        assertThat(AccessibilityUtils.getEnabledServicesFromSettings(mContext)).isEmpty();
+    }
+
+    @Test
+    public void getEnabledServicesFromSettings_badFormat_emptyResult() {
+        Settings.Secure.putStringForUser(
+                mContext.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                ":",
+                UserHandle.myUserId());
+
+        assertThat(AccessibilityUtils.getEnabledServicesFromSettings(mContext)).isEmpty();
+    }
+
+    @Test
+    public void getEnabledServicesFromSettings_1Service_1result() {
+        final ComponentName cn = new ComponentName("pkg", "serv");
+        Settings.Secure.putStringForUser(
+                mContext.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                cn.flattenToString() + ":",
+                UserHandle.myUserId());
+
+        assertThat(AccessibilityUtils.getEnabledServicesFromSettings(mContext))
+                .containsExactly(cn);
+    }
+
+    @Test
+    public void getEnabledServicesFromSettings_2Services_2results() {
+        final ComponentName cn1 = new ComponentName("pkg", "serv");
+        final ComponentName cn2 = new ComponentName("pkg", "serv2");
+        Settings.Secure.putStringForUser(
+                mContext.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                cn1.flattenToString() + ":" + cn2.flattenToString(),
+                UserHandle.myUserId());
+
+        assertThat(AccessibilityUtils.getEnabledServicesFromSettings(mContext))
+                .containsExactly(cn1, cn2);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index fc1b2238..6e66805 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -28,7 +28,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.robolectric.RuntimeEnvironment.application;
-import static org.robolectric.shadow.api.Shadow.extract;
 
 import android.app.ActivityManager;
 import android.content.ContentResolver;
@@ -52,9 +51,6 @@
 import android.util.Pair;
 import android.widget.RemoteViews;
 
-import com.android.settingslib.R;
-import com.android.settingslib.suggestions.SuggestionParser;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -67,7 +63,6 @@
 import org.robolectric.annotation.Implements;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -164,35 +159,6 @@
     }
 
     @Test
-    public void getTilesForIntent_shouldSkipFilteredApps() {
-        Intent intent = new Intent();
-        Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
-        List<Tile> outTiles = new ArrayList<>();
-        List<ResolveInfo> info = new ArrayList<>();
-        ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
-                URI_GET_SUMMARY);
-        addMetadataToInfo(resolveInfo, "com.android.settings.require_account", "com.google");
-        addMetadataToInfo(resolveInfo, "com.android.settings.require_connection", "true");
-        info.add(resolveInfo);
-
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
-                .thenReturn(info);
-
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
-
-        assertThat(outTiles.size()).isEqualTo(1);
-        SuggestionParser parser = new SuggestionParser(
-                mContext,
-                null,
-                Collections.emptyList(),
-                "0,10");
-        parser.filterSuggestions(outTiles, 0, false);
-        assertThat(outTiles.size()).isEqualTo(0);
-    }
-
-    @Test
     public void getCategories_shouldHandleExtraIntentAction() {
         final String testCategory = "category1";
         final String testAction = "action1";
@@ -392,108 +358,6 @@
         assertThat(outTiles.size()).isEqualTo(1);
     }
 
-    @Test
-    public void getTilesForIntent_shouldShowRemoteViewIfSpecified() {
-        Intent intent = new Intent();
-        Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
-        List<Tile> outTiles = new ArrayList<>();
-        List<ResolveInfo> info = new ArrayList<>();
-        ResolveInfo resolveInfo = newInfo(true, null /* category */);
-        resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view",
-                R.layout.user_preference);
-        info.add(resolveInfo);
-
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
-                .thenReturn(info);
-
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
-
-        assertThat(outTiles.size()).isEqualTo(1);
-        Tile tile = outTiles.get(0);
-        assertThat(tile.remoteViews).isNotNull();
-        assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference);
-    }
-
-    @Test
-    public void getTilesForIntent_summaryUriSpecified_shouldOverrideRemoteViewSummary()
-            throws RemoteException {
-        Intent intent = new Intent();
-        Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
-        List<Tile> outTiles = new ArrayList<>();
-        List<ResolveInfo> info = new ArrayList<>();
-        ResolveInfo resolveInfo = newInfo(true, null /* category */, null,
-                null, URI_GET_SUMMARY);
-        resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view",
-                R.layout.user_preference);
-        info.add(resolveInfo);
-
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
-                .thenReturn(info);
-
-        // Mock the content provider interaction.
-        Bundle bundle = new Bundle();
-        bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, "new summary text");
-        when(mIContentProvider.call(anyString(),
-                eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY),
-                any())).thenReturn(bundle);
-        when(mContentResolver.acquireUnstableProvider(anyString()))
-                .thenReturn(mIContentProvider);
-        when(mContentResolver.acquireUnstableProvider(any(Uri.class)))
-                .thenReturn(mIContentProvider);
-
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
-
-        assertThat(outTiles.size()).isEqualTo(1);
-        Tile tile = outTiles.get(0);
-        assertThat(tile.remoteViews).isNotNull();
-        assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference);
-        // Make sure the summary TextView got a new text string.
-        TileUtilsShadowRemoteViews shadowRemoteViews = extract(tile.remoteViews);
-        assertThat(shadowRemoteViews.overrideViewId).isEqualTo(android.R.id.summary);
-        assertThat(shadowRemoteViews.overrideText).isEqualTo("new summary text");
-    }
-
-    @Test
-    public void getTilesForIntent_providerUnavailable_shouldNotOverrideRemoteViewSummary()
-            throws RemoteException {
-        Intent intent = new Intent();
-        Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
-        List<Tile> outTiles = new ArrayList<>();
-        List<ResolveInfo> info = new ArrayList<>();
-        ResolveInfo resolveInfo = newInfo(true, null /* category */, null,
-                null, URI_GET_SUMMARY);
-        resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view",
-                R.layout.user_preference);
-        info.add(resolveInfo);
-
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
-                .thenReturn(info);
-
-        // Mock the content provider interaction.
-        Bundle bundle = new Bundle();
-        bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, "new summary text");
-        when(mIContentProvider.call(anyString(),
-                eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY),
-                any())).thenReturn(bundle);
-
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */, true /* forceTintExternalIcon */);
-
-        assertThat(outTiles.size()).isEqualTo(1);
-        Tile tile = outTiles.get(0);
-        assertThat(tile.remoteViews).isNotNull();
-        assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference);
-        // Make sure the summary TextView didn't get any text view updates.
-        TileUtilsShadowRemoteViews shadowRemoteViews = extract(tile.remoteViews);
-        assertThat(shadowRemoteViews.overrideViewId).isNull();
-        assertThat(shadowRemoteViews.overrideText).isNull();
-    }
-
     public static ResolveInfo newInfo(boolean systemApp, String category) {
         return newInfo(systemApp, category, null);
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java
deleted file mode 100644
index d05bcfd..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.suggestions;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.robolectric.RuntimeEnvironment.application;
-import static org.robolectric.shadow.api.Shadow.extract;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.ResolveInfo;
-import android.os.Bundle;
-import android.preference.PreferenceManager;
-
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.drawer.Tile;
-import com.android.settingslib.drawer.TileUtilsTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.shadows.ShadowPackageManager;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-@RunWith(SettingsLibRobolectricTestRunner.class)
-public class SuggestionParserTest {
-
-    private ShadowPackageManager mPackageManager;
-    private SuggestionParser mSuggestionParser;
-    private SuggestionCategory mMultipleCategory;
-    private SuggestionCategory mExclusiveCategory;
-    private SuggestionCategory mExpiredExclusiveCategory;
-    private List<Tile> mSuggestionsBeforeDismiss;
-    private List<Tile> mSuggestionsAfterDismiss;
-    private SharedPreferences mPrefs;
-    private Tile mSuggestion;
-
-    @Before
-    public void setUp() {
-        mPackageManager = extract(application.getPackageManager());
-        mPrefs = PreferenceManager.getDefaultSharedPreferences(application);
-        mSuggestion = new Tile();
-        mSuggestion.intent = new Intent("action");
-        mSuggestion.intent.setComponent(new ComponentName("pkg", "cls"));
-        mSuggestion.metaData = new Bundle();
-        mMultipleCategory = new SuggestionCategory();
-        mMultipleCategory.category = "category1";
-        mMultipleCategory.multiple = true;
-        mExclusiveCategory = new SuggestionCategory();
-        mExclusiveCategory.category = "category2";
-        mExclusiveCategory.exclusive = true;
-        mExpiredExclusiveCategory = new SuggestionCategory();
-        mExpiredExclusiveCategory.category = "category3";
-        mExpiredExclusiveCategory.exclusive = true;
-        mExpiredExclusiveCategory.exclusiveExpireDaysInMillis = 0;
-
-        mSuggestionParser = new SuggestionParser(application, mPrefs,
-                Arrays.asList(mMultipleCategory, mExclusiveCategory, mExpiredExclusiveCategory),
-                "0");
-
-        ResolveInfo info1 = TileUtilsTest.newInfo(true, null);
-        info1.activityInfo.packageName = "pkg";
-        ResolveInfo infoDupe1 = TileUtilsTest.newInfo(true, null);
-        infoDupe1.activityInfo.packageName = "pkg";
-
-        ResolveInfo info2 = TileUtilsTest.newInfo(true, null);
-        info2.activityInfo.packageName = "pkg2";
-        ResolveInfo info3 = TileUtilsTest.newInfo(true, null);
-        info3.activityInfo.packageName = "pkg3";
-        ResolveInfo info4 = TileUtilsTest.newInfo(true, null);
-        info4.activityInfo.packageName = "pkg4";
-
-        Intent intent1 = new Intent(Intent.ACTION_MAIN).addCategory("category1");
-        Intent intent2 = new Intent(Intent.ACTION_MAIN).addCategory("category2");
-        Intent intent3 = new Intent(Intent.ACTION_MAIN).addCategory("category3");
-
-        mPackageManager.addResolveInfoForIntent(intent1, info1);
-        mPackageManager.addResolveInfoForIntent(intent1, info2);
-        mPackageManager.addResolveInfoForIntent(intent1, infoDupe1);
-        mPackageManager.addResolveInfoForIntent(intent2, info3);
-        mPackageManager.addResolveInfoForIntent(intent3, info4);
-    }
-
-    @Test
-    public void dismissSuggestion_shouldDismiss() {
-        assertThat(mSuggestionParser.dismissSuggestion(mSuggestion)).isTrue();
-    }
-
-    @Test
-    public void testGetSuggestions_withoutSmartSuggestions_shouldDismiss() {
-        readAndDismissSuggestion(false);
-        mSuggestionParser.readSuggestions(mMultipleCategory, mSuggestionsAfterDismiss, false);
-        assertThat(mSuggestionsBeforeDismiss).hasSize(2);
-        assertThat(mSuggestionsAfterDismiss).hasSize(1);
-        assertThat(mSuggestionsBeforeDismiss.get(1)).isEqualTo(mSuggestionsAfterDismiss.get(0));
-    }
-
-    @Test
-    public void testGetSuggestions_withSmartSuggestions_shouldDismiss() {
-        readAndDismissSuggestion(true);
-        assertThat(mSuggestionsBeforeDismiss).hasSize(2);
-        assertThat(mSuggestionsAfterDismiss).hasSize(1);
-    }
-
-    @Test
-    public void testGetSuggestion_exclusiveNotAvailable_onlyRegularCategoryAndNoDupe() {
-        mPackageManager.removeResolveInfosForIntent(
-                new Intent(Intent.ACTION_MAIN).addCategory("category2"),
-                "pkg3");
-        mPackageManager.removeResolveInfosForIntent(
-                new Intent(Intent.ACTION_MAIN).addCategory("category3"),
-                "pkg4");
-
-        // If exclusive item is not available, the other categories should be shown
-        final SuggestionList sl =
-                mSuggestionParser.getSuggestions(false /* isSmartSuggestionEnabled */);
-        final List<Tile> suggestions = sl.getSuggestions();
-        assertThat(suggestions).hasSize(2);
-
-        assertThat(suggestions.get(0).intent.getComponent().getPackageName()).isEqualTo("pkg");
-        assertThat(suggestions.get(1).intent.getComponent().getPackageName()).isEqualTo("pkg2");
-    }
-
-    @Test
-    public void testGetSuggestion_exclusiveExpiredAvailable_shouldLoadWithRegularCategory() {
-        // First remove permanent exclusive
-        mPackageManager.removeResolveInfosForIntent(
-                new Intent(Intent.ACTION_MAIN).addCategory("category2"),
-                "pkg3");
-        // Set the other exclusive to be expired.
-        mPrefs.edit()
-                .putLong(mExpiredExclusiveCategory.category + "_setup_time",
-                        System.currentTimeMillis() - 1000)
-                .commit();
-
-        // If exclusive is expired, they should be shown together with the other categories
-        final SuggestionList sl =
-                mSuggestionParser.getSuggestions(true /* isSmartSuggestionEnabled */);
-        final List<Tile> suggestions = sl.getSuggestions();
-
-        assertThat(suggestions).hasSize(3);
-    }
-
-    @Test
-    public void testGetSuggestions_exclusive() {
-        final SuggestionList sl =
-                mSuggestionParser.getSuggestions(false /* isSmartSuggestionEnabled */);
-        final List<Tile> suggestions = sl.getSuggestions();
-
-        assertThat(suggestions).hasSize(1);
-    }
-
-    @Test
-    public void isSuggestionDismissed_dismissedSuggestion_shouldReturnTrue() {
-        final Tile suggestion = new Tile();
-        suggestion.metaData = new Bundle();
-        suggestion.metaData.putString(SuggestionParser.META_DATA_DISMISS_CONTROL, "1,2,3");
-        suggestion.intent = new Intent().setComponent(new ComponentName("pkg", "cls"));
-
-        // Dismiss suggestion when smart suggestion is not enabled.
-        mSuggestionParser.dismissSuggestion(suggestion);
-
-        assertThat(mSuggestionParser.isDismissed(suggestion, true /* isSmartSuggestionEnabled */))
-                .isTrue();
-    }
-
-    private void readAndDismissSuggestion(boolean isSmartSuggestionEnabled) {
-        mSuggestionsBeforeDismiss = new ArrayList<>();
-        mSuggestionsAfterDismiss = new ArrayList<>();
-        mSuggestionParser.readSuggestions(
-                mMultipleCategory, mSuggestionsBeforeDismiss, isSmartSuggestionEnabled);
-
-        final Tile suggestion = mSuggestionsBeforeDismiss.get(0);
-        if (mSuggestionParser.dismissSuggestion(suggestion)) {
-            mPackageManager.removeResolveInfosForIntent(
-                    new Intent(Intent.ACTION_MAIN).addCategory(mMultipleCategory.category),
-                    suggestion.intent.getComponent().getPackageName());
-        }
-        mSuggestionParser.readSuggestions(
-                mMultipleCategory, mSuggestionsAfterDismiss, isSmartSuggestionEnabled);
-    }
-}
diff --git a/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml b/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml
index 8b56b68..42d541e3 100644
--- a/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml
@@ -58,6 +58,7 @@
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
             android:layout_gravity="center_vertical"
+            android:paddingStart="2.5dp"
             android:paddingEnd="1dp"
             android:visibility="gone" />
         <Space
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index de69c6b..eed1df0 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -55,7 +55,7 @@
     <dimen name="status_bar_left_clock_end_padding">7dp</dimen>
 
     <!-- Spacing after the wifi signals that is present if there are any icons following it. -->
-    <dimen name="status_bar_wifi_signal_spacer_width">4dp</dimen>
+    <dimen name="status_bar_wifi_signal_spacer_width">2.5dp</dimen>
 
     <!-- Spacing before the airplane mode icon if there are any icons preceding it. -->
     <dimen name="status_bar_airplane_spacer_width">4dp</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 4e060f6..d5d96fe 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -73,6 +73,7 @@
 
     private ArraySet<View> mVisibleInDoze;
     private boolean mPulsing;
+    private boolean mWasPulsing;
     private float mDarkAmount = 0;
     private int mTextColor;
     private float mWidgetPadding;
@@ -224,7 +225,8 @@
         boolean hasHeader = mKeyguardSlice.hasHeader();
         boolean smallClock = hasHeader || mPulsing;
         long duration = KeyguardSliceView.DEFAULT_ANIM_DURATION;
-        long delay = smallClock ? 0 : duration / 4;
+        long delay = smallClock || mWasPulsing ? 0 : duration / 4;
+        mWasPulsing = false;
 
         boolean shouldAnimate = mKeyguardSlice.getLayoutTransition() != null
                 && mKeyguardSlice.getLayoutTransition().isRunning();
@@ -448,6 +450,12 @@
     }
 
     public void setPulsing(boolean pulsing, boolean animate) {
+        if (mPulsing == pulsing) {
+            return;
+        }
+        if (mPulsing) {
+            mWasPulsing = true;
+        }
         mPulsing = pulsing;
         mKeyguardSlice.setPulsing(pulsing, animate);
         updateDozeVisibleViews();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index d9a1b11..075faa1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1590,6 +1590,10 @@
         }
     }
 
+    public boolean isKeyguardVisible() {
+        return mKeyguardIsVisible;
+    }
+
     /**
      * Notifies that the visibility state of Keyguard has changed.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 9a43d9e..3c8a461d 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.os.Trace;
 import android.os.UserHandle;
 import android.util.Log;
 import android.view.Display;
@@ -46,7 +45,7 @@
 public class SysuiColorExtractor extends ColorExtractor implements Dumpable {
     private static final String TAG = "SysuiColorExtractor";
     private boolean mWallpaperVisible;
-    private boolean mMediaBackdropVisible;
+    private boolean mHasBackdrop;
     // Colors to return when the wallpaper isn't visible
     private final GradientColors mWpHiddenColors;
 
@@ -165,7 +164,7 @@
                 return mWpHiddenColors;
             }
         } else {
-            if (mMediaBackdropVisible) {
+            if (mHasBackdrop) {
                 return mWpHiddenColors;
             } else {
                 return super.getColors(which, type);
@@ -181,9 +180,9 @@
         }
     }
 
-    public void setMediaBackdropVisible(boolean visible) {
-        if (mMediaBackdropVisible != visible) {
-            mMediaBackdropVisible = visible;
+    public void setHasBackdrop(boolean hasBackdrop) {
+        if (mHasBackdrop != hasBackdrop) {
+            mHasBackdrop = hasBackdrop;
             triggerColorsChanged(WallpaperManager.FLAG_LOCK);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index af88911..83db6aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -37,6 +37,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.os.Build;
+import android.os.SystemClock;
 import android.os.Bundle;
 import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
@@ -108,6 +109,7 @@
     private static final int COLORED_DIVIDER_ALPHA = 0x7B;
     private static final int MENU_VIEW_INDEX = 0;
     private static final String TAG = "ExpandableNotifRow";
+    public static final float DEFAULT_HEADER_VISIBLE_AMOUNT = 1.0f;
 
     /**
      * Listener for when {@link ExpandableNotificationRow} is laid out.
@@ -157,7 +159,7 @@
     private boolean mSensitiveHiddenInGeneral;
     private boolean mShowingPublicInitialized;
     private boolean mHideSensitiveForIntrinsicHeight;
-    private float mHeaderVisibleAmount = 1.0f;
+    private float mHeaderVisibleAmount = DEFAULT_HEADER_VISIBLE_AMOUNT;
 
     /**
      * Is this notification expanded by the system. The expansion state can be overridden by the
@@ -992,6 +994,7 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
+        mEntry.setInitializationTime(SystemClock.elapsedRealtime());
         Dependency.get(PluginManager.class).addPluginListener(this,
                 NotificationMenuRowPlugin.class, false /* Allow multiple */);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
index 39485c3..ac289d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
@@ -21,6 +21,8 @@
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Parcelable;
 import android.util.AttributeSet;
 import android.view.Display;
 import android.view.DisplayCutout;
@@ -38,6 +40,12 @@
  * The view in the statusBar that contains part of the heads-up information
  */
 public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
+    private static final String HEADS_UP_STATUS_BAR_VIEW_SUPER_PARCELABLE =
+            "heads_up_status_bar_view_super_parcelable";
+    private static final String FIRST_LAYOUT = "first_layout";
+    private static final String PUBLIC_MODE = "public_mode";
+    private static final String VISIBILITY = "visibility";
+    private static final String ALPHA = "alpha";
     private int mAbsoluteStartPadding;
     private int mEndMargin;
     private View mIconPlaceholder;
@@ -107,6 +115,39 @@
         updateMaxWidth();
     }
 
+    @Override
+    public Bundle onSaveInstanceState() {
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(HEADS_UP_STATUS_BAR_VIEW_SUPER_PARCELABLE,
+                super.onSaveInstanceState());
+        bundle.putBoolean(FIRST_LAYOUT, mFirstLayout);
+        bundle.putBoolean(PUBLIC_MODE, mPublicMode);
+        bundle.putInt(VISIBILITY, getVisibility());
+        bundle.putFloat(ALPHA, getAlpha());
+
+        return bundle;
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !(state instanceof Bundle)) {
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        Bundle bundle = (Bundle) state;
+        Parcelable superState = bundle.getParcelable(HEADS_UP_STATUS_BAR_VIEW_SUPER_PARCELABLE);
+        super.onRestoreInstanceState(superState);
+        mFirstLayout = bundle.getBoolean(FIRST_LAYOUT, true);
+        mPublicMode = bundle.getBoolean(PUBLIC_MODE, false);
+        if (bundle.containsKey(VISIBILITY)) {
+            setVisibility(bundle.getInt(VISIBILITY));
+        }
+        if (bundle.containsKey(ALPHA)) {
+            setAlpha(bundle.getFloat(ALPHA));
+        }
+    }
+
     @VisibleForTesting
     public HeadsUpStatusBarView(Context context, View iconPlaceholder, TextView textView) {
         this(context);
@@ -178,11 +219,7 @@
      * @param translationX how to translate the horizontal position
      */
     public void setPanelTranslation(float translationX) {
-        if (isLayoutRtl()) {
-            setTranslationX(translationX + mCutOutInset);
-        } else {
-            setTranslationX(translationX - mCutOutInset);
-        }
+        setTranslationX(translationX);
         updateDrawingRect();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 1a645d1..a58752c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -84,6 +84,7 @@
     public static final class Entry {
         private static final long LAUNCH_COOLDOWN = 2000;
         private static final long REMOTE_INPUT_COOLDOWN = 500;
+        private static final long INITIALIZATION_DELAY = 400;
         private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN;
         private static final int COLOR_INVALID = 1;
         public String key;
@@ -114,6 +115,9 @@
         public ArraySet<Integer> mActiveAppOps = new ArraySet<>(3);
         public CharSequence headsUpStatusBarText;
         public CharSequence headsUpStatusBarTextPublic;
+
+        private long initializationTime = -1;
+
         /**
          * Whether or not this row represents a system notification. Note that if this is
          * {@code null}, that means we were either unable to retrieve the info or have yet to
@@ -169,6 +173,11 @@
             return SystemClock.elapsedRealtime() < lastRemoteInputSent + REMOTE_INPUT_COOLDOWN;
         }
 
+        public boolean hasFinishedInitialization() {
+            return initializationTime == -1 ||
+                    SystemClock.elapsedRealtime() > initializationTime + INITIALIZATION_DELAY;
+        }
+
         /**
          * Create the icons for a notification
          * @param context the context to create the icons with
@@ -341,6 +350,12 @@
             }
             return false;
         }
+
+        public void setInitializationTime(long time) {
+            if (initializationTime == -1) {
+                initializationTime = time;
+            }
+        }
     }
 
     private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index 2fc2cdb..ade27f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.notification;
 
+import static com.android.systemui.statusbar.ExpandableNotificationRow
+        .DEFAULT_HEADER_VISIBLE_AMOUNT;
 import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
 
 import android.app.Notification;
@@ -123,6 +125,9 @@
 
         // Reinspect the notification.
         resolveHeaderViews();
+        if (row.getHeaderVisibleAmount() != DEFAULT_HEADER_VISIBLE_AMOUNT) {
+            setHeaderVisibleAmount(row.getHeaderVisibleAmount());
+        }
         updateTransformedTypes();
         addRemainingTransformTypes();
         updateCropToPaddingForImageViews();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index f7b7eeb..ea70ebb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -22,6 +22,8 @@
 import android.app.Fragment;
 import android.app.StatusBarManager;
 import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.SparseArray;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -89,7 +91,8 @@
         super.onViewCreated(view, savedInstanceState);
         mStatusBar = (PhoneStatusBarView) view;
         if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_PANEL_STATE)) {
-            mStatusBar.go(savedInstanceState.getInt(EXTRA_PANEL_STATE));
+            mStatusBar.restoreHierarchyState(
+                    savedInstanceState.getSparseParcelableArray(EXTRA_PANEL_STATE));
         }
         mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
         mDarkIconManager.setShouldLog(true);
@@ -105,7 +108,9 @@
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        outState.putInt(EXTRA_PANEL_STATE, mStatusBar.getState());
+        SparseArray<Parcelable> states = new SparseArray<>();
+        mStatusBar.saveHierarchyState(states);
+        outState.putSparseParcelableArray(EXTRA_PANEL_STATE, states);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 409a783..e1936fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.view.DisplayCutout;
 import android.view.View;
 import android.view.WindowInsets;
 
@@ -53,9 +54,12 @@
             mSetTrackingHeadsUp = this::setTrackingHeadsUp;
     private final Runnable mUpdatePanelTranslation = this::updatePanelTranslation;
     private final BiConsumer<Float, Float> mSetExpandedHeight = this::setExpandedHeight;
-    private float mExpandedHeight;
-    private boolean mIsExpanded;
-    private float mExpandFraction;
+    @VisibleForTesting
+    float mExpandedHeight;
+    @VisibleForTesting
+    boolean mIsExpanded;
+    @VisibleForTesting
+    float mExpandFraction;
     private ExpandableNotificationRow mTrackedChild;
     private boolean mShown;
     private final View.OnLayoutChangeListener mStackScrollLayoutChangeListener =
@@ -99,6 +103,20 @@
         mClockView = clockView;
         mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
         mDarkIconDispatcher.addDarkReceiver(this);
+
+        mHeadsUpStatusBarView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                if (shouldBeVisible()) {
+                    updateTopEntry();
+
+                    // trigger scroller to notify the latest panel translation
+                    mStackScroller.requestLayout();
+                }
+                mHeadsUpStatusBarView.removeOnLayoutChangeListener(this);
+            }
+        });
     }
 
 
@@ -159,8 +177,15 @@
         }
 
         WindowInsets windowInset = mStackScroller.getRootWindowInsets();
-        return windowInset.getSystemWindowInsetLeft() + mStackScroller.getRight()
-                + windowInset.getSystemWindowInsetRight() - realDisplaySize;
+        DisplayCutout cutout = (windowInset != null) ? windowInset.getDisplayCutout() : null;
+        int sysWinLeft = (windowInset != null) ? windowInset.getStableInsetLeft() : 0;
+        int sysWinRight = (windowInset != null) ? windowInset.getStableInsetRight() : 0;
+        int cutoutLeft = (cutout != null) ? cutout.getSafeInsetLeft() : 0;
+        int cutoutRight = (cutout != null) ? cutout.getSafeInsetRight() : 0;
+        int leftInset = Math.max(sysWinLeft, cutoutLeft);
+        int rightInset = Math.max(sysWinRight, cutoutRight);
+
+        return leftInset + mStackScroller.getRight() + rightInset - realDisplaySize;
     }
 
     public void updatePanelTranslation() {
@@ -293,4 +318,13 @@
         mHeadsUpStatusBarView.setPublicMode(publicMode);
         updateTopEntry();
     }
+
+    void readFrom(HeadsUpAppearanceController oldController) {
+        if (oldController != null) {
+            mTrackedChild = oldController.mTrackedChild;
+            mExpandedHeight = oldController.mExpandedHeight;
+            mIsExpanded = oldController.mIsExpanded;
+            mExpandFraction = oldController.mExpandFraction;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 46d9827..e2f3319 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -367,10 +367,10 @@
         }
     }
 
-    private void startFinishingCircleAnimation(float velocity, Runnable mAnimationEndRunnable,
+    private void startFinishingCircleAnimation(float velocity, Runnable animationEndRunnable,
             boolean right) {
         KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon;
-        targetView.finishAnimation(velocity, mAnimationEndRunnable);
+        targetView.finishAnimation(velocity, animationEndRunnable);
     }
 
     private void setTranslation(float translation, boolean isReset, boolean animateReset) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 3ad207a..165b9b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2738,13 +2738,14 @@
 
     public void setPulsing(boolean pulsing) {
         mPulsing = pulsing;
-        final boolean canAnimatePulse =
-                !DozeParameters.getInstance(mContext).getDisplayNeedsBlanking();
-        if (canAnimatePulse) {
+        DozeParameters dozeParameters = DozeParameters.getInstance(mContext);
+        final boolean animatePulse = !dozeParameters.getDisplayNeedsBlanking()
+                && dozeParameters.getAlwaysOn();
+        if (animatePulse) {
             mAnimateNextPositionUpdate = true;
         }
-        mNotificationStackScroller.setPulsing(pulsing, canAnimatePulse);
-        mKeyguardStatusView.setPulsing(pulsing, canAnimatePulse);
+        mNotificationStackScroller.setPulsing(pulsing, animatePulse);
+        mKeyguardStatusView.setPulsing(pulsing, animatePulse);
     }
 
     public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index c4d7e72..18bc4e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -17,6 +17,8 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
+import android.os.Bundle;
+import android.os.Parcelable;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.MotionEvent;
@@ -27,6 +29,8 @@
     public static final boolean DEBUG = false;
     public static final String TAG = PanelBar.class.getSimpleName();
     private static final boolean SPEW = false;
+    private static final String PANEL_BAR_SUPER_PARCELABLE = "panel_bar_super_parcelable";
+    private static final String STATE = "state";
     private boolean mBouncerShowing;
     private boolean mExpanded;
 
@@ -48,8 +52,26 @@
         mState = state;
     }
 
-    public int getState() {
-        return mState;
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(PANEL_BAR_SUPER_PARCELABLE, super.onSaveInstanceState());
+        bundle.putInt(STATE, mState);
+        return bundle;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !(state instanceof Bundle)) {
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        Bundle bundle = (Bundle) state;
+        super.onRestoreInstanceState(bundle.getParcelable(PANEL_BAR_SUPER_PARCELABLE));
+        if (((Bundle) state).containsKey(STATE)) {
+            go(bundle.getInt(STATE, STATE_CLOSED));
+        }
     }
 
     public PanelBar(Context context, AttributeSet attrs) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 5477f88..075883a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -331,30 +331,25 @@
         // or letterboxing from the right or left sides.
 
         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
-        if (mDisplayCutout == null) {
+        if (mDisplayCutout == null || mDisplayCutout.isEmpty()
+                || mLastOrientation != ORIENTATION_PORTRAIT || cornerCutoutMargins == null) {
             lp.leftMargin = 0;
             lp.rightMargin = 0;
             return;
         }
 
-        lp.leftMargin = mDisplayCutout.getSafeInsetLeft();
-        lp.rightMargin = mDisplayCutout.getSafeInsetRight();
+        lp.leftMargin = Math.max(lp.leftMargin, cornerCutoutMargins.first);
+        lp.rightMargin = Math.max(lp.rightMargin, cornerCutoutMargins.second);
 
-        if (cornerCutoutMargins != null) {
-            lp.leftMargin = Math.max(lp.leftMargin, cornerCutoutMargins.first);
-            lp.rightMargin = Math.max(lp.rightMargin, cornerCutoutMargins.second);
-
-            // If we're already inset enough (e.g. on the status bar side), we can have 0 margin
-            WindowInsets insets = getRootWindowInsets();
-            int leftInset = insets.getSystemWindowInsetLeft();
-            int rightInset = insets.getSystemWindowInsetRight();
-            if (lp.leftMargin <= leftInset) {
-                lp.leftMargin = 0;
-            }
-            if (lp.rightMargin <= rightInset) {
-                lp.rightMargin = 0;
-            }
-
+        // If we're already inset enough (e.g. on the status bar side), we can have 0 margin
+        WindowInsets insets = getRootWindowInsets();
+        int leftInset = insets.getSystemWindowInsetLeft();
+        int rightInset = insets.getSystemWindowInsetRight();
+        if (lp.leftMargin <= leftInset) {
+            lp.leftMargin = 0;
+        }
+        if (lp.rightMargin <= rightInset) {
+            lp.rightMargin = 0;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index de499d6..fe141661 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -29,9 +29,7 @@
 import android.os.Trace;
 import android.util.Log;
 import android.util.MathUtils;
-import android.view.Choreographer;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
@@ -43,12 +41,11 @@
 import com.android.internal.graphics.ColorUtils;
 import com.android.internal.util.function.TriConsumer;
 import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.stack.ViewState;
 import com.android.systemui.util.AlarmTimeout;
@@ -482,21 +479,13 @@
         // Make sure we have the right gradients and their opacities will satisfy GAR.
         if (mNeedsDrawableColorUpdate) {
             mNeedsDrawableColorUpdate = false;
-            final GradientColors currentScrimColors;
-            if (mState == ScrimState.KEYGUARD || mState == ScrimState.BOUNCER_SCRIMMED
-                    || mState == ScrimState.BOUNCER) {
-                // Always animate color changes if we're seeing the keyguard
-                mScrimInFront.setColors(mLockColors, true /* animated */);
-                mScrimBehind.setColors(mLockColors, true /* animated */);
-                currentScrimColors = mLockColors;
-            } else {
-                // Only animate scrim color if the scrim view is actually visible
-                boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0;
-                boolean animateScrimBehind = mScrimBehind.getViewAlpha() != 0;
-                mScrimInFront.setColors(mSystemColors, animateScrimInFront);
-                mScrimBehind.setColors(mSystemColors, animateScrimBehind);
-                currentScrimColors = mSystemColors;
-            }
+            boolean isKeyguard = mKeyguardUpdateMonitor.isKeyguardVisible() && !mKeyguardOccluded;
+            GradientColors currentScrimColors = isKeyguard ? mLockColors : mSystemColors;
+            // Only animate scrim color if the scrim view is actually visible
+            boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0 && !mBlankScreen;
+            boolean animateScrimBehind = mScrimBehind.getViewAlpha() != 0 && !mBlankScreen;
+            mScrimInFront.setColors(currentScrimColors, animateScrimInFront);
+            mScrimBehind.setColors(currentScrimColors, animateScrimBehind);
 
             // Calculate minimum scrim opacity for white or black text.
             int textColor = currentScrimColors.supportsDarkText() ? Color.BLACK : Color.WHITE;
@@ -899,6 +888,13 @@
         updateScrims();
     }
 
+    public void setHasBackdrop(boolean hasBackdrop) {
+        ScrimState[] states = ScrimState.values();
+        for (int i = 0; i < states.length; i++) {
+            states[i].setHasBackdrop(hasBackdrop);
+        }
+    }
+
     public interface Callback {
         default void onStart() {
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 713356b..ec6ada4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -20,7 +20,6 @@
 import android.os.Trace;
 import android.util.MathUtils;
 
-import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
@@ -106,8 +105,7 @@
         public void prepare(ScrimState previousState) {
             final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
             mBlankScreen = mDisplayRequiresBlanking;
-            mCurrentBehindAlpha = mWallpaperSupportsAmbientMode
-                    && !mKeyguardUpdateMonitor.hasLockscreenWallpaper() ? 0f : 1f;
+            mCurrentBehindAlpha = mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
             mCurrentInFrontAlpha = alwaysOnEnabled ? mAodFrontScrimAlpha : 1f;
             mCurrentInFrontTint = Color.BLACK;
             mCurrentBehindTint = Color.BLACK;
@@ -131,8 +129,7 @@
         public void prepare(ScrimState previousState) {
             mCurrentInFrontAlpha = 0;
             mCurrentInFrontTint = Color.BLACK;
-            mCurrentBehindAlpha = mWallpaperSupportsAmbientMode
-                    && !mKeyguardUpdateMonitor.hasLockscreenWallpaper() ? 0f : 1f;
+            mCurrentBehindAlpha = mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
             mCurrentBehindTint = Color.BLACK;
             mBlankScreen = mDisplayRequiresBlanking;
         }
@@ -178,8 +175,8 @@
     DozeParameters mDozeParameters;
     boolean mDisplayRequiresBlanking;
     boolean mWallpaperSupportsAmbientMode;
-    KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     int mIndex;
+    boolean mHasBackdrop;
 
     ScrimState(int index) {
         mIndex = index;
@@ -190,7 +187,6 @@
         mScrimBehind = scrimBehind;
         mDozeParameters = dozeParameters;
         mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking();
-        mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(scrimInFront.getContext());
     }
 
     public void prepare(ScrimState previousState) {
@@ -256,4 +252,8 @@
     public boolean isLowPowerState() {
         return false;
     }
+
+    public void setHasBackdrop(boolean hasBackdrop) {
+        mHasBackdrop = hasBackdrop;
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index a7d27c5..4e984e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -843,13 +843,27 @@
                     mStatusBarView.setBar(this);
                     mStatusBarView.setPanel(mNotificationPanel);
                     mStatusBarView.setScrimController(mScrimController);
+
+                    // CollapsedStatusBarFragment re-inflated PhoneStatusBarView and both of
+                    // mStatusBarView.mExpanded and mStatusBarView.mBouncerShowing are false.
+                    // PhoneStatusBarView's new instance will set to be gone in
+                    // PanelBar.updateVisibility after calling mStatusBarView.setBouncerShowing
+                    // that will trigger PanelBar.updateVisibility. If there is a heads up showing,
+                    // it needs to notify PhoneStatusBarView's new instance to update the correct
+                    // status by calling mNotificationPanel.notifyBarPanelExpansionChanged().
+                    if (mHeadsUpManager.hasPinnedHeadsUp()) {
+                        mNotificationPanel.notifyBarPanelExpansionChanged();
+                    }
                     mStatusBarView.setBouncerShowing(mBouncerShowing);
+
+                    HeadsUpAppearanceController oldController = mHeadsUpAppearanceController;
                     if (mHeadsUpAppearanceController != null) {
                         // This view is being recreated, let's destroy the old one
                         mHeadsUpAppearanceController.destroy();
                     }
                     mHeadsUpAppearanceController = new HeadsUpAppearanceController(
                             mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow);
+                    mHeadsUpAppearanceController.readFrom(oldController);
                     setAreThereNotifications();
                     checkBarModes();
                 }).getFragmentManager()
@@ -1656,8 +1670,12 @@
                 && mStatusBarKeyguardViewManager.isOccluded();
 
         final boolean hasArtwork = artworkDrawable != null;
+        mColorExtractor.setHasBackdrop(hasArtwork);
+        if (mScrimController != null) {
+            mScrimController.setHasBackdrop(hasArtwork);
+        }
 
-        if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) && !mDozing
+        if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK)
                 && (mState != StatusBarState.SHADE || allowWhenShade)
                 && mFingerprintUnlockController.getMode()
                         != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
@@ -1673,7 +1691,6 @@
                     mBackdrop.setAlpha(1f);
                 }
                 mStatusBarWindowManager.setBackdropShowing(true);
-                mColorExtractor.setMediaBackdropVisible(true);
                 metaDataChanged = true;
                 if (DEBUG_MEDIA) {
                     Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork");
@@ -1725,7 +1742,6 @@
                 if (DEBUG_MEDIA) {
                     Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
                 }
-                mColorExtractor.setMediaBackdropVisible(false);
                 boolean cannotAnimateDoze = mDozing && !ScrimState.AOD.getAnimateChange();
                 if (mFingerprintUnlockController.getMode()
                         == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
@@ -3857,7 +3873,7 @@
      * Switches theme from light to dark and vice-versa.
      */
     protected void updateTheme() {
-        final boolean inflated = mStackScroller != null;
+        final boolean inflated = mStackScroller != null && mStatusBarWindowManager != null;
 
         // The system wallpaper defines if QS should be light or dark.
         WallpaperColors systemColors = mColorExtractor
@@ -4738,10 +4754,8 @@
             // Bouncer needs the front scrim when it's on top of an activity,
             // tapping on a notification, editing QS or being dismissed by
             // FLAG_DISMISS_KEYGUARD_ACTIVITY.
-            ScrimState state = mIsOccluded || mStatusBarKeyguardViewManager.bouncerNeedsScrimming()
-                    || mStatusBarKeyguardViewManager.willDismissWithAction()
-                    || mStatusBarKeyguardViewManager.isFullscreenBouncer() ?
-                    ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
+            ScrimState state = mStatusBarKeyguardViewManager.bouncerNeedsScrimming()
+                    ? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
             mScrimController.transitionTo(state);
         } else if (mLaunchCameraOnScreenTurningOn || isInLaunchTransition()) {
             mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 914bba2..affc424 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -170,8 +170,7 @@
         // • Full-screen user switcher is displayed.
         if (mNotificationPanelView.isUnlockHintRunning()) {
             mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
-        } else if (mOccluded || mBouncer.willDismissWithAction() || mBouncer.isShowingScrimmed()
-                || mStatusBar.isFullScreenUserSwitcherState()) {
+        } else if (bouncerNeedsScrimming()) {
             mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
         } else if (mShowing && !mDozing) {
             if (!isWakeAndUnlocking() && !mStatusBar.isInLaunchTransition()) {
@@ -731,12 +730,9 @@
         }
     }
 
-    public boolean willDismissWithAction() {
-        return mBouncer.willDismissWithAction();
-    }
-
     public boolean bouncerNeedsScrimming() {
-        return mBouncer.isShowingScrimmed();
+        return mOccluded || mBouncer.willDismissWithAction()  || mBouncer.needsFullscreenBouncer()
+                || mStatusBar.isFullScreenUserSwitcherState() || mBouncer.isShowingScrimmed();
     }
 
     public void dump(PrintWriter pw) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 0390f60..237ca25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -37,6 +37,7 @@
 import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.view.ActionMode;
+import android.view.DisplayCutout;
 import android.view.InputDevice;
 import android.view.InputQueue;
 import android.view.KeyEvent;
@@ -118,10 +119,21 @@
             boolean paddingChanged = insets.top != getPaddingTop()
                     || insets.bottom != getPaddingBottom();
 
+            int rightCutout = 0;
+            int leftCutout = 0;
+            DisplayCutout displayCutout = getRootWindowInsets().getDisplayCutout();
+            if (displayCutout != null) {
+                leftCutout = displayCutout.getSafeInsetLeft();
+                rightCutout = displayCutout.getSafeInsetRight();
+            }
+
+            int targetLeft = Math.max(insets.left, leftCutout);
+            int targetRight = Math.max(insets.right, rightCutout);
+
             // Super-special right inset handling, because scrims and backdrop need to ignore it.
-            if (insets.right != mRightInset || insets.left != mLeftInset) {
-                mRightInset = insets.right;
-                mLeftInset = insets.left;
+            if (targetRight != mRightInset || targetLeft != mLeftInset) {
+                mRightInset = targetRight;
+                mLeftInset = targetLeft;
                 applyMargins();
             }
             // Drop top inset, and pass through bottom inset.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 9aa8044..8517d90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -25,6 +25,7 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Parcelable;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.text.Spannable;
@@ -65,6 +66,12 @@
         DarkReceiver, ConfigurationListener {
 
     public static final String CLOCK_SECONDS = "clock_seconds";
+    private static final String CLOCK_SUPER_PARCELABLE = "clock_super_parcelable";
+    private static final String CURRENT_USER_ID = "current_user_id";
+    private static final String VISIBLE_BY_POLICY = "visible_by_policy";
+    private static final String VISIBLE_BY_USER = "visible_by_user";
+    private static final String SHOW_SECONDS = "show_seconds";
+    private static final String VISIBILITY = "visibility";
 
     private final CurrentUserTracker mCurrentUserTracker;
     private int mCurrentUserId;
@@ -129,6 +136,40 @@
     }
 
     @Override
+    public Parcelable onSaveInstanceState() {
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(CLOCK_SUPER_PARCELABLE, super.onSaveInstanceState());
+        bundle.putInt(CURRENT_USER_ID, mCurrentUserId);
+        bundle.putBoolean(VISIBLE_BY_POLICY, mClockVisibleByPolicy);
+        bundle.putBoolean(VISIBLE_BY_USER, mClockVisibleByUser);
+        bundle.putBoolean(SHOW_SECONDS, mShowSeconds);
+        bundle.putInt(VISIBILITY, getVisibility());
+
+        return bundle;
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !(state instanceof Bundle)) {
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        Bundle bundle = (Bundle) state;
+        Parcelable superState = bundle.getParcelable(CLOCK_SUPER_PARCELABLE);
+        super.onRestoreInstanceState(superState);
+        if (bundle.containsKey(CURRENT_USER_ID)) {
+            mCurrentUserId = bundle.getInt(CURRENT_USER_ID);
+        }
+        mClockVisibleByPolicy = bundle.getBoolean(VISIBLE_BY_POLICY, true);
+        mClockVisibleByUser = bundle.getBoolean(VISIBLE_BY_USER, true);
+        mShowSeconds = bundle.getBoolean(SHOW_SECONDS, false);
+        if (bundle.containsKey(VISIBILITY)) {
+            setVisibility(bundle.getInt(VISIBILITY));
+        }
+    }
+
+    @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
index a8464b3..fd49b26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
@@ -137,6 +137,10 @@
                 // to look nice
                 customDelay = StackStateAnimator.ANIMATION_DELAY_HEADS_UP_CLICKED
                         + StackStateAnimator.ANIMATION_DELAY_HEADS_UP;
+            } else if (ev.animationType == NotificationStackScrollLayout.AnimationEvent
+                    .ANIMATION_TYPE_PULSE_APPEAR || ev.animationType ==
+                    NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_PULSE_DISAPPEAR) {
+                customDelay = StackStateAnimator.ANIMATION_DURATION_PULSE_APPEAR / 2;
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 75e527c..7bed01b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2053,11 +2053,9 @@
     }
 
     private int getScrollRange() {
-        int contentHeight = getContentHeight();
-        int scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight);
+        int scrollRange = Math.max(0, mContentHeight - mMaxLayoutHeight);
         int imeInset = getImeInset();
-        scrollRange += Math.min(imeInset, Math.max(0,
-                getContentHeight() - (getHeight() - imeInset)));
+        scrollRange += Math.min(imeInset, Math.max(0, mContentHeight - (getHeight() - imeInset)));
         return scrollRange;
     }
 
@@ -2158,10 +2156,6 @@
         return count;
     }
 
-    public int getContentHeight() {
-        return mContentHeight;
-    }
-
     private void updateContentHeight() {
         int height = 0;
         float previousPaddingRequest = mPaddingBetweenElements;
@@ -2225,7 +2219,11 @@
             }
         }
         mIntrinsicContentHeight = height;
-        mContentHeight = height + mTopPadding + mBottomMargin;
+
+        // We don't want to use the toppadding since that might be interpolated and we want
+        // to take the final value of the animation.
+        int topPadding = mAmbientState.isFullyDark() ? mDarkTopPadding : mRegularTopPadding;
+        mContentHeight = height + topPadding + mBottomMargin;
         updateScrollability();
         clampScrollPosition();
         mAmbientState.setLayoutMaxHeight(mContentHeight);
@@ -4717,10 +4715,13 @@
 
             if (currView instanceof ExpandableNotificationRow) {
                 ExpandableNotificationRow row = (ExpandableNotificationRow) currView;
-                mCurrMenuRow = row.createMenu();
-                mCurrMenuRow.setSwipeActionHelper(NotificationSwipeHelper.this);
-                mCurrMenuRow.setMenuClickListener(NotificationStackScrollLayout.this);
-                mCurrMenuRow.onTouchEvent(currView, ev, 0 /* velocity */);
+
+                if (row.getEntry().hasFinishedInitialization()) {
+                    mCurrMenuRow = row.createMenu();
+                    mCurrMenuRow.setSwipeActionHelper(NotificationSwipeHelper.this);
+                    mCurrMenuRow.setMenuClickListener(NotificationStackScrollLayout.this);
+                    mCurrMenuRow.onTouchEvent(currView, ev, 0 /* velocity */);
+                }
             }
         }
 
@@ -5067,11 +5068,13 @@
                 // ANIMATION_TYPE_PULSE_APPEAR
                 new AnimationFilter()
                         .animateAlpha()
+                        .hasDelays()
                         .animateY(),
 
                 // ANIMATION_TYPE_PULSE_DISAPPEAR
                 new AnimationFilter()
                         .animateAlpha()
+                        .hasDelays()
                         .animateY(),
         };
 
@@ -5135,10 +5138,10 @@
                 StackStateAnimator.ANIMATION_DURATION_STANDARD,
 
                 // ANIMATION_TYPE_PULSE_APPEAR
-                KeyguardSliceView.DEFAULT_ANIM_DURATION,
+                StackStateAnimator.ANIMATION_DURATION_PULSE_APPEAR,
 
                 // ANIMATION_TYPE_PULSE_DISAPPEAR
-                KeyguardSliceView.DEFAULT_ANIM_DURATION / 2,
+                StackStateAnimator.ANIMATION_DURATION_PULSE_APPEAR / 2,
         };
 
         static final int ANIMATION_TYPE_ADD = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 0d50f5a..ee006d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -178,7 +178,7 @@
             return false;
         }
         ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-        if (row.areGutsExposed()) {
+        if (row.areGutsExposed() || !row.getEntry().hasFinishedInitialization()) {
             return false;
         }
         return row.canViewBeDismissed();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index a75d40f..b83a09d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -24,6 +24,7 @@
 import android.view.ViewGroup;
 import android.view.animation.Interpolator;
 
+import com.android.keyguard.KeyguardSliceView;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -51,6 +52,8 @@
             = (int) (ANIMATION_DURATION_HEADS_UP_APPEAR
                     * HeadsUpAppearInterpolator.getFractionUntilOvershoot());
     public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 300;
+    public static final int ANIMATION_DURATION_PULSE_APPEAR =
+            KeyguardSliceView.DEFAULT_ANIM_DURATION;
     public static final int ANIMATION_DURATION_BLOCKING_HELPER_FADE = 240;
     public static final int ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING = 80;
     public static final int ANIMATION_DELAY_PER_ELEMENT_MANUAL = 32;
@@ -430,15 +433,26 @@
             } else if (event.animationType == NotificationStackScrollLayout
                     .AnimationEvent.ANIMATION_TYPE_PULSE_APPEAR) {
                 ExpandableViewState viewState = finalState.getViewStateForView(changingView);
-                mTmpState.copyFrom(viewState);
-                mTmpState.yTranslation += mPulsingAppearingTranslation;
-                mTmpState.alpha = 0;
-                mTmpState.applyToView(changingView);
+                if (viewState != null) {
+                    mTmpState.copyFrom(viewState);
+                    mTmpState.yTranslation += mPulsingAppearingTranslation;
+                    mTmpState.alpha = 0;
+                    mTmpState.applyToView(changingView);
+                }
             } else if (event.animationType == NotificationStackScrollLayout
                     .AnimationEvent.ANIMATION_TYPE_PULSE_DISAPPEAR) {
                 ExpandableViewState viewState = finalState.getViewStateForView(changingView);
-                viewState.yTranslation += mPulsingAppearingTranslation;
-                viewState.alpha = 0;
+                if (viewState != null) {
+                    viewState.alpha = 0;
+                    // We want to animate the alpha away before the view starts translating,
+                    // otherwise everything will overlap and look xtra ugly.
+                    float originalYTranslation = viewState.yTranslation;
+                    viewState.yTranslation = changingView.getTranslationY();
+                    mAnimationFilter.animateAlpha = true;
+                    mAnimationProperties.duration = ANIMATION_DURATION_PULSE_APPEAR / 2;
+                    viewState.animateTo(changingView, mAnimationProperties);
+                    viewState.yTranslation = originalYTranslation;
+                }
             } else if (event.animationType == NotificationStackScrollLayout
                     .AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR) {
                 // This item is added, initialize it's properties.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
index 8153953..13dc36d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
@@ -93,7 +93,7 @@
         SysuiColorExtractor extractor = getTestableExtractor(colors);
         simulateEvent(extractor);
         extractor.setWallpaperVisible(true);
-        extractor.setMediaBackdropVisible(true);
+        extractor.setHasBackdrop(true);
 
         ColorExtractor.GradientColors fallbackColors = extractor.getFallbackColors();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index 537bfd4..fe7bf25 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -123,6 +123,27 @@
     }
 
     @Test
+    public void testHeaderReadFromOldController() {
+        mHeadsUpAppearanceController.setExpandedHeight(1.0f, 1.0f);
+
+        HeadsUpAppearanceController newController = new HeadsUpAppearanceController(
+                mock(NotificationIconAreaController.class),
+                mHeadsUpManager,
+                mHeadsUpStatusBarView,
+                mStackScroller,
+                mPanelView,
+                new View(mContext));
+        newController.readFrom(mHeadsUpAppearanceController);
+
+        Assert.assertEquals(mHeadsUpAppearanceController.mExpandedHeight,
+                newController.mExpandedHeight, 0.0f);
+        Assert.assertEquals(mHeadsUpAppearanceController.mExpandFraction,
+                newController.mExpandFraction, 0.0f);
+        Assert.assertEquals(mHeadsUpAppearanceController.mIsExpanded,
+                newController.mIsExpanded);
+    }
+
+    @Test
     public void testDestroy() {
         reset(mHeadsUpManager);
         reset(mDarkIconDispatcher);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index e95702c..89d562a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -44,7 +44,6 @@
 
 import com.android.internal.colorextraction.ColorExtractor.GradientColors;
 import com.android.internal.util.function.TriConsumer;
-import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.util.wakelock.WakeLock;
@@ -94,6 +93,7 @@
                     mScrimInFrontColor = scrimInFrontColor;
                 },
                 visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager);
+        mScrimController.setHasBackdrop(false);
     }
 
     @Test
@@ -140,12 +140,7 @@
 
     @Test
     public void transitionToAod_withAodWallpaperAndLockScreenWallpaper() {
-        ScrimState.AOD.mKeyguardUpdateMonitor = new KeyguardUpdateMonitor(getContext()) {
-            @Override
-            public boolean hasLockscreenWallpaper() {
-                return true;
-            }
-        };
+        mScrimController.setHasBackdrop(true);
         mScrimController.setWallpaperSupportsAmbientMode(true);
         mScrimController.transitionTo(ScrimState.AOD);
         mScrimController.finishAnimationsImmediately();
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 72f11e0..a23c6d3 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -457,6 +457,8 @@
   // Identifier for experimental scoring parameter settings.
   optional string score_experiment_id = 117;
 
+  // Data on wifi radio usage
+  optional WifiRadioUsage wifi_radio_usage = 118;
 }
 
 // Information that gets logged for every WiFi connection.
@@ -1503,3 +1505,12 @@
     optional int32 count = 2;
   }
 }
+
+// Usage data for the wifi radio while device is running on battery.
+message WifiRadioUsage {
+  // Duration of log (ms)
+  optional int64 logging_duration_ms = 1;
+
+  // Total time for which the radio is awake due to scan.
+  optional int64 scan_time_ms = 2;
+}
\ No newline at end of file
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 79fd29a..48f27d8 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -993,6 +993,7 @@
         final int requestId = AutofillManager.getRequestIdFromAuthenticationId(authenticationId);
         final FillResponse authenticatedResponse = mResponses.get(requestId);
         if (authenticatedResponse == null || data == null) {
+            Slog.w(TAG, "no authenticated response");
             removeSelf();
             return;
         }
@@ -1003,6 +1004,7 @@
         if (datasetIdx != AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED) {
             final Dataset dataset = authenticatedResponse.getDatasets().get(datasetIdx);
             if (dataset == null) {
+                Slog.w(TAG, "no dataset with index " + datasetIdx + " on fill response");
                 removeSelf();
                 return;
             }
@@ -1012,7 +1014,7 @@
         final Bundle newClientState = data.getBundle(AutofillManager.EXTRA_CLIENT_STATE);
         if (sDebug) {
             Slog.d(TAG, "setAuthenticationResultLocked(): result=" + result
-                    + ", clientState=" + newClientState);
+                    + ", clientState=" + newClientState + ", authenticationId=" + authenticationId);
         }
         if (result instanceof FillResponse) {
             logAuthenticationStatusLocked(requestId, MetricsEvent.AUTOFILL_AUTHENTICATED);
@@ -1029,6 +1031,8 @@
                 authenticatedResponse.getDatasets().set(datasetIdx, dataset);
                 autoFill(requestId, datasetIdx, dataset, false);
             } else {
+                Slog.w(TAG, "invalid index (" + datasetIdx + ") for authentication id "
+                        + authenticationId);
                 logAuthenticationStatusLocked(requestId,
                         MetricsEvent.AUTOFILL_INVALID_DATASET_AUTHENTICATION);
             }
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 786d757..1167e1d 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -198,7 +198,7 @@
     @VisibleForTesting
     final SparseArray<UidState> mUidStates = new SparseArray<>();
 
-    long mLastUptime;
+    long mLastRealtime;
 
     /*
      * These are app op restrictions imposed per user from various parties.
@@ -770,7 +770,7 @@
                     } else {
                         settleTime = mConstants.BG_STATE_SETTLE_TIME;
                     }
-                    uidState.pendingStateCommitTime = SystemClock.uptimeMillis() + settleTime;
+                    uidState.pendingStateCommitTime = SystemClock.elapsedRealtime() + settleTime;
                 }
                 if (uidState.startNesting != 0) {
                     // There is some actively running operation...  need to find it
@@ -1881,11 +1881,11 @@
             mUidStates.put(uid, uidState);
         } else {
             if (uidState.pendingStateCommitTime != 0) {
-                if (uidState.pendingStateCommitTime < mLastUptime) {
+                if (uidState.pendingStateCommitTime < mLastRealtime) {
                     commitUidPendingStateLocked(uidState);
                 } else {
-                    mLastUptime = SystemClock.uptimeMillis();
-                    if (uidState.pendingStateCommitTime < mLastUptime) {
+                    mLastRealtime = SystemClock.elapsedRealtime();
+                    if (uidState.pendingStateCommitTime < mLastRealtime) {
                         commitUidPendingStateLocked(uidState);
                     }
                 }
@@ -3284,7 +3284,7 @@
                 }
                 if (uidState.pendingStateCommitTime != 0) {
                     pw.print("    pendingStateCommitTime=");
-                    TimeUtils.formatDuration(uidState.pendingStateCommitTime, nowUptime, pw);
+                    TimeUtils.formatDuration(uidState.pendingStateCommitTime, nowElapsed, pw);
                     pw.println();
                 }
                 if (uidState.startNesting != 0) {
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 732ea8d..0941bc8 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -57,8 +57,6 @@
 import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
 import android.view.textservice.SpellCheckerInfo;
 import android.view.textservice.SpellCheckerSubtype;
 
@@ -71,6 +69,7 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.function.Predicate;
 
 public class TextServicesManagerService extends ITextServicesManager.Stub {
@@ -537,52 +536,39 @@
                 && !allowImplicitlySelectedSubtype) {
             return null;
         }
-        String candidateLocale = null;
-        if (subtypeHashCode == 0) {
-            // Spell checker language settings == "auto"
-            final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
-            if (imm != null) {
-                final InputMethodSubtype currentInputMethodSubtype =
-                        imm.getCurrentInputMethodSubtype();
-                if (currentInputMethodSubtype != null) {
-                    final String localeString = currentInputMethodSubtype.getLocale();
-                    if (!TextUtils.isEmpty(localeString)) {
-                        // 1. Use keyboard locale if available in the spell checker
-                        candidateLocale = localeString;
-                    }
+
+        final int numSubtypes = sci.getSubtypeCount();
+        if (subtypeHashCode != 0) {
+            // Use the user specified spell checker subtype
+            for (int i = 0; i < numSubtypes; ++i) {
+                final SpellCheckerSubtype scs = sci.getSubtypeAt(i);
+                if (scs.hashCode() == subtypeHashCode) {
+                    return scs;
                 }
             }
-            if (candidateLocale == null) {
-                // 2. Use System locale if available in the spell checker
-                candidateLocale = systemLocale.toString();
-            }
+            return null;
         }
-        SpellCheckerSubtype candidate = null;
+
+        // subtypeHashCode == 0 means spell checker language settings is "auto"
+
+        if (systemLocale == null) {
+            return null;
+        }
+        SpellCheckerSubtype firstLanguageMatchingSubtype = null;
         for (int i = 0; i < sci.getSubtypeCount(); ++i) {
             final SpellCheckerSubtype scs = sci.getSubtypeAt(i);
-            if (subtypeHashCode == 0) {
-                final String scsLocale = scs.getLocale();
-                if (candidateLocale.equals(scsLocale)) {
-                    return scs;
-                } else if (candidate == null) {
-                    if (candidateLocale.length() >= 2 && scsLocale.length() >= 2
-                            && candidateLocale.startsWith(scsLocale)) {
-                        // Fall back to the applicable language
-                        candidate = scs;
-                    }
-                }
-            } else if (scs.hashCode() == subtypeHashCode) {
-                if (DBG) {
-                    Slog.w(TAG, "Return subtype " + scs.hashCode() + ", " + scs.getLocale());
-                }
-                // 3. Use the user specified spell check language
+            final Locale scsLocale = scs.getLocaleObject();
+            if (Objects.equals(scsLocale, systemLocale)) {
+                // Exact match wins.
                 return scs;
             }
+            if (firstLanguageMatchingSubtype == null && scsLocale != null
+                    && TextUtils.equals(systemLocale.getLanguage(), scsLocale.getLanguage())) {
+                // Remember as a fall back candidate
+                firstLanguageMatchingSubtype = scs;
+            }
         }
-        // 4. Fall back to the applicable language and return it if not null
-        // 5. Simply just return it even if it's null which means we could find no suitable
-        // spell check languages
-        return candidate;
+        return firstLanguageMatchingSubtype;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 6de43de..ee93fc8 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -140,7 +140,7 @@
                 + " to displayId=" + mDisplayId + " position=" + position);
         addStackReferenceIfNeeded(stack);
         positionChildAt(stack, position);
-        mSupervisor.mService.updateSleepIfNeededLocked();
+        mSupervisor.mService.mAm.updateSleepIfNeededLocked();
     }
 
     void removeChild(ActivityStack stack) {
@@ -148,7 +148,7 @@
                 + " from displayId=" + mDisplayId);
         mStacks.remove(stack);
         removeStackReferenceIfNeeded(stack);
-        mSupervisor.mService.updateSleepIfNeededLocked();
+        mSupervisor.mService.mAm.updateSleepIfNeededLocked();
         onStackOrderChanged();
     }
 
@@ -300,7 +300,7 @@
             }
         }
 
-        final ActivityManagerService service = mSupervisor.mService;
+        final ActivityManagerService service = mSupervisor.mService.mAm;
         if (!isWindowingModeSupported(windowingMode, service.mSupportsMultiWindow,
                 service.mSupportsSplitScreenMultiWindow, service.mSupportsFreeformWindowManagement,
                 service.mSupportsPictureInPicture, activityType)) {
@@ -536,7 +536,7 @@
         }
 
         // Make sure the windowing mode we are trying to use makes sense for what is supported.
-        final ActivityManagerService service = mSupervisor.mService;
+        final ActivityManagerService service = mSupervisor.mService.mAm;
         boolean supportsMultiWindow = service.mSupportsMultiWindow;
         boolean supportsSplitScreen = service.mSupportsSplitScreenMultiWindow;
         boolean supportsFreeform = service.mSupportsFreeformWindowManagement;
@@ -714,7 +714,7 @@
 
     boolean shouldSleep() {
         return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
-                && (mSupervisor.mService.mRunningVoice == null);
+                && (mSupervisor.mService.mAm.mRunningVoice == null);
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7417326..ac4f6ab 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -615,10 +615,7 @@
     private Installer mInstaller;
 
     /** Run all ActivityStacks through this */
-    final ActivityStackSupervisor mStackSupervisor;
-    final KeyguardController mKeyguardController;
-
-    private final ActivityStartController mActivityStartController;
+    ActivityStackSupervisor mStackSupervisor;
 
     final InstrumentationReporter mInstrumentationReporter = new InstrumentationReporter();
 
@@ -680,11 +677,6 @@
      */
     String mDeviceOwnerName;
 
-    /**
-     * The controller for all operations related to locktask.
-     */
-    private final LockTaskController mLockTaskController;
-
     final UserController mUserController;
 
     /**
@@ -741,7 +733,7 @@
 
     public boolean canShowErrorDialogs() {
         return mShowDialogs && !mSleeping && !mShuttingDown
-                && !mKeyguardController.isKeyguardOrAodShowing(DEFAULT_DISPLAY)
+                && !mActivityTaskManager.mKeyguardController.isKeyguardOrAodShowing(DEFAULT_DISPLAY)
                 && !mUserController.hasUserRestriction(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
                         mUserController.getCurrentUserId())
                 && !(UserManager.isDeviceInDemoMode(mContext)
@@ -1293,16 +1285,6 @@
      */
     final AppOpsService mAppOpsService;
 
-    /** Current sequencing integer of the configuration, for skipping old configurations. */
-    private int mConfigurationSeq;
-
-    /**
-     * Temp object used when global and/or display override configuration is updated. It is also
-     * sent to outer world instead of {@link #getGlobalConfiguration} because we don't trust
-     * anyone...
-     */
-    private Configuration mTempConfig = new Configuration();
-
     /**
      * Hardware-reported OpenGLES version.
      */
@@ -2596,15 +2578,14 @@
             mWindowManager = wm;
             mActivityTaskManager.setWindowManager(wm);
             mStackSupervisor.setWindowManager(wm);
-            mLockTaskController.setWindowManager(wm);
         }
     }
 
     public void setActivityTaskManager(ActivityTaskManagerService atm) {
         synchronized (this) {
             mActivityTaskManager = atm;
-            mStackSupervisor.setActivityTaskManager(atm);
             mActivityTaskManager.setActivityManagerService(this);
+            mStackSupervisor = mActivityTaskManager.mStackSupervisor;
         }
     }
 
@@ -2843,7 +2824,6 @@
         mContext = mInjector.getContext();
         mUiContext = null;
         GL_ES_VERSION = 0;
-        mActivityStartController = null;
         mAppErrors = null;
         mAppWarnings = null;
         mAppOpsService = mInjector.getAppOpsService(null, null);
@@ -2854,17 +2834,14 @@
         mHandler = null;
         mHandlerThread = null;
         mIntentFirewall = null;
-        mKeyguardController = null;
         mPermissionReviewRequired = false;
         mProcessCpuThread = null;
         mProcessStats = null;
         mProviderMap = null;
         mServices = null;
-        mStackSupervisor = null;
         mSystemThread = null;
         mUiHandler = injector.getUiHandler(null);
         mUserController = null;
-        mLockTaskController = null;
         mProcStartHandlerThread = null;
         mProcStartHandler = null;
         mHiddenApiBlacklist = null;
@@ -2948,16 +2925,8 @@
         }
 
         mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations"));
-        mTempConfig.setToDefaults();
-        mTempConfig.setLocales(LocaleList.getDefault());
-        mConfigurationSeq = mTempConfig.seq = 1;
-        mStackSupervisor = createStackSupervisor();
-        mStackSupervisor.onConfigurationChanged(mTempConfig);
-        mKeyguardController = mStackSupervisor.getKeyguardController();
         mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
         mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
-        mActivityStartController = new ActivityStartController(this);
-        mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mHandler);
 
         mProcessCpuThread = new Thread("CpuTracker") {
             @Override
@@ -3011,12 +2980,6 @@
 
     }
 
-    protected ActivityStackSupervisor createStackSupervisor() {
-        final ActivityStackSupervisor supervisor = new ActivityStackSupervisor(this, mHandler.getLooper());
-        supervisor.initialize();
-        return supervisor;
-    }
-
     public void setSystemServiceManager(SystemServiceManager mgr) {
         mSystemServiceManager = mgr;
     }
@@ -4405,7 +4368,7 @@
                 // For ANR debugging to verify if the user activity is the one that actually
                 // launched.
                 final String myReason = reason + ":" + userId + ":" + resolvedUserId;
-                mActivityStartController.startHomeActivity(intent, aInfo, myReason);
+                mActivityTaskManager.getActivityStartController().startHomeActivity(intent, aInfo, myReason);
             }
         } else {
             Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
@@ -6196,7 +6159,7 @@
                 ProcessList.INVALID_ADJ, callerWillRestart, true, doit, evenPersistent,
                 packageName == null ? ("stop user " + userId) : ("stop " + packageName));
 
-        didSomething |= mActivityStartController.clearPendingActivityLaunches(packageName);
+        didSomething |= mActivityTaskManager.getActivityStartController().clearPendingActivityLaunches(packageName);
 
         if (mStackSupervisor.finishDisabledPackageActivitiesLocked(
                 packageName, null, doit, evenPersistent, userId)) {
@@ -9366,7 +9329,7 @@
         synchronized (this) {
             if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Whitelisting " + userId + ":" +
                     Arrays.toString(packages));
-            mLockTaskController.updateLockTaskPackages(userId, packages);
+            mActivityTaskManager.getLockTaskController().updateLockTaskPackages(userId, packages);
         }
     }
 
@@ -10138,18 +10101,6 @@
         return AppGlobals.getPackageManager();
     }
 
-    ActivityStartController getActivityStartController() {
-        return mActivityStartController;
-    }
-
-    LockTaskController getLockTaskController() {
-        return mLockTaskController;
-    }
-
-    ClientLifecycleManager getLifecycleManager() {
-        return mActivityTaskManager.getLifecycleManager();
-    }
-
     PackageManagerInternal getPackageManagerInternalLocked() {
         if (mPackageManagerInt == null) {
             mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
@@ -10913,11 +10864,6 @@
         }
     }
 
-    /** Pokes the task persister. */
-    void notifyTaskPersisterLocked(TaskRecord task, boolean flush) {
-        mActivityTaskManager.getRecentTasks().notifyTaskPersisterLocked(task, flush);
-    }
-
     @Override
     public void notifyCleartextNetwork(int uid, byte[] firstPacket) {
         mHandler.obtainMessage(NOTIFY_CLEARTEXT_NETWORK_MSG, uid, 0, firstPacket).sendToTarget();
@@ -10947,7 +10893,7 @@
         mBatteryStatsService.shutdown();
         synchronized (this) {
             mProcessStats.shutdownLocked();
-            notifyTaskPersisterLocked(null, true);
+            mActivityTaskManager.notifyTaskPersisterLocked(null, true);
         }
 
         return timedout;
@@ -10992,7 +10938,7 @@
             final long ident = Binder.clearCallingIdentity();
             try {
                 if (mUserController.shouldConfirmCredentials(userId)) {
-                    if (mKeyguardController.isKeyguardLocked()) {
+                    if (mActivityTaskManager.mKeyguardController.isKeyguardLocked()) {
                         // Showing launcher to avoid user entering credential twice.
                         final int currentUserId = mUserController.getCurrentUserId();
                         startHomeActivityLocked(currentUserId, "notifyLockedProfile");
@@ -11034,7 +10980,7 @@
             mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
                     + APP_SWITCH_DELAY_TIME;
             mDidAppSwitch = false;
-            mActivityStartController.schedulePendingActivityLaunches(APP_SWITCH_DELAY_TIME);
+            mActivityTaskManager.getActivityStartController().schedulePendingActivityLaunches(APP_SWITCH_DELAY_TIME);
         }
     }
 
@@ -13602,7 +13548,7 @@
 
     private void dumpActivityStarterLocked(PrintWriter pw, String dumpPackage) {
         pw.println("ACTIVITY MANAGER STARTER (dumpsys activity starter)");
-        mActivityStartController.dump(pw, "", dumpPackage);
+        mActivityTaskManager.getActivityStartController().dump(pw, "", dumpPackage);
     }
 
     void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
@@ -19554,8 +19500,8 @@
     /** Update default (global) configuration and notify listeners about changes. */
     private int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,
             boolean persistent, int userId, boolean deferResume) {
-        mTempConfig.setTo(getGlobalConfiguration());
-        final int changes = mTempConfig.updateFrom(values);
+        mActivityTaskManager.mTempConfig.setTo(getGlobalConfiguration());
+        final int changes = mActivityTaskManager.mTempConfig.updateFrom(values);
         if (changes == 0) {
             // Since calling to Activity.setRequestedOrientation leads to freezing the window with
             // setting WindowManagerService.mWaitingForConfig to true, it is important that we call
@@ -19605,34 +19551,34 @@
                     locales.get(bestLocaleIndex)));
         }
 
-        mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
-        mTempConfig.seq = mConfigurationSeq;
+        mActivityTaskManager.mConfigurationSeq = Math.max(++mActivityTaskManager.mConfigurationSeq, 1);
+        mActivityTaskManager.mTempConfig.seq = mActivityTaskManager.mConfigurationSeq;
 
         // Update stored global config and notify everyone about the change.
-        mStackSupervisor.onConfigurationChanged(mTempConfig);
+        mStackSupervisor.onConfigurationChanged(mActivityTaskManager.mTempConfig);
 
-        Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig);
+        Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mActivityTaskManager.mTempConfig);
         // TODO(multi-display): Update UsageEvents#Event to include displayId.
-        mUsageStatsService.reportConfigurationChange(mTempConfig,
+        mUsageStatsService.reportConfigurationChange(mActivityTaskManager.mTempConfig,
                 mUserController.getCurrentUserId());
 
         // TODO: If our config changes, should we auto dismiss any currently showing dialogs?
-        updateShouldShowDialogsLocked(mTempConfig);
+        updateShouldShowDialogsLocked(mActivityTaskManager.mTempConfig);
 
         AttributeCache ac = AttributeCache.instance();
         if (ac != null) {
-            ac.updateConfiguration(mTempConfig);
+            ac.updateConfiguration(mActivityTaskManager.mTempConfig);
         }
 
         // Make sure all resources in our process are updated right now, so that anyone who is going
         // to retrieve resource values after we return will be sure to get the new ones. This is
         // especially important during boot, where the first config change needs to guarantee all
         // resources have that config before following boot code is executed.
-        mSystemThread.applyConfigurationToResources(mTempConfig);
+        mSystemThread.applyConfigurationToResources(mActivityTaskManager.mTempConfig);
 
         // We need another copy of global config because we're scheduling some calls instead of
         // running them in place. We need to be sure that object we send will be handled unchanged.
-        final Configuration configCopy = new Configuration(mTempConfig);
+        final Configuration configCopy = new Configuration(mActivityTaskManager.mTempConfig);
         if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
             Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
             msg.obj = configCopy;
@@ -19646,7 +19592,7 @@
                 if (app.thread != null) {
                     if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending to proc "
                             + app.processName + " new config " + configCopy);
-                    getLifecycleManager().scheduleTransaction(app.thread,
+                    mActivityTaskManager.getLifecycleManager().scheduleTransaction(app.thread,
                             ConfigurationChangeItem.obtain(configCopy));
                 }
             } catch (Exception e) {
@@ -19743,12 +19689,12 @@
 
     private int performDisplayOverrideConfigUpdate(Configuration values, boolean deferResume,
             int displayId) {
-        mTempConfig.setTo(mStackSupervisor.getDisplayOverrideConfiguration(displayId));
-        final int changes = mTempConfig.updateFrom(values);
+        mActivityTaskManager.mTempConfig.setTo(mStackSupervisor.getDisplayOverrideConfiguration(displayId));
+        final int changes = mActivityTaskManager.mTempConfig.updateFrom(values);
         if (changes != 0) {
             Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " "
-                    + mTempConfig + " for displayId=" + displayId);
-            mStackSupervisor.setDisplayOverrideConfiguration(mTempConfig, displayId);
+                    + mActivityTaskManager.mTempConfig + " for displayId=" + displayId);
+            mStackSupervisor.setDisplayOverrideConfiguration(mActivityTaskManager.mTempConfig, displayId);
 
             final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
             if (isDensityChange && displayId == DEFAULT_DISPLAY) {
@@ -19765,7 +19711,7 @@
         // ensureActivityConfiguration().
         if (mWindowManager != null) {
             final int[] resizedStacks =
-                    mWindowManager.setNewDisplayOverrideConfiguration(mTempConfig, displayId);
+                    mWindowManager.setNewDisplayOverrideConfiguration(mActivityTaskManager.mTempConfig, displayId);
             if (resizedStacks != null) {
                 for (int stackId : resizedStacks) {
                     resizeStackWithBoundsFromWindowManager(stackId, deferResume);
@@ -21807,7 +21753,8 @@
     }
 
     private final ActivityRecord resumedAppLocked() {
-        ActivityRecord act = mStackSupervisor.getResumedActivityLocked();
+        final ActivityRecord act =
+                mStackSupervisor != null ? mStackSupervisor.getResumedActivityLocked() : null;
         String pkg;
         int uid;
         if (act != null) {
@@ -21889,7 +21836,9 @@
             uidRec.reset();
         }
 
-        mStackSupervisor.rankTaskLayersIfNeeded();
+        if (mStackSupervisor != null) {
+            mStackSupervisor.rankTaskLayersIfNeeded();
+        }
 
         mAdjSeq++;
         mNewNumServiceProcs = 0;
@@ -23455,7 +23404,7 @@
                     pw.println("  Reason: " + reason);
                 }
                 pw.println();
-                mActivityStartController.dump(pw, "  ", null);
+                mActivityTaskManager.getActivityStartController().dump(pw, "  ", null);
                 pw.println();
                 pw.println("-------------------------------------------------------------------------------");
                 dumpActivitiesLocked(null /* fd */, pw, null /* args */, 0 /* opti */,
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 9e9f638..1611a38 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -185,6 +185,10 @@
 
         mWindowState = WINDOW_STATE_INVALID;
         ActivityStack stack = mSupervisor.getFocusedStack();
+        if (stack == null) {
+            return;
+        }
+
         if (stack.isActivityTypeAssistant()) {
             mWindowState = WINDOW_STATE_ASSISTANT;
             return;
@@ -407,7 +411,7 @@
     }
 
     private void checkVisibility(TaskRecord t, ActivityRecord r) {
-        synchronized (mSupervisor.mService) {
+        synchronized (mSupervisor.mService.mGlobalLock) {
 
             final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(
                     r.getWindowingMode());
@@ -663,8 +667,8 @@
 
     private ProcessRecord findProcessForActivity(ActivityRecord launchedActivity) {
         return launchedActivity != null
-                ? mSupervisor.mService.mProcessNames.get(launchedActivity.processName,
-                        launchedActivity.appInfo.uid)
+                ? mSupervisor.mService.mAm.mProcessNames.get(
+                        launchedActivity.processName, launchedActivity.appInfo.uid)
                 : null;
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index a55ffdb..0e427d6 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1098,7 +1098,7 @@
             return true;
         }
         // Allow the recents component to launch the home activity.
-        final RecentTasks recentTasks = mStackSupervisor.mService.mActivityTaskManager.getRecentTasks();
+        final RecentTasks recentTasks = mStackSupervisor.mService.getRecentTasks();
         if (recentTasks != null && recentTasks.isCallerRecents(uid)) {
             return true;
         }
@@ -2930,16 +2930,16 @@
             throw new XmlPullParserException("restoreActivity error intent=" + intent);
         }
 
-        final ActivityManagerService service = stackSupervisor.mService;
+        final ActivityTaskManagerService service = stackSupervisor.mService;
         final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
                 userId, Binder.getCallingUid());
         if (aInfo == null) {
             throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
                     " resolvedType=" + resolvedType);
         }
-        final ActivityRecord r = new ActivityRecord(service.mActivityTaskManager, null /* caller */,
+        final ActivityRecord r = new ActivityRecord(service, null /* caller */,
                 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, intent, resolvedType,
-                aInfo, service.getConfiguration(), null /* resultTo */, null /* resultWho */,
+                aInfo, service.mAm.getConfiguration(), null /* resultTo */, null /* resultWho */,
                 0 /* reqCode */, componentSpecified, false /* rootVoiceInteraction */,
                 stackSupervisor, null /* options */, null /* sourceRecord */);
 
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3869f83..6118131 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -271,7 +271,7 @@
     // the input bounds right or bottom side minus the width or height divided by this value.
     private static final int FIT_WITHIN_BOUNDS_DIVIDER = 3;
 
-    final ActivityManagerService mService;
+    final ActivityTaskManagerService mService;
     private final WindowManagerService mWindowManager;
     T mWindowContainerController;
 
@@ -391,18 +391,18 @@
                     // We don't at this point know if the activity is fullscreen,
                     // so we need to be conservative and assume it isn't.
                     Slog.w(TAG, "Activity pause timeout for " + r);
-                    synchronized (mService) {
+                    synchronized (mService.mGlobalLock) {
                         if (r.app != null) {
-                            mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
+                            mService.mAm.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
                         }
                         activityPausedLocked(r.appToken, true);
                     }
                 } break;
                 case LAUNCH_TICK_MSG: {
                     ActivityRecord r = (ActivityRecord)msg.obj;
-                    synchronized (mService) {
+                    synchronized (mService.mGlobalLock) {
                         if (r.continueLaunchTickingLocked()) {
-                            mService.logAppTooSlow(r.app, r.launchTickTime, "launching " + r);
+                            mService.mAm.logAppTooSlow(r.app, r.launchTickTime, "launching " + r);
                         }
                     }
                 } break;
@@ -411,7 +411,7 @@
                     // We don't at this point know if the activity is fullscreen,
                     // so we need to be conservative and assume it isn't.
                     Slog.w(TAG, "Activity destroy timeout for " + r);
-                    synchronized (mService) {
+                    synchronized (mService.mGlobalLock) {
                         activityDestroyedLocked(r != null ? r.appToken : null, "destroyTimeout");
                     }
                 } break;
@@ -420,7 +420,7 @@
                     // We don't at this point know if the activity is fullscreen,
                     // so we need to be conservative and assume it isn't.
                     Slog.w(TAG, "Activity stop timeout for " + r);
-                    synchronized (mService) {
+                    synchronized (mService.mGlobalLock) {
                         if (r.isInHistory()) {
                             r.activityStoppedLocked(null /* icicle */,
                                     null /* persistentState */, null /* description */);
@@ -429,12 +429,12 @@
                 } break;
                 case DESTROY_ACTIVITIES_MSG: {
                     ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
-                    synchronized (mService) {
+                    synchronized (mService.mGlobalLock) {
                         destroyActivitiesLocked(args.mOwner, args.mReason);
                     }
                 } break;
                 case TRANSLUCENT_TIMEOUT_MSG: {
-                    synchronized (mService) {
+                    synchronized (mService.mGlobalLock) {
                         notifyActivityDrawnLocked(null);
                     }
                 } break;
@@ -454,10 +454,10 @@
             int windowingMode, int activityType, boolean onTop) {
         mStackSupervisor = supervisor;
         mService = supervisor.mService;
-        mHandler = new ActivityStackHandler(mService.mHandler.getLooper());
+        mHandler = new ActivityStackHandler(supervisor.mLooper);
         mWindowManager = mService.mWindowManager;
         mStackId = stackId;
-        mCurrentUser = mService.mUserController.getCurrentUserId();
+        mCurrentUser = mService.mAm.mUserController.getCurrentUserId();
         mTmpRect2.setEmpty();
         // Set display id before setting activity and window type to make sure it won't affect
         // stacks on a wrong display.
@@ -495,7 +495,7 @@
             if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:"
                     + reason);
             setResumedActivity(record, reason + " - onActivityStateChanged");
-            mService.setResumedActivityUncheckLocked(record, reason);
+            mService.mAm.setResumedActivityUncheckLocked(record, reason);
             mStackSupervisor.mRecentTasks.add(record.getTask());
         }
     }
@@ -552,7 +552,7 @@
                 // Looks like we can't launch in split screen mode or the stack we are launching
                 // doesn't support split-screen mode, go ahead an dismiss split-screen and display a
                 // warning toast about it.
-                mService.mActivityTaskManager.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
+                mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
                 display.getSplitScreenPrimaryStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN,
                         false /* animate */, false /* showRecents */,
                         false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */);
@@ -573,7 +573,7 @@
             // Inform the user that they are starting an app that may not work correctly in
             // multi-window mode.
             final String packageName = topActivity.appInfo.packageName;
-            mService.mActivityTaskManager.getTaskChangeNotificationController().notifyActivityForcedResizable(
+            mService.getTaskChangeNotificationController().notifyActivityForcedResizable(
                     topTask.taskId, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN, packageName);
         }
 
@@ -1451,14 +1451,14 @@
 
         mStackSupervisor.getLaunchTimeTracker().stopFullyDrawnTraceIfNeeded(getWindowingMode());
 
-        mService.updateCpuStats();
+        mService.mAm.updateCpuStats();
 
         if (prev.app != null && prev.app.thread != null) {
             if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
             try {
                 EventLogTags.writeAmPauseActivity(prev.userId, System.identityHashCode(prev),
                         prev.shortComponentName, "userLeaving=" + userLeaving);
-                mService.updateUsageStats(prev, false);
+                mService.mAm.updateUsageStats(prev, false);
 
                 mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
                         PauseActivityItem.obtain(prev.finishing, userLeaving,
@@ -1478,7 +1478,7 @@
 
         // If we are not going to sleep, we want to ensure the device is
         // awake until the next activity is started.
-        if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
+        if (!uiSleeping && !mService.mAm.isSleepingOrShuttingDownLocked()) {
             mStackSupervisor.acquireLaunchWakelock();
         }
 
@@ -1621,11 +1621,11 @@
             prev.resumeKeyDispatchingLocked();
 
             if (prev.app != null && prev.cpuTimeAtResume > 0
-                    && mService.mBatteryStatsService.isOnBattery()) {
-                long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
+                    && mService.mAm.mBatteryStatsService.isOnBattery()) {
+                long diff = mService.mAm.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
                         - prev.cpuTimeAtResume;
                 if (diff > 0) {
-                    BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
+                    BatteryStatsImpl bsi = mService.mAm.mBatteryStatsService.getActiveStatistics();
                     synchronized (bsi) {
                         BatteryStatsImpl.Uid.Proc ps =
                                 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
@@ -1644,7 +1644,7 @@
         // task stack changes, because its positioning may depend on it.
         if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause
                 || getDisplay().hasPinnedStack()) {
-            mService.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskStackChanged();
+            mService.getTaskChangeNotificationController().notifyTaskStackChanged();
             mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
         }
 
@@ -2328,7 +2328,7 @@
 
     @GuardedBy("mService")
     private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
-        if (!mService.mBooting && !mService.mBooted) {
+        if (!mService.mAm.mBooting && !mService.mAm.mBooted) {
             // Not ready yet!
             return false;
         }
@@ -2388,7 +2388,7 @@
         // Make sure that the user who owns this activity is started.  If not,
         // we will just leave it as is because someone should be bringing
         // another user's activities to the top of the stack.
-        if (!mService.mUserController.hasStartedUserState(next.userId)) {
+        if (!mService.mAm.mUserController.hasStartedUserState(next.userId)) {
             Slog.w(TAG, "Skipping resume of top activity " + next
                     + ": user " + next.userId + " is stopped");
             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -2452,7 +2452,7 @@
             // very soon and it would be a waste to let it get killed if it
             // happens to be sitting towards the end.
             if (next.app != null && next.app.thread != null) {
-                mService.updateLruProcessLocked(next.app, true, null);
+                mService.mAm.updateLruProcessLocked(next.app, true, null);
             }
             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
             if (lastResumed != null) {
@@ -2611,16 +2611,16 @@
                         lastStack == null ? null :lastStack.mResumedActivity;
                 final ActivityState lastState = next.getState();
 
-                mService.updateCpuStats();
+                mService.mAm.updateCpuStats();
 
                 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
                         + " (in existing)");
 
                 next.setState(RESUMED, "resumeTopActivityInnerLocked");
 
-                mService.updateLruProcessLocked(next.app, true, null);
+                mService.mAm.updateLruProcessLocked(next.app, true, null);
                 updateLRUListLocked(next);
-                mService.updateOomAdjLocked();
+                mService.mAm.updateOomAdjLocked();
 
                 // Have the window manager re-evaluate the orientation of
                 // the screen based on the new activity order.
@@ -2689,14 +2689,14 @@
                             next.shortComponentName);
 
                     next.sleeping = false;
-                    mService.getAppWarningsLocked().onResumeActivity(next);
-                    mService.showAskCompatModeDialogLocked(next);
+                    mService.mAm.getAppWarningsLocked().onResumeActivity(next);
+                    mService.mAm.showAskCompatModeDialogLocked(next);
                     next.app.pendingUiClean = true;
-                    next.app.forceProcessStateUpTo(mService.mTopProcessState);
+                    next.app.forceProcessStateUpTo(mService.mAm.mTopProcessState);
                     next.clearOptionsLocked();
                     transaction.setLifecycleStateRequest(
                             ResumeActivityItem.obtain(next.app.repProcState,
-                                    mService.mActivityTaskManager.isNextTransitionForward()));
+                                    mService.isNextTransitionForward()));
                     mService.getLifecycleManager().scheduleTransaction(transaction);
 
                     if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
@@ -3338,7 +3338,7 @@
             String resultWho, int requestCode, int resultCode, Intent data) {
 
         if (callingUid > 0) {
-            mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
+            mService.mAm.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
                     data, r.getUriPermissionsLocked(), r.userId);
         }
 
@@ -3535,7 +3535,7 @@
                 }
             }
         }
-        mService.updateOomAdjLocked();
+        mService.mAm.updateOomAdjLocked();
     }
 
     /**
@@ -3578,7 +3578,7 @@
         if (activityNdx >= 0) {
             r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx);
             if (r.isState(RESUMED, PAUSING, PAUSED)) {
-                if (!r.isActivityTypeHome() || mService.mHomeProcess != r.app) {
+                if (!r.isActivityTypeHome() || mService.mAm.mHomeProcess != r.app) {
                     Slog.w(TAG, "  Force finishing activity "
                             + r.intent.getComponent().flattenToShortString());
                     finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false);
@@ -3616,7 +3616,7 @@
                         } catch (RemoteException re) {
                             // Ok
                         }
-                        mService.finishRunningVoiceLocked();
+                        mService.mAm.finishRunningVoiceLocked();
                         break;
                     }
                 }
@@ -3624,7 +3624,7 @@
         }
 
         if (didOne) {
-            mService.updateOomAdjLocked();
+            mService.mAm.updateOomAdjLocked();
         }
     }
 
@@ -3653,12 +3653,11 @@
                 }
             }
             if (r.info.applicationInfo.uid > 0) {
-                mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
+                mService.mAm.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
                         resultTo.packageName, resultData,
                         resultTo.getUriPermissionsLocked(), resultTo.userId);
             }
-            resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
-                                     resultData);
+            resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode, resultData);
             r.resultTo = null;
         }
         else if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "No result destination from " + r);
@@ -3723,7 +3722,7 @@
                 if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                         "Prepare close transition: finishing " + r);
                 if (endTask) {
-                    mService.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskRemovalStarted(
+                    mService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
                             task.taskId);
                 }
                 mWindowManager.prepareAppTransition(transit, false);
@@ -3814,7 +3813,7 @@
                     "Moving to STOPPING: "+ r + " (finish requested)");
             r.setState(STOPPING, "finishCurrentActivityLocked");
             if (oomAdj) {
-                mService.updateOomAdjLocked();
+                mService.mAm.updateOomAdjLocked();
             }
             return r;
         }
@@ -3957,7 +3956,7 @@
             }
         }
 
-        IActivityController controller = mService.mController;
+        IActivityController controller = mService.mAm.mController;
         if (controller != null) {
             ActivityRecord next = topRunningActivityLocked(srec.appToken, 0);
             if (next != null) {
@@ -3966,7 +3965,7 @@
                 try {
                     resumeOK = controller.activityResuming(next.packageName);
                 } catch (RemoteException e) {
-                    mService.mController = null;
+                    mService.mAm.mController = null;
                     Watchdog.getInstance().setActivityController(null);
                 }
 
@@ -4075,7 +4074,7 @@
             for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
                 PendingIntentRecord rec = apr.get();
                 if (rec != null) {
-                    mService.cancelIntentSenderLocked(rec, false);
+                    mService.mAm.cancelIntentSenderLocked(rec, false);
                 }
             }
             r.pendingResults = null;
@@ -4162,7 +4161,7 @@
             Iterator<ConnectionRecord> it = r.connections.iterator();
             while (it.hasNext()) {
                 ConnectionRecord c = it.next();
-                mService.mServices.removeConnectionLocked(c, null, r);
+                mService.mAm.mServices.removeConnectionLocked(c, null, r);
             }
             r.connections = null;
         }
@@ -4294,18 +4293,18 @@
         if (hadApp) {
             if (removeFromApp) {
                 r.app.activities.remove(r);
-                if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
-                    mService.mHeavyWeightProcess = null;
-                    mService.mHandler.sendEmptyMessage(
+                if (mService.mAm.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
+                    mService.mAm.mHeavyWeightProcess = null;
+                    mService.mAm.mHandler.sendEmptyMessage(
                             ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
                 }
                 if (r.app.activities.isEmpty()) {
                     // Update any services we are bound to that might care about whether
                     // their client may have activities.
-                    mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
+                    mService.mAm.mServices.updateServiceConnectionActivitiesLocked(r.app);
                     // No longer have activities, so update LRU list and oom adj.
-                    mService.updateLruProcessLocked(r.app, false, null);
-                    mService.updateOomAdjLocked();
+                    mService.mAm.updateLruProcessLocked(r.app, false, null);
+                    mService.mAm.updateOomAdjLocked();
                 }
             }
 
@@ -4483,7 +4482,7 @@
                                     r.getTask().taskId, r.shortComponentName,
                                     "proc died without state saved");
                             if (r.getState() == RESUMED) {
-                                mService.updateUsageStats(r, false);
+                                mService.mAm.updateUsageStats(r, false);
                             }
                         }
                     } else {
@@ -4629,7 +4628,7 @@
             mStackSupervisor.resumeFocusedStackTopActivityLocked();
             EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
 
-            mService.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.taskId);
+            mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.taskId);
         } finally {
             getDisplay().continueUpdateImeTarget();
         }
@@ -4663,7 +4662,7 @@
         // If we have a watcher, preflight the move before committing to it.  First check
         // for *other* available tasks, but if none are available, then try again allowing the
         // current task to be selected.
-        if (isTopStackOnDisplay() && mService.mController != null) {
+        if (isTopStackOnDisplay() && mService.mAm.mController != null) {
             ActivityRecord next = topRunningActivityLocked(null, taskId);
             if (next == null) {
                 next = topRunningActivityLocked(null, 0);
@@ -4672,9 +4671,9 @@
                 // ask watcher if this is allowed
                 boolean moveOK = true;
                 try {
-                    moveOK = mService.mController.activityResuming(next.packageName);
+                    moveOK = mService.mAm.mController.activityResuming(next.packageName);
                 } catch (RemoteException e) {
-                    mService.mController = null;
+                    mService.mAm.mController = null;
                     Watchdog.getInstance().setActivityController(null);
                 }
                 if (!moveOK) {
@@ -4751,7 +4750,7 @@
     // TODO: Figure-out a way to consolidate with resize() method below.
     @Override
     public void requestResize(Rect bounds) {
-        mService.mActivityTaskManager.resizeStack(mStackId, bounds,
+        mService.resizeStack(mStackId, bounds,
                 true /* allowResizeInDockedMode */, false /* preserveWindows */,
                 false /* animate */, -1 /* animationDuration */);
     }
@@ -5160,7 +5159,7 @@
 
         // Notify if a task from the pinned stack is being removed (or moved depending on the mode)
         if (inPinnedWindowingMode()) {
-            mService.mActivityTaskManager.getTaskChangeNotificationController().notifyActivityUnpinned();
+            mService.getTaskChangeNotificationController().notifyActivityUnpinned();
         }
     }
 
@@ -5337,11 +5336,11 @@
             return false;
         }
 
-        return display != null ? display.isSleeping() : mService.isSleepingLocked();
+        return display != null ? display.isSleeping() : mService.mAm.isSleepingLocked();
     }
 
     boolean shouldSleepOrShutDownActivities() {
-        return shouldSleepActivities() || mService.isShuttingDownLocked();
+        return shouldSleepActivities() || mService.mAm.isShuttingDownLocked();
     }
 
     public void writeToProto(ProtoOutputStream proto, long fieldId) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index df09b4a..a77d734 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -304,7 +304,7 @@
     /** The number of distinct task ids that can be assigned to the tasks of a single user */
     private static final int MAX_TASK_IDS_PER_USER = UserHandle.PER_USER_RANGE;
 
-    ActivityManagerService mService;
+    ActivityTaskManagerService mService;
 
     /** The historial list of recent tasks including inactive tasks */
     RecentTasks mRecentTasks;
@@ -318,7 +318,6 @@
     /** Short cut */
     WindowManagerService mWindowManager;
     DisplayManager mDisplayManager;
-    ActivityTaskManagerService mAtm;
 
     private LaunchParamsController mLaunchParamsController;
 
@@ -489,7 +488,7 @@
             // No restrictions for the default display.
             return true;
         }
-        if (!mService.mSupportsMultiDisplay) {
+        if (!mService.mAm.mSupportsMultiDisplay) {
             // Can't launch on secondary displays if feature is not supported.
             return false;
         }
@@ -604,14 +603,14 @@
         }
     }
 
-    public ActivityStackSupervisor(ActivityManagerService service, Looper looper) {
+    public ActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) {
         mService = service;
         mLooper = looper;
         mHandler = new ActivityStackSupervisorHandler(looper);
     }
 
     @VisibleForTesting
-    void setService(ActivityManagerService service) {
+    void setService(ActivityTaskManagerService service) {
         mService = service;
     }
 
@@ -622,11 +621,10 @@
 
         mInitialized = true;
         mRunningTasks = createRunningTasks();
-        mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext,
-                mHandler.getLooper());
-        mKeyguardController = new KeyguardController(mService, this);
+        mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext, mHandler.getLooper());
+        mKeyguardController = new KeyguardController(mService.mAm, this);
 
-        mLaunchParamsController = new LaunchParamsController(mService);
+        mLaunchParamsController = new LaunchParamsController(mService.mAm);
         mLaunchParamsController.registerDefaultModifiers(this);
     }
 
@@ -665,10 +663,6 @@
         mLaunchingActivity.setReferenceCounted(false);
     }
 
-    void setActivityTaskManager(ActivityTaskManagerService atm) {
-        mAtm = atm;
-    }
-
     void setWindowManager(WindowManagerService wm) {
         mWindowManager = wm;
         getKeyguardController().setWindowManager(wm);
@@ -715,6 +709,11 @@
         if (!focusCandidate.isFocusable()) {
             // The focus candidate isn't focusable. Move focus to the top stack that is focusable.
             focusCandidate = getNextFocusableStackLocked(focusCandidate, false /* ignoreCurrent */);
+            if (focusCandidate == null) {
+                Slog.w(TAG,
+                        "setFocusStackUnchecked: No focusable stack found, focus home as default");
+                focusCandidate = mHomeStack;
+            }
         }
 
         if (focusCandidate != mFocusedStack) {
@@ -727,7 +726,7 @@
         }
 
         final ActivityRecord r = topRunningActivityLocked();
-        if (mService.mBooting || !mService.mBooted) {
+        if (mService.mAm.mBooting || !mService.mAm.mBooted) {
             if (r != null && r.idle) {
                 checkFinishBootingLocked();
             }
@@ -759,7 +758,7 @@
     }
 
     boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
-        if (!mService.mBooting && !mService.mBooted) {
+        if (!mService.mAm.mBooting && !mService.mAm.mBooted) {
             // Not ready yet!
             return false;
         }
@@ -773,7 +772,7 @@
             moveFocusableActivityStackToFrontLocked(r, myReason);
             return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
         }
-        return mService.startHomeActivityLocked(mCurrentUser, myReason);
+        return mService.mAm.startHomeActivityLocked(mCurrentUser, myReason);
     }
 
     TaskRecord anyTaskForIdLocked(int id) {
@@ -911,7 +910,7 @@
                         // result to an activity belonging to userId. Example case: a document
                         // picker for personal files, opened by a work app, should still get locked.
                         if (taskTopActivityIsUser(task, userId)) {
-                            mService.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskProfileLocked(
+                            mService.mAm.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskProfileLocked(
                                     task.taskId, userId);
                         }
                     }
@@ -1166,7 +1165,7 @@
             }
         }
         if (changed) {
-            mService.notifyAll();
+            mService.mAm.notifyAll();
         }
     }
 
@@ -1196,7 +1195,7 @@
         }
 
         if (changed) {
-            mService.notifyAll();
+            mService.mAm.notifyAll();
         }
     }
 
@@ -1217,7 +1216,7 @@
             }
         }
         if (changed) {
-            mService.notifyAll();
+            mService.mAm.notifyAll();
         }
     }
 
@@ -1322,19 +1321,19 @@
             // Don't debug things in the system process
             if (!aInfo.processName.equals("system")) {
                 if ((startFlags & ActivityManager.START_FLAG_DEBUG) != 0) {
-                    mService.setDebugApp(aInfo.processName, true, false);
+                    mService.mAm.setDebugApp(aInfo.processName, true, false);
                 }
 
                 if ((startFlags & ActivityManager.START_FLAG_NATIVE_DEBUGGING) != 0) {
-                    mService.setNativeDebuggingAppLocked(aInfo.applicationInfo, aInfo.processName);
+                    mService.mAm.setNativeDebuggingAppLocked(aInfo.applicationInfo, aInfo.processName);
                 }
 
                 if ((startFlags & ActivityManager.START_FLAG_TRACK_ALLOCATION) != 0) {
-                    mService.setTrackAllocationApp(aInfo.applicationInfo, aInfo.processName);
+                    mService.mAm.setTrackAllocationApp(aInfo.applicationInfo, aInfo.processName);
                 }
 
                 if (profilerInfo != null) {
-                    mService.setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo);
+                    mService.mAm.setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo);
                 }
             }
             final String intentLaunchToken = intent.getLaunchToken();
@@ -1347,7 +1346,7 @@
 
     ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags,
             int filterCallingUid) {
-        synchronized (mService) {
+        synchronized (mService.mGlobalLock) {
             try {
                 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "resolveIntent");
                 int modifiedFlags = flags
@@ -1364,7 +1363,7 @@
                 // (e.g. AMS.startActivityAsUser).
                 final long token = Binder.clearCallingIdentity();
                 try {
-                    return mService.getPackageManagerInternalLocked().resolveIntent(
+                    return mService.mAm.getPackageManagerInternalLocked().resolveIntent(
                             intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
                 } finally {
                     Binder.restoreCallingIdentity(token);
@@ -1453,8 +1452,8 @@
             if (idx < 0) {
                 app.activities.add(r);
             }
-            mService.updateLruProcessLocked(app, true, null);
-            mService.updateOomAdjLocked();
+            mService.mAm.updateLruProcessLocked(app, true, null);
+            mService.mAm.updateOomAdjLocked();
 
             final LockTaskController lockTaskController = mService.getLockTaskController();
             if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
@@ -1484,20 +1483,20 @@
                         System.identityHashCode(r), task.taskId, r.shortComponentName);
                 if (r.isActivityTypeHome()) {
                     // Home process is the root process of the task.
-                    mService.mHomeProcess = task.mActivities.get(0).app;
+                    mService.mAm.mHomeProcess = task.mActivities.get(0).app;
                 }
-                mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
+                mService.mAm.notifyPackageUse(r.intent.getComponent().getPackageName(),
                         PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
                 r.sleeping = false;
                 r.forceNewConfig = false;
-                mService.getAppWarningsLocked().onStartActivity(r);
-                mService.showAskCompatModeDialogLocked(r);
-                r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
+                mService.mAm.getAppWarningsLocked().onStartActivity(r);
+                mService.mAm.showAskCompatModeDialogLocked(r);
+                r.compat = mService.mAm.compatibilityInfoForPackageLocked(r.info.applicationInfo);
                 ProfilerInfo profilerInfo = null;
-                if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
-                    if (mService.mProfileProc == null || mService.mProfileProc == app) {
-                        mService.mProfileProc = app;
-                        ProfilerInfo profilerInfoSvc = mService.mProfilerInfo;
+                if (mService.mAm.mProfileApp != null && mService.mAm.mProfileApp.equals(app.processName)) {
+                    if (mService.mAm.mProfileProc == null || mService.mAm.mProfileProc == app) {
+                        mService.mAm.mProfileProc = app;
+                        ProfilerInfo profilerInfoSvc = mService.mAm.mProfilerInfo;
                         if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) {
                             if (profilerInfoSvc.profileFd != null) {
                                 try {
@@ -1514,13 +1513,13 @@
 
                 app.hasShownUi = true;
                 app.pendingUiClean = true;
-                app.forceProcessStateUpTo(mService.mTopProcessState);
+                app.forceProcessStateUpTo(mService.mAm.mTopProcessState);
                 // Because we could be starting an Activity in the system process this may not go
                 // across a Binder interface which would create a new Configuration. Consequently
                 // we have to always create a new Configuration here.
 
                 final MergedConfiguration mergedConfiguration = new MergedConfiguration(
-                        mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
+                        mService.mAm.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
                 r.setLastReportedConfiguration(mergedConfiguration);
 
                 logIfTransactionTooLarge(r.intent, r.icicle);
@@ -1536,13 +1535,13 @@
                         mergedConfiguration.getGlobalConfiguration(),
                         mergedConfiguration.getOverrideConfiguration(), r.compat,
                         r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
-                        r.persistentState, results, newIntents, mService.mActivityTaskManager.isNextTransitionForward(),
+                        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                         profilerInfo));
 
                 // Set desired final state.
                 final ActivityLifecycleItem lifecycleItem;
                 if (andResume) {
-                    lifecycleItem = ResumeActivityItem.obtain(mService.mActivityTaskManager.isNextTransitionForward());
+                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
                 } else {
                     lifecycleItem = PauseActivityItem.obtain();
                 }
@@ -1551,25 +1550,24 @@
                 // Schedule transaction.
                 mService.getLifecycleManager().scheduleTransaction(clientTransaction);
 
-
                 if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0
-                        && mService.mHasHeavyWeightFeature) {
+                        && mService.mAm.mHasHeavyWeightFeature) {
                     // This may be a heavy-weight process!  Note that the package
                     // manager will ensure that only activity can run in the main
                     // process of the .apk, which is the only thing that will be
                     // considered heavy-weight.
                     if (app.processName.equals(app.info.packageName)) {
-                        if (mService.mHeavyWeightProcess != null
-                                && mService.mHeavyWeightProcess != app) {
+                        if (mService.mAm.mHeavyWeightProcess != null
+                                && mService.mAm.mHeavyWeightProcess != app) {
                             Slog.w(TAG, "Starting new heavy weight process " + app
                                     + " when already running "
-                                    + mService.mHeavyWeightProcess);
+                                    + mService.mAm.mHeavyWeightProcess);
                         }
-                        mService.mHeavyWeightProcess = app;
-                        Message msg = mService.mHandler.obtainMessage(
+                        mService.mAm.mHeavyWeightProcess = app;
+                        Message msg = mService.mAm.mHandler.obtainMessage(
                                 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
                         msg.obj = r;
-                        mService.mHandler.sendMessage(msg);
+                        mService.mAm.mHandler.sendMessage(msg);
                     }
                 }
 
@@ -1580,7 +1578,7 @@
                     Slog.e(TAG, "Second failure launching "
                             + r.intent.getComponent().flattenToShortString()
                             + ", giving up", e);
-                    mService.appDiedLocked(app);
+                    mService.mAm.appDiedLocked(app);
                     stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
                             "2nd-crash", false);
                     return false;
@@ -1627,7 +1625,7 @@
         // Update any services we are bound to that might care about whether
         // their client may have activities.
         if (r.app != null) {
-            mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
+            mService.mAm.mServices.updateServiceConnectionActivitiesLocked(r.app);
         }
 
         return true;
@@ -1663,7 +1661,7 @@
         }
 
         // Update the configuration of the activities on the display.
-        return mService.updateDisplayOverrideConfigurationLocked(config, starting, deferResume,
+        return mService.mAm.updateDisplayOverrideConfigurationLocked(config, starting, deferResume,
                 displayId);
     }
 
@@ -1685,7 +1683,7 @@
     void startSpecificActivityLocked(ActivityRecord r,
             boolean andResume, boolean checkConfig) {
         // Is this activity's application already running?
-        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
+        ProcessRecord app = mService.mAm.getProcessRecordLocked(r.processName,
                 r.info.applicationInfo.uid, true);
 
         getLaunchTimeTracker().setLaunchTime(r);
@@ -1699,7 +1697,7 @@
                     // part of the framework so doesn't make sense to track as a
                     // separate apk in the process.
                     app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
-                            mService.mProcessStats);
+                            mService.mAm.mProcessStats);
                 }
                 realStartActivityLocked(r, app, andResume, checkConfig);
                 return;
@@ -1712,7 +1710,7 @@
             // restart the application.
         }
 
-        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
+        mService.mAm.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                 "activity", r.intent.getComponent(), false, false, true);
     }
 
@@ -1728,16 +1726,16 @@
                     || !resumedActivity.app.equals(targetActivity.app);
         }
 
-        if (sendHint && mService.mLocalPowerManager != null) {
-            mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
+        if (sendHint && mService.mAm.mLocalPowerManager != null) {
+            mService.mAm.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
             mPowerHintSent = true;
         }
     }
 
     void sendPowerHintForLaunchEndIfNeeded() {
         // Trigger launch power hint if activity is launched
-        if (mPowerHintSent && mService.mLocalPowerManager != null) {
-            mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
+        if (mPowerHintSent && mService.mAm.mLocalPowerManager != null) {
+            mService.mAm.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
             mPowerHintSent = false;
         }
     }
@@ -1746,9 +1744,9 @@
             String resultWho, int requestCode, int callingPid, int callingUid,
             String callingPackage, boolean ignoreTargetSecurity, boolean launchingInTask,
             ProcessRecord callerApp, ActivityRecord resultRecord, ActivityStack resultStack) {
-        final boolean isCallerRecents = mService.mActivityTaskManager.getRecentTasks() != null
-                && mService.mActivityTaskManager.getRecentTasks().isCallerRecents(callingUid);
-        final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid,
+        final boolean isCallerRecents = mService.getRecentTasks() != null
+                && mService.getRecentTasks().isCallerRecents(callingUid);
+        final int startAnyPerm = mService.mAm.checkPermission(START_ANY_ACTIVITY, callingPid,
                 callingUid);
         if (startAnyPerm == PERMISSION_GRANTED || (isCallerRecents && launchingInTask)) {
             // If the caller has START_ANY_ACTIVITY, ignore all checks below. In addition, if the
@@ -1827,7 +1825,7 @@
 
         // Check if the caller has enough privileges to embed activities and launch to private
         // displays.
-        final int startAnyPerm = mService.checkPermission(INTERNAL_SYSTEM_WINDOW, callingPid,
+        final int startAnyPerm = mService.mAm.checkPermission(INTERNAL_SYSTEM_WINDOW, callingPid,
                 callingUid);
         if (startAnyPerm == PERMISSION_GRANTED) {
             if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
@@ -1849,7 +1847,7 @@
                 return false;
             }
             // Check if the caller is allowed to embed activities from other apps.
-            if (mService.checkPermission(ACTIVITY_EMBEDDING, callingPid, callingUid)
+            if (mService.mAm.checkPermission(ACTIVITY_EMBEDDING, callingPid, callingUid)
                     == PERMISSION_DENIED && !uidPresentOnDisplay) {
                 if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
                         + " disallow activity embedding without permission.");
@@ -1907,7 +1905,7 @@
 
     private int getComponentRestrictionForCallingPackage(ActivityInfo activityInfo,
             String callingPackage, int callingPid, int callingUid, boolean ignoreTargetSecurity) {
-        if (!ignoreTargetSecurity && mService.checkComponentPermission(activityInfo.permission,
+        if (!ignoreTargetSecurity && mService.mAm.checkComponentPermission(activityInfo.permission,
                 callingPid, callingUid, activityInfo.applicationInfo.uid, activityInfo.exported)
                 == PERMISSION_DENIED) {
             return ACTIVITY_RESTRICTION_PERMISSION;
@@ -1922,7 +1920,7 @@
             return ACTIVITY_RESTRICTION_NONE;
         }
 
-        if (mService.mAppOpsService.noteOperation(opCode, callingUid,
+        if (mService.mAm.mAppOpsService.noteOperation(opCode, callingUid,
                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
             if (!ignoreTargetSecurity) {
                 return ACTIVITY_RESTRICTION_APPOP;
@@ -1956,7 +1954,7 @@
             return ACTIVITY_RESTRICTION_NONE;
         }
 
-        if (mService.checkPermission(permission, callingPid, callingUid) == PERMISSION_DENIED) {
+        if (mService.mAm.checkPermission(permission, callingPid, callingUid) == PERMISSION_DENIED) {
             return ACTIVITY_RESTRICTION_PERMISSION;
         }
 
@@ -1965,7 +1963,7 @@
             return ACTIVITY_RESTRICTION_NONE;
         }
 
-        if (mService.mAppOpsService.noteOperation(opCode, callingUid,
+        if (mService.mAm.mAppOpsService.noteOperation(opCode, callingUid,
                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
             return ACTIVITY_RESTRICTION_APPOP;
         }
@@ -1990,19 +1988,19 @@
 
     /**
      * Called when the frontmost task is idle.
-     * @return the state of mService.mBooting before this was called.
+     * @return the state of mService.mAm.mBooting before this was called.
      */
     @GuardedBy("mService")
     private boolean checkFinishBootingLocked() {
-        final boolean booting = mService.mBooting;
+        final boolean booting = mService.mAm.mBooting;
         boolean enableScreen = false;
-        mService.mBooting = false;
-        if (!mService.mBooted) {
-            mService.mBooted = true;
+        mService.mAm.mBooting = false;
+        if (!mService.mAm.mBooted) {
+            mService.mAm.mBooted = true;
             enableScreen = true;
         }
         if (booting || enableScreen) {
-            mService.postFinishBooting(booting, enableScreen);
+            mService.mAm.postFinishBooting(booting, enableScreen);
         }
         return booting;
     }
@@ -2051,7 +2049,7 @@
 
         if (allResumedActivitiesIdle()) {
             if (r != null) {
-                mService.scheduleAppGcsLocked();
+                mService.mAm.scheduleAppGcsLocked();
             }
 
             if (mLaunchingActivity.isHeld()) {
@@ -2108,12 +2106,12 @@
             // Complete user switch
             if (startingUsers != null) {
                 for (int i = 0; i < startingUsers.size(); i++) {
-                    mService.mUserController.finishUserSwitch(startingUsers.get(i));
+                    mService.mAm.mUserController.finishUserSwitch(startingUsers.get(i));
                 }
             }
         }
 
-        mService.trimApplications();
+        mService.mAm.trimApplications();
         //dump();
         //mWindowManager.dump();
 
@@ -2207,10 +2205,10 @@
         // Now set this one as the previous process, only if that really
         // makes sense to.
         if (r.app != null && fgApp != null && r.app != fgApp
-                && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
-                && r.app != mService.mHomeProcess) {
-            mService.mPreviousProcess = r.app;
-            mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
+                && r.lastVisibleTime > mService.mAm.mPreviousProcessVisibleTime
+                && r.app != mService.mAm.mHomeProcess) {
+            mService.mAm.mPreviousProcess = r.app;
+            mService.mAm.mPreviousProcessVisibleTime = r.lastVisibleTime;
         }
     }
 
@@ -2349,9 +2347,9 @@
         if (options == null || options.getLaunchBounds() == null) {
             return false;
         }
-        return (mService.mSupportsPictureInPicture
+        return (mService.mAm.mSupportsPictureInPicture
                 && options.getLaunchWindowingMode() == WINDOWING_MODE_PINNED)
-                || mService.mSupportsFreeformWindowManagement;
+                || mService.mAm.mSupportsFreeformWindowManagement;
     }
 
     LaunchParamsController getLaunchParamsController() {
@@ -3098,7 +3096,7 @@
         }
 
         // Find any running services associated with this app and stop if needed.
-        mService.mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent()));
+        mService.mAm.mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent()));
 
         if (!killProcess) {
             return;
@@ -3107,7 +3105,7 @@
         // Determine if the process(es) for this task should be killed.
         final String pkg = component.getPackageName();
         ArrayList<ProcessRecord> procsToKill = new ArrayList<>();
-        ArrayMap<String, SparseArray<ProcessRecord>> pmap = mService.mProcessNames.getMap();
+        ArrayMap<String, SparseArray<ProcessRecord>> pmap = mService.mAm.mProcessNames.getMap();
         for (int i = 0; i < pmap.size(); i++) {
 
             SparseArray<ProcessRecord> uids = pmap.valueAt(i);
@@ -3117,7 +3115,7 @@
                     // Don't kill process for a different user.
                     continue;
                 }
-                if (proc == mService.mHomeProcess) {
+                if (proc == mService.mAm.mHomeProcess) {
                     // Don't kill the home process along with tasks from the same package.
                     continue;
                 }
@@ -3260,21 +3258,21 @@
 
         // Ensure that we aren't trying to move into a multi-window stack without multi-window
         // support
-        if (inMultiWindowMode && !mService.mSupportsMultiWindow) {
+        if (inMultiWindowMode && !mService.mAm.mSupportsMultiWindow) {
             throw new IllegalArgumentException("Device doesn't support multi-window, can not"
                     + " reparent task=" + task + " to stack=" + stack);
         }
 
         // Ensure that we're not moving a task to a dynamic stack if device doesn't support
         // multi-display.
-        if (stack.mDisplayId != DEFAULT_DISPLAY && !mService.mSupportsMultiDisplay) {
+        if (stack.mDisplayId != DEFAULT_DISPLAY && !mService.mAm.mSupportsMultiDisplay) {
             throw new IllegalArgumentException("Device doesn't support multi-display, can not"
                     + " reparent task=" + task + " to stackId=" + stackId);
         }
 
         // Ensure that we aren't trying to move into a freeform stack without freeform support
         if (stack.getWindowingMode() == WINDOWING_MODE_FREEFORM
-                && !mService.mSupportsFreeformWindowManagement) {
+                && !mService.mAm.mSupportsFreeformWindowManagement) {
             throw new IllegalArgumentException("Device doesn't support freeform, can not reparent"
                     + " task=" + task);
         }
@@ -3307,7 +3305,7 @@
             return false;
         }
 
-        if (!mService.mForceResizableActivities && !r.supportsPictureInPicture()) {
+        if (!mService.mAm.mForceResizableActivities && !r.supportsPictureInPicture()) {
             Slog.w(TAG,
                     "moveTopStackActivityToPinnedStackLocked: Picture-In-Picture not supported for "
                             + " r=" + r);
@@ -3388,7 +3386,7 @@
         ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
         resumeFocusedStackTopActivityLocked();
 
-        mService.mActivityTaskManager.getTaskChangeNotificationController().notifyActivityPinned(r);
+        mService.getTaskChangeNotificationController().notifyActivityPinned(r);
     }
 
     /** Move activity with its stack to front and make the stack focused. */
@@ -3495,7 +3493,7 @@
                     throw new IllegalStateException("Calling must be system uid");
                 }
                 mLaunchingActivity.release();
-                mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
+                mService.mAm.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
             }
         }
 
@@ -3520,7 +3518,7 @@
                 long timeRemaining = endTime - System.currentTimeMillis();
                 if (timeRemaining > 0) {
                     try {
-                        mService.wait(timeRemaining);
+                        mService.mAm.wait(timeRemaining);
                     } catch (InterruptedException e) {
                     }
                 } else {
@@ -3602,7 +3600,7 @@
     }
 
     void checkReadyForSleepLocked(boolean allowDelay) {
-        if (!mService.isSleepingOrShuttingDownLocked()) {
+        if (!mService.mAm.isSleepingOrShuttingDownLocked()) {
             // Do not care.
             return;
         }
@@ -3619,8 +3617,8 @@
         if (mGoingToSleep.isHeld()) {
             mGoingToSleep.release();
         }
-        if (mService.mShuttingDown) {
-            mService.notifyAll();
+        if (mService.mAm.mShuttingDown) {
+            mService.mAm.notifyAll();
         }
     }
 
@@ -3648,7 +3646,7 @@
 
         final ActivityStack stack = r.getStack();
         if (isFocusedStack(stack)) {
-            mService.updateUsageStats(r, true);
+            mService.mAm.updateUsageStats(r, true);
         }
         if (allResumedActivitiesComplete()) {
             ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
@@ -3675,7 +3673,7 @@
 
         r.mLaunchTaskBehind = false;
         mRecentTasks.add(task);
-        mService.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskStackChanged();
+        mService.getTaskChangeNotificationController().notifyTaskStackChanged();
         r.setVisibility(false);
 
         // When launching tasks behind, update the last active time of the top task after the new
@@ -3875,7 +3873,7 @@
     /** Checks whether the userid is a profile of the current user. */
     boolean isCurrentProfileLocked(int userId) {
         if (userId == mCurrentUser) return true;
-        return mService.mUserController.isCurrentProfile(userId);
+        return mService.mAm.mUserController.isCurrentProfile(userId);
     }
 
     /**
@@ -3922,7 +3920,7 @@
                 final ActivityStack stack = s.getStack();
                 final boolean shouldSleepOrShutDown = stack != null
                         ? stack.shouldSleepOrShutDownActivities()
-                        : mService.isSleepingOrShuttingDownLocked();
+                        : mService.mAm.isSleepingOrShuttingDownLocked();
                 if (!waitingVisible || shouldSleepOrShutDown) {
                     if (!processPausingActivities && s.isState(PAUSING)) {
                         // Defer processing pausing activities in this iteration and reschedule
@@ -4276,7 +4274,7 @@
     }
 
     private void handleDisplayAdded(int displayId) {
-        synchronized (mService) {
+        synchronized (mService.mGlobalLock) {
             getActivityDisplayOrCreateLocked(displayId);
         }
     }
@@ -4339,7 +4337,7 @@
             throw new IllegalArgumentException("Can't remove the primary display.");
         }
 
-        synchronized (mService) {
+        synchronized (mService.mGlobalLock) {
             final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
             if (activityDisplay == null) {
                 return;
@@ -4354,7 +4352,7 @@
     }
 
     private void handleDisplayChanged(int displayId) {
-        synchronized (mService) {
+        synchronized (mService.mGlobalLock) {
             ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
             // TODO: The following code block should be moved into {@link ActivityDisplay}.
             if (activityDisplay != null) {
@@ -4363,7 +4361,7 @@
                     int displayState = activityDisplay.mDisplay.getState();
                     if (displayState == Display.STATE_OFF && activityDisplay.mOffToken == null) {
                         activityDisplay.mOffToken =
-                                mService.acquireSleepToken("Display-off", displayId);
+                                mService.mAm.acquireSleepToken("Display-off", displayId);
                     } else if (displayState == Display.STATE_ON
                             && activityDisplay.mOffToken != null) {
                         activityDisplay.mOffToken.release();
@@ -4396,7 +4394,7 @@
         if (display != null) {
             display.mAllSleepTokens.remove(token);
             if (display.mAllSleepTokens.isEmpty()) {
-                mService.updateSleepIfNeededLocked();
+                mService.mAm.updateSleepIfNeededLocked();
             }
         }
     }
@@ -4410,7 +4408,7 @@
         }
         display.mAllSleepTokens.clear();
 
-        mService.updateSleepIfNeededLocked();
+        mService.mAm.updateSleepIfNeededLocked();
     }
 
     private StackInfo getStackInfo(ActivityStack stack) {
@@ -4503,12 +4501,12 @@
             }
             // The task might have landed on a display different from requested.
             // TODO(multi-display): Find proper stack for the task on the default display.
-            mAtm.setTaskWindowingMode(task.taskId,
+            mService.setTaskWindowingMode(task.taskId,
                     WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, true /* toTop */);
             if (preferredDisplayId != actualDisplayId) {
                 // Display a warning toast that we tried to put a non-resizeable task on a secondary
                 // display with config different from global config.
-                mService.mActivityTaskManager.getTaskChangeNotificationController()
+                mService.getTaskChangeNotificationController()
                         .notifyActivityLaunchOnSecondaryDisplayFailed();
                 return;
             }
@@ -4517,7 +4515,7 @@
         if (!task.supportsSplitScreenWindowingMode() || forceNonResizable) {
             // Display a warning toast that we tried to put an app that doesn't support split-screen
             // in split-screen.
-            mService.mActivityTaskManager.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
+            mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
 
             // Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
             // we need to move it to top of fullscreen stack, otherwise it will be covered.
@@ -4537,7 +4535,7 @@
             final int reason = isSecondaryDisplayPreferred
                     ? FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY
                     : FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
-            mService.mActivityTaskManager.getTaskChangeNotificationController().notifyActivityForcedResizable(
+            mService.getTaskChangeNotificationController().notifyActivityForcedResizable(
                     task.taskId, reason, packageName);
         }
     }
@@ -4661,7 +4659,7 @@
         }
 
         void activityIdleInternal(ActivityRecord r, boolean processPausingActivities) {
-            synchronized (mService) {
+            synchronized (mService.mGlobalLock) {
                 activityIdleInternalLocked(r != null ? r.appToken : null, true /* fromTimeout */,
                         processPausingActivities, null);
             }
@@ -4671,7 +4669,7 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case REPORT_MULTI_WINDOW_MODE_CHANGED_MSG: {
-                    synchronized (mService) {
+                    synchronized (mService.mGlobalLock) {
                         for (int i = mMultiWindowModeChangedActivities.size() - 1; i >= 0; i--) {
                             final ActivityRecord r = mMultiWindowModeChangedActivities.remove(i);
                             r.updateMultiWindowMode();
@@ -4679,7 +4677,7 @@
                     }
                 } break;
                 case REPORT_PIP_MODE_CHANGED_MSG: {
-                    synchronized (mService) {
+                    synchronized (mService.mGlobalLock) {
                         for (int i = mPipModeChangedActivities.size() - 1; i >= 0; i--) {
                             final ActivityRecord r = mPipModeChangedActivities.remove(i);
                             r.updatePictureInPictureMode(mPipModeChangedTargetStackBounds,
@@ -4701,20 +4699,20 @@
                             false /* processPausingActivities */);
                 } break;
                 case RESUME_TOP_ACTIVITY_MSG: {
-                    synchronized (mService) {
+                    synchronized (mService.mGlobalLock) {
                         resumeFocusedStackTopActivityLocked();
                     }
                 } break;
                 case SLEEP_TIMEOUT_MSG: {
-                    synchronized (mService) {
-                        if (mService.isSleepingOrShuttingDownLocked()) {
+                    synchronized (mService.mGlobalLock) {
+                        if (mService.mAm.isSleepingOrShuttingDownLocked()) {
                             Slog.w(TAG, "Sleep timeout!  Sleeping now.");
                             checkReadyForSleepLocked(false /* allowDelay */);
                         }
                     }
                 } break;
                 case LAUNCH_TIMEOUT_MSG: {
-                    synchronized (mService) {
+                    synchronized (mService.mGlobalLock) {
                         if (mLaunchingActivity.isHeld()) {
                             Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
                             if (VALIDATE_WAKE_LOCK_CALLER
@@ -4735,7 +4733,7 @@
                     handleDisplayRemoved(msg.arg1);
                 } break;
                 case LAUNCH_TASK_BEHIND_COMPLETE: {
-                    synchronized (mService) {
+                    synchronized (mService.mGlobalLock) {
                         ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj);
                         if (r != null) {
                             handleLaunchTaskBehindCompleteLocked(r);
@@ -4823,14 +4821,14 @@
 
             // If the user must confirm credentials (e.g. when first launching a work app and the
             // Work Challenge is present) let startActivityInPackage handle the intercepting.
-            if (!mService.mUserController.shouldConfirmCredentials(task.userId)
+            if (!mService.mAm.mUserController.shouldConfirmCredentials(task.userId)
                     && task.getRootActivity() != null) {
                 final ActivityRecord targetActivity = task.getTopActivity();
 
                 sendPowerHintForLaunchStartIfNeeded(true /* forceSend */, targetActivity);
                 mActivityMetricsLogger.notifyActivityLaunching();
                 try {
-                    mService.mActivityTaskManager.moveTaskToFrontLocked(task.taskId, 0, options,
+                    mService.moveTaskToFrontLocked(task.taskId, 0, options,
                             true /* fromRecents */);
                 } finally {
                     mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
@@ -4951,7 +4949,7 @@
 
         @Override
         public void release() {
-            synchronized (mService) {
+            synchronized (mService.mGlobalLock) {
                 removeSleepTokenLocked(this);
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index a7c3200..fa001df 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -65,7 +65,7 @@
 
     private static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 1;
 
-    private final ActivityManagerService mService;
+    private final ActivityTaskManagerService mService;
     private final ActivityStackSupervisor mSupervisor;
 
     /** Last home activity record we attempted to start. */
@@ -96,7 +96,7 @@
         public void handleMessage(Message msg) {
             switch(msg.what) {
                 case DO_PENDING_ACTIVITY_LAUNCHES_MSG:
-                    synchronized (mService) {
+                    synchronized (mService.mGlobalLock) {
                         doPendingActivityLaunches(true);
                     }
                     break;
@@ -111,22 +111,22 @@
      */
     private ActivityStarter mLastStarter;
 
-    ActivityStartController(ActivityManagerService service) {
+    ActivityStartController(ActivityTaskManagerService service) {
         this(service, service.mStackSupervisor,
                 new DefaultFactory(service, service.mStackSupervisor,
                     new ActivityStartInterceptor(service, service.mStackSupervisor)));
     }
 
     @VisibleForTesting
-    ActivityStartController(ActivityManagerService service, ActivityStackSupervisor supervisor,
+    ActivityStartController(ActivityTaskManagerService service, ActivityStackSupervisor supervisor,
             Factory factory) {
         mService = service;
         mSupervisor = supervisor;
-        mHandler = new StartHandler(mService.mHandlerThread.getLooper());
+        mHandler = new StartHandler(mService.mH.getLooper());
         mFactory = factory;
         mFactory.setController(this);
         mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service,
-                service.mHandler);
+                service.mH);
     }
 
     /**
@@ -182,7 +182,7 @@
      */
     void startSetupActivity() {
         // Only do this once per boot.
-        if (mService.getCheckedForSetup()) {
+        if (mService.mAm.getCheckedForSetup()) {
             return;
         }
 
@@ -190,10 +190,10 @@
         // version than the last one shown, and we are not running in
         // low-level factory test mode.
         final ContentResolver resolver = mService.mContext.getContentResolver();
-        if (mService.mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL &&
+        if (mService.mAm.mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL &&
                 Settings.Global.getInt(resolver,
                         Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
-            mService.setCheckedForSetup(true);
+            mService.mAm.setCheckedForSetup(true);
 
             // See if we should be showing the platform update setup UI.
             final Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
@@ -237,10 +237,10 @@
     int checkTargetUser(int targetUserId, boolean validateIncomingUser,
             int realCallingPid, int realCallingUid, String reason) {
         if (validateIncomingUser) {
-            return mService.mUserController.handleIncomingUser(realCallingPid, realCallingUid,
+            return mService.mAm.mUserController.handleIncomingUser(realCallingPid, realCallingUid,
                     targetUserId, false, ALLOW_FULL_ONLY, reason, null);
         } else {
-            mService.mUserController.ensureNotSpecialUser(targetUserId);
+            mService.mAm.mUserController.ensureNotSpecialUser(targetUserId);
             return targetUserId;
         }
     }
@@ -320,7 +320,7 @@
         }
         final long origId = Binder.clearCallingIdentity();
         try {
-            synchronized (mService) {
+            synchronized (mService.mGlobalLock) {
                 ActivityRecord[] outActivity = new ActivityRecord[1];
                 for (int i=0; i < intents.length; i++) {
                     Intent intent = intents[i];
@@ -343,7 +343,7 @@
                             null, userId, ActivityStarter.computeResolveFilterUid(
                                     callingUid, realCallingUid, UserHandle.USER_NULL));
                     // TODO: New, check if this is correct
-                    aInfo = mService.getActivityInfoForUser(aInfo, userId);
+                    aInfo = mService.mAm.getActivityInfoForUser(aInfo, userId);
 
                     if (aInfo != null &&
                             (aInfo.applicationInfo.privateFlags
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index ff97db8..171c0bb 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -66,7 +66,7 @@
  */
 class ActivityStartInterceptor {
 
-    private final ActivityManagerService mService;
+    private final ActivityTaskManagerService mService;
     private final ActivityStackSupervisor mSupervisor;
     private final Context mServiceContext;
     private final UserController mUserController;
@@ -99,12 +99,13 @@
     TaskRecord mInTask;
     ActivityOptions mActivityOptions;
 
-    ActivityStartInterceptor(ActivityManagerService service, ActivityStackSupervisor supervisor) {
-        this(service, supervisor, service.mContext, service.mUserController);
+    ActivityStartInterceptor(
+            ActivityTaskManagerService service, ActivityStackSupervisor supervisor) {
+        this(service, supervisor, service.mContext, service.mAm.mUserController);
     }
 
     @VisibleForTesting
-    ActivityStartInterceptor(ActivityManagerService service, ActivityStackSupervisor supervisor,
+    ActivityStartInterceptor(ActivityTaskManagerService service, ActivityStackSupervisor supervisor,
             Context context, UserController userController) {
         mService = service;
         mSupervisor = supervisor;
@@ -127,7 +128,7 @@
 
     private IntentSender createIntentSenderForOriginalIntent(int callingUid, int flags) {
         Bundle activityOptions = deferCrossProfileAppsAnimationIfNecessary();
-        final IIntentSender target = mService.getIntentSenderLocked(
+        final IIntentSender target = mService.mAm.getIntentSenderLocked(
                 INTENT_SENDER_ACTIVITY, mCallingPackage, callingUid, mUserId, null /*token*/,
                 null /*resultCode*/, 0 /*requestCode*/,
                 new Intent[] { mIntent }, new String[] { mResolvedType },
@@ -238,7 +239,7 @@
                 (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) == 0) {
             return false;
         }
-        final PackageManagerInternal pmi = mService.getPackageManagerInternalLocked();
+        final PackageManagerInternal pmi = mService.mAm.getPackageManagerInternalLocked();
         if (pmi == null) {
             return false;
         }
@@ -319,7 +320,7 @@
     private boolean interceptHarmfulAppIfNeeded() {
         CharSequence harmfulAppWarning;
         try {
-            harmfulAppWarning = mService.getPackageManager()
+            harmfulAppWarning = mService.mAm.getPackageManager()
                     .getHarmfulAppWarning(mAInfo.packageName, mUserId);
         } catch (RemoteException ex) {
             return false;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 796018c..f50bb37 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -132,7 +132,7 @@
     private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
     private static final int INVALID_LAUNCH_MODE = -1;
 
-    private final ActivityManagerService mService;
+    private final ActivityTaskManagerService mService;
     private final ActivityStackSupervisor mSupervisor;
     private final ActivityStartInterceptor mInterceptor;
     private final ActivityStartController mController;
@@ -233,14 +233,14 @@
         private final int MAX_STARTER_COUNT = 3;
 
         private ActivityStartController mController;
-        private ActivityManagerService mService;
+        private ActivityTaskManagerService mService;
         private ActivityStackSupervisor mSupervisor;
         private ActivityStartInterceptor mInterceptor;
 
         private SynchronizedPool<ActivityStarter> mStarterPool =
                 new SynchronizedPool<>(MAX_STARTER_COUNT);
 
-        DefaultFactory(ActivityManagerService service,
+        DefaultFactory(ActivityTaskManagerService service,
                 ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
             mService = service;
             mSupervisor = supervisor;
@@ -410,7 +410,7 @@
         }
     }
 
-    ActivityStarter(ActivityStartController controller, ActivityManagerService service,
+    ActivityStarter(ActivityStartController controller, ActivityTaskManagerService service,
             ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
         mController = controller;
         mService = service;
@@ -583,7 +583,7 @@
 
         ProcessRecord callerApp = null;
         if (caller != null) {
-            callerApp = mService.getRecordForAppLocked(caller);
+            callerApp = mService.mAm.getRecordForAppLocked(caller);
             if (callerApp != null) {
                 callingPid = callerApp.pid;
                 callingUid = callerApp.info.uid;
@@ -672,7 +672,7 @@
                     && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
                 try {
                     intent.addCategory(Intent.CATEGORY_VOICE);
-                    if (!mService.getPackageManager().activitySupportsIntent(
+                    if (!mService.mAm.getPackageManager().activitySupportsIntent(
                             intent.getComponent(), intent, resolvedType)) {
                         Slog.w(TAG,
                                 "Activity being started in current voice task does not support voice: "
@@ -690,7 +690,7 @@
             // If the caller is starting a new voice session, just make sure the target
             // is actually allowing it to run this way.
             try {
-                if (!mService.getPackageManager().activitySupportsIntent(intent.getComponent(),
+                if (!mService.mAm.getPackageManager().activitySupportsIntent(intent.getComponent(),
                         intent, resolvedType)) {
                     Slog.w(TAG,
                             "Activity being started in new voice task does not support: "
@@ -717,7 +717,7 @@
         boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
                 inTask != null, callerApp, resultRecord, resultStack);
-        abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
+        abort |= !mService.mAm.mIntentFirewall.checkStartActivity(intent, callingUid,
                 callingPid, resolvedType, aInfo.applicationInfo);
 
         // Merge the two options bundles, while realCallerOptions takes precedence.
@@ -729,15 +729,15 @@
                     .getPendingRemoteAnimationRegistry()
                     .overrideOptionsIfNeeded(callingPackage, checkedOptions);
         }
-        if (mService.mController != null) {
+        if (mService.mAm.mController != null) {
             try {
                 // The Intent we give to the watcher has the extra data
                 // stripped off, since it can contain private information.
                 Intent watchIntent = intent.cloneFilter();
-                abort |= !mService.mController.activityStarting(watchIntent,
+                abort |= !mService.mAm.mController.activityStarting(watchIntent,
                         aInfo.applicationInfo.packageName);
             } catch (RemoteException e) {
-                mService.mController = null;
+                mService.mAm.mController = null;
             }
         }
 
@@ -770,10 +770,10 @@
         // If permissions need a review before any of the app components can run, we
         // launch the review activity and pass a pending intent to start the activity
         // we are to launching now after the review is completed.
-        if (mService.mPermissionReviewRequired && aInfo != null) {
-            if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
+        if (mService.mAm.mPermissionReviewRequired && aInfo != null) {
+            if (mService.mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                     aInfo.packageName, userId)) {
-                IIntentSender target = mService.getIntentSenderLocked(
+                IIntentSender target = mService.mAm.getIntentSenderLocked(
                         ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
                         callingUid, userId, null, null, 0, new Intent[]{intent},
                         new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
@@ -823,9 +823,9 @@
             aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
         }
 
-        ActivityRecord r = new ActivityRecord(mService.mActivityTaskManager, callerApp, callingPid,
+        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid,
                 callingUid,
-                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
+                callingPackage, intent, resolvedType, aInfo, mService.mAm.getGlobalConfiguration(),
                 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                 mSupervisor, checkedOptions, sourceRecord);
         if (outActivity != null) {
@@ -844,7 +844,7 @@
         // one, check whether app switches are allowed.
         if (voiceSession == null && (stack.getResumedActivity() == null
                 || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
-            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
+            if (!mService.mAm.checkAppSwitchAllowedLocked(callingPid, callingUid,
                     realCallingPid, realCallingUid, "Activity start")) {
                 mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
                         sourceRecord, startFlags, stack, callerApp));
@@ -853,15 +853,15 @@
             }
         }
 
-        if (mService.mDidAppSwitch) {
+        if (mService.mAm.mDidAppSwitch) {
             // This is the second allowed switch since we stopped switches,
             // so now just generally allow switches.  Use case: user presses
             // home (switches disabled, switch to home, mDidAppSwitch now true);
             // user taps a home icon (coming from home so allowed, we hit here
             // and now allow anyone to switch again).
-            mService.mAppSwitchesAllowedTime = 0;
+            mService.mAm.mAppSwitchesAllowedTime = 0;
         } else {
-            mService.mDidAppSwitch = true;
+            mService.mAm.mDidAppSwitch = true;
         }
 
         mController.doPendingActivityLaunches(false);
@@ -879,7 +879,7 @@
             String resolvedType, int userId) {
         if (auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo) {
             // request phase two resolution
-            mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
+            mService.mAm.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
                     auxiliaryResponse, originalIntent, resolvedType, callingPackage,
                     verificationBundle, userId);
         }
@@ -930,7 +930,7 @@
             // anyone interested in this piece of information.
             switch (startedActivityStack.getWindowingMode()) {
                 case WINDOWING_MODE_PINNED:
-                    mService.mActivityTaskManager.getTaskChangeNotificationController().notifyPinnedActivityRestartAttempt(
+                    mService.getTaskChangeNotificationController().notifyPinnedActivityRestartAttempt(
                             clearedTask);
                     break;
                 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
@@ -979,7 +979,7 @@
                 && !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
                 && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
                 && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
-                && mService.getPackageManagerInternalLocked()
+                && mService.mAm.getPackageManagerInternalLocked()
                         .isInstantAppInstallerComponent(intent.getComponent())) {
             // intercept intents targeted directly to the ephemeral installer the
             // ephemeral installer should never be started with a raw Intent; instead
@@ -1021,10 +1021,10 @@
         // Collect information about the target of the Intent.
         ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
 
-        synchronized (mService) {
+        synchronized (mService.mGlobalLock) {
             final ActivityStack stack = mSupervisor.mFocusedStack;
             stack.mConfigWillChange = globalConfig != null
-                    && mService.getGlobalConfiguration().diff(globalConfig) != 0;
+                    && mService.mAm.getGlobalConfiguration().diff(globalConfig) != 0;
             if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                     "Starting activity when config will change = " + stack.mConfigWillChange);
 
@@ -1033,16 +1033,16 @@
             if (aInfo != null &&
                     (aInfo.applicationInfo.privateFlags
                             & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 &&
-                    mService.mHasHeavyWeightFeature) {
+                    mService.mAm.mHasHeavyWeightFeature) {
                 // This may be a heavy-weight process!  Check to see if we already
                 // have another, different heavy-weight process running.
                 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
-                    final ProcessRecord heavy = mService.mHeavyWeightProcess;
+                    final ProcessRecord heavy = mService.mAm.mHeavyWeightProcess;
                     if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
                             || !heavy.processName.equals(aInfo.processName))) {
                         int appCallingUid = callingUid;
                         if (caller != null) {
-                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
+                            ProcessRecord callerApp = mService.mAm.getRecordForAppLocked(caller);
                             if (callerApp != null) {
                                 appCallingUid = callerApp.info.uid;
                             } else {
@@ -1054,7 +1054,7 @@
                             }
                         }
 
-                        IIntentSender target = mService.getIntentSenderLocked(
+                        IIntentSender target = mService.mAm.getIntentSenderLocked(
                                 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
                                 appCallingUid, userId, null, null, 0, new Intent[] { intent },
                                 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
@@ -1090,7 +1090,7 @@
                                         callingUid, realCallingUid, mRequest.filterCallingUid));
                         aInfo = rInfo != null ? rInfo.activityInfo : null;
                         if (aInfo != null) {
-                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
+                            aInfo = mService.mAm.getActivityInfoForUser(aInfo, userId);
                         }
                     }
                 }
@@ -1110,12 +1110,12 @@
                 // do so now.  This allows a clean switch, as we are waiting
                 // for the current activity to pause (so we will not destroy
                 // it), and have not yet started the next activity.
-                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
+                mService.mAm.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
                         "updateConfiguration()");
                 stack.mConfigWillChange = false;
                 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                         "Updating to new configuration after starting activity.");
-                mService.updateConfigurationLocked(globalConfig, null, false);
+                mService.mAm.updateConfigurationLocked(globalConfig, null, false);
             }
 
             if (outResult != null) {
@@ -1128,7 +1128,7 @@
                         mSupervisor.mWaitingActivityLaunched.add(outResult);
                         do {
                             try {
-                                mService.wait();
+                                mService.mGlobalLock.wait();
                             } catch (InterruptedException e) {
                             }
                         } while (outResult.result != START_TASK_TO_FRONT
@@ -1159,7 +1159,7 @@
                             // Note: the timeout variable is not currently not ever set.
                             do {
                                 try {
-                                    mService.wait();
+                                    mService.mGlobalLock.wait();
                                 } catch (InterruptedException e) {
                                 }
                             } while (!outResult.timeout && outResult.who == null);
@@ -1423,9 +1423,9 @@
             return result;
         }
 
-        mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
+        mService.mAm.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
                 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
-        mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
+        mService.mAm.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
                 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
         if (newTask) {
             EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
@@ -1821,7 +1821,7 @@
         }
 
         // Get the virtual display id from ActivityManagerService.
-        int displayId = mService.mVr2dDisplayId;
+        int displayId = mService.mAm.mVr2dDisplayId;
         if (displayId != INVALID_DISPLAY) {
             if (DEBUG_STACK) {
                 Slog.d(TAG, "getSourceDisplayId :" + displayId);
@@ -2115,13 +2115,13 @@
             // be not suitable. Let's check other displays.
             if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
                 // Can't use target display, lets find a stack on the source display.
-                mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
+                mTargetStack = mSupervisor.getValidLaunchStackOnDisplay(
                         sourceStack.mDisplayId, mStartActivity);
             }
             if (mTargetStack == null) {
                 // There are no suitable stacks on the target and source display(s). Look on all
                 // displays.
-                mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
+                mTargetStack = mSupervisor.getNextValidLaunchStackLocked(
                         mStartActivity, -1 /* currentFocus */);
             }
         }
@@ -2252,7 +2252,7 @@
 
         final ActivityStack stack = task.getStack();
         if (stack != null && stack.resizeStackWithLaunchBounds()) {
-            mService.mActivityTaskManager.resizeStack(
+            mService.resizeStack(
                     stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
         } else {
             task.updateOverrideConfiguration(bounds);
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 37ee3f7..90097fd 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -128,6 +128,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.LocaleList;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PersistableBundle;
@@ -222,6 +223,9 @@
     KeyguardController mKeyguardController;
     private final ClientLifecycleManager mLifecycleManager;
     private TaskChangeNotificationController mTaskChangeNotificationController;
+    /** The controller for all operations related to locktask. */
+    private LockTaskController mLockTaskController;
+    private ActivityStartController mActivityStartController;
 
     boolean mSuppressResizeConfigChanges;
 
@@ -240,6 +244,16 @@
         }
     }
 
+    /** Current sequencing integer of the configuration, for skipping old configurations. */
+    int mConfigurationSeq;
+
+    /**
+     * Temp object used when global and/or display override configuration is updated. It is also
+     * sent to outer world instead of {@link #getGlobalConfiguration} because we don't trust
+     * anyone...
+     */
+    Configuration mTempConfig = new Configuration();
+
     ActivityTaskManagerService(Context context) {
         mContext = context;
         mLifecycleManager = new ClientLifecycleManager();
@@ -256,17 +270,32 @@
         mAm = am;
         mGlobalLock = mAm;
         mH = new H(mAm.mHandlerThread.getLooper());
-        mStackSupervisor = mAm.mStackSupervisor;
+
+        mTempConfig.setToDefaults();
+        mTempConfig.setLocales(LocaleList.getDefault());
+        mConfigurationSeq = mTempConfig.seq = 1;
+        mStackSupervisor = createStackSupervisor();
+        mStackSupervisor.onConfigurationChanged(mTempConfig);
+
         mTaskChangeNotificationController =
                 new TaskChangeNotificationController(mAm, mStackSupervisor, mH);
+        mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mH);
+        mActivityStartController = new ActivityStartController(this);
         mRecentTasks = createRecentTasks();
         mStackSupervisor.setRecentTasks(mRecentTasks);
         mVrController = new VrController(mAm);
         mKeyguardController = mStackSupervisor.getKeyguardController();
     }
 
+    protected ActivityStackSupervisor createStackSupervisor() {
+        final ActivityStackSupervisor supervisor = new ActivityStackSupervisor(this, mH.getLooper());
+        supervisor.initialize();
+        return supervisor;
+    }
+
     void setWindowManager(WindowManagerService wm) {
         mWindowManager = wm;
+        mLockTaskController.setWindowManager(wm);
     }
 
     protected RecentTasks createRecentTasks() {
@@ -281,10 +310,18 @@
         return mLifecycleManager;
     }
 
+    ActivityStartController getActivityStartController() {
+        return mActivityStartController;
+    }
+
     TaskChangeNotificationController getTaskChangeNotificationController() {
         return mTaskChangeNotificationController;
     }
 
+    LockTaskController getLockTaskController() {
+        return mLockTaskController;
+    }
+
     private void start() {
         LocalServices.addService(ActivityTaskManagerInternal.class, new LocalService());
     }
@@ -326,7 +363,7 @@
         userId = mAm.mUserController.handleIncomingUser(Binder.getCallingPid(),
                 Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, reason, null);
         // TODO: Switch to user app stacks here.
-        return mAm.getActivityStartController().startActivities(caller, -1, callingPackage, intents,
+        return getActivityStartController().startActivities(caller, -1, callingPackage, intents,
                 resolvedTypes, resultTo, SafeActivityOptions.fromBundle(bOptions), userId, reason);
     }
 
@@ -345,11 +382,11 @@
             boolean validateIncomingUser) {
         mAm.enforceNotIsolatedCaller("startActivityAsUser");
 
-        userId = mAm.getActivityStartController().checkTargetUser(userId, validateIncomingUser,
+        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                 Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
 
         // TODO: Switch to user app stacks here.
-        return mAm.getActivityStartController().obtainStarter(intent, "startActivityAsUser")
+        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                 .setCaller(caller)
                 .setCallingPackage(callingPackage)
                 .setResolvedType(resolvedType)
@@ -488,7 +525,7 @@
 
             final long origId = Binder.clearCallingIdentity();
             // TODO(b/64750076): Check if calling pid should really be -1.
-            final int res = mAm.getActivityStartController()
+            final int res = getActivityStartController()
                     .obtainStarter(intent, "startNextMatchingActivity")
                     .setCaller(r.app.thread)
                     .setResolvedType(r.resolvedType)
@@ -524,7 +561,7 @@
                     Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY,
                     "startActivityAndWait", null);
             // TODO: Switch to user app stacks here.
-            mAm.getActivityStartController().obtainStarter(intent, "startActivityAndWait")
+            getActivityStartController().obtainStarter(intent, "startActivityAndWait")
                     .setCaller(caller)
                     .setCallingPackage(callingPackage)
                     .setResolvedType(resolvedType)
@@ -551,7 +588,7 @@
                     Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY,
                     "startActivityWithConfig", null);
             // TODO: Switch to user app stacks here.
-            return mAm.getActivityStartController().obtainStarter(intent, "startActivityWithConfig")
+            return getActivityStartController().obtainStarter(intent, "startActivityWithConfig")
                     .setCaller(caller)
                     .setCallingPackage(callingPackage)
                     .setResolvedType(resolvedType)
@@ -626,7 +663,7 @@
 
         // TODO: Switch to user app stacks here.
         try {
-            return mAm.getActivityStartController().obtainStarter(intent, "startActivityAsCaller")
+            return getActivityStartController().obtainStarter(intent, "startActivityAsCaller")
                     .setCallingUid(targetUid)
                     .setCallingPackage(targetPackage)
                     .setResolvedType(resolvedType)
@@ -667,7 +704,7 @@
         userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
                 ALLOW_FULL_ONLY, "startVoiceActivity", null);
         // TODO: Switch to user app stacks here.
-        return mAm.getActivityStartController().obtainStarter(intent, "startVoiceActivity")
+        return getActivityStartController().obtainStarter(intent, "startVoiceActivity")
                 .setCallingUid(callingUid)
                 .setCallingPackage(callingPackage)
                 .setResolvedType(resolvedType)
@@ -687,7 +724,7 @@
         userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
                 ALLOW_FULL_ONLY, "startAssistantActivity", null);
 
-        return mAm.getActivityStartController().obtainStarter(intent, "startAssistantActivity")
+        return getActivityStartController().obtainStarter(intent, "startAssistantActivity")
                 .setCallingUid(callingUid)
                 .setCallingPackage(callingPackage)
                 .setResolvedType(resolvedType)
@@ -709,7 +746,7 @@
 
                 // Start a new recents animation
                 final RecentsAnimation anim = new RecentsAnimation(mAm, mStackSupervisor,
-                        mAm.getActivityStartController(), mAm.mWindowManager, mAm.mUserController,
+                        getActivityStartController(), mAm.mWindowManager, mAm.mUserController,
                         callingPid);
                 anim.startRecentsActivity(intent, recentsAnimationRunner, recentsComponent,
                         recentsUid, assistDataReceiver);
@@ -769,7 +806,7 @@
             }
             // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can
             // finish.
-            if (mAm.getLockTaskController().activityBlockedFromFinish(r)) {
+            if (getLockTaskController().activityBlockedFromFinish(r)) {
                 return false;
             }
 
@@ -836,7 +873,7 @@
                 // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps
                 // can finish.
                 final TaskRecord task = r.getTask();
-                if (mAm.getLockTaskController().activityBlockedFromFinish(r)) {
+                if (getLockTaskController().activityBlockedFromFinish(r)) {
                     return false;
                 }
                 return task.getStack().finishActivityAffinityLocked(r);
@@ -1442,7 +1479,7 @@
                 Slog.d(TAG, "Could not find task for id: "+ taskId);
                 return;
             }
-            if (mAm.getLockTaskController().isLockTaskModeViolation(task)) {
+            if (getLockTaskController().isLockTaskModeViolation(task)) {
                 Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
                 return;
             }
@@ -1812,7 +1849,7 @@
             // When a task is locked, dismiss the pinned stack if it exists
             mStackSupervisor.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
 
-            mAm.getLockTaskController().startLockTaskMode(task, isSystemCaller, callingUid);
+            getLockTaskController().startLockTaskMode(task, isSystemCaller, callingUid);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -1823,7 +1860,7 @@
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
-                mAm.getLockTaskController().stopLockTaskMode(task, isSystemCaller, callingUid);
+                getLockTaskController().stopLockTaskMode(task, isSystemCaller, callingUid);
             }
             // Launch in-call UI if a call is ongoing. This is necessary to allow stopping the lock
             // task and jumping straight into a call in the case of emergency call back.
@@ -1844,7 +1881,7 @@
     @Override
     public int getLockTaskModeState() {
         synchronized (mGlobalLock) {
-            return mAm.getLockTaskController().getLockTaskModeState();
+            return getLockTaskController().getLockTaskModeState();
         }
     }
 
@@ -2601,7 +2638,7 @@
             if (r == null) {
                 return;
             }
-            mAm.getLockTaskController().showLockTaskToast();
+            getLockTaskController().showLockTaskToast();
         }
     }
 
@@ -3319,7 +3356,7 @@
         synchronized (mGlobalLock) {
             if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Allowing features " + userId + ":0x" +
                     Integer.toHexString(flags));
-            mAm.getLockTaskController().updateLockTaskFeatures(userId, flags);
+            getLockTaskController().updateLockTaskFeatures(userId, flags);
         }
     }
 
@@ -3383,7 +3420,7 @@
         synchronized (mGlobalLock) {
             final long origId = Binder.clearCallingIdentity();
             try {
-                mAm.getActivityStartController().registerRemoteAnimationForNextActivityStart(
+                getActivityStartController().registerRemoteAnimationForNextActivityStart(
                         packageName, adapter);
             } finally {
                 Binder.restoreCallingIdentity(origId);
@@ -3595,7 +3632,7 @@
             }
 
             synchronized (mGlobalLock) {
-                return mAm.getActivityStartController().startActivitiesInPackage(
+                return getActivityStartController().startActivitiesInPackage(
                         packageUid, packageName,
                         intents, resolvedTypes, null /* resultTo */,
                         SafeActivityOptions.fromBundle(bOptions), userId,
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 75090d4..eac3501 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -479,7 +479,7 @@
                         final Set<String> cats = task.intent != null
                                 ? task.intent.getCategories() : null;
                         if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) {
-                            mService.getActivityStartController().startActivityInPackage(
+                            mService.mActivityTaskManager.getActivityStartController().startActivityInPackage(
                                     task.mCallingUid, callingPid, callingUid, task.mCallingPackage,
                                     task.intent, null, null, null, 0, 0,
                                     new SafeActivityOptions(ActivityOptions.makeBasic()),
diff --git a/services/core/java/com/android/server/am/AppTaskImpl.java b/services/core/java/com/android/server/am/AppTaskImpl.java
index 4a7c21c..953d3b8 100644
--- a/services/core/java/com/android/server/am/AppTaskImpl.java
+++ b/services/core/java/com/android/server/am/AppTaskImpl.java
@@ -127,7 +127,7 @@
             }
         }
 
-        return mService.mAm.getActivityStartController().obtainStarter(intent, "AppTaskImpl")
+        return mService.getActivityStartController().obtainStarter(intent, "AppTaskImpl")
                 .setCaller(appThread)
                 .setCallingPackage(callingPackage)
                 .setResolvedType(resolvedType)
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index e0aa2a2..db09165 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -343,12 +343,12 @@
                                 allIntents[allIntents.length-1] = finalIntent;
                                 allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
 
-                                res = owner.getActivityStartController().startActivitiesInPackage(
+                                res = owner.mActivityTaskManager.getActivityStartController().startActivitiesInPackage(
                                         uid, key.packageName, allIntents, allResolvedTypes,
                                         resultTo, mergedOptions, userId,
                                         false /* validateIncomingUser */);
                             } else {
-                                res = owner.getActivityStartController().startActivityInPackage(uid,
+                                res = owner.mActivityTaskManager.getActivityStartController().startActivityInPackage(uid,
                                         callingPid, callingUid, key.packageName, finalIntent,
                                         resolvedType, resultTo, resultWho, requestCode, 0,
                                         mergedOptions, userId, null, "PendingIntentRecord",
diff --git a/services/core/java/com/android/server/am/PendingRemoteAnimationRegistry.java b/services/core/java/com/android/server/am/PendingRemoteAnimationRegistry.java
index 77713f5..877d896 100644
--- a/services/core/java/com/android/server/am/PendingRemoteAnimationRegistry.java
+++ b/services/core/java/com/android/server/am/PendingRemoteAnimationRegistry.java
@@ -33,9 +33,9 @@
 
     private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
     private final Handler mHandler;
-    private final ActivityManagerService mService;
+    private final ActivityTaskManagerService mService;
 
-    PendingRemoteAnimationRegistry(ActivityManagerService service, Handler handler) {
+    PendingRemoteAnimationRegistry(ActivityTaskManagerService service, Handler handler) {
         mService = service;
         mHandler = handler;
     }
@@ -74,7 +74,7 @@
             this.packageName = packageName;
             this.adapter = adapter;
             mHandler.postDelayed(() -> {
-                synchronized (mService) {
+                synchronized (mService.mGlobalLock) {
                     final Entry entry = mEntries.get(packageName);
                     if (entry == this) {
                         mEntries.remove(packageName);
diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java
index 29898b1..edc6e53 100644
--- a/services/core/java/com/android/server/am/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/am/PinnedActivityStack.java
@@ -55,7 +55,7 @@
     void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration,
             boolean fromFullscreen) {
         if (skipResizeAnimation(toBounds == null /* toFullscreen */)) {
-            mService.mActivityTaskManager.moveTasksToFullscreenStack(mStackId, true /* onTop */);
+            mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
         } else {
             getWindowContainerController().animateResizePinnedStack(toBounds, sourceHintBounds,
                     animationDuration, fromFullscreen);
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 5390127..749589b 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -529,7 +529,7 @@
         }
         for (int i = mTasks.size() - 1; i >= 0; --i) {
             final TaskRecord tr = mTasks.get(i);
-            if (tr.userId == userId && !mService.mAm.getLockTaskController().isTaskWhitelisted(tr)) {
+            if (tr.userId == userId && !mService.getLockTaskController().isTaskWhitelisted(tr)) {
                 remove(tr);
             }
         }
@@ -1162,7 +1162,7 @@
         }
 
         // If we're in lock task mode, ignore the root task
-        if (task == mService.mAm.getLockTaskController().getRootTask()) {
+        if (task == mService.getLockTaskController().getRootTask()) {
             return false;
         }
 
diff --git a/services/core/java/com/android/server/am/SafeActivityOptions.java b/services/core/java/com/android/server/am/SafeActivityOptions.java
index 55d17a9..778990b 100644
--- a/services/core/java/com/android/server/am/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/am/SafeActivityOptions.java
@@ -192,7 +192,7 @@
         // component or has the START_TASKS_FROM_RECENTS permission
         if (options.getLaunchTaskId() != INVALID_TASK_ID
                 && !supervisor.mRecentTasks.isCallerRecents(callingUid)) {
-            final int startInTaskPerm = supervisor.mService.checkPermission(
+            final int startInTaskPerm = supervisor.mService.mAm.checkPermission(
                     START_TASKS_FROM_RECENTS, callingPid, callingUid);
             if (startInTaskPerm == PERMISSION_DENIED) {
                 final String msg = "Permission Denial: starting " + getIntentString(intent)
@@ -230,7 +230,7 @@
 
         // Check permission for remote animations
         final RemoteAnimationAdapter adapter = options.getRemoteAnimationAdapter();
-        if (adapter != null && supervisor.mService.checkPermission(
+        if (adapter != null && supervisor.mService.mAm.checkPermission(
                 CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, callingPid, callingUid)
                         != PERMISSION_GRANTED) {
             final String msg = "Permission Denial: starting " + getIntentString(intent)
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
index 7896e2d..efb80be 100644
--- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -52,7 +52,8 @@
     // Delay in notifying task stack change listeners (in millis)
     private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
 
-    private final ActivityManagerService mService;
+    // Global lock used by the service the instantiate objects of this class.
+    private final Object mServiceLock;
     private final ActivityStackSupervisor mStackSupervisor;
     private final Handler mHandler;
 
@@ -149,7 +150,7 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case LOG_STACK_STATE_MSG: {
-                    synchronized (mService) {
+                    synchronized (mServiceLock) {
                         mStackSupervisor.logStackState();
                     }
                     break;
@@ -209,15 +210,15 @@
         }
     }
 
-    public TaskChangeNotificationController(ActivityManagerService service,
+    public TaskChangeNotificationController(Object serviceLock,
             ActivityStackSupervisor stackSupervisor, Handler handler) {
-        mService = service;
+        mServiceLock = serviceLock;
         mStackSupervisor = stackSupervisor;
         mHandler = new MainHandler(handler.getLooper());
     }
 
     public void registerTaskStackListener(ITaskStackListener listener) {
-        synchronized (mService) {
+        synchronized (mServiceLock) {
             if (listener != null) {
                 if (Binder.getCallingPid() == android.os.Process.myPid()) {
                     if (!mLocalTaskStackListeners.contains(listener)) {
@@ -231,7 +232,7 @@
     }
 
     public void unregisterTaskStackListener(ITaskStackListener listener) {
-        synchronized (mService) {
+        synchronized (mServiceLock) {
             if (listener != null) {
                 if (Binder.getCallingPid() == android.os.Process.myPid()) {
                     mLocalTaskStackListeners.remove(listener);
@@ -243,7 +244,7 @@
     }
 
     private void forAllRemoteListeners(TaskStackConsumer callback, Message message) {
-        synchronized (mService) {
+        synchronized (mServiceLock) {
             for (int i = mRemoteTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
                 try {
                     // Make a one-way callback to the listener
@@ -257,7 +258,7 @@
     }
 
     private void forAllLocalListeners(TaskStackConsumer callback, Message message) {
-        synchronized (mService) {
+        synchronized (mServiceLock) {
             for (int i = mLocalTaskStackListeners.size() - 1; i >= 0; i--) {
                 try {
                     callback.accept(mLocalTaskStackListeners.get(i), message);
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index b363866..6eac4bc 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -295,7 +295,7 @@
     int mCallingUid;
     String mCallingPackage;
 
-    final ActivityManagerService mService;
+    final ActivityTaskManagerService mService;
 
     private final Rect mTmpStableBounds = new Rect();
     private final Rect mTmpNonDecorBounds = new Rect();
@@ -320,10 +320,10 @@
     private TaskWindowContainerController mWindowContainerController;
 
     /**
-     * Don't use constructor directly. Use {@link #create(ActivityManagerService, int, ActivityInfo,
-     * Intent, TaskDescription)} instead.
+     * Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
+     * ActivityInfo, Intent, TaskDescription)} instead.
      */
-    TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
+    TaskRecord(ActivityTaskManagerService service, int _taskId, ActivityInfo info, Intent _intent,
             IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
         mService = service;
         userId = UserHandle.getUserId(info.applicationInfo.uid);
@@ -339,14 +339,15 @@
         setIntent(_intent, info);
         setMinDimensions(info);
         touchActiveTime();
-        mService.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
+        mService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
     }
 
     /**
-     * Don't use constructor directly. Use {@link #create(ActivityManagerService, int, ActivityInfo,
+     * Don't use constructor directly.
+     * Use {@link #create(ActivityTaskManagerService, int, ActivityInfo,
      * Intent, IVoiceInteractionSession, IVoiceInteractor)} instead.
      */
-    TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
+    TaskRecord(ActivityTaskManagerService service, int _taskId, ActivityInfo info, Intent _intent,
             TaskDescription _taskDescription) {
         mService = service;
         userId = UserHandle.getUserId(info.applicationInfo.uid);
@@ -369,13 +370,13 @@
 
         lastTaskDescription = _taskDescription;
         touchActiveTime();
-        mService.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
+        mService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
     }
 
     /**
      * Don't use constructor directly. This is only used by XML parser.
      */
-    TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
+    TaskRecord(ActivityTaskManagerService service, int _taskId, Intent _intent,
             Intent _affinityIntent, String _affinity, String _rootAffinity,
             ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
             boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
@@ -419,7 +420,7 @@
         mSupportsPictureInPicture = supportsPictureInPicture;
         mMinWidth = minWidth;
         mMinHeight = minHeight;
-        mService.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
+        mService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
     }
 
     TaskWindowContainerController getWindowContainerController() {
@@ -460,13 +461,13 @@
             // default configuration the next time it launches.
             updateOverrideConfiguration(null);
         }
-        mService.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskRemoved(taskId);
+        mService.getTaskChangeNotificationController().notifyTaskRemoved(taskId);
         mWindowContainerController = null;
     }
 
     @Override
     public void onSnapshotChanged(TaskSnapshot snapshot) {
-        mService.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskSnapshotChanged(taskId, snapshot);
+        mService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(taskId, snapshot);
     }
 
     void setResizeMode(int resizeMode) {
@@ -486,7 +487,7 @@
     // TODO: Consolidate this with the resize() method below.
     @Override
     public void requestResize(Rect bounds, int resizeMode) {
-        mService.mActivityTaskManager.resizeTask(taskId, bounds, resizeMode);
+        mService.resizeTask(taskId, bounds, resizeMode);
     }
 
     boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
@@ -1302,7 +1303,7 @@
             // We normally notify listeners of task stack changes on pause, however pinned stack
             // activities are normally in the paused state so no notification will be sent there
             // before the activity is removed. We send it here so instead.
-            mService.mActivityTaskManager.getTaskChangeNotificationController().notifyTaskStackChanged();
+            mService.getTaskChangeNotificationController().notifyTaskStackChanged();
         }
 
         if (mActivities.isEmpty()) {
@@ -1493,7 +1494,7 @@
     }
 
     private boolean isResizeable(boolean checkSupportsPip) {
-        return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
+        return (mService.mAm.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
                 || (checkSupportsPip && mSupportsPictureInPicture));
     }
 
@@ -1506,8 +1507,8 @@
         // A task can not be docked even if it is considered resizeable because it only supports
         // picture-in-picture mode but has a non-resizeable resizeMode
         return super.supportsSplitScreenWindowingMode()
-                && mService.mSupportsSplitScreenMultiWindow
-                && (mService.mForceResizableActivities
+                && mService.mAm.mSupportsSplitScreenMultiWindow
+                && (mService.mAm.mForceResizableActivities
                         || (isResizeable(false /* checkSupportsPip */)
                                 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
     }
@@ -2205,14 +2206,14 @@
         sTaskRecordFactory = factory;
     }
 
-    static TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
+    static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
             Intent intent, IVoiceInteractionSession voiceSession,
             IVoiceInteractor voiceInteractor) {
         return getTaskRecordFactory().create(
                 service, taskId, info, intent, voiceSession, voiceInteractor);
     }
 
-    static TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
+    static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
             Intent intent, TaskDescription taskDescription) {
         return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription);
     }
@@ -2229,14 +2230,14 @@
      */
     static class TaskRecordFactory {
 
-        TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
+        TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
                 Intent intent, IVoiceInteractionSession voiceSession,
                 IVoiceInteractor voiceInteractor) {
             return new TaskRecord(
                     service, taskId, info, intent, voiceSession, voiceInteractor);
         }
 
-        TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
+        TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
                 Intent intent, TaskDescription taskDescription) {
             return new TaskRecord(service, taskId, info, intent, taskDescription);
         }
@@ -2244,7 +2245,7 @@
         /**
          * Should only be used when we're restoring {@link TaskRecord} from storage.
          */
-        TaskRecord create(ActivityManagerService service, int taskId, Intent intent,
+        TaskRecord create(ActivityTaskManagerService service, int taskId, Intent intent,
                 Intent affinityIntent, String affinity, String rootAffinity,
                 ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
                 boolean autoRemoveRecents, boolean askedCompatMode, int userId,
@@ -2468,7 +2469,8 @@
                 }
             }
 
-            final TaskRecord task = create(stackSupervisor.mService, taskId, intent, affinityIntent,
+            final TaskRecord task = create(stackSupervisor.mService,
+                    taskId, intent, affinityIntent,
                     affinity, rootAffinity, realActivity, origActivity, rootHasReset,
                     autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
                     activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 2fbe56b..b500bbf 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -2248,7 +2248,7 @@
 
         protected void clearAllLockedTasks(String reason) {
             synchronized (mService) {
-                mService.getLockTaskController().clearLockedTasks(reason);
+                mService.mActivityTaskManager.getLockTaskController().clearLockedTasks(reason);
             }
         }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0897b8a..32f1744 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3408,20 +3408,27 @@
 
         @Override
         public void applyEnqueuedAdjustmentFromAssistant(INotificationListener token,
-                Adjustment adjustment) throws RemoteException {
+                Adjustment adjustment) {
+            boolean foundEnqueued = false;
             final long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mNotificationLock) {
                     mAssistants.checkServiceTokenLocked(token);
                     int N = mEnqueuedNotifications.size();
                     for (int i = 0; i < N; i++) {
-                        final NotificationRecord n = mEnqueuedNotifications.get(i);
-                        if (Objects.equals(adjustment.getKey(), n.getKey())
-                                && Objects.equals(adjustment.getUser(), n.getUserId())) {
-                            applyAdjustment(n, adjustment);
+                        final NotificationRecord r = mEnqueuedNotifications.get(i);
+                        if (Objects.equals(adjustment.getKey(), r.getKey())
+                                && Objects.equals(adjustment.getUser(), r.getUserId())) {
+                            applyAdjustment(r, adjustment);
+                            r.applyAdjustments();
+                            foundEnqueued = true;
                             break;
                         }
                     }
+                    if (!foundEnqueued) {
+                        // adjustment arrived too late to apply to enqueued; apply to posted
+                        applyAdjustmentFromAssistant(token, adjustment);
+                    }
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -3430,7 +3437,7 @@
 
         @Override
         public void applyAdjustmentFromAssistant(INotificationListener token,
-                Adjustment adjustment) throws RemoteException {
+                Adjustment adjustment) {
             final long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mNotificationLock) {
@@ -3446,7 +3453,7 @@
 
         @Override
         public void applyAdjustmentsFromAssistant(INotificationListener token,
-                List<Adjustment> adjustments) throws RemoteException {
+                List<Adjustment> adjustments) {
 
             final long identity = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 08d0ae9..fa6079c 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -19,6 +19,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
@@ -1377,7 +1378,7 @@
             setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
 
             // We can now show all of the drawn windows!
-            if (!mService.mOpeningApps.contains(this)) {
+            if (!mService.mOpeningApps.contains(this) && canShowWindows()) {
                 showAllWindowsLocked();
             }
         }
@@ -2270,4 +2271,21 @@
     boolean isClosingOrEnteringPip() {
         return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
     }
+
+    /**
+     * @return Whether we are allowed to show non-starting windows at the moment. We disallow
+     *         showing windows during transitions in case we have windows that have wide-color-gamut
+     *         color mode set to avoid jank in the middle of the transition.
+     */
+    boolean canShowWindows() {
+        return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
+    }
+
+    /**
+     * @return true if we have a window that has a non-default color mode set; false otherwise.
+     */
+    private boolean hasNonDefaultColorWindow() {
+        return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
+                true /* topToBottom */);
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index f364753..0cbf8a7 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -404,7 +404,7 @@
         WindowStateAnimator winAnimator = w.mWinAnimator;
         final AppWindowToken atoken = w.mAppToken;
         if (winAnimator.mDrawState == READY_TO_SHOW) {
-            if (atoken == null || atoken.allDrawn) {
+            if (atoken == null || atoken.canShowWindows()) {
                 if (w.performShowLocked()) {
                     pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
                     if (DEBUG_LAYOUT_REPEATS) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 26fe24b..14e0e13 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -41,11 +41,11 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
 import static com.android.server.wm.WindowManagerService.logWithStack;
-import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
 import static com.android.server.wm.WindowStateAnimatorProto.DRAW_STATE;
 import static com.android.server.wm.WindowStateAnimatorProto.LAST_CLIP_RECT;
 import static com.android.server.wm.WindowStateAnimatorProto.SURFACE;
 import static com.android.server.wm.WindowStateAnimatorProto.SYSTEM_DECOR_RECT;
+import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
 import static com.android.server.wm.utils.CoordinateTransforms.transformToRotation;
 
 import android.content.Context;
@@ -366,7 +366,8 @@
         mDrawState = READY_TO_SHOW;
         boolean result = false;
         final AppWindowToken atoken = mWin.mAppToken;
-        if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
+        if (atoken == null || atoken.canShowWindows()
+                || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
             result = mWin.performShowLocked();
         }
         return result;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 1ce41a6..0674d85 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -174,7 +174,7 @@
 
         // #notifyAll will be called on the ActivityManagerService. we must hold the object lock
         // when this happens.
-        synchronized (mSupervisor.mService) {
+        synchronized (mSupervisor.mService.mGlobalLock) {
             final WaitResult taskToFrontWait = new WaitResult();
             mSupervisor.mWaitingActivityLaunched.add(taskToFrontWait);
             mSupervisor.reportWaitingActivityLaunchedIfNeeded(firstActivity, START_TASK_TO_FRONT);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
index 7948e4c..a86372a 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
@@ -59,8 +59,8 @@
         super.setUp();
         mService = createActivityManagerService();
         mFactory = mock(Factory.class);
-        mController = new ActivityStartController(mService, mService.mStackSupervisor, mFactory);
-        mStarter = spy(new ActivityStarter(mController, mService, mService.mStackSupervisor,
+        mController = new ActivityStartController(mService.mActivityTaskManager, mService.mStackSupervisor, mFactory);
+        mStarter = spy(new ActivityStarter(mController, mService.mActivityTaskManager, mService.mStackSupervisor,
                 mock(ActivityStartInterceptor.class)));
         doReturn(mStarter).when(mFactory).obtain();
     }
@@ -96,7 +96,7 @@
     @Test
     public void testRecycling() throws Exception {
         final Intent intent = new Intent();
-        final ActivityStarter optionStarter = new ActivityStarter(mController, mService,
+        final ActivityStarter optionStarter = new ActivityStarter(mController, mService.mActivityTaskManager,
                 mService.mStackSupervisor, mock(ActivityStartInterceptor.class));
         optionStarter
                 .setIntent(intent)
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
index 9d35ef1..7f55824 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
@@ -57,7 +57,7 @@
  * Unit tests for {@link ActivityStartInterceptorTest}.
  *
  * Build/Install/Run:
- *  bit FrameworksServicesTests:com.android.server.am.ActivityStartInterceptorTest
+ *  atest FrameworksServicesTests:com.android.server.am.ActivityStartInterceptorTest
  */
 @Presubmit
 @SmallTest
@@ -82,7 +82,9 @@
     @Mock
     private Context mContext;
     @Mock
-    private ActivityManagerService mService;
+    private ActivityManagerService mAm;
+    @Mock
+    private ActivityTaskManagerService mService;
     @Mock
     private ActivityStackSupervisor mSupervisor;
     @Mock
@@ -104,6 +106,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mService.mAm = mAm;
         mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext,
                 mUserController);
         mInterceptor.setStates(TEST_USER_ID, TEST_REAL_CALLING_PID, TEST_REAL_CALLING_UID,
@@ -113,10 +116,9 @@
         LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
         LocalServices.addService(DevicePolicyManagerInternal.class,
                 mDevicePolicyManager);
-        when(mDevicePolicyManager
-                        .createShowAdminSupportIntent(TEST_USER_ID, true))
+        when(mDevicePolicyManager.createShowAdminSupportIntent(TEST_USER_ID, true))
                 .thenReturn(ADMIN_SUPPORT_INTENT);
-        when(mService.getPackageManagerInternalLocked()).thenReturn(mPackageManagerInternal);
+        when(mAm.getPackageManagerInternalLocked()).thenReturn(mPackageManagerInternal);
 
         // Mock UserManager
         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
@@ -129,7 +131,7 @@
                 thenReturn(CONFIRM_CREDENTIALS_INTENT);
 
         // Mock PackageManager
-        when(mService.getPackageManager()).thenReturn(mPackageManager);
+        when(mAm.getPackageManager()).thenReturn(mPackageManager);
         when(mPackageManager.getHarmfulAppWarning(TEST_PACKAGE_NAME, TEST_USER_ID))
                 .thenReturn(null);
 
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index 74e5816..10d255e7 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -109,7 +109,7 @@
         super.setUp();
         mService = createActivityManagerService();
         mController = mock(ActivityStartController.class);
-        mStarter = new ActivityStarter(mController, mService, mService.mStackSupervisor,
+        mStarter = new ActivityStarter(mController, mService.mActivityTaskManager, mService.mStackSupervisor,
                 mock(ActivityStartInterceptor.class));
     }
 
@@ -193,7 +193,7 @@
         final IPackageManager packageManager = mock(IPackageManager.class);
         final ActivityStartController controller = mock(ActivityStartController.class);
 
-        final ActivityStarter starter = new ActivityStarter(controller, service,
+        final ActivityStarter starter = new ActivityStarter(controller, service.mActivityTaskManager,
                 service.mStackSupervisor, mock(ActivityStartInterceptor.class));
         final IApplicationThread caller = mock(IApplicationThread.class);
 
@@ -282,7 +282,7 @@
 
         // Ensure that {@link ActivityOptions} are aborted with unsuccessful result.
         if (expectedResult != START_SUCCESS) {
-            final ActivityStarter optionStarter = new ActivityStarter(mController, mService,
+            final ActivityStarter optionStarter = new ActivityStarter(mController, mService.mActivityTaskManager,
                     mService.mStackSupervisor, mock(ActivityStartInterceptor.class));
             final ActivityOptions options = spy(ActivityOptions.makeBasic());
 
@@ -336,7 +336,7 @@
         info.applicationInfo = new ApplicationInfo();
         info.applicationInfo.packageName = ActivityBuilder.getDefaultComponent().getPackageName();
 
-        return new ActivityStarter(mController, mService,
+        return new ActivityStarter(mController, mService.mActivityTaskManager,
                 mService.mStackSupervisor, mock(ActivityStartInterceptor.class))
                 .setIntent(intent)
                 .setActivityInfo(info);
@@ -456,7 +456,7 @@
 
         final ActivityStarter starter = prepareStarter(0);
 
-        final LockTaskController lockTaskController = mService.getLockTaskController();
+        final LockTaskController lockTaskController = mService.mActivityTaskManager.getLockTaskController();
         doReturn(true).when(lockTaskController).isLockTaskModeViolation(any());
 
         final int result = starter.setReason("testTaskModeViolation").execute();
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 47c4de2..06ac3b0 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -111,10 +111,11 @@
     protected ActivityManagerService setupActivityManagerService(
             ActivityManagerService service, ActivityTaskManagerService atm) {
         service = spy(service);
+        // Makes sure activity task is created with the spy object.
         atm = spy(atm);
-        // Makes sure the supervisor is using with the spy object.
-        service.mStackSupervisor.setService(service);
         service.setActivityTaskManager(atm);
+        // Makes sure the supervisor is using with the spy object.
+        atm.mStackSupervisor.setService(atm);
         doReturn(mock(IPackageManager.class)).when(service).getPackageManager();
         doNothing().when(service).grantEphemeralAccessLocked(anyInt(), any(), anyInt(), anyInt());
         service.mWindowManager = prepareMockWindowManager();
@@ -328,7 +329,7 @@
         }
 
         private static class TestTaskRecord extends TaskRecord {
-            TestTaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info,
+            TestTaskRecord(ActivityTaskManagerService service, int _taskId, ActivityInfo info,
                        Intent _intent, IVoiceInteractionSession _voiceSession,
                        IVoiceInteractor _voiceInteractor) {
                 super(service, _taskId, info, _intent, _voiceSession, _voiceInteractor);
@@ -346,37 +347,13 @@
     }
 
     protected static class TestActivityTaskManagerService extends ActivityTaskManagerService {
+        private LockTaskController mLockTaskController;
+
         TestActivityTaskManagerService(Context context) {
             super(context);
         }
-    }
-
-    /**
-     * An {@link ActivityManagerService} subclass which provides a test
-     * {@link ActivityStackSupervisor}.
-     */
-    protected static class TestActivityManagerService extends ActivityManagerService {
-        private ClientLifecycleManager mLifecycleManager;
-        private LockTaskController mLockTaskController;
-
-        TestActivityManagerService(Context context) {
-            super(context);
-            mSupportsMultiWindow = true;
-            mSupportsMultiDisplay = true;
-            mSupportsSplitScreenMultiWindow = true;
-            mSupportsFreeformWindowManagement = true;
-            mSupportsPictureInPicture = true;
-            mWindowManager = WindowTestUtils.getMockWindowManagerService();
-        }
 
         @Override
-        public ClientLifecycleManager getLifecycleManager() {
-            if (mLifecycleManager == null) {
-                return super.getLifecycleManager();
-            }
-            return mLifecycleManager;
-        }
-
         public LockTaskController getLockTaskController() {
             if (mLockTaskController == null) {
                 mLockTaskController = spy(super.getLockTaskController());
@@ -411,12 +388,33 @@
         }
 
         protected ActivityStackSupervisor createTestSupervisor() {
-            return new TestActivityStackSupervisor(this, mHandlerThread.getLooper());
+            return new TestActivityStackSupervisor(this, mH.getLooper());
+        }
+    }
+
+    /**
+     * An {@link ActivityManagerService} subclass which provides a test
+     * {@link ActivityStackSupervisor}.
+     */
+    protected static class TestActivityManagerService extends ActivityManagerService {
+
+        TestActivityManagerService(Context context) {
+            super(context);
+            mSupportsMultiWindow = true;
+            mSupportsMultiDisplay = true;
+            mSupportsSplitScreenMultiWindow = true;
+            mSupportsFreeformWindowManagement = true;
+            mSupportsPictureInPicture = true;
         }
 
         @Override
         void updateUsageStats(ActivityRecord component, boolean resumed) {
         }
+
+        @Override
+        Configuration getGlobalConfiguration() {
+            return mContext.getResources().getConfiguration();
+        }
     }
 
     /**
@@ -427,7 +425,7 @@
         private ActivityDisplay mDisplay;
         private KeyguardController mKeyguardController;
 
-        public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
+        public TestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) {
             super(service, looper);
             mDisplayManager =
                     (DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
diff --git a/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java b/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
index 2baf995..e73661b 100644
--- a/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
@@ -62,7 +62,7 @@
         mService.mHandlerThread.getThreadHandler().runWithScissors(() -> {
             mHandler = new TestHandler(null, mClock);
         }, 0);
-        mRegistry = new PendingRemoteAnimationRegistry(mService, mHandler);
+        mRegistry = new PendingRemoteAnimationRegistry(mService.mActivityTaskManager, mHandler);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index f98c50a..cd70677 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -837,6 +837,12 @@
         protected RecentTasks createRecentTasks() {
             return new TestRecentTasks(this, mTaskPersister, new TestUserController(mAm));
         }
+
+        @Override
+        protected ActivityStackSupervisor createTestSupervisor() {
+            return new MyTestActivityStackSupervisor(this, mH.getLooper());
+        }
+
     }
 
     private class MyTestActivityManagerService extends TestActivityManagerService {
@@ -845,18 +851,13 @@
         }
 
         @Override
-        protected ActivityStackSupervisor createTestSupervisor() {
-            return new MyTestActivityStackSupervisor(this, mHandlerThread.getLooper());
-        }
-
-        @Override
         public boolean isUserRunning(int userId, int flags) {
             return true;
         }
     }
 
     private class MyTestActivityStackSupervisor extends TestActivityStackSupervisor {
-        public MyTestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
+        public MyTestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) {
             super(service, looper);
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java b/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
index 057fdc8..72851d01 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
@@ -155,7 +155,8 @@
     }
 
     private TaskRecord createTaskRecord(int taskId) {
-        return new TaskRecord(mService, taskId, new Intent(), null, null, null, null, null, false,
+        return new TaskRecord(mService.mActivityTaskManager, taskId, new Intent(), null, null, null,
+                null, null, false,
                 false, false, 0, 10050, null, new ArrayList<>(), 0, false, null, 0, 0, 0, 0, 0,
                 null, 0, false, false, false, 0, 0);
     }
@@ -164,7 +165,7 @@
         private boolean mCreated = false;
 
         @Override
-        TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
+        TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
                 Intent intent,
                 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
             mCreated = true;
@@ -172,7 +173,7 @@
         }
 
         @Override
-        TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
+        TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
                 Intent intent,
                 ActivityManager.TaskDescription taskDescription) {
             mCreated = true;
@@ -180,7 +181,7 @@
         }
 
         @Override
-        TaskRecord create(ActivityManagerService service, int taskId, Intent intent,
+        TaskRecord create(ActivityTaskManagerService service, int taskId, Intent intent,
                 Intent affinityIntent, String affinity, String rootAffinity,
                 ComponentName realActivity,
                 ComponentName origActivity, boolean rootWasReset, boolean autoRemoveRecents,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 3b21390..96c948f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2405,6 +2405,45 @@
     }
 
     @Test
+    public void testTooLateAdjustmentTriggersUpdate() throws Exception {
+        final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+        mService.addNotification(r);
+        NotificationManagerService.WorkerHandler handler = mock(
+                NotificationManagerService.WorkerHandler.class);
+        mService.setHandler(handler);
+
+        Bundle signals = new Bundle();
+        signals.putInt(Adjustment.KEY_USER_SENTIMENT,
+                NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+        Adjustment adjustment = new Adjustment(
+                r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
+        mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
+
+        waitForIdle();
+
+        verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate();
+    }
+
+    @Test
+    public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception {
+        final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+        mService.addEnqueuedNotification(r);
+        NotificationManagerService.WorkerHandler handler = mock(
+                NotificationManagerService.WorkerHandler.class);
+        mService.setHandler(handler);
+
+        Bundle signals = new Bundle();
+        signals.putInt(Adjustment.KEY_USER_SENTIMENT,
+                NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+        Adjustment adjustment = new Adjustment(
+                r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
+        mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
+
+        assertEquals(NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE,
+                r.getUserSentiment());
+    }
+
+    @Test
     public void testRecents() throws Exception {
         Set<NotifyingApp> expected = new HashSet<>();
 
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 1d5eece..b8dfd38 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -866,7 +866,7 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 return UsageStatsService.this.queryEventsForPackage(userId, beginTime,
-                        endTime, callingPackage);
+                        endTime, pkg);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index aa832ad..6a1e97a 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -68,6 +68,7 @@
     private static final String SHORTCUT_ID_ATTR = "shortcutId";
     private static final String STANDBY_BUCKET_ATTR = "standbyBucket";
     private static final String APP_LAUNCH_COUNT_ATTR = "appLaunchCount";
+    private static final String NOTIFICATION_CHANNEL_ATTR = "notificationChannel";
 
     // Time attributes stored as an offset of the beginTime.
     private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
@@ -189,6 +190,11 @@
             case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
                 event.mBucketAndReason = XmlUtils.readIntAttribute(parser, STANDBY_BUCKET_ATTR, 0);
                 break;
+            case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                final String channelId =
+                        XmlUtils.readStringAttribute(parser, NOTIFICATION_CHANNEL_ATTR);
+                event.mNotificationChannelId = (channelId != null) ? channelId.intern() : null;
+                break;
         }
 
         if (statsOut.events == null) {
@@ -307,6 +313,13 @@
                 if (event.mBucketAndReason != 0) {
                     XmlUtils.writeIntAttribute(xml, STANDBY_BUCKET_ATTR, event.mBucketAndReason);
                 }
+                break;
+            case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                if (event.mNotificationChannelId != null) {
+                    XmlUtils.writeStringAttribute(
+                            xml, NOTIFICATION_CHANNEL_ATTR, event.mNotificationChannelId);
+                }
+                break;
         }
 
         xml.endTag(null, EVENT_TAG);
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 9cb98f3..4efe0b5 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -604,6 +604,9 @@
             pw.printPair("standbyBucket", event.getStandbyBucket());
             pw.printPair("reason", UsageStatsManager.reasonToString(event.getStandbyReason()));
         }
+        if (event.mNotificationChannelId != null) {
+            pw.printPair("channelId", event.mNotificationChannelId);
+        }
         pw.printHexPair("flags", event.mFlags);
         pw.println();
     }
diff --git a/telephony/java/android/telephony/NetworkService.java b/telephony/java/android/telephony/NetworkService.java
index f7e6840..4354314 100644
--- a/telephony/java/android/telephony/NetworkService.java
+++ b/telephony/java/android/telephony/NetworkService.java
@@ -36,8 +36,8 @@
 /**
  * Base class of network service. Services that extend NetworkService must register the service in
  * their AndroidManifest to be detected by the framework. They must be protected by the permission
- * "android.permission.BIND_NETWORK_SERVICE". The network service definition in the manifest must
- * follow the following format:
+ * "android.permission.BIND_TELEPHONY_NETWORK_SERVICE". The network service definition in the
+ * manifest must follow the following format:
  * ...
  * <service android:name=".xxxNetworkService"
  *     android:permission="android.permission.BIND_TELEPHONY_NETWORK_SERVICE" >
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d7568b4..0940738 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5432,23 +5432,6 @@
     }
 
     /**
-     * @return true if the IMS resolver is busy resolving a binding and should not be considered
-     * available, false if the IMS resolver is idle.
-     * @hide
-     */
-    public boolean isResolvingImsBinding() {
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null) {
-                return telephony.isResolvingImsBinding();
-            }
-        } catch (RemoteException e) {
-            Rlog.e(TAG, "isResolvingImsBinding, RemoteException: " + e.getMessage());
-        }
-        return false;
-    }
-
-    /**
      * Set IMS registration state
      *
      * @param Registration state
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 4ca5ce3..1db5850 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -44,11 +44,11 @@
 /**
  * Base class of data service. Services that extend DataService must register the service in
  * their AndroidManifest to be detected by the framework. They must be protected by the permission
- * "android.permission.BIND_DATA_SERVICE". The data service definition in the manifest must follow
- * the following format:
+ * "android.permission.BIND_TELEPHONY_DATA_SERVICE". The data service definition in the manifest
+ * must follow the following format:
  * ...
  * <service android:name=".xxxDataService"
- *     android:permission="android.permission.BIND_DATA_SERVICE" >
+ *     android:permission="android.permission.BIND_TELEPHONY_DATA_SERVICE" >
  *     <intent-filter>
  *         <action android:name="android.telephony.data.DataService" />
  *     </intent-filter>
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 6ea8ccb..84a18b4 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -817,12 +817,6 @@
     IImsConfig getImsConfig(int slotId, int feature);
 
     /**
-     * @return true if the IMS resolver is busy resolving a binding and should not be considered
-     * available, false if the IMS resolver is idle.
-     */
-    boolean isResolvingImsBinding();
-
-    /**
     *  @return true if the ImsService to bind to for the slot id specified was set, false otherwise.
     */
     boolean setImsService(int slotId, boolean isCarrierImsService, String packageName);
diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk
index 021185f..c723d90 100644
--- a/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk
+++ b/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_MIN_SDK_VERSION := 21
 
 # We need this to retain the R.java generated for this library.
 LOCAL_JAR_EXCLUDE_FILES := none
diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk
index 39bd481..90a7f62 100644
--- a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk
+++ b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk
@@ -24,6 +24,7 @@
 LOCAL_MODULE_TAGS := tests
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_MIN_SDK_VERSION := 21
 
 # We need this to retain the R.java generated for this library.
 LOCAL_JAR_EXCLUDE_FILES := none