Merge changes from topic "cherrypick-bt-apm-notification-6f5u3o536b-tm-mainline-prod"

* changes:
  [automerged blank] Use message ID from proto for BT APM notification 2p: 47d70626de
  Use message ID from proto for BT APM notification Bug: 249590939 Bug: 239983569 Test: atest ServiceBluetoothTests
diff --git a/core/api/current.txt b/core/api/current.txt
index c7ca0cd..e30761f 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -22438,6 +22438,7 @@
     field public static final String MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
     field public static final String MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
     field public static final String MIMETYPE_IMAGE_ANDROID_HEIC = "image/vnd.android.heic";
+    field public static final String MIMETYPE_IMAGE_AVIF = "image/avif";
     field public static final String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
     field public static final String MIMETYPE_TEXT_CEA_708 = "text/cea-708";
     field public static final String MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 8b3451e..92088e9 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -65,6 +65,7 @@
 import android.annotation.UiContext;
 import android.app.ActivityManager;
 import android.app.Dialog;
+import android.app.compat.CompatChanges;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -546,6 +547,20 @@
     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
     public static final long FINISH_INPUT_NO_FALLBACK_CONNECTION = 156215187L; // This is a bug id.
 
+    /**
+     * Disallow IMEs to override {@link InputMethodService#onCreateInputMethodSessionInterface()}
+     * method.
+     *
+     * <p>If IMEs targeting on Android U and beyond override the
+     * {@link InputMethodService#onCreateInputMethodSessionInterface()}, an {@link LinkageError}
+     * would be thrown.</p>
+     *
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    private static final long DISALLOW_INPUT_METHOD_INTERFACE_OVERRIDE = 148086656L;
+
     LayoutInflater mInflater;
     TypedArray mThemeAttrs;
     @UnsupportedAppUsage
@@ -1527,6 +1542,11 @@
     }
 
     @Override public void onCreate() {
+        if (methodIsOverridden("onCreateInputMethodSessionInterface")
+                && CompatChanges.isChangeEnabled(DISALLOW_INPUT_METHOD_INTERFACE_OVERRIDE)) {
+            throw new LinkageError("InputMethodService#onCreateInputMethodSessionInterface()"
+                    + " can no longer be overridden!");
+        }
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.onCreate");
         mTheme = Resources.selectSystemTheme(mTheme,
                 getApplicationInfo().targetSdkVersion,
@@ -1764,6 +1784,9 @@
      * {@link InputMethodService#onDisplayCompletions(CompletionInfo[])},
      * {@link InputMethodService#onUpdateExtractedText(int, ExtractedText)},
      * {@link InputMethodService#onUpdateSelection(int, int, int, int, int, int)} instead.
+     *
+     * <p>IMEs targeting on Android U and above cannot override this method, or an
+     * {@link LinkageError} would be thrown.</p>
      */
     @Deprecated
     @Override
@@ -4067,4 +4090,13 @@
         final KeyEvent upEvent = createBackKeyEvent(KeyEvent.ACTION_UP, hasStartedTracking);
         onKeyUp(KeyEvent.KEYCODE_BACK, upEvent);
     }
+
+    private boolean methodIsOverridden(String methodName, Class<?>... parameterTypes) {
+        try {
+            return getClass().getMethod(methodName, parameterTypes).getDeclaringClass()
+                    != InputMethodService.class;
+        } catch (NoSuchMethodException e) {
+            throw new RuntimeException("Method must exist.", e);
+        }
+    }
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index b2a26fa..067946e 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -67,6 +67,7 @@
 import android.view.displayhash.DisplayHash;
 import android.view.displayhash.VerifiedDisplayHash;
 import android.window.ITaskFpsCallback;
+import android.window.ScreenCapture;
 
 /**
  * System private interface to the window manager.
@@ -968,4 +969,11 @@
      * treatment.
      */
     boolean isLetterboxBackgroundMultiColored();
+
+    /**
+     * Captures the entire display specified by the displayId using the args provided. If the args
+     * are null or if the sourceCrop is invalid or null, the entire display bounds will be captured.
+     */
+    oneway void captureDisplay(int displayId, in @nullable ScreenCapture.CaptureArgs captureArgs,
+            in ScreenCapture.ScreenCaptureListener listener);
 }
diff --git a/core/java/android/window/ScreenCapture.aidl b/core/java/android/window/ScreenCapture.aidl
new file mode 100644
index 0000000..267a7c6
--- /dev/null
+++ b/core/java/android/window/ScreenCapture.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 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.window;
+
+/** @hide */
+parcelable ScreenCapture.CaptureArgs;
+
+/** @hide */
+parcelable ScreenCapture.ScreenshotHardwareBuffer;
+
+/** @hide */
+parcelable ScreenCapture.ScreenCaptureListener;
\ No newline at end of file
diff --git a/core/java/android/window/ScreenCapture.java b/core/java/android/window/ScreenCapture.java
index 887d027..8a7efb9 100644
--- a/core/java/android/window/ScreenCapture.java
+++ b/core/java/android/window/ScreenCapture.java
@@ -24,11 +24,17 @@
 import android.graphics.Rect;
 import android.hardware.HardwareBuffer;
 import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.util.Log;
+import android.util.Pair;
 import android.view.SurfaceControl;
 
+import libcore.util.NativeAllocationRegistry;
+
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
 
 /**
  * Handles display and layer captures for the system.
@@ -37,20 +43,26 @@
  */
 public class ScreenCapture {
     private static final String TAG = "ScreenCapture";
+    private static final int SCREENSHOT_WAIT_TIME_S = 1;
 
     private static native int nativeCaptureDisplay(DisplayCaptureArgs captureArgs,
-            ScreenCaptureListener captureListener);
+            long captureListener);
     private static native int nativeCaptureLayers(LayerCaptureArgs captureArgs,
-            ScreenCaptureListener captureListener);
+            long captureListener);
+    private static native long nativeCreateScreenCaptureListener(
+            Consumer<ScreenshotHardwareBuffer> consumer);
+    private static native void nativeWriteListenerToParcel(long nativeObject, Parcel out);
+    private static native long nativeReadListenerFromParcel(Parcel in);
+    private static native long getNativeListenerFinalizer();
 
     /**
-     * @param captureArgs Arguments about how to take the screenshot
+     * @param captureArgs     Arguments about how to take the screenshot
      * @param captureListener A listener to receive the screenshot callback
      * @hide
      */
     public static int captureDisplay(@NonNull DisplayCaptureArgs captureArgs,
             @NonNull ScreenCaptureListener captureListener) {
-        return nativeCaptureDisplay(captureArgs, captureListener);
+        return nativeCaptureDisplay(captureArgs, captureListener.mNativeObject);
     }
 
     /**
@@ -61,28 +73,29 @@
      */
     public static ScreenshotHardwareBuffer captureDisplay(
             DisplayCaptureArgs captureArgs) {
-        SyncScreenCaptureListener
-                screenCaptureListener = new SyncScreenCaptureListener();
-
-        int status = captureDisplay(captureArgs, screenCaptureListener);
+        Pair<ScreenCaptureListener, ScreenshotSync> syncScreenCapture = createSyncCaptureListener();
+        int status = captureDisplay(captureArgs, syncScreenCapture.first);
         if (status != 0) {
             return null;
         }
 
-        return screenCaptureListener.waitForScreenshot();
+        try {
+            return syncScreenCapture.second.get();
+        } catch (Exception e) {
+            return null;
+        }
     }
 
     /**
      * Captures a layer and its children and returns a {@link HardwareBuffer} with the content.
      *
-     * @param layer            The root layer to capture.
-     * @param sourceCrop       The portion of the root surface to capture; caller may pass in 'new
-     *                         Rect()' or null if no cropping is desired. If the root layer does not
-     *                         have a buffer or a crop set, then a non-empty source crop must be
-     *                         specified.
-     * @param frameScale       The desired scale of the returned buffer; the raw
-     *                         screen will be scaled up/down.
-     *
+     * @param layer      The root layer to capture.
+     * @param sourceCrop The portion of the root surface to capture; caller may pass in 'new
+     *                   Rect()' or null if no cropping is desired. If the root layer does not
+     *                   have a buffer or a crop set, then a non-empty source crop must be
+     *                   specified.
+     * @param frameScale The desired scale of the returned buffer; the raw screen will be scaled
+     *                   up/down.
      * @return Returns a HardwareBuffer that contains the layer capture.
      * @hide
      */
@@ -94,15 +107,14 @@
     /**
      * Captures a layer and its children and returns a {@link HardwareBuffer} with the content.
      *
-     * @param layer            The root layer to capture.
-     * @param sourceCrop       The portion of the root surface to capture; caller may pass in 'new
-     *                         Rect()' or null if no cropping is desired. If the root layer does not
-     *                         have a buffer or a crop set, then a non-empty source crop must be
-     *                         specified.
-     * @param frameScale       The desired scale of the returned buffer; the raw
-     *                         screen will be scaled up/down.
-     * @param format           The desired pixel format of the returned buffer.
-     *
+     * @param layer      The root layer to capture.
+     * @param sourceCrop The portion of the root surface to capture; caller may pass in 'new
+     *                   Rect()' or null if no cropping is desired. If the root layer does not
+     *                   have a buffer or a crop set, then a non-empty source crop must be
+     *                   specified.
+     * @param frameScale The desired scale of the returned buffer; the raw screen will be scaled
+     *                   up/down.
+     * @param format     The desired pixel format of the returned buffer.
      * @return Returns a HardwareBuffer that contains the layer capture.
      * @hide
      */
@@ -120,21 +132,24 @@
     /**
      * @hide
      */
-    public static ScreenshotHardwareBuffer captureLayers(
-            LayerCaptureArgs captureArgs) {
-        SyncScreenCaptureListener screenCaptureListener = new SyncScreenCaptureListener();
-
-        int status = captureLayers(captureArgs, screenCaptureListener);
+    public static ScreenshotHardwareBuffer captureLayers(LayerCaptureArgs captureArgs) {
+        Pair<ScreenCaptureListener, ScreenshotSync> syncScreenCapture = createSyncCaptureListener();
+        int status = captureLayers(captureArgs, syncScreenCapture.first);
         if (status != 0) {
             return null;
         }
 
-        return screenCaptureListener.waitForScreenshot();
+        try {
+            return syncScreenCapture.second.get();
+        } catch (Exception e) {
+            return null;
+        }
     }
 
     /**
      * Like {@link #captureLayers(SurfaceControl, Rect, float, int)} but with an array of layer
      * handles to exclude.
+     *
      * @hide
      */
     public static ScreenshotHardwareBuffer captureLayersExcluding(SurfaceControl layer,
@@ -150,24 +165,13 @@
     }
 
     /**
-     * @param captureArgs Arguments about how to take the screenshot
+     * @param captureArgs     Arguments about how to take the screenshot
      * @param captureListener A listener to receive the screenshot callback
      * @hide
      */
     public static int captureLayers(@NonNull LayerCaptureArgs captureArgs,
             @NonNull ScreenCaptureListener captureListener) {
-        return nativeCaptureLayers(captureArgs, captureListener);
-    }
-
-    /**
-     * @hide
-     */
-    public interface ScreenCaptureListener {
-        /**
-         * The callback invoked when the screen capture is complete.
-         * @param hardwareBuffer Data containing info about the screen capture.
-         */
-        void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer);
+        return nativeCaptureLayers(captureArgs, captureListener.mNativeObject);
     }
 
     /**
@@ -190,15 +194,16 @@
             mContainsHdrLayers = containsHdrLayers;
         }
 
-       /**
-        * Create ScreenshotHardwareBuffer from an existing HardwareBuffer object.
-        * @param hardwareBuffer The existing HardwareBuffer object
-        * @param namedColorSpace Integer value of a named color space {@link ColorSpace.Named}
-        * @param containsSecureLayers Indicates whether this graphic buffer contains captured
-        *                             contents of secure layers, in which case the screenshot
-        *                             should not be persisted.
-        * @param containsHdrLayers Indicates whether this graphic buffer contains HDR content.
-        */
+        /**
+         * Create ScreenshotHardwareBuffer from an existing HardwareBuffer object.
+         *
+         * @param hardwareBuffer       The existing HardwareBuffer object
+         * @param namedColorSpace      Integer value of a named color space {@link ColorSpace.Named}
+         * @param containsSecureLayers Indicates whether this graphic buffer contains captured
+         *                             contents of secure layers, in which case the screenshot
+         *                             should not be persisted.
+         * @param containsHdrLayers    Indicates whether this graphic buffer contains HDR content.
+         */
         private static ScreenshotHardwareBuffer createFromNative(HardwareBuffer hardwareBuffer,
                 int namedColorSpace, boolean containsSecureLayers, boolean containsHdrLayers) {
             ColorSpace colorSpace = ColorSpace.get(ColorSpace.Named.values()[namedColorSpace]);
@@ -220,6 +225,7 @@
         public boolean containsSecureLayers() {
             return mContainsSecureLayers;
         }
+
         /**
          * Returns whether the screenshot contains at least one HDR layer.
          * This information may be useful for informing the display whether this screenshot
@@ -234,7 +240,7 @@
          * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap
          * into
          * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
-         *
+         * <p>
          * CAVEAT: This can be extremely slow; avoid use unless absolutely necessary; prefer to
          * directly
          * use the {@link HardwareBuffer} directly.
@@ -250,44 +256,23 @@
         }
     }
 
-    private static class SyncScreenCaptureListener implements ScreenCaptureListener {
-        private static final int SCREENSHOT_WAIT_TIME_S = 1;
-        private ScreenshotHardwareBuffer mScreenshotHardwareBuffer;
-        private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
-
-        @Override
-        public void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer) {
-            mScreenshotHardwareBuffer = hardwareBuffer;
-            mCountDownLatch.countDown();
-        }
-
-        private ScreenshotHardwareBuffer waitForScreenshot() {
-            try {
-                mCountDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS);
-            } catch (Exception e) {
-                Log.e(TAG, "Failed to wait for screen capture result", e);
-            }
-
-            return mScreenshotHardwareBuffer;
-        }
-    }
-
     /**
      * A common arguments class used for various screenshot requests. This contains arguments that
      * are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs}
+     *
      * @hide
      */
-    private abstract static class CaptureArgs {
-        private final int mPixelFormat;
-        private final Rect mSourceCrop = new Rect();
-        private final float mFrameScaleX;
-        private final float mFrameScaleY;
-        private final boolean mCaptureSecureLayers;
-        private final boolean mAllowProtected;
-        private final long mUid;
-        private final boolean mGrayscale;
+    public static class CaptureArgs implements Parcelable {
+        public final int mPixelFormat;
+        public final Rect mSourceCrop = new Rect();
+        public final float mFrameScaleX;
+        public final float mFrameScaleY;
+        public final boolean mCaptureSecureLayers;
+        public final boolean mAllowProtected;
+        public final long mUid;
+        public final boolean mGrayscale;
 
-        private CaptureArgs(Builder<? extends Builder<?>> builder) {
+        private CaptureArgs(CaptureArgs.Builder<? extends CaptureArgs.Builder<?>> builder) {
             mPixelFormat = builder.mPixelFormat;
             mSourceCrop.set(builder.mSourceCrop);
             mFrameScaleX = builder.mFrameScaleX;
@@ -298,12 +283,23 @@
             mGrayscale = builder.mGrayscale;
         }
 
+        private CaptureArgs(Parcel in) {
+            mPixelFormat = in.readInt();
+            mSourceCrop.readFromParcel(in);
+            mFrameScaleX = in.readFloat();
+            mFrameScaleY = in.readFloat();
+            mCaptureSecureLayers = in.readBoolean();
+            mAllowProtected = in.readBoolean();
+            mUid = in.readLong();
+            mGrayscale = in.readBoolean();
+        }
+
         /**
          * The Builder class used to construct {@link CaptureArgs}
          *
-         * @param <T> A builder that extends {@link Builder}
+         * @param <T> A builder that extends {@link CaptureArgs.Builder}
          */
-        abstract static class Builder<T extends Builder<T>> {
+        public static class Builder<T extends CaptureArgs.Builder<T>> {
             private int mPixelFormat = PixelFormat.RGBA_8888;
             private final Rect mSourceCrop = new Rect();
             private float mFrameScaleX = 1;
@@ -314,6 +310,14 @@
             private boolean mGrayscale;
 
             /**
+             * Construct a new {@link CaptureArgs} with the set parameters. The builder remains
+             * valid.
+             */
+            public CaptureArgs build() {
+                return new CaptureArgs(this);
+            }
+
+            /**
              * The desired pixel format of the returned buffer.
              */
             public T setPixelFormat(int pixelFormat) {
@@ -395,15 +399,47 @@
             /**
              * Each sub class should return itself to allow the builder to chain properly
              */
-            abstract T getThis();
+            T getThis() {
+                return (T) this;
+            }
         }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeInt(mPixelFormat);
+            mSourceCrop.writeToParcel(dest, flags);
+            dest.writeFloat(mFrameScaleX);
+            dest.writeFloat(mFrameScaleY);
+            dest.writeBoolean(mCaptureSecureLayers);
+            dest.writeBoolean(mAllowProtected);
+            dest.writeLong(mUid);
+            dest.writeBoolean(mGrayscale);
+        }
+
+        public static final Parcelable.Creator<CaptureArgs> CREATOR =
+                new Parcelable.Creator<CaptureArgs>() {
+                    @Override
+                    public CaptureArgs createFromParcel(Parcel in) {
+                        return new CaptureArgs(in);
+                    }
+
+                    @Override
+                    public CaptureArgs[] newArray(int size) {
+                        return new CaptureArgs[size];
+                    }
+                };
     }
 
     /**
      * The arguments class used to make display capture requests.
      *
-     * @see #nativeCaptureDisplay(DisplayCaptureArgs, ScreenCaptureListener)
      * @hide
+     * @see #nativeCaptureDisplay(DisplayCaptureArgs, long)
      */
     public static class DisplayCaptureArgs extends CaptureArgs {
         private final IBinder mDisplayToken;
@@ -488,8 +524,8 @@
     /**
      * The arguments class used to make layer capture requests.
      *
-     * @see #nativeCaptureLayers(LayerCaptureArgs, ScreenCaptureListener)
      * @hide
+     * @see #nativeCaptureLayers(LayerCaptureArgs, long)
      */
     public static class LayerCaptureArgs extends CaptureArgs {
         private final long mNativeLayer;
@@ -530,6 +566,17 @@
                 return new LayerCaptureArgs(this);
             }
 
+            public Builder(SurfaceControl layer, CaptureArgs args) {
+                setLayer(layer);
+                setPixelFormat(args.mPixelFormat);
+                setSourceCrop(args.mSourceCrop);
+                setFrameScale(args.mFrameScaleX, args.mFrameScaleY);
+                setCaptureSecureLayers(args.mCaptureSecureLayers);
+                setAllowProtected(args.mAllowProtected);
+                setUid(args.mUid);
+                setGrayscale(args.mGrayscale);
+            }
+
             public Builder(SurfaceControl layer) {
                 setLayer(layer);
             }
@@ -542,7 +589,6 @@
                 return this;
             }
 
-
             /**
              * An array of layer handles to exclude.
              */
@@ -564,8 +610,109 @@
             Builder getThis() {
                 return this;
             }
-
         }
     }
 
+    /**
+     * The object used to receive the results when invoking screen capture requests via
+     * {@link #captureDisplay(DisplayCaptureArgs, ScreenCaptureListener)} or
+     * {@link #captureLayers(LayerCaptureArgs, ScreenCaptureListener)}
+     *
+     * This listener can only be used for a single call to capture content call.
+     */
+    public static class ScreenCaptureListener implements Parcelable {
+        private final long mNativeObject;
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        ScreenCaptureListener.class.getClassLoader(), getNativeListenerFinalizer());
+
+        /**
+         * @param consumer The callback invoked when the screen capture is complete.
+         */
+        public ScreenCaptureListener(Consumer<ScreenshotHardwareBuffer> consumer) {
+            mNativeObject = nativeCreateScreenCaptureListener(consumer);
+            sRegistry.registerNativeAllocation(this, mNativeObject);
+        }
+
+        private ScreenCaptureListener(Parcel in) {
+            if (in.readBoolean()) {
+                mNativeObject = nativeReadListenerFromParcel(in);
+                sRegistry.registerNativeAllocation(this, mNativeObject);
+            } else {
+                mNativeObject = 0;
+            }
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            if (mNativeObject == 0) {
+                dest.writeBoolean(false);
+            } else {
+                dest.writeBoolean(true);
+                nativeWriteListenerToParcel(mNativeObject, dest);
+            }
+        }
+
+        public static final Parcelable.Creator<ScreenCaptureListener> CREATOR =
+                new Parcelable.Creator<ScreenCaptureListener>() {
+                    @Override
+                    public ScreenCaptureListener createFromParcel(Parcel in) {
+                        return new ScreenCaptureListener(in);
+                    }
+
+                    @Override
+                    public ScreenCaptureListener[] newArray(int size) {
+                        return new ScreenCaptureListener[0];
+                    }
+                };
+    }
+
+    /**
+     * A helper method to handle the async screencapture callbacks synchronously. This should only
+     * be used if the screencapture caller doesn't care that it blocks waiting for a screenshot.
+     *
+     * @return a Pair that holds the {@link ScreenCaptureListener} that should be used for capture
+     * calls into SurfaceFlinger and a {@link ScreenshotSync} object to retrieve the results.
+     */
+    public static Pair<ScreenCaptureListener, ScreenshotSync> createSyncCaptureListener() {
+        final ScreenshotSync screenshotSync = new ScreenshotSync();
+        final ScreenCaptureListener screenCaptureListener = new ScreenCaptureListener(
+                screenshotSync::setScreenshotHardwareBuffer);
+        return new Pair<>(screenCaptureListener, screenshotSync);
+    }
+
+    /**
+     * Helper class to synchronously get the {@link ScreenshotHardwareBuffer} when calling
+     * {@link #captureLayers(LayerCaptureArgs, ScreenCaptureListener)} or
+     * {@link #captureDisplay(DisplayCaptureArgs, ScreenCaptureListener)}
+     */
+    public static class ScreenshotSync {
+        private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
+        private ScreenshotHardwareBuffer mScreenshotHardwareBuffer;
+
+        private void setScreenshotHardwareBuffer(
+                ScreenshotHardwareBuffer screenshotHardwareBuffer) {
+            mScreenshotHardwareBuffer = screenshotHardwareBuffer;
+            mCountDownLatch.countDown();
+        }
+
+        /**
+         * Get the {@link ScreenshotHardwareBuffer} synchronously. This can be null if the
+         * screenshot failed or if there was no callback in {@link #SCREENSHOT_WAIT_TIME_S} seconds.
+         */
+        public ScreenshotHardwareBuffer get() {
+            try {
+                mCountDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS);
+                return mScreenshotHardwareBuffer;
+            } catch (Exception e) {
+                Log.e(TAG, "Failed to wait for screen capture result", e);
+                return null;
+            }
+        }
+    }
 }
diff --git a/core/jni/android_window_ScreenCapture.cpp b/core/jni/android_window_ScreenCapture.cpp
index 3bada15..c1929c6 100644
--- a/core/jni/android_window_ScreenCapture.cpp
+++ b/core/jni/android_window_ScreenCapture.cpp
@@ -61,9 +61,8 @@
 } gLayerCaptureArgsClassInfo;
 
 static struct {
-    jclass clazz;
-    jmethodID onScreenCaptureComplete;
-} gScreenCaptureListenerClassInfo;
+    jmethodID accept;
+} gConsumerClassInfo;
 
 static struct {
     jclass clazz;
@@ -98,14 +97,14 @@
 public:
     explicit ScreenCaptureListenerWrapper(JNIEnv* env, jobject jobject) {
         env->GetJavaVM(&mVm);
-        mScreenCaptureListenerObject = env->NewGlobalRef(jobject);
-        LOG_ALWAYS_FATAL_IF(!mScreenCaptureListenerObject, "Failed to make global ref");
+        mConsumerObject = env->NewGlobalRef(jobject);
+        LOG_ALWAYS_FATAL_IF(!mConsumerObject, "Failed to make global ref");
     }
 
     ~ScreenCaptureListenerWrapper() {
-        if (mScreenCaptureListenerObject) {
-            getenv()->DeleteGlobalRef(mScreenCaptureListenerObject);
-            mScreenCaptureListenerObject = nullptr;
+        if (mConsumerObject) {
+            getenv()->DeleteGlobalRef(mConsumerObject);
+            mConsumerObject = nullptr;
         }
     }
 
@@ -113,9 +112,8 @@
             const gui::ScreenCaptureResults& captureResults) override {
         JNIEnv* env = getenv();
         if (!captureResults.fenceResult.ok() || captureResults.buffer == nullptr) {
-            env->CallVoidMethod(mScreenCaptureListenerObject,
-                                gScreenCaptureListenerClassInfo.onScreenCaptureComplete, nullptr);
-            checkAndClearException(env, "onScreenCaptureComplete");
+            env->CallVoidMethod(mConsumerObject, gConsumerClassInfo.accept, nullptr);
+            checkAndClearException(env, "accept");
             return binder::Status::ok();
         }
         captureResults.fenceResult.value()->waitForever(LOG_TAG);
@@ -130,17 +128,15 @@
                                             captureResults.capturedSecureLayers,
                                             captureResults.capturedHdrLayers);
         checkAndClearException(env, "builder");
-        env->CallVoidMethod(mScreenCaptureListenerObject,
-                            gScreenCaptureListenerClassInfo.onScreenCaptureComplete,
-                            screenshotHardwareBuffer);
-        checkAndClearException(env, "onScreenCaptureComplete");
+        env->CallVoidMethod(mConsumerObject, gConsumerClassInfo.accept, screenshotHardwareBuffer);
+        checkAndClearException(env, "accept");
         env->DeleteLocalRef(jhardwareBuffer);
         env->DeleteLocalRef(screenshotHardwareBuffer);
         return binder::Status::ok();
     }
 
 private:
-    jobject mScreenCaptureListenerObject;
+    jobject mConsumerObject;
     JavaVM* mVm;
 
     JNIEnv* getenv() {
@@ -194,7 +190,7 @@
 }
 
 static jint nativeCaptureDisplay(JNIEnv* env, jclass clazz, jobject displayCaptureArgsObject,
-                                 jobject screenCaptureListenerObject) {
+                                 jlong screenCaptureListenerObject) {
     const DisplayCaptureArgs captureArgs =
             displayCaptureArgsFromObject(env, displayCaptureArgsObject);
 
@@ -202,13 +198,13 @@
         return BAD_VALUE;
     }
 
-    sp<IScreenCaptureListener> captureListener =
-            sp<ScreenCaptureListenerWrapper>::make(env, screenCaptureListenerObject);
+    sp<gui::IScreenCaptureListener> captureListener =
+            reinterpret_cast<gui::IScreenCaptureListener*>(screenCaptureListenerObject);
     return ScreenshotClient::captureDisplay(captureArgs, captureListener);
 }
 
 static jint nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureArgsObject,
-                                jobject screenCaptureListenerObject) {
+                                jlong screenCaptureListenerObject) {
     LayerCaptureArgs captureArgs;
     getCaptureArgs(env, layerCaptureArgsObject, captureArgs);
     SurfaceControl* layer = reinterpret_cast<SurfaceControl*>(
@@ -238,21 +234,70 @@
         }
     }
 
-    sp<IScreenCaptureListener> captureListener =
-            sp<ScreenCaptureListenerWrapper>::make(env, screenCaptureListenerObject);
+    sp<gui::IScreenCaptureListener> captureListener =
+            reinterpret_cast<gui::IScreenCaptureListener*>(screenCaptureListenerObject);
     return ScreenshotClient::captureLayers(captureArgs, captureListener);
 }
 
+static jlong nativeCreateScreenCaptureListener(JNIEnv* env, jclass clazz, jobject consumerObj) {
+    sp<gui::IScreenCaptureListener> listener =
+            sp<ScreenCaptureListenerWrapper>::make(env, consumerObj);
+    listener->incStrong((void*)nativeCreateScreenCaptureListener);
+    return reinterpret_cast<jlong>(listener.get());
+}
+
+static void nativeWriteListenerToParcel(JNIEnv* env, jclass clazz, jlong nativeObject,
+                                        jobject parcelObj) {
+    Parcel* parcel = parcelForJavaObject(env, parcelObj);
+    if (parcel == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    ScreenCaptureListenerWrapper* const self =
+            reinterpret_cast<ScreenCaptureListenerWrapper*>(nativeObject);
+    if (self != nullptr) {
+        parcel->writeStrongBinder(IInterface::asBinder(self));
+    }
+}
+
+static jlong nativeReadListenerFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) {
+    Parcel* parcel = parcelForJavaObject(env, parcelObj);
+    if (parcel == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return 0;
+    }
+    sp<gui::IScreenCaptureListener> listener =
+            interface_cast<gui::IScreenCaptureListener>(parcel->readStrongBinder());
+    if (listener == nullptr) {
+        return 0;
+    }
+    listener->incStrong((void*)nativeCreateScreenCaptureListener);
+    return reinterpret_cast<jlong>(listener.get());
+}
+
+void destroyNativeListener(void* ptr) {
+    ScreenCaptureListenerWrapper* listener = reinterpret_cast<ScreenCaptureListenerWrapper*>(ptr);
+    listener->decStrong((void*)nativeCreateScreenCaptureListener);
+}
+
+static jlong getNativeListenerFinalizer(JNIEnv* env, jclass clazz) {
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeListener));
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod sScreenCaptureMethods[] = {
         // clang-format off
-   {"nativeCaptureDisplay",
-            "(Landroid/window/ScreenCapture$DisplayCaptureArgs;Landroid/window/ScreenCapture$ScreenCaptureListener;)I",
+    {"nativeCaptureDisplay", "(Landroid/window/ScreenCapture$DisplayCaptureArgs;J)I",
             (void*)nativeCaptureDisplay },
-    {"nativeCaptureLayers",
-            "(Landroid/window/ScreenCapture$LayerCaptureArgs;Landroid/window/ScreenCapture$ScreenCaptureListener;)I",
+    {"nativeCaptureLayers",  "(Landroid/window/ScreenCapture$LayerCaptureArgs;J)I",
             (void*)nativeCaptureLayers },
+    {"nativeCreateScreenCaptureListener", "(Ljava/util/function/Consumer;)J",
+            (void*)nativeCreateScreenCaptureListener },
+    {"nativeWriteListenerToParcel", "(JLandroid/os/Parcel;)V", (void*)nativeWriteListenerToParcel },
+    {"nativeReadListenerFromParcel", "(Landroid/os/Parcel;)J",
+            (void*)nativeReadListenerFromParcel },
+    {"getNativeListenerFinalizer", "()J", (void*)getNativeListenerFinalizer },
         // clang-format on
 };
 
@@ -293,12 +338,8 @@
     gLayerCaptureArgsClassInfo.childrenOnly =
             GetFieldIDOrDie(env, layerCaptureArgsClazz, "mChildrenOnly", "Z");
 
-    jclass screenCaptureListenerClazz =
-            FindClassOrDie(env, "android/window/ScreenCapture$ScreenCaptureListener");
-    gScreenCaptureListenerClassInfo.clazz = MakeGlobalRefOrDie(env, screenCaptureListenerClazz);
-    gScreenCaptureListenerClassInfo.onScreenCaptureComplete =
-            GetMethodIDOrDie(env, screenCaptureListenerClazz, "onScreenCaptureComplete",
-                             "(Landroid/window/ScreenCapture$ScreenshotHardwareBuffer;)V");
+    jclass consumer = FindClassOrDie(env, "java/util/function/Consumer");
+    gConsumerClassInfo.accept = GetMethodIDOrDie(env, consumer, "accept", "(Ljava/lang/Object;)V");
 
     jclass screenshotGraphicsBufferClazz =
             FindClassOrDie(env, "android/window/ScreenCapture$ScreenshotHardwareBuffer");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index c11c577..37a50b6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -188,14 +188,16 @@
             @ShellMainThread Choreographer mainChoreographer,
             ShellTaskOrganizer taskOrganizer,
             DisplayController displayController,
-            SyncTransactionQueue syncQueue) {
+            SyncTransactionQueue syncQueue,
+            @DynamicOverride DesktopModeController desktopModeController) {
         return new CaptionWindowDecorViewModel(
                         context,
                         mainHandler,
                         mainChoreographer,
                         taskOrganizer,
                         displayController,
-                        syncQueue);
+                        syncQueue,
+                        desktopModeController);
     }
 
     //
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
index 9474cfe..99739c4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
@@ -177,6 +177,25 @@
     }
 
     /**
+     * Turn desktop mode on or off
+     * @param active the desired state for desktop mode setting
+     */
+    public void setDesktopModeActive(boolean active) {
+        int value = active ? 1 : 0;
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.DESKTOP_MODE, value);
+    }
+
+    /**
+     * Returns the windowing mode of the display area with the specified displayId.
+     * @param displayId
+     * @return
+     */
+    public int getDisplayAreaWindowingMode(int displayId) {
+        return mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId)
+                .configuration.windowConfiguration.getWindowingMode();
+    }
+
+    /**
      * A {@link ContentObserver} for listening to changes to {@link Settings.System#DESKTOP_MODE}
      */
     private final class SettingsObserver extends ContentObserver {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 8b36db920..9e49b51 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -37,6 +37,7 @@
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.desktopmode.DesktopModeController;
 import com.android.wm.shell.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
 import com.android.wm.shell.transition.Transitions;
@@ -54,6 +55,7 @@
     private final DisplayController mDisplayController;
     private final SyncTransactionQueue mSyncQueue;
     private FreeformTaskTransitionStarter mTransitionStarter;
+    private DesktopModeController mDesktopModeController;
 
     public CaptionWindowDecorViewModel(
             Context context,
@@ -61,7 +63,8 @@
             Choreographer mainChoreographer,
             ShellTaskOrganizer taskOrganizer,
             DisplayController displayController,
-            SyncTransactionQueue syncQueue) {
+            SyncTransactionQueue syncQueue,
+            DesktopModeController desktopModeController) {
         mContext = context;
         mMainHandler = mainHandler;
         mMainChoreographer = mainChoreographer;
@@ -69,6 +72,7 @@
         mTaskOrganizer = taskOrganizer;
         mDisplayController = displayController;
         mSyncQueue = syncQueue;
+        mDesktopModeController = desktopModeController;
     }
 
     @Override
@@ -211,8 +215,10 @@
         }
 
         private void handleEventForMove(MotionEvent e) {
-            if (mTaskOrganizer.getRunningTaskInfo(mTaskId).getWindowingMode()
-                    == WINDOWING_MODE_FULLSCREEN) {
+            RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
+            int windowingMode =  mDesktopModeController
+                    .getDisplayAreaWindowingMode(taskInfo.displayId);
+            if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
                 return;
             }
             switch (e.getActionMasked()) {
@@ -230,8 +236,14 @@
                 case MotionEvent.ACTION_UP:
                 case MotionEvent.ACTION_CANCEL: {
                     int dragPointerIdx = e.findPointerIndex(mDragPointerId);
+                    int statusBarHeight = mDisplayController.getDisplayLayout(taskInfo.displayId)
+                            .stableInsets().top;
                     mDragResizeCallback.onDragResizeEnd(
                             e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
+                    if (e.getRawY(dragPointerIdx) <= statusBarHeight
+                            && windowingMode == WINDOWING_MODE_FREEFORM) {
+                        mDesktopModeController.setDesktopModeActive(false);
+                    }
                     break;
                 }
             }
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 59c914f..03f02de 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -243,7 +243,9 @@
     mContext->unpinImages();
 
     for (size_t i = 0; i < mLayers.size(); i++) {
-        mLayers[i]->apply();
+        if (mLayers[i]) {
+            mLayers[i]->apply();
+        }
     }
     mLayers.clear();
     mContext->setContentDrawBounds(mContentDrawBounds);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index be9862b..49b314d 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -242,13 +242,14 @@
      * To decode such an image, {@link MediaCodec} decoder for
      * {@link #MIMETYPE_VIDEO_HEVC} shall be used. The client needs to form
      * the correct {@link #MediaFormat} based on additional information in
-     * the track format, and send it to {@link MediaCodec#configure}.
+     * the track format (shown in the next paragraph), and send it to
+     * {@link MediaCodec#configure}.
      *
      * The track's MediaFormat will come with {@link #KEY_WIDTH} and
      * {@link #KEY_HEIGHT} keys, which describes the width and height
      * of the image. If the image doesn't contain grid (i.e. none of
      * {@link #KEY_TILE_WIDTH}, {@link #KEY_TILE_HEIGHT},
-     * {@link #KEY_GRID_ROWS}, {@link #KEY_GRID_COLUMNS} are present}), the
+     * {@link #KEY_GRID_ROWS}, {@link #KEY_GRID_COLUMNS} are present), the
      * track will contain a single sample of coded data for the entire image,
      * and the image width and height should be used to set up the decoder.
      *
@@ -266,6 +267,36 @@
     public static final String MIMETYPE_IMAGE_ANDROID_HEIC = "image/vnd.android.heic";
 
     /**
+     * MIME type for AVIF still image data encoded in AV1.
+     *
+     * To decode such an image, {@link MediaCodec} decoder for
+     * {@link #MIMETYPE_VIDEO_AV1} shall be used. The client needs to form
+     * the correct {@link #MediaFormat} based on additional information in
+     * the track format (shown in the next paragraph), and send it to
+     * {@link MediaCodec#configure}.
+     *
+     * The track's MediaFormat will come with {@link #KEY_WIDTH} and
+     * {@link #KEY_HEIGHT} keys, which describes the width and height
+     * of the image. If the image doesn't contain grid (i.e. none of
+     * {@link #KEY_TILE_WIDTH}, {@link #KEY_TILE_HEIGHT},
+     * {@link #KEY_GRID_ROWS}, {@link #KEY_GRID_COLUMNS} are present), the
+     * track will contain a single sample of coded data for the entire image,
+     * and the image width and height should be used to set up the decoder.
+     *
+     * If the image does come with grid, each sample from the track will
+     * contain one tile in the grid, of which the size is described by
+     * {@link #KEY_TILE_WIDTH} and {@link #KEY_TILE_HEIGHT}. This size
+     * (instead of {@link #KEY_WIDTH} and {@link #KEY_HEIGHT}) should be
+     * used to set up the decoder. The track contains {@link #KEY_GRID_ROWS}
+     * by {@link #KEY_GRID_COLUMNS} samples in row-major, top-row first,
+     * left-to-right order. The output image should be reconstructed by
+     * first tiling the decoding results of the tiles in the correct order,
+     * then trimming (before rotation is applied) on the bottom and right
+     * side, if the tiled area is larger than the image width and height.
+     */
+    public static final String MIMETYPE_IMAGE_AVIF = "image/avif";
+
+    /**
      * MIME type for WebVTT subtitle data.
      */
     public static final String MIMETYPE_TEXT_VTT = "text/vtt";
@@ -485,9 +516,11 @@
 
     /**
      * A key describing the width (in pixels) of each tile of the content in a
-     * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} track. The associated value is an integer.
+     * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} track.
+     * The associated value is an integer.
      *
-     * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} on decoding instructions of such tracks.
+     * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} on decoding
+     * instructions of such tracks.
      *
      * @see #KEY_TILE_HEIGHT
      * @see #KEY_GRID_ROWS
@@ -497,9 +530,11 @@
 
     /**
      * A key describing the height (in pixels) of each tile of the content in a
-     * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} track. The associated value is an integer.
+     * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} track.
+     * The associated value is an integer.
      *
-     * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} on decoding instructions of such tracks.
+     * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} on decoding
+     * instructions of such tracks.
      *
      * @see #KEY_TILE_WIDTH
      * @see #KEY_GRID_ROWS
@@ -509,9 +544,11 @@
 
     /**
      * A key describing the number of grid rows in the content in a
-     * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} track. The associated value is an integer.
+     * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} track.
+     * The associated value is an integer.
      *
-     * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} on decoding instructions of such tracks.
+     * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} on decoding
+     * instructions of such tracks.
      *
      * @see #KEY_TILE_WIDTH
      * @see #KEY_TILE_HEIGHT
@@ -521,9 +558,11 @@
 
     /**
      * A key describing the number of grid columns in the content in a
-     * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} track. The associated value is an integer.
+     * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} track.
+     * The associated value is an integer.
      *
-     * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} on decoding instructions of such tracks.
+     * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} on decoding
+     * instructions of such tracks.
      *
      * @see #KEY_TILE_WIDTH
      * @see #KEY_TILE_HEIGHT
@@ -1350,9 +1389,9 @@
      * selected in the absence of a specific user choice.
      * This is currently used in two scenarios:
      * 1) for subtitle tracks, when the user selected 'Default' for the captioning locale.
-     * 2) for a {@link #MIMETYPE_IMAGE_ANDROID_HEIC} track, indicating the image is the
-     * primary item in the file.
-
+     * 2) for a {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} track,
+     * indicating the image is the primary item in the file.
+     *
      * The associated value is an integer, where non-0 means TRUE.  This is an optional
      * field; if not specified, DEFAULT is considered to be FALSE.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index f1e54e0..2cd564f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -149,32 +149,6 @@
                 }
             }
         }
-
-    companion object {
-        private const val SQUISHINESS_SCALE_START = 0.5
-        private const val SQUISHINESS_SCALE_FACTOR = 0.5
-        private fun getSquishinessScale(squishinessFraction: Float): Double {
-            return SQUISHINESS_SCALE_START + SQUISHINESS_SCALE_FACTOR * squishinessFraction
-        }
-    }
-
-    var squishinessFraction: Float = 1f
-        set(value) {
-            if (field == value) {
-                return
-            }
-            field = value
-
-            val scale = getSquishinessScale(field)
-            for (mediaPlayer in MediaPlayerData.players()) {
-                mediaPlayer.mediaViewHolder?.let {
-                    it.player.bottom = it.player.top + (scale * it.player.measuredHeight).toInt()
-                } ?: mediaPlayer.recommendationViewHolder?.let {
-                    it.recommendations.bottom = it.recommendations.top +
-                            (scale * it.recommendations.measuredHeight).toInt()
-                }
-            }
-        }
     private val configListener = object : ConfigurationController.ConfigurationListener {
         override fun onDensityOrFontScaleChanged() {
             // System font changes should only happen when UMO is offscreen or a flicker may occur
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index f41b905..18bd6b7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -27,7 +27,6 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.media.MediaCarouselController;
 import com.android.systemui.media.MediaHierarchyManager;
 import com.android.systemui.media.MediaHost;
 import com.android.systemui.media.MediaHostState;
@@ -76,14 +75,13 @@
             @Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
             @Named(QS_PANEL) MediaHost mediaHost,
             QSTileRevealController.Factory qsTileRevealControllerFactory,
-            DumpManager dumpManager, MediaCarouselController mediaCarouselController,
-            MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
+            DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
             QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
             BrightnessSliderController.Factory brightnessSliderFactory,
             FalsingManager falsingManager,
             StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
         super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
-                metricsLogger, uiEventLogger, qsLogger, dumpManager, mediaCarouselController);
+                metricsLogger, uiEventLogger, qsLogger, dumpManager);
         mTunerService = tunerService;
         mQsCustomizerController = qsCustomizerController;
         mQsTileRevealControllerFactory = qsTileRevealControllerFactory;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index a5c60a4..ded466a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -32,7 +32,6 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.Dumpable;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.media.MediaCarouselController;
 import com.android.systemui.media.MediaHost;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTileView;
@@ -71,7 +70,6 @@
     private final UiEventLogger mUiEventLogger;
     private final QSLogger mQSLogger;
     private final DumpManager mDumpManager;
-    private final MediaCarouselController mMediaCarouselController;
     protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
     protected boolean mShouldUseSplitNotificationShade;
 
@@ -133,8 +131,7 @@
             MetricsLogger metricsLogger,
             UiEventLogger uiEventLogger,
             QSLogger qsLogger,
-            DumpManager dumpManager,
-            MediaCarouselController mediaCarouselController
+            DumpManager dumpManager
     ) {
         super(view);
         mHost = host;
@@ -147,7 +144,6 @@
         mDumpManager = dumpManager;
         mShouldUseSplitNotificationShade =
                 LargeScreenUtils.shouldUseSplitNotificationShade(getResources());
-        mMediaCarouselController = mediaCarouselController;
     }
 
     @Override
@@ -165,7 +161,6 @@
 
     public void setSquishinessFraction(float squishinessFraction) {
         mView.setSquishinessFraction(squishinessFraction);
-        mMediaCarouselController.setSquishinessFraction(squishinessFraction);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index 7ce0ad0..9739974 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -26,7 +26,6 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.R;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.media.MediaCarouselController;
 import com.android.systemui.media.MediaHierarchyManager;
 import com.android.systemui.media.MediaHost;
 import com.android.systemui.plugins.qs.QSTile;
@@ -56,10 +55,10 @@
             @Named(QS_USING_COLLAPSED_LANDSCAPE_MEDIA)
                     Provider<Boolean> usingCollapsedLandscapeMediaProvider,
             MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
-            DumpManager dumpManager, MediaCarouselController mediaCarouselController
+            DumpManager dumpManager
     ) {
         super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
-                uiEventLogger, qsLogger, dumpManager, mediaCarouselController);
+                uiEventLogger, qsLogger, dumpManager);
         mUsingCollapsedLandscapeMediaProvider = usingCollapsedLandscapeMediaProvider;
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
index e3e3b74..5ad3542 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
@@ -30,7 +30,6 @@
 import com.android.systemui.statusbar.notification.collection.provider.OnReorderingAllowedListener
 import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider
 import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.util.animation.TransitionLayout
 import com.android.systemui.util.concurrency.DelayableExecutor
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
@@ -46,7 +45,6 @@
 import org.mockito.Mock
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
 import org.mockito.Mockito.`when` as whenever
 import org.mockito.MockitoAnnotations
 
@@ -73,10 +71,6 @@
     @Mock lateinit var dumpManager: DumpManager
     @Mock lateinit var logger: MediaUiEventLogger
     @Mock lateinit var debugLogger: MediaCarouselControllerLogger
-    @Mock lateinit var mediaViewHolder: MediaViewHolder
-    @Mock lateinit var player: TransitionLayout
-    @Mock lateinit var recommendationViewHolder: RecommendationViewHolder
-    @Mock lateinit var recommendations: TransitionLayout
     @Mock lateinit var mediaPlayer: MediaControlPanel
     @Mock lateinit var mediaViewController: MediaViewController
     @Mock lateinit var smartspaceMediaData: SmartspaceMediaData
@@ -282,46 +276,6 @@
         verify(logger).logRecommendationRemoved(eq(packageName), eq(instanceId!!))
     }
 
-    @Test
-    fun testSetSquishinessFractionForMedia_setPlayerBottom() {
-        whenever(panel.mediaViewHolder).thenReturn(mediaViewHolder)
-        whenever(mediaViewHolder.player).thenReturn(player)
-        whenever(player.measuredHeight).thenReturn(100)
-
-        val playingLocal = Triple("playing local",
-                DATA.copy(active = true, isPlaying = true,
-                        playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false),
-                4500L)
-        MediaPlayerData.addMediaPlayer(playingLocal.first, playingLocal.second, panel, clock,
-                false, debugLogger)
-
-        mediaCarouselController.squishinessFraction = 0.0f
-        verify(player).bottom = 50
-        verifyNoMoreInteractions(recommendationViewHolder)
-
-        mediaCarouselController.squishinessFraction = 0.5f
-        verify(player).bottom = 75
-        verifyNoMoreInteractions(recommendationViewHolder)
-    }
-
-    @Test
-    fun testSetSquishinessFractionForRecommendation_setPlayerBottom() {
-        whenever(panel.recommendationViewHolder).thenReturn(recommendationViewHolder)
-        whenever(recommendationViewHolder.recommendations).thenReturn(recommendations)
-        whenever(recommendations.measuredHeight).thenReturn(100)
-
-        MediaPlayerData.addMediaRecommendation(SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA, panel,
-                false, clock)
-
-        mediaCarouselController.squishinessFraction = 0.0f
-        verifyNoMoreInteractions(mediaViewHolder)
-        verify(recommendationViewHolder.recommendations).bottom = 50
-
-        mediaCarouselController.squishinessFraction = 0.5f
-        verifyNoMoreInteractions(mediaViewHolder)
-        verify(recommendationViewHolder.recommendations).bottom = 75
-    }
-
     fun testMediaLoaded_ScrollToActivePlayer() {
         listener.value.onMediaDataLoaded("playing local",
                 null,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index cbe1186..3cad2a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -44,7 +44,6 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.media.MediaCarouselController;
 import com.android.systemui.media.MediaHost;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTileView;
@@ -87,7 +86,6 @@
     @Mock
     private QSLogger mQSLogger;
     private DumpManager mDumpManager = new DumpManager();
-    private MediaCarouselController mMediaCarouselController;
     @Mock
     QSTileImpl mQSTile;
     @Mock
@@ -110,9 +108,9 @@
         protected TestableQSPanelControllerBase(QSPanel view, QSTileHost host,
                 QSCustomizerController qsCustomizerController, MediaHost mediaHost,
                 MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
-                DumpManager dumpManager, MediaCarouselController mediaCarouselController) {
+                DumpManager dumpManager) {
             super(view, host, qsCustomizerController, true, mediaHost, metricsLogger, uiEventLogger,
-                    qsLogger, dumpManager, mediaCarouselController);
+                    qsLogger, dumpManager);
         }
 
         @Override
@@ -146,7 +144,7 @@
 
         mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
                 mQSCustomizerController, mMediaHost,
-                mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mMediaCarouselController);
+                mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
 
         mController.init();
         reset(mQSTileRevealController);
@@ -158,7 +156,7 @@
 
         QSPanelControllerBase<QSPanel> controller = new TestableQSPanelControllerBase(mQSPanel,
                 mQSTileHost, mQSCustomizerController, mMediaHost,
-                mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mMediaCarouselController) {
+                mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager) {
             @Override
             protected QSTileRevealController createTileRevealController() {
                 return mQSTileRevealController;
@@ -253,7 +251,7 @@
         when(mQSPanel.getDumpableTag()).thenReturn("QSPanelLandscape");
         mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
                 mQSCustomizerController, mMediaHost,
-                mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mMediaCarouselController);
+                mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
         mController.init();
 
         assertThat(mController.shouldUseHorizontalLayout()).isTrue();
@@ -262,7 +260,7 @@
         when(mQSPanel.getDumpableTag()).thenReturn("QSPanelPortrait");
         mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
                 mQSCustomizerController, mMediaHost,
-                mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mMediaCarouselController);
+                mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
         mController.init();
 
         assertThat(mController.shouldUseHorizontalLayout()).isFalse();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
index 98d499a..5eb9a98 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
@@ -6,7 +6,6 @@
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.media.MediaCarouselController
 import com.android.systemui.media.MediaHost
 import com.android.systemui.media.MediaHostState
 import com.android.systemui.plugins.FalsingManager
@@ -41,7 +40,6 @@
     @Mock private lateinit var qsCustomizerController: QSCustomizerController
     @Mock private lateinit var qsTileRevealControllerFactory: QSTileRevealController.Factory
     @Mock private lateinit var dumpManager: DumpManager
-    @Mock private lateinit var mediaCarouselController: MediaCarouselController
     @Mock private lateinit var metricsLogger: MetricsLogger
     @Mock private lateinit var uiEventLogger: UiEventLogger
     @Mock private lateinit var qsLogger: QSLogger
@@ -78,7 +76,6 @@
             mediaHost,
             qsTileRevealControllerFactory,
             dumpManager,
-            mediaCarouselController,
             metricsLogger,
             uiEventLogger,
             qsLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index 4af5b90..6af8e49 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -23,7 +23,6 @@
 import com.android.internal.logging.testing.UiEventLoggerFake
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.media.MediaCarouselController
 import com.android.systemui.media.MediaHost
 import com.android.systemui.media.MediaHostState
 import com.android.systemui.plugins.qs.QSTile
@@ -60,7 +59,6 @@
     @Mock private lateinit var tileLayout: TileLayout
     @Mock private lateinit var tileView: QSTileView
     @Captor private lateinit var captor: ArgumentCaptor<QSPanel.OnConfigurationChangedListener>
-    @Mock private lateinit var mediaCarouselController: MediaCarouselController
 
     private val uiEventLogger = UiEventLoggerFake()
     private val dumpManager = DumpManager()
@@ -90,8 +88,7 @@
                 metricsLogger,
                 uiEventLogger,
                 qsLogger,
-                dumpManager,
-                mediaCarouselController)
+                dumpManager)
 
         controller.init()
     }
@@ -158,8 +155,7 @@
         metricsLogger: MetricsLogger,
         uiEventLogger: UiEventLoggerFake,
         qsLogger: QSLogger,
-        dumpManager: DumpManager,
-        mediaCarouselController: MediaCarouselController
+        dumpManager: DumpManager
     ) :
         QuickQSPanelController(
             view,
@@ -171,8 +167,7 @@
             metricsLogger,
             uiEventLogger,
             qsLogger,
-            dumpManager,
-            mediaCarouselController) {
+            dumpManager) {
 
         private var rotation = RotationUtils.ROTATION_NONE
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
index c47ea9c..6ace404 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
@@ -275,10 +275,9 @@
         EditText editText = view.findViewById(R.id.remote_input_text);
         editText.setText(TEST_REPLY);
         ClipDescription description = new ClipDescription("", new String[] {"image/png"});
-        // We need to use an (arbitrary) real resource here so that an actual image gets attached.
+        // We need to use an (arbitrary) real resource here so that an actual image gets attached
         ClipData clip = new ClipData(description, new ClipData.Item(
-                Uri.parse("android.resource://com.android.systemui/"
-                        + R.drawable.default_thumbnail)));
+                Uri.parse("android.resource://android/" + android.R.drawable.btn_default)));
         ContentInfo payload =
                 new ContentInfo.Builder(clip, SOURCE_CLIPBOARD).build();
         view.setAttachment(payload);
diff --git a/services/core/java/com/android/server/am/ProcessProfileRecord.java b/services/core/java/com/android/server/am/ProcessProfileRecord.java
index 7369e8f..4c15308 100644
--- a/services/core/java/com/android/server/am/ProcessProfileRecord.java
+++ b/services/core/java/com/android/server/am/ProcessProfileRecord.java
@@ -17,7 +17,6 @@
 package com.android.server.am;
 
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
-import static android.app.ActivityManager.processStateAmToProto;
 
 import android.annotation.IntDef;
 import android.app.IApplicationThread;
@@ -318,12 +317,6 @@
                             origBase.setState(ProcessStats.STATE_NOTHING,
                                     tracker.getMemFactorLocked(), SystemClock.uptimeMillis(),
                                     pkgList.getPackageListLocked());
-                            pkgList.forEachPackage((pkgName, holder) ->
-                                    FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
-                                        mApp.uid, mApp.processName, pkgName,
-                                        processStateAmToProto(ProcessStats.STATE_NOTHING),
-                                        holder.appVersion)
-                            );
                         }
                         origBase.makeInactive();
                     }
@@ -362,12 +355,6 @@
                         origBase.setState(ProcessStats.STATE_NOTHING,
                                 tracker.getMemFactorLocked(), SystemClock.uptimeMillis(),
                                 pkgList.getPackageListLocked());
-                        pkgList.forEachPackage((pkgName, holder) ->
-                                FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
-                                    mApp.uid, mApp.processName, pkgName,
-                                    processStateAmToProto(ProcessStats.STATE_NOTHING),
-                                    holder.appVersion)
-                        );
                     }
                     origBase.makeInactive();
                     setBaseProcessTracker(null);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 07b6fcd..482e6a7 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -54,7 +54,6 @@
 import com.android.internal.app.procstats.ProcessState;
 import com.android.internal.app.procstats.ProcessStats;
 import com.android.internal.os.Zygote;
-import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.wm.WindowProcessController;
 import com.android.server.wm.WindowProcessListener;
 
@@ -1212,12 +1211,6 @@
                     long now = SystemClock.uptimeMillis();
                     baseProcessTracker.setState(ProcessStats.STATE_NOTHING,
                             tracker.getMemFactorLocked(), now, mPkgList.getPackageListLocked());
-                    mPkgList.forEachPackage((pkgName, holder) ->
-                            FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
-                                uid, processName, pkgName,
-                                ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING),
-                                holder.appVersion)
-                    );
                     if (numOfPkgs != 1) {
                         mPkgList.forEachPackageProcessStats(holder -> {
                             if (holder.state != null && holder.state != baseProcessTracker) {
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index ef13778..d2ef479 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -35,7 +35,6 @@
 
 import com.android.internal.annotations.CompositeRWLock;
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.am.PlatformCompatCache.CachedCompatChangeId;
 
 import java.io.PrintWriter;
@@ -599,12 +598,6 @@
     @GuardedBy({"mService", "mProcLock"})
     void setReportedProcState(int repProcState) {
         mRepProcState = repProcState;
-        mApp.getPkgList().forEachPackage((pkgName, holder) ->
-                FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
-                    mApp.uid, mApp.processName, pkgName,
-                    ActivityManager.processStateAmToProto(mRepProcState),
-                    holder.appVersion)
-        );
         mApp.getWindowProcessController().setReportedProcState(repProcState);
     }
 
@@ -620,12 +613,6 @@
                 mRepProcState = newState;
                 setCurProcState(newState);
                 setCurRawProcState(newState);
-                mApp.getPkgList().forEachPackage((pkgName, holder) ->
-                        FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
-                            mApp.uid, mApp.processName, pkgName,
-                            ActivityManager.processStateAmToProto(mRepProcState),
-                            holder.appVersion)
-                );
             }
         }
     }
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 2b8a196..cd074c0 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -385,6 +385,11 @@
         } else if (snapshot.isInstantApp(options.getPackageName(), UserHandle.getCallingUserId())) {
             return false;
         }
+        var pkg = snapshot.getPackage(options.getPackageName());
+        if (pkg != null && pkg.isApex()) {
+            // skip APEX
+            return true;
+        }
 
         if (options.isDexoptOnlySecondaryDex()) {
             return mPm.getDexManager().dexoptSecondaryDex(options);
@@ -427,6 +432,10 @@
                 // Package could not be found. Report failure.
                 return PackageDexOptimizer.DEX_OPT_FAILED;
             }
+            if (p.isApex()) {
+                // APEX needs no dexopt
+                return PackageDexOptimizer.DEX_OPT_SKIPPED;
+            }
             mPm.getPackageUsage().maybeWriteAsync(mPm.mSettings.getPackagesLocked());
             mPm.mCompilerStats.maybeWriteAsync();
         }
@@ -498,6 +507,9 @@
         if (packageState == null || pkg == null) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
+        if (pkg.isApex()) {
+            throw new IllegalArgumentException("Can't dexopt APEX package: " + packageName);
+        }
 
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
 
diff --git a/services/core/java/com/android/server/pm/InstallSource.java b/services/core/java/com/android/server/pm/InstallSource.java
index 404285c..e5f7f71 100644
--- a/services/core/java/com/android/server/pm/InstallSource.java
+++ b/services/core/java/com/android/server/pm/InstallSource.java
@@ -131,7 +131,8 @@
             @Nullable PackageSignatures initiatingPackageSignatures) {
         if (initiatingPackageName == null && originatingPackageName == null
                 && installerPackageName == null && initiatingPackageSignatures == null
-                && !isInitiatingPackageUninstalled) {
+                && !isInitiatingPackageUninstalled
+                && packageSource == PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED) {
             return isOrphaned ? EMPTY_ORPHANED : EMPTY;
         }
         return new InstallSource(initiatingPackageName, originatingPackageName,
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 3fb4066..178d0ea 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -189,6 +189,11 @@
             return false;
         }
 
+        // We do not dexopt APEX packages.
+        if (pkg.isApex()) {
+            return false;
+        }
+
         // We do not dexopt unused packages.
         // It's possible for this to be called before app hibernation service is ready due to
         // an OTA dexopt. In this case, we ignore the hibernation check here. This is fine since
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index d8d75ed..9ed77fc 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1354,10 +1354,6 @@
         return true;
     }
 
-    void setAppTimeTracker(AppTimeTracker att) {
-        appTimeTracker = att;
-    }
-
     /** Update the saved state of an activity. */
     void setSavedState(@Nullable Bundle savedState) {
         mIcicle = savedState;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 5bddae6..b473700 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -139,7 +139,6 @@
 import com.android.internal.content.ReferrerIntent;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.function.pooled.PooledConsumer;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
 import com.android.server.am.ActivityManagerService;
@@ -1578,17 +1577,12 @@
         if (rootTask.getWindowingMode() == WINDOWING_MODE_PINNED) {
             removePinnedRootTaskInSurfaceTransaction(rootTask);
         } else {
-            final PooledConsumer c = PooledLambda.obtainConsumer(
-                    ActivityTaskSupervisor::processRemoveTask, this, PooledLambda.__(Task.class));
-            rootTask.forAllLeafTasks(c, true /* traverseTopToBottom */);
-            c.recycle();
+            rootTask.forAllLeafTasks(task -> {
+                removeTask(task, true /* killProcess */, REMOVE_FROM_RECENTS, "remove-root-task");
+            }, true /* traverseTopToBottom */);
         }
     }
 
-    private void processRemoveTask(Task task) {
-        removeTask(task, true /* killProcess */, REMOVE_FROM_RECENTS, "remove-root-task");
-    }
-
     /**
      * Removes the root task associated with the given {@param task}. If the {@param task} is the
      * pinned task, then its child tasks are not explicitly removed when the root task is
@@ -2268,23 +2262,17 @@
     }
 
     void scheduleUpdateMultiWindowMode(Task task) {
-        final PooledConsumer c = PooledLambda.obtainConsumer(
-                ActivityTaskSupervisor::addToMultiWindowModeChangedList, this,
-                PooledLambda.__(ActivityRecord.class));
-        task.forAllActivities(c);
-        c.recycle();
+        task.forAllActivities(r -> {
+            if (r.attachedToProcess()) {
+                mMultiWindowModeChangedActivities.add(r);
+            }
+        });
 
         if (!mHandler.hasMessages(REPORT_MULTI_WINDOW_MODE_CHANGED_MSG)) {
             mHandler.sendEmptyMessage(REPORT_MULTI_WINDOW_MODE_CHANGED_MSG);
         }
     }
 
-    private void addToMultiWindowModeChangedList(ActivityRecord r) {
-        if (r.attachedToProcess()) {
-            mMultiWindowModeChangedActivities.add(r);
-        }
-    }
-
     void scheduleUpdatePictureInPictureModeIfNeeded(Task task, Task prevRootTask) {
         final Task rootTask = task.getRootTask();
         if ((prevRootTask == null || (prevRootTask != rootTask
@@ -2296,11 +2284,14 @@
     }
 
     void scheduleUpdatePictureInPictureModeIfNeeded(Task task, Rect targetRootTaskBounds) {
-        final PooledConsumer c = PooledLambda.obtainConsumer(
-                ActivityTaskSupervisor::addToPipModeChangedList, this,
-                PooledLambda.__(ActivityRecord.class));
-        task.forAllActivities(c);
-        c.recycle();
+        task.forAllActivities(r -> {
+            if (!r.attachedToProcess()) return;
+            mPipModeChangedActivities.add(r);
+            // If we are scheduling pip change, then remove this activity from multi-window
+            // change list as the processing of pip change will make sure multi-window changed
+            // message is processed in the right order relative to pip changed.
+            mMultiWindowModeChangedActivities.remove(r);
+        });
 
         mPipModeChangedTargetRootTaskBounds = targetRootTaskBounds;
 
@@ -2309,16 +2300,6 @@
         }
     }
 
-    private void addToPipModeChangedList(ActivityRecord r) {
-        if (!r.attachedToProcess()) return;
-
-        mPipModeChangedActivities.add(r);
-        // If we are scheduling pip change, then remove this activity from multi-window
-        // change list as the processing of pip change will make sure multi-window changed
-        // message is processed in the right order relative to pip changed.
-        mMultiWindowModeChangedActivities.remove(r);
-    }
-
     void wakeUp(String reason) {
         mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_APPLICATION,
                 "android.server.am:TURN_ON:" + reason);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c6fe017..669cd5d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -241,7 +241,6 @@
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.ToBooleanFunction;
 import com.android.internal.util.function.TriConsumer;
-import com.android.internal.util.function.pooled.PooledConsumer;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.internal.util.function.pooled.PooledPredicate;
 import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -3075,18 +3074,13 @@
      */
     boolean pointWithinAppWindow(int x, int y) {
         final int[] targetWindowType = {-1};
-        final PooledConsumer fn = PooledLambda.obtainConsumer((w, nonArg) -> {
-            if (targetWindowType[0] != -1) {
-                return;
-            }
-
+        forAllWindows(w -> {
             if (w.isOnScreen() && w.isVisible() && w.getFrame().contains(x, y)) {
                 targetWindowType[0] = w.mAttrs.type;
-                return;
+                return true;
             }
-        }, PooledLambda.__(WindowState.class), mTmpRect);
-        forAllWindows(fn, true /* traverseTopToBottom */);
-        fn.recycle();
+            return false;
+        }, true /* traverseTopToBottom */);
         return FIRST_APPLICATION_WINDOW <= targetWindowType[0]
                 && targetWindowType[0] <= LAST_APPLICATION_WINDOW;
     }
@@ -3112,11 +3106,7 @@
             mTmpRect.setEmpty();
             mTmpRect2.setEmpty();
 
-            final PooledConsumer c = PooledLambda.obtainConsumer(
-                    DisplayContent::processTaskForTouchExcludeRegion, this,
-                    PooledLambda.__(Task.class), focusedTask, delta);
-            forAllTasks(c);
-            c.recycle();
+            forAllTasks(t -> { processTaskForTouchExcludeRegion(t, focusedTask, delta); });
 
             // If we removed the focused task above, add it back and only leave its
             // outside touch area in the exclusion. TapDetector is not interested in
@@ -6187,17 +6177,10 @@
     /** Update and get all UIDs that are present on the display and have access to it. */
     IntArray getPresentUIDs() {
         mDisplayAccessUIDs.clear();
-        final PooledConsumer c = PooledLambda.obtainConsumer(DisplayContent::addActivityUid,
-                PooledLambda.__(ActivityRecord.class), mDisplayAccessUIDs);
-        mDisplayContent.forAllActivities(c);
-        c.recycle();
+        mDisplayContent.forAllActivities(r -> { mDisplayAccessUIDs.add(r.getUid()); });
         return mDisplayAccessUIDs;
     }
 
-    private static void addActivityUid(ActivityRecord r, IntArray uids) {
-        uids.add(r.getUid());
-    }
-
     @VisibleForTesting
     boolean shouldDestroyContentOnRemove() {
         return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 9e01f10..bffab7a 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -62,8 +62,6 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
-import com.android.internal.util.function.pooled.PooledConsumer;
-import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
 import com.android.server.inputmethod.InputMethodManagerInternal;
 import com.android.server.statusbar.StatusBarManagerInternal;
@@ -403,11 +401,11 @@
         final Task targetRootTask = mDisplayContent.getDefaultTaskDisplayArea()
                 .getRootTask(WINDOWING_MODE_UNDEFINED, targetActivityType);
         if (targetRootTask != null) {
-            final PooledConsumer c = PooledLambda.obtainConsumer((t, outList) ->
-	            { if (!outList.contains(t)) outList.add(t); }, PooledLambda.__(Task.class),
-                    visibleTasks);
-            targetRootTask.forAllLeafTasks(c, true /* traverseTopToBottom */);
-            c.recycle();
+            targetRootTask.forAllLeafTasks(t -> {
+                if (!visibleTasks.contains(t)) {
+                    visibleTasks.add(t);
+                }
+            }, true /* traverseTopToBottom */);
         }
 
         final int taskCount = visibleTasks.size();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index ba834de..b2ec3f3 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -3102,9 +3102,8 @@
     }
 
     void finishVoiceTask(IVoiceInteractionSession session) {
-        forAllRootTasks(rootTask -> {
-            rootTask.finishVoiceTask(session);
-        });
+        final IBinder binder = session.asBinder();
+        forAllLeafTasks(t -> t.finishIfVoiceTask(binder), true /* traverseTopToBottom */);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 120fec0..a753b55 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -23,18 +23,16 @@
 import android.os.UserHandle;
 import android.util.ArraySet;
 
-import com.android.internal.util.function.pooled.PooledConsumer;
-import com.android.internal.util.function.pooled.PooledLambda;
-
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
 import java.util.TreeSet;
+import java.util.function.Consumer;
 
 /**
  * Class for resolving the set of running tasks in the system.
  */
-class RunningTasks {
+class RunningTasks implements Consumer<Task> {
 
     static final int FLAG_FILTER_ONLY_VISIBLE_RECENTS = 1;
     static final int FLAG_ALLOWED = 1 << 1;
@@ -61,7 +59,7 @@
     private boolean mKeepIntentExtra;
 
     void getTasks(int maxNum, List<RunningTaskInfo> list, int flags, RecentTasks recentTasks,
-            WindowContainer root, int callingUid, ArraySet<Integer> profileIds) {
+            WindowContainer<?> root, int callingUid, ArraySet<Integer> profileIds) {
         // Return early if there are no tasks to fetch
         if (maxNum <= 0) {
             return;
@@ -79,10 +77,7 @@
         mRecentTasks = recentTasks;
         mKeepIntentExtra = (flags & FLAG_KEEP_INTENT_EXTRA) == FLAG_KEEP_INTENT_EXTRA;
 
-        final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
-                PooledLambda.__(Task.class));
-        root.forAllLeafTasks(c, false);
-        c.recycle();
+        root.forAllLeafTasks(this, false /* traverseTopToBottom */);
 
         // Take the first {@param maxNum} tasks and create running task infos for them
         final Iterator<Task> iter = mTmpSortedSet.iterator();
@@ -97,7 +92,8 @@
         }
     }
 
-    private void processTask(Task task) {
+    @Override
+    public void accept(Task task) {
         if (task.getTopNonFinishingActivity() == null) {
             // Skip if there are no activities in the task
             return;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1508870..63c6c35 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -196,7 +196,6 @@
 import com.android.internal.protolog.ProtoLogGroup;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.XmlUtils;
-import com.android.internal.util.function.pooled.PooledConsumer;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.internal.util.function.pooled.PooledPredicate;
 import com.android.server.Watchdog;
@@ -1188,11 +1187,7 @@
         if (oldParent != null) {
             final Task oldParentTask = oldParent.asTask();
             if (oldParentTask != null) {
-                final PooledConsumer c = PooledLambda.obtainConsumer(
-                        Task::cleanUpActivityReferences, oldParentTask,
-                        PooledLambda.__(ActivityRecord.class));
-                forAllActivities(c);
-                c.recycle();
+                forAllActivities(oldParentTask::cleanUpActivityReferences);
             }
 
             if (oldParent.inPinnedWindowingMode()
@@ -2371,10 +2366,7 @@
 
     int getDescendantTaskCount() {
         final int[] currentCount = {0};
-        final PooledConsumer c = PooledLambda.obtainConsumer((t, count) -> { count[0]++; },
-                PooledLambda.__(Task.class), currentCount);
-        forAllLeafTasks(c, false /* traverseTopToBottom */);
-        c.recycle();
+        forAllLeafTasks(t -> currentCount[0]++, false /* traverseTopToBottom */);
         return currentCount[0];
     }
 
@@ -2783,10 +2775,7 @@
                 && displayContent.mDividerControllerLocked.isResizing();
         if (inFreeformWindowingMode()) {
             boolean[] foundTop = { false };
-            final PooledConsumer c = PooledLambda.obtainConsumer(Task::getMaxVisibleBounds,
-                    PooledLambda.__(ActivityRecord.class), out, foundTop);
-            forAllActivities(c);
-            c.recycle();
+            forAllActivities(a -> { getMaxVisibleBounds(a, out, foundTop); });
             if (foundTop[0]) {
                 return;
             }
@@ -4349,14 +4338,6 @@
         }
     }
 
-
-    void setActivityWindowingMode(int windowingMode) {
-        PooledConsumer c = PooledLambda.obtainConsumer(ActivityRecord::setWindowingMode,
-                PooledLambda.__(ActivityRecord.class), windowingMode);
-        forAllActivities(c);
-        c.recycle();
-    }
-
     /**
      * Sets/unsets the forced-hidden state flag for this task depending on {@param set}.
      * @return Whether the force hidden state changed
@@ -5209,26 +5190,19 @@
         return finishedTask;
     }
 
-    void finishVoiceTask(IVoiceInteractionSession session) {
-        final PooledConsumer c = PooledLambda.obtainConsumer(Task::finishIfVoiceTask,
-                PooledLambda.__(Task.class), session.asBinder());
-        forAllLeafTasks(c, true /* traverseTopToBottom */);
-        c.recycle();
-    }
-
-    private static void finishIfVoiceTask(Task tr, IBinder binder) {
-        if (tr.voiceSession != null && tr.voiceSession.asBinder() == binder) {
-            tr.forAllActivities((r) -> {
+    void finishIfVoiceTask(IBinder binder) {
+        if (voiceSession != null && voiceSession.asBinder() == binder) {
+            forAllActivities((r) -> {
                 if (r.finishing) return;
                 r.finishIfPossible("finish-voice", false /* oomAdj */);
-                tr.mAtmService.updateOomAdj();
+                mAtmService.updateOomAdj();
             });
         } else {
             // Check if any of the activities are using voice
             final PooledPredicate f = PooledLambda.obtainPredicate(
                     Task::finishIfVoiceActivity, PooledLambda.__(ActivityRecord.class),
                     binder);
-            tr.forAllActivities(f);
+            forAllActivities(f);
             f.recycle();
         }
     }
@@ -5447,10 +5421,7 @@
 
         if (timeTracker != null) {
             // The caller wants a time tracker associated with this task.
-            final PooledConsumer c = PooledLambda.obtainConsumer(ActivityRecord::setAppTimeTracker,
-                    PooledLambda.__(ActivityRecord.class), timeTracker);
-            tr.forAllActivities(c);
-            c.recycle();
+            tr.forAllActivities(a -> { a.appTimeTracker = timeTracker; });
         }
 
         try {
@@ -5621,11 +5592,11 @@
         try {
             // TODO: Why not just set this on the root task directly vs. on each tasks?
             // Update override configurations of all tasks in the root task.
-            final PooledConsumer c = PooledLambda.obtainConsumer(
-                    Task::processTaskResizeBounds, PooledLambda.__(Task.class),
-                    displayedBounds);
-            forAllTasks(c, true /* traverseTopToBottom */);
-            c.recycle();
+            forAllTasks(task -> {
+                if (task.isResizeable()) {
+                    task.setBounds(displayedBounds);
+                }
+            }, true /* traverseTopToBottom */);
 
             if (!deferResume) {
                 ensureVisibleActivitiesConfiguration(topRunningActivity(), preserveWindows);
@@ -5636,12 +5607,6 @@
         }
     }
 
-    private static void processTaskResizeBounds(Task task, Rect displayedBounds) {
-        if (!task.isResizeable()) return;
-
-        task.setBounds(displayedBounds);
-    }
-
     boolean willActivityBeVisible(IBinder token) {
         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
         if (r == null) {
@@ -5727,22 +5692,15 @@
 
         // All activities that came from the package must be
         // restarted as if there was a config change.
-        PooledConsumer c = PooledLambda.obtainConsumer(Task::restartPackage,
-                PooledLambda.__(ActivityRecord.class), starting, packageName);
-        forAllActivities(c);
-        c.recycle();
-
-        return starting;
-    }
-
-    private static void restartPackage(
-            ActivityRecord r, ActivityRecord starting, String packageName) {
-        if (r.info.packageName.equals(packageName)) {
+        forAllActivities(r -> {
+            if (!r.info.packageName.equals(packageName)) return;
             r.forceNewConfig = true;
             if (starting != null && r == starting && r.mVisibleRequested) {
                 r.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT);
             }
-        }
+        });
+
+        return starting;
     }
 
     Task reuseOrCreateTask(ActivityInfo info, Intent intent, boolean toTop) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 90e3c51..29ab562 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -309,8 +309,6 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.LatencyTracker;
-import com.android.internal.util.function.pooled.PooledConsumer;
-import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.internal.view.WindowManagerPolicyThread;
 import com.android.server.AnimationThread;
 import com.android.server.DisplayThread;
@@ -475,10 +473,7 @@
         public void onVrStateChanged(boolean enabled) {
             synchronized (mGlobalLock) {
                 mVrModeEnabled = enabled;
-                final PooledConsumer c = PooledLambda.obtainConsumer(
-                        DisplayPolicy::onVrStateChangedLw, PooledLambda.__(), enabled);
-                mRoot.forAllDisplayPolicies(c);
-                c.recycle();
+                mRoot.forAllDisplayPolicies(p -> p.onVrStateChangedLw(enabled));
             }
         }
     };
@@ -900,11 +895,8 @@
             }
             mPointerLocationEnabled = enablePointerLocation;
             synchronized (mGlobalLock) {
-                final PooledConsumer c = PooledLambda.obtainConsumer(
-                        DisplayPolicy::setPointerLocationEnabled, PooledLambda.__(),
-                        mPointerLocationEnabled);
-                mRoot.forAllDisplayPolicies(c);
-                c.recycle();
+                mRoot.forAllDisplayPolicies(
+                        p -> p.setPointerLocationEnabled(mPointerLocationEnabled));
             }
         }
 
@@ -3139,10 +3131,7 @@
 
     @Override
     public void onPowerKeyDown(boolean isScreenOn) {
-        final PooledConsumer c = PooledLambda.obtainConsumer(
-                DisplayPolicy::onPowerKeyDown, PooledLambda.__(), isScreenOn);
-        mRoot.forAllDisplayPolicies(c);
-        c.recycle();
+        mRoot.forAllDisplayPolicies(p -> p.onPowerKeyDown(isScreenOn));
     }
 
     @Override
@@ -8391,10 +8380,7 @@
     void onLockTaskStateChanged(int lockTaskState) {
         // TODO: pass in displayId to determine which display the lock task state changed
         synchronized (mGlobalLock) {
-            final PooledConsumer c = PooledLambda.obtainConsumer(
-                    DisplayPolicy::onLockTaskStateChangedLw, PooledLambda.__(), lockTaskState);
-            mRoot.forAllDisplayPolicies(c);
-            c.recycle();
+            mRoot.forAllDisplayPolicies(p -> p.onLockTaskStateChangedLw(lockTaskState));
         }
     }
 
@@ -9286,4 +9272,46 @@
                         "Unexpected letterbox background type: " + letterboxBackgroundType);
         }
     }
+
+    @Override
+    public void captureDisplay(int displayId, @Nullable ScreenCapture.CaptureArgs captureArgs,
+            ScreenCapture.ScreenCaptureListener listener) {
+        Slog.d(TAG, "captureDisplay");
+        if (!checkCallingPermission(READ_FRAME_BUFFER, "captureDisplay()")) {
+            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
+        }
+
+        ScreenCapture.captureLayers(getCaptureArgs(displayId, captureArgs), listener);
+    }
+
+    @VisibleForTesting
+    ScreenCapture.LayerCaptureArgs getCaptureArgs(int displayId,
+            @Nullable ScreenCapture.CaptureArgs captureArgs) {
+        final SurfaceControl displaySurfaceControl;
+        synchronized (mGlobalLock) {
+            DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                throw new IllegalArgumentException("Trying to screenshot and invalid display: "
+                        + displayId);
+            }
+
+            displaySurfaceControl = displayContent.getSurfaceControl();
+
+            if (captureArgs == null) {
+                captureArgs = new ScreenCapture.CaptureArgs.Builder<>()
+                        .build();
+            }
+
+            if (captureArgs.mSourceCrop.isEmpty()) {
+                displayContent.getBounds(mTmpRect);
+                mTmpRect.offsetTo(0, 0);
+            } else {
+                mTmpRect.set(captureArgs.mSourceCrop);
+            }
+        }
+
+        return new ScreenCapture.LayerCaptureArgs.Builder(displaySurfaceControl, captureArgs)
+                        .setSourceCrop(mTmpRect)
+                        .build();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 2e1477d..e2f833c 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -91,8 +91,6 @@
 import com.android.internal.protolog.ProtoLogGroup;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.function.pooled.PooledConsumer;
-import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
 import com.android.server.pm.LauncherAppsService.LauncherAppsServiceInternal;
 
@@ -482,7 +480,7 @@
             }
             final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
             final int hopSize = hops.size();
-            ArraySet<WindowContainer> haveConfigChanges = new ArraySet<>();
+            final ArraySet<WindowContainer<?>> haveConfigChanges = new ArraySet<>();
             Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
                     t.getChanges().entrySet().iterator();
             while (entries.hasNext()) {
@@ -592,16 +590,10 @@
                 mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
                 mService.mRootWindowContainer.resumeFocusedTasksTopActivities();
             } else if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
-                final PooledConsumer f = PooledLambda.obtainConsumer(
-                        ActivityRecord::ensureActivityConfiguration,
-                        PooledLambda.__(ActivityRecord.class), 0,
-                        true /* preserveWindow */);
-                try {
-                    for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
-                        haveConfigChanges.valueAt(i).forAllActivities(f);
-                    }
-                } finally {
-                    f.recycle();
+                for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
+                    haveConfigChanges.valueAt(i).forAllActivities(r -> {
+                        r.ensureActivityConfiguration(0, PRESERVE_WINDOWS);
+                    });
                 }
             }
 
@@ -716,7 +708,7 @@
 
         final int childWindowingMode = c.getActivityWindowingMode();
         if (childWindowingMode > -1) {
-            tr.setActivityWindowingMode(childWindowingMode);
+            tr.forAllActivities(a -> { a.setWindowingMode(childWindowingMode); });
         }
 
         if (t != null) {
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index 2918365..107bbe1 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -79,7 +79,10 @@
         <activity android:name="com.android.server.wm.ActivityOptionsTest$MainActivity"
                   android:turnScreenOn="true"
                   android:showWhenLocked="true" />
-        <activity android:name="com.android.server.wm.ScreenshotTests$ScreenshotActivity" />
+        <activity android:name="com.android.server.wm.ScreenshotTests$ScreenshotActivity"
+                  android:theme="@style/WhiteBackgroundTheme"
+                  android:turnScreenOn="true"
+                  android:showWhenLocked="true"/>
         <activity android:name="android.view.cts.surfacevalidator.CapturedActivity"/>
 
         <service android:name="android.view.cts.surfacevalidator.LocalMediaProjectionService"
diff --git a/services/tests/wmtests/res/values/styles.xml b/services/tests/wmtests/res/values/styles.xml
new file mode 100644
index 0000000..6857ff99
--- /dev/null
+++ b/services/tests/wmtests/res/values/styles.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2022 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.
+  -->
+
+<resources>
+    <style name="WhiteBackgroundTheme" parent="@android:style/Theme.DeviceDefault">
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowFullscreen">true</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
+    </style>
+</resources>
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index adf694c..170b388 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -1532,7 +1532,7 @@
 
         @Override
         void getTasks(int maxNum, List<RunningTaskInfo> list, int flags, RecentTasks recentTasks,
-                WindowContainer root, int callingUid, ArraySet<Integer> profileIds) {
+                WindowContainer<?> root, int callingUid, ArraySet<Integer> profileIds) {
             mLastAllowed = (flags & FLAG_ALLOWED) == FLAG_ALLOWED;
             super.getTasks(maxNum, list, flags, recentTasks, root, callingUid, profileIds);
         }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java
index 0b58428..736f8f7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java
@@ -16,6 +16,10 @@
 
 package com.android.server.wm;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowInsets.Type.displayCutout;
+import static android.view.WindowInsets.Type.statusBars;
+
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertNotNull;
@@ -23,20 +27,33 @@
 
 import android.app.Activity;
 import android.app.Instrumentation;
+import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.ColorSpace;
 import android.graphics.GraphicBuffer;
+import android.graphics.Insets;
 import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.DataSpace;
+import android.hardware.HardwareBuffer;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.ServiceManager;
 import android.platform.test.annotations.Presubmit;
+import android.util.Pair;
+import android.view.IWindowManager;
 import android.view.PointerIcon;
 import android.view.SurfaceControl;
-import android.view.WindowManager;
+import android.view.cts.surfacevalidator.BitmapPixelChecker;
+import android.view.cts.surfacevalidator.PixelColor;
+import android.view.cts.surfacevalidator.SaveBitmapHelper;
 import android.window.ScreenCapture;
+import android.window.ScreenCapture.ScreenCaptureListener;
+import android.window.ScreenCapture.ScreenshotHardwareBuffer;
+import android.window.ScreenCapture.ScreenshotSync;
 
 import androidx.annotation.Nullable;
 import androidx.test.filters.SmallTest;
@@ -45,6 +62,7 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestName;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -60,6 +78,8 @@
     private static final int BUFFER_HEIGHT = 100;
 
     private final Instrumentation mInstrumentation = getInstrumentation();
+    @Rule
+    public TestName mTestName = new TestName();
 
     @Rule
     public ActivityTestRule<ScreenshotActivity> mActivityRule =
@@ -95,8 +115,8 @@
         buffer.unlockCanvasAndPost(canvas);
 
         t.show(secureSC)
-                .setBuffer(secureSC, buffer)
-                .setColorSpace(secureSC, ColorSpace.get(ColorSpace.Named.SRGB))
+                .setBuffer(secureSC, HardwareBuffer.createFromGraphicBuffer(buffer))
+                .setDataSpace(secureSC, DataSpace.DATASPACE_SRGB)
                 .apply(true);
 
         ScreenCapture.LayerCaptureArgs args = new ScreenCapture.LayerCaptureArgs.Builder(secureSC)
@@ -112,15 +132,70 @@
         Bitmap swBitmap = screenshot.copy(Bitmap.Config.ARGB_8888, false);
         screenshot.recycle();
 
-        int numMatchingPixels = PixelChecker.getNumMatchingPixels(swBitmap,
-                new PixelColor(PixelColor.RED));
-        long sizeOfBitmap = swBitmap.getWidth() * swBitmap.getHeight();
+        BitmapPixelChecker bitmapPixelChecker = new BitmapPixelChecker(PixelColor.RED);
+        Rect bounds = new Rect(0, 0, swBitmap.getWidth(), swBitmap.getHeight());
+        int numMatchingPixels = bitmapPixelChecker.getNumMatchingPixels(swBitmap, bounds);
+        int sizeOfBitmap = bounds.width() * bounds.height();
         boolean success = numMatchingPixels == sizeOfBitmap;
         swBitmap.recycle();
 
         assertTrue(success);
     }
 
+    @Test
+    public void testCaptureDisplay() throws Exception {
+        IWindowManager windowManager = IWindowManager.Stub.asInterface(
+                ServiceManager.getService(Context.WINDOW_SERVICE));
+        SurfaceControl sc = new SurfaceControl.Builder()
+                .setName("Layer")
+                .setCallsite("testCaptureDisplay")
+                .build();
+
+        SurfaceControl.Transaction t = mActivity.addChildSc(sc);
+        mInstrumentation.waitForIdleSync();
+
+        GraphicBuffer buffer = GraphicBuffer.create(BUFFER_WIDTH, BUFFER_HEIGHT,
+                PixelFormat.RGBA_8888,
+                GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER
+                        | GraphicBuffer.USAGE_SW_WRITE_RARELY);
+
+        Canvas canvas = buffer.lockCanvas();
+        canvas.drawColor(Color.RED);
+        buffer.unlockCanvasAndPost(canvas);
+
+        Point point = mActivity.getPositionBelowStatusBar();
+        t.show(sc)
+                .setBuffer(sc, HardwareBuffer.createFromGraphicBuffer(buffer))
+                .setDataSpace(sc, DataSpace.DATASPACE_SRGB)
+                .setPosition(sc, point.x, point.y)
+                .apply(true);
+
+        Pair<ScreenCaptureListener, ScreenshotSync> syncScreenCapture =
+                ScreenCapture.createSyncCaptureListener();
+        windowManager.captureDisplay(DEFAULT_DISPLAY, null, syncScreenCapture.first);
+        ScreenshotHardwareBuffer hardwareBuffer = syncScreenCapture.second.get();
+        assertNotNull(hardwareBuffer);
+
+        Bitmap screenshot = hardwareBuffer.asBitmap();
+        assertNotNull(screenshot);
+
+        Bitmap swBitmap = screenshot.copy(Bitmap.Config.ARGB_8888, false);
+        screenshot.recycle();
+
+        BitmapPixelChecker bitmapPixelChecker = new BitmapPixelChecker(PixelColor.RED);
+        Rect bounds = new Rect(point.x, point.y, BUFFER_WIDTH + point.x, BUFFER_HEIGHT + point.y);
+        int numMatchingPixels = bitmapPixelChecker.getNumMatchingPixels(swBitmap, bounds);
+        int pixelMatchSize = bounds.width() * bounds.height();
+        boolean success = numMatchingPixels == pixelMatchSize;
+
+        if (!success) {
+            SaveBitmapHelper.saveBitmap(swBitmap, getClass(), mTestName, "failedImage");
+        }
+        swBitmap.recycle();
+        assertTrue("numMatchingPixels=" + numMatchingPixels + " pixelMatchSize=" + pixelMatchSize,
+                success);
+    }
+
     public static class ScreenshotActivity extends Activity {
         private static final long WAIT_TIMEOUT_S = 5;
         private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -130,7 +205,6 @@
             super.onCreate(savedInstanceState);
             getWindow().getDecorView().setPointerIcon(
                     PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL));
-            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
         }
 
         SurfaceControl.Transaction addChildSc(SurfaceControl surfaceControl) {
@@ -148,88 +222,14 @@
             }
             return t;
         }
-    }
 
-    public abstract static class PixelChecker {
-        static int getNumMatchingPixels(Bitmap bitmap, PixelColor pixelColor) {
-            int numMatchingPixels = 0;
-            for (int x = 0; x < bitmap.getWidth(); x++) {
-                for (int y = 0; y < bitmap.getHeight(); y++) {
-                    int color = bitmap.getPixel(x, y);
-                    if (matchesColor(pixelColor, color)) {
-                        numMatchingPixels++;
-                    }
-                }
-            }
-            return numMatchingPixels;
-        }
+        public Point getPositionBelowStatusBar() {
+            Insets statusBarInsets = getWindow()
+                    .getDecorView()
+                    .getRootWindowInsets()
+                    .getInsets(statusBars() | displayCutout());
 
-        static boolean matchesColor(PixelColor expectedColor, int color) {
-            final float red = Color.red(color);
-            final float green = Color.green(color);
-            final float blue = Color.blue(color);
-            final float alpha = Color.alpha(color);
-
-            return alpha <= expectedColor.mMaxAlpha
-                    && alpha >= expectedColor.mMinAlpha
-                    && red <= expectedColor.mMaxRed
-                    && red >= expectedColor.mMinRed
-                    && green <= expectedColor.mMaxGreen
-                    && green >= expectedColor.mMinGreen
-                    && blue <= expectedColor.mMaxBlue
-                    && blue >= expectedColor.mMinBlue;
-        }
-    }
-
-    public static class PixelColor {
-        public static final int BLACK = 0xFF000000;
-        public static final int RED = 0xFF0000FF;
-        public static final int GREEN = 0xFF00FF00;
-        public static final int BLUE = 0xFFFF0000;
-        public static final int YELLOW = 0xFF00FFFF;
-        public static final int MAGENTA = 0xFFFF00FF;
-        public static final int WHITE = 0xFFFFFFFF;
-
-        public static final int TRANSPARENT_RED = 0x7F0000FF;
-        public static final int TRANSPARENT_BLUE = 0x7FFF0000;
-        public static final int TRANSPARENT = 0x00000000;
-
-        // Default to black
-        public short mMinAlpha;
-        public short mMaxAlpha;
-        public short mMinRed;
-        public short mMaxRed;
-        public short mMinBlue;
-        public short mMaxBlue;
-        public short mMinGreen;
-        public short mMaxGreen;
-
-        public PixelColor(int color) {
-            short alpha = (short) ((color >> 24) & 0xFF);
-            short blue = (short) ((color >> 16) & 0xFF);
-            short green = (short) ((color >> 8) & 0xFF);
-            short red = (short) (color & 0xFF);
-
-            mMinAlpha = (short) getMinValue(alpha);
-            mMaxAlpha = (short) getMaxValue(alpha);
-            mMinRed = (short) getMinValue(red);
-            mMaxRed = (short) getMaxValue(red);
-            mMinBlue = (short) getMinValue(blue);
-            mMaxBlue = (short) getMaxValue(blue);
-            mMinGreen = (short) getMinValue(green);
-            mMaxGreen = (short) getMaxValue(green);
-        }
-
-        public PixelColor() {
-            this(BLACK);
-        }
-
-        private int getMinValue(short color) {
-            return Math.max(color - 4, 0);
-        }
-
-        private int getMaxValue(short color) {
-            return Math.min(color + 4, 0xFF);
+            return new Point(statusBarInsets.left, statusBarInsets.top);
         }
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index 46b4b76..8b63904 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -41,6 +41,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.mockito.ArgumentMatchers.any;
@@ -68,6 +69,7 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.window.ClientWindowFrames;
+import android.window.ScreenCapture;
 import android.window.WindowContainerToken;
 
 import androidx.test.filters.SmallTest;
@@ -423,6 +425,45 @@
                 LETTERBOX_BACKGROUND_SOLID_COLOR)).isFalse();
     }
 
+    @Test
+    public void testCaptureDisplay() {
+        Rect displayBounds = new Rect(0, 0, 100, 200);
+        spyOn(mDisplayContent);
+        when(mDisplayContent.getBounds()).thenReturn(displayBounds);
+
+        // Null captureArgs
+        ScreenCapture.LayerCaptureArgs resultingArgs =
+                mWm.getCaptureArgs(DEFAULT_DISPLAY, null /* captureArgs */);
+        assertEquals(displayBounds, resultingArgs.mSourceCrop);
+
+        // Non null captureArgs, didn't set rect
+        ScreenCapture.CaptureArgs captureArgs = new ScreenCapture.CaptureArgs.Builder<>().build();
+        resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs);
+        assertEquals(displayBounds, resultingArgs.mSourceCrop);
+
+        // Non null captureArgs, invalid rect
+        captureArgs = new ScreenCapture.CaptureArgs.Builder<>()
+                .setSourceCrop(new Rect(0, 0, -1, -1))
+                .build();
+        resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs);
+        assertEquals(displayBounds, resultingArgs.mSourceCrop);
+
+        // Non null captureArgs, null rect
+        captureArgs = new ScreenCapture.CaptureArgs.Builder<>()
+                .setSourceCrop(null)
+                .build();
+        resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs);
+        assertEquals(displayBounds, resultingArgs.mSourceCrop);
+
+        // Non null captureArgs, valid rect
+        Rect validRect = new Rect(0, 0, 10, 50);
+        captureArgs = new ScreenCapture.CaptureArgs.Builder<>()
+                .setSourceCrop(validRect)
+                .build();
+        resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs);
+        assertEquals(validRect, resultingArgs.mSourceCrop);
+    }
+
     private void setupActivityWithLaunchCookie(IBinder launchCookie, WindowContainerToken wct) {
         final WindowContainer.RemoteToken remoteToken = mock(WindowContainer.RemoteToken.class);
         when(remoteToken.toWindowContainerToken()).thenReturn(wct);