Merge changes Ib0099b0f,I4c4de052 into main

* changes:
  [1/n] Enforce Shell desktop cascading in Launch Params
  [0/n] Create bug fix flag for Shell initial bounds regression
diff --git a/core/api/current.txt b/core/api/current.txt
index 1312753..3da5a5c 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -16993,7 +16993,7 @@
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
     method public void setFontFeatureSettings(String);
-    method @FlaggedApi("com.android.text.flags.typeface_redesign_readonly") public boolean setFontVariationOverride(@Nullable String);
+    method @FlaggedApi("com.android.text.flags.typeface_redesign_readonly") public void setFontVariationOverride(@Nullable String);
     method public boolean setFontVariationSettings(String);
     method public void setHinting(int);
     method public void setLetterSpacing(float);
@@ -23332,12 +23332,12 @@
   public static final class MediaCodecInfo.CodecCapabilities {
     ctor public MediaCodecInfo.CodecCapabilities();
     method public static android.media.MediaCodecInfo.CodecCapabilities createFromProfileLevel(String, int, int);
-    method public android.media.MediaCodecInfo.AudioCapabilities getAudioCapabilities();
+    method @Nullable public android.media.MediaCodecInfo.AudioCapabilities getAudioCapabilities();
     method public android.media.MediaFormat getDefaultFormat();
-    method public android.media.MediaCodecInfo.EncoderCapabilities getEncoderCapabilities();
+    method @Nullable public android.media.MediaCodecInfo.EncoderCapabilities getEncoderCapabilities();
     method public int getMaxSupportedInstances();
     method public String getMimeType();
-    method public android.media.MediaCodecInfo.VideoCapabilities getVideoCapabilities();
+    method @Nullable public android.media.MediaCodecInfo.VideoCapabilities getVideoCapabilities();
     method public boolean isFeatureRequired(String);
     method public boolean isFeatureSupported(String);
     method public boolean isFormatSupported(android.media.MediaFormat);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 514a582..00ec48b 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2128,6 +2128,12 @@
     method public android.media.PlaybackParams setAudioStretchMode(int);
   }
 
+  public class Utils {
+    ctor public Utils();
+    field public static final String SYNCHRONIZED_VIBRATION = "synchronized";
+    field public static final String VIBRATION_URI_PARAM = "vibration_uri";
+  }
+
   public final class VolumePolicy implements android.os.Parcelable {
     ctor public VolumePolicy(boolean, boolean, boolean, int);
     method public int describeContents();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 69d3e8d..f9ec214 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -550,35 +550,35 @@
     public static final int START_ASSISTANT_NOT_ACTIVE_SESSION = FIRST_START_FATAL_ERROR_CODE + 11;
 
     /**
-     * Result for IActivityManaqer.startActivity: the activity was started
+     * Result for IActivityManager.startActivity: the activity was started
      * successfully as normal.
      * @hide
      */
     public static final int START_SUCCESS = FIRST_START_SUCCESS_CODE;
 
     /**
-     * Result for IActivityManaqer.startActivity: the caller asked that the Intent not
+     * Result for IActivityManager.startActivity: the caller asked that the Intent not
      * be executed if it is the recipient, and that is indeed the case.
      * @hide
      */
     public static final int START_RETURN_INTENT_TO_CALLER = FIRST_START_SUCCESS_CODE + 1;
 
     /**
-     * Result for IActivityManaqer.startActivity: activity was started or brought forward in an
+     * Result for IActivityManager.startActivity: activity was started or brought forward in an
      * existing task which was brought to the foreground.
      * @hide
      */
     public static final int START_TASK_TO_FRONT = FIRST_START_SUCCESS_CODE + 2;
 
     /**
-     * Result for IActivityManaqer.startActivity: activity wasn't really started, but
+     * Result for IActivityManager.startActivity: activity wasn't really started, but
      * the given Intent was given to the existing top activity.
      * @hide
      */
     public static final int START_DELIVERED_TO_TOP = FIRST_START_SUCCESS_CODE + 3;
 
     /**
-     * Result for IActivityManaqer.startActivity: request was canceled because
+     * Result for IActivityManager.startActivity: request was canceled because
      * app switches are temporarily canceled to ensure the user's last request
      * (such as pressing home) is performed.
      * @hide
@@ -586,7 +586,7 @@
     public static final int START_SWITCHES_CANCELED = FIRST_START_NON_FATAL_ERROR_CODE;
 
     /**
-     * Result for IActivityManaqer.startActivity: a new activity was attempted to be started
+     * Result for IActivityManager.startActivity: a new activity was attempted to be started
      * while in Lock Task Mode.
      * @hide
      */
@@ -594,55 +594,55 @@
             FIRST_START_NON_FATAL_ERROR_CODE + 1;
 
     /**
-     * Result for IActivityManaqer.startActivity: a new activity start was aborted. Never returned
+     * Result for IActivityManager.startActivity: a new activity start was aborted. Never returned
      * externally.
      * @hide
      */
     public static final int START_ABORTED = FIRST_START_NON_FATAL_ERROR_CODE + 2;
 
     /**
-     * Flag for IActivityManaqer.startActivity: do special start mode where
+     * Flag for IActivityManager.startActivity: do special start mode where
      * a new activity is launched only if it is needed.
      * @hide
      */
     public static final int START_FLAG_ONLY_IF_NEEDED = 1<<0;
 
     /**
-     * Flag for IActivityManaqer.startActivity: launch the app for
+     * Flag for IActivityManager.startActivity: launch the app for
      * debugging.
      * @hide
      */
     public static final int START_FLAG_DEBUG = 1<<1;
 
     /**
-     * Flag for IActivityManaqer.startActivity: launch the app for
+     * Flag for IActivityManager.startActivity: launch the app for
      * allocation tracking.
      * @hide
      */
     public static final int START_FLAG_TRACK_ALLOCATION = 1<<2;
 
     /**
-     * Flag for IActivityManaqer.startActivity: launch the app with
+     * Flag for IActivityManager.startActivity: launch the app with
      * native debugging support.
      * @hide
      */
     public static final int START_FLAG_NATIVE_DEBUGGING = 1<<3;
 
     /**
-     * Flag for IActivityManaqer.startActivity: launch the app for
+     * Flag for IActivityManager.startActivity: launch the app for
      * debugging and suspend threads.
      * @hide
      */
     public static final int START_FLAG_DEBUG_SUSPEND = 1 << 4;
 
     /**
-     * Result for IActivityManaqer.broadcastIntent: success!
+     * Result for IActivityManager.broadcastIntent: success!
      * @hide
      */
     public static final int BROADCAST_SUCCESS = 0;
 
     /**
-     * Result for IActivityManaqer.broadcastIntent: attempt to broadcast
+     * Result for IActivityManager.broadcastIntent: attempt to broadcast
      * a sticky intent without appropriate permission.
      * @hide
      */
@@ -656,20 +656,20 @@
     public static final int BROADCAST_FAILED_USER_STOPPED = -2;
 
     /**
-     * Type for IActivityManaqer.getIntentSender: this PendingIntent type is unknown.
+     * Type for IActivityManager.getIntentSender: this PendingIntent type is unknown.
      * @hide
      */
     public static final int INTENT_SENDER_UNKNOWN = 0;
 
     /**
-     * Type for IActivityManaqer.getIntentSender: this PendingIntent is
+     * Type for IActivityManager.getIntentSender: this PendingIntent is
      * for a sendBroadcast operation.
      * @hide
      */
     public static final int INTENT_SENDER_BROADCAST = 1;
 
     /**
-     * Type for IActivityManaqer.getIntentSender: this PendingIntent is
+     * Type for IActivityManager.getIntentSender: this PendingIntent is
      * for a startActivity operation.
      * @hide
      */
@@ -677,21 +677,21 @@
     public static final int INTENT_SENDER_ACTIVITY = 2;
 
     /**
-     * Type for IActivityManaqer.getIntentSender: this PendingIntent is
+     * Type for IActivityManager.getIntentSender: this PendingIntent is
      * for an activity result operation.
      * @hide
      */
     public static final int INTENT_SENDER_ACTIVITY_RESULT = 3;
 
     /**
-     * Type for IActivityManaqer.getIntentSender: this PendingIntent is
+     * Type for IActivityManager.getIntentSender: this PendingIntent is
      * for a startService operation.
      * @hide
      */
     public static final int INTENT_SENDER_SERVICE = 4;
 
     /**
-     * Type for IActivityManaqer.getIntentSender: this PendingIntent is
+     * Type for IActivityManager.getIntentSender: this PendingIntent is
      * for a startForegroundService operation.
      * @hide
      */
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1a6e9b0..dc5974f 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -22,14 +22,12 @@
 import static android.permission.flags.Flags.shouldRegisterAttributionSource;
 import static android.view.WindowManager.LayoutParams.WindowType;
 
-import android.Manifest;
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.annotation.UiContext;
-import android.companion.virtual.VirtualDevice;
 import android.companion.virtual.VirtualDeviceManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.AttributionSource;
@@ -2367,47 +2365,11 @@
             Log.v(TAG, "Treating renounced permission " + permission + " as denied");
             return PERMISSION_DENIED;
         }
-        int deviceId = resolveDeviceIdForPermissionCheck(permission);
+        int deviceId = PermissionManager.resolveDeviceIdForPermissionCheck(this, getDeviceId(),
+                permission);
         return PermissionManager.checkPermission(permission, pid, uid, deviceId);
     }
 
-    private int resolveDeviceIdForPermissionCheck(String permission) {
-        // When checking a device-aware permission on a remote device, if the permission is CAMERA
-        // or RECORD_AUDIO we need to check remote device's corresponding capability. If the remote
-        // device doesn't have capability fall back to checking permission on the default device.
-        // Note: we only perform permission check redirection when the device id is not explicitly
-        // set in the context.
-        int deviceId = getDeviceId();
-        if (deviceId != Context.DEVICE_ID_DEFAULT
-                && !mIsExplicitDeviceId
-                && PermissionManager.DEVICE_AWARE_PERMISSIONS.contains(permission)) {
-            VirtualDeviceManager virtualDeviceManager =
-                    getSystemService(VirtualDeviceManager.class);
-            if (virtualDeviceManager == null) {
-                Slog.e(
-                        TAG,
-                        "VDM is not enabled when device id is not default. deviceId = "
-                                + deviceId);
-            } else {
-                VirtualDevice virtualDevice = virtualDeviceManager.getVirtualDevice(deviceId);
-                if (virtualDevice != null) {
-                    if ((Objects.equals(permission, Manifest.permission.RECORD_AUDIO)
-                            && !virtualDevice.hasCustomAudioInputSupport())
-                            || (Objects.equals(permission, Manifest.permission.CAMERA)
-                            && !virtualDevice.hasCustomCameraSupport())) {
-                        deviceId = Context.DEVICE_ID_DEFAULT;
-                    }
-                } else {
-                    Slog.e(
-                            TAG,
-                            "virtualDevice is not found when device id is not default. deviceId = "
-                                    + deviceId);
-                }
-            }
-        }
-        return deviceId;
-    }
-
     /** @hide */
     @Override
     public int checkPermission(String permission, int pid, int uid, IBinder callerToken) {
@@ -2511,7 +2473,8 @@
     @Override
     public int getPermissionRequestState(String permission) {
         Objects.requireNonNull(permission, "Permission name can't be null");
-        int deviceId = resolveDeviceIdForPermissionCheck(permission);
+        int deviceId = PermissionManager.resolveDeviceIdForPermissionCheck(this, getDeviceId(),
+                permission);
         PermissionManager permissionManager = getSystemService(PermissionManager.class);
         return permissionManager.getPermissionRequestState(getOpPackageName(), permission,
                 deviceId);
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index c573161..38141cf 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -293,6 +293,7 @@
 
     // The test mode. This is only used to ensure that the test functions setTestMode() and
     // testPropertyName() are used correctly.
+    @GuardedBy("sGlobalLock")
     private static boolean sTestMode = false;
 
     /**
@@ -668,7 +669,7 @@
         // True if this handler is in test mode.  If it is in test mode, then nonces are stored
         // and retrieved from mTestNonce.
         @GuardedBy("mLock")
-        private boolean mTestMode = false;
+        private boolean mTestMode;
 
         // This is the local value of the nonce, as last set by the NonceHandler.  It is always
         // updated by the setNonce() operation.  The getNonce() operation returns this value in
@@ -692,6 +693,9 @@
 
         NonceHandler(@NonNull String name) {
             mName = name;
+            synchronized (sGlobalLock) {
+                mTestMode = sTestMode;
+            }
         }
 
         /**
@@ -1414,9 +1418,13 @@
 
     /**
      * Enable or disable testing.  The protocol requires that the mode toggle: for instance, it is
-     * illegal to clear the test mode if the test mode is already off.  The purpose is solely to
-     * ensure that test clients do not forget to use the test mode properly, even though the
-     * current logic does not care.
+     * illegal to clear the test mode if the test mode is already off.  Enabling test mode puts
+     * all caches in the process into test mode; all nonces are initialized to UNSET and
+     * subsequent reads and writes are to process memory.  This has the effect of disabling all
+     * caches that are not local to the process.  Disabling test mode restores caches to normal
+     * operation.
+     * @param mode The desired test mode.
+     * @throws IllegalStateException if the supplied mode is already set.
      * @hide
      */
     @VisibleForTesting
@@ -1431,10 +1439,8 @@
                 }
             }
             sTestMode = mode;
-            if (mode) {
-                // No action when testing begins.
-            } else {
-                resetAfterTestLocked();
+            if (Flags.picTestMode() || !mode) {
+                setTestModeLocked(mode);
             }
         }
     }
@@ -1445,11 +1451,11 @@
      * that were not originally in test mode.
      */
     @GuardedBy("sGlobalLock")
-    private static void resetAfterTestLocked() {
+    private static void setTestModeLocked(boolean mode) {
         for (Iterator<String> e = sHandlers.keys().asIterator(); e.hasNext(); ) {
             String s = e.next();
             final NonceHandler h = sHandlers.get(s);
-            h.setTestMode(false);
+            h.setTestMode(mode);
         }
     }
 
diff --git a/core/java/android/app/performance.aconfig b/core/java/android/app/performance.aconfig
index 2569f7b..82875eb 100644
--- a/core/java/android/app/performance.aconfig
+++ b/core/java/android/app/performance.aconfig
@@ -50,3 +50,10 @@
      description: "Cache null returns from binder calls"
      bug: "372923336"
 }
+
+flag {
+     namespace: "system_performance"
+     name: "pic_test_mode"
+     description: "Updated test mode for PIC"
+     bug: "396173886"
+}
diff --git a/core/java/android/app/servertransaction/ClientTransaction.java b/core/java/android/app/servertransaction/ClientTransaction.java
index 6e3e86c..e726bc9 100644
--- a/core/java/android/app/servertransaction/ClientTransaction.java
+++ b/core/java/android/app/servertransaction/ClientTransaction.java
@@ -236,9 +236,17 @@
      * 2. The transaction message is scheduled.
      * 3. The client calls {@link TransactionExecutor#execute(ClientTransaction)}, which executes
      *    all callbacks and necessary lifecycle transitions.
+     *
+     * @return {@link RemoteException} if the transaction failed.
      */
-    public void schedule() throws RemoteException {
-        mClient.scheduleTransaction(this);
+    @Nullable
+    public RemoteException schedule() {
+        try {
+            mClient.scheduleTransaction(this);
+            return null;
+        } catch (RemoteException e) {
+            return e;
+        }
     }
 
     // Parcelable implementation
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index 255a08c..42bef0e 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -400,3 +400,11 @@
     bug: "378539511"
     is_fixed_read_only: true
 }
+
+flag {
+    name: "cloud_compilation_verification"
+    namespace: "art_mainline"
+    description: "Feature flag to enable the Cloud Compilation install-time verification in the package manager."
+    bug: "377474232"
+    is_fixed_read_only: true
+}
diff --git a/core/java/android/os/IpcDataCache.java b/core/java/android/os/IpcDataCache.java
index 240bc4f..2e7c3be 100644
--- a/core/java/android/os/IpcDataCache.java
+++ b/core/java/android/os/IpcDataCache.java
@@ -719,9 +719,13 @@
 
     /**
      * Enable or disable testing.  The protocol requires that the mode toggle: for instance, it is
-     * illegal to clear the test mode if the test mode is already off.  The purpose is solely to
-     * ensure that test clients do not forget to use the test mode properly, even though the
-     * current logic does not care.
+     * illegal to clear the test mode if the test mode is already off.  Enabling test mode puts
+     * all caches in the process into test mode; all nonces are initialized to UNSET and
+     * subsequent reads and writes are to process memory.  This has the effect of disabling all
+     * caches that are not local to the process.  Disabling test mode restores caches to normal
+     * operation.
+     * @param mode The desired test mode.
+     * @throws IllegalStateException if the supplied mode is already set.
      * @hide
      */
     @TestApi
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 5188204..561a2c9 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -16,6 +16,7 @@
 
 package android.permission;
 
+import static android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -2039,12 +2040,49 @@
                 new PackageNamePermissionQuery(permName, pkgName, persistentDeviceId, userId));
     }
 
+    /**
+     * When checking a device-aware permission on a remote device, if the permission is CAMERA
+     * or RECORD_AUDIO we need to check remote device's corresponding capability. If the remote
+     * device doesn't have capability fall back to checking permission on the default device.
+     *
+     * @hide
+     */
+    public static int resolveDeviceIdForPermissionCheck(@NonNull Context context, int deviceId,
+            @Nullable String permission) {
+        if (deviceId == Context.DEVICE_ID_DEFAULT || !DEVICE_AWARE_PERMISSIONS.contains(
+                permission)) {
+            return Context.DEVICE_ID_DEFAULT;
+        }
+
+        VirtualDeviceManager virtualDeviceManager =
+                context.getSystemService(VirtualDeviceManager.class);
+        if (virtualDeviceManager == null) {
+            Slog.e(LOG_TAG, "VDM is not enabled when device id is not default. deviceId = "
+                    + deviceId);
+        } else {
+            VirtualDevice virtualDevice = virtualDeviceManager.getVirtualDevice(deviceId);
+            if (virtualDevice != null) {
+                if ((Objects.equals(permission, Manifest.permission.RECORD_AUDIO)
+                        && !virtualDevice.hasCustomAudioInputSupport())
+                        || (Objects.equals(permission, Manifest.permission.CAMERA)
+                        && !virtualDevice.hasCustomCameraSupport())) {
+                    deviceId = Context.DEVICE_ID_DEFAULT;
+                }
+            } else {
+                Slog.e(LOG_TAG,
+                        "virtualDevice is not found when device id is not default. deviceId = "
+                                + deviceId);
+            }
+        }
+        return deviceId;
+    }
+
     @Nullable
     private String getPersistentDeviceId(int deviceId) {
         String persistentDeviceId = null;
 
         if (deviceId == Context.DEVICE_ID_DEFAULT) {
-            persistentDeviceId = VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT;
+            persistentDeviceId = PERSISTENT_DEVICE_ID_DEFAULT;
         } else {
             VirtualDeviceManager virtualDeviceManager = mContext.getSystemService(
                     VirtualDeviceManager.class);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c048d79..f50d77e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -34463,7 +34463,10 @@
      */
     @FlaggedApi(android.app.jank.Flags.FLAG_DETAILED_APP_JANK_METRICS_API)
     public void reportAppJankStats(@NonNull AppJankStats appJankStats) {
-        getRootView().reportAppJankStats(appJankStats);
+        View rootView = getRootView();
+        if (rootView == this) return;
+
+        rootView.reportAppJankStats(appJankStats);
     }
 
     /**
@@ -34471,6 +34474,10 @@
      * @hide
      */
     public @Nullable JankTracker getJankTracker() {
-        return getRootView().getJankTracker();
+        View rootView = getRootView();
+        if (rootView == this) {
+            return null;
+        }
+        return rootView.getJankTracker();
     }
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7fd7be8..e157da7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -153,6 +153,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.ResourcesManager;
+import android.app.UiModeManager;
 import android.app.WindowConfiguration;
 import android.app.compat.CompatChanges;
 import android.app.servertransaction.WindowStateTransactionItem;
@@ -196,6 +197,7 @@
 import android.hardware.input.InputManagerGlobal;
 import android.hardware.input.InputSettings;
 import android.media.AudioManager;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -472,8 +474,6 @@
     @Nullable
     private ContentObserver mForceInvertObserver;
 
-    private static final int INVALID_VALUE = Integer.MIN_VALUE;
-    private int mForceInvertEnabled = INVALID_VALUE;
     /**
      * Callback for notifying about global configuration changes.
      */
@@ -555,6 +555,8 @@
     @UiContext
     public final Context mContext;
 
+    private UiModeManager mUiModeManager;
+
     @UnsupportedAppUsage
     final IWindowSession mWindowSession;
     @NonNull Display mDisplay;
@@ -1804,23 +1806,6 @@
         }
     }
 
-    private boolean isForceInvertEnabled() {
-        if (mForceInvertEnabled == INVALID_VALUE) {
-            reloadForceInvertEnabled();
-        }
-        return mForceInvertEnabled == 1;
-    }
-
-    private void reloadForceInvertEnabled() {
-        if (forceInvertColor()) {
-            mForceInvertEnabled = Settings.Secure.getIntForUser(
-                    mContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
-                    /* def= */ 0,
-                    UserHandle.myUserId());
-        }
-    }
-
     /**
      * Register any kind of listeners if setView was success.
      */
@@ -1856,17 +1841,22 @@
                 mForceInvertObserver = new ContentObserver(mHandler) {
                     @Override
                     public void onChange(boolean selfChange) {
-                        reloadForceInvertEnabled();
                         updateForceDarkMode();
                     }
                 };
-                mContext.getContentResolver().registerContentObserver(
-                        Settings.Secure.getUriFor(
-                                Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED
-                        ),
-                        false,
-                        mForceInvertObserver,
-                        UserHandle.myUserId());
+
+                final Uri[] urisToObserve = {
+                    Settings.Secure.getUriFor(
+                        Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED),
+                    Settings.Secure.getUriFor(Settings.Secure.UI_NIGHT_MODE)
+                };
+                for (Uri uri : urisToObserve) {
+                    mContext.getContentResolver().registerContentObserver(
+                            uri,
+                            false,
+                            mForceInvertObserver,
+                            UserHandle.myUserId());
+                }
             }
         }
     }
@@ -2073,21 +2063,25 @@
         return getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
     }
 
-    /** Returns true if force dark should be enabled according to various settings */
+    /**
+     * Determines the type of force dark to apply, considering force inversion, system night mode,
+     * and app-specific settings (including developer opt-outs).
+     *
+     * @return A {@link ForceDarkType.ForceDarkTypeDef} constant indicating the force dark type.
+     */
     @VisibleForTesting
     public @ForceDarkType.ForceDarkTypeDef int determineForceDarkType() {
         if (forceInvertColor()) {
             // Force invert ignores all developer opt-outs.
             // We also ignore dark theme, since the app developer can override the user's preference
-            // for dark mode in configuration.uiMode. Instead, we assume that the force invert
-            // setting will be enabled at the same time dark theme is in the Settings app.
-            if (isForceInvertEnabled()) {
+            // for dark mode in configuration.uiMode. Instead, we assume that both force invert and
+            // the system's dark theme are enabled.
+            if (getUiModeManager().getForceInvertState() == UiModeManager.FORCE_INVERT_TYPE_DARK) {
                 return ForceDarkType.FORCE_INVERT_COLOR_DARK;
             }
         }
 
         boolean useAutoDark = getNightMode() == Configuration.UI_MODE_NIGHT_YES;
-
         if (useAutoDark) {
             boolean forceDarkAllowedDefault =
                     SystemProperties.getBoolean(ThreadedRenderer.DEBUG_FORCE_DARK, false);
@@ -9401,6 +9395,13 @@
         return mAudioManager;
     }
 
+    private UiModeManager getUiModeManager() {
+        if (mUiModeManager == null) {
+            mUiModeManager = mContext.getSystemService(UiModeManager.class);
+        }
+        return mUiModeManager;
+    }
+
     private Vibrator getSystemVibrator() {
         if (mVibrator == null) {
             mVibrator = mContext.getSystemService(Vibrator.class);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 196ae5e..83dc79b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -631,6 +631,12 @@
     int TRANSIT_FLAG_AOD_APPEARING = (1 << 15); // 0x8000
 
     /**
+     * Transition flag: Indicates that the task shouldn't move to front when launching the activity.
+     * @hide
+     */
+    int TRANSIT_FLAG_AVOID_MOVE_TO_FRONT = (1 << 16); // 0x10000
+
+    /**
      * @hide
      */
     @IntDef(flag = true, prefix = { "TRANSIT_FLAG_" }, value = {
@@ -650,6 +656,7 @@
             TRANSIT_FLAG_KEYGUARD_UNOCCLUDING,
             TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH,
             TRANSIT_FLAG_AOD_APPEARING,
+            TRANSIT_FLAG_AVOID_MOVE_TO_FRONT,
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface TransitionFlags {}
diff --git a/core/java/android/webkit/TEST_MAPPING b/core/java/android/webkit/TEST_MAPPING
index 3858059..c9b5476 100644
--- a/core/java/android/webkit/TEST_MAPPING
+++ b/core/java/android/webkit/TEST_MAPPING
@@ -17,15 +17,6 @@
           "exclude-annotation": "android.test.FlakyTest"
         }
       ]
-    },
-    {
-      "name": "GtsWebViewHostTestCases",
-      "keywords": ["internal"],
-      "options": [
-        {
-          "exclude-annotation": "android.test.FlakyTest"
-        }
-      ]
     }
   ]
 }
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 14b208a..ab7a4f2 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -1458,13 +1458,14 @@
     public abstract void setNeedInitialFocus(boolean flag);
 
     /**
-     * Sets the priority of the Render thread. Unlike the other settings, this
+     * Sets the CPU scheduling priority of the Render thread. Unlike the other settings, this
      * one only needs to be called once per process. The default value is
      * {@link RenderPriority#NORMAL}.
      *
      * @param priority the priority
-     * @deprecated It is not recommended to adjust thread priorities, and this will
-     *             not be supported in future versions.
+     * @deprecated This is no longer supported. See {@link WebView#setRendererPriorityPolicy} if you
+     *             instead want to control how freely the system should kill the renderer process
+     *             under low memory conditions.
      */
     @Deprecated
     public abstract void setRenderPriority(RenderPriority priority);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index b666399..5e22c28 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2287,26 +2287,53 @@
     public @interface RendererPriority {}
 
     /**
-     * The renderer associated with this WebView is bound with
-     * {@link Context#BIND_WAIVE_PRIORITY}. At this priority level
-     * {@link WebView} renderers will be strong targets for out of memory
-     * killing.
+     * This is the lowest binding priority for the WebView renderer process. This is equivalent to
+     * {@link Context#BIND_WAIVE_PRIORITY}. At this priority level {@link WebView} renderers will be
+     * frequent targets for being killed when the system is running low on memory.
      *
-     * Use with {@link #setRendererPriorityPolicy}.
+     * <p>If using this priority, we recommend handling the {@link
+     * WebViewClient#onRenderProcessGone} callback to recover from low memory kills as well as other
+     * types of renderer crashes.
+     *
+     * @see #setRendererPriorityPolicy
+     * @see #getRendererPriorityPolicy
+     * @see RenderProcessGoneDetail#rendererPriorityAtExit
      */
     public static final int RENDERER_PRIORITY_WAIVED = 0;
+
     /**
-     * The renderer associated with this WebView is bound with
-     * the default priority for services.
+     * This is the medium binding priority for the WebView renderer process. This is equivalent to
+     * the standard priority used by the system for calls to {@link
+     * Context#bindService(Intent,android.content.ServiceConnection,int)} when no flags are
+     * provided. At this priority level {@link WebView} renderers will be slightly more likely
+     * targets for being killed when the system is running low on memory.
      *
-     * Use with {@link #setRendererPriorityPolicy}.
+     * <p>If using this priority, we recommend handling the {@link
+     * WebViewClient#onRenderProcessGone} callback to recover from low memory kills as well as other
+     * types of renderer crashes.
+     *
+     * @see #setRendererPriorityPolicy
+     * @see #getRendererPriorityPolicy
+     * @see RenderProcessGoneDetail#rendererPriorityAtExit
      */
     public static final int RENDERER_PRIORITY_BOUND = 1;
+
     /**
-     * The renderer associated with this WebView is bound with
-     * {@link Context#BIND_IMPORTANT}.
+     * This is the highest binding priority for the WebView renderer process, and the default value
+     * WebView uses to bind to the renderer process. This is equivalent to {@link
+     * Context#BIND_IMPORTANT}. At this priority level {@link WebView} renderers are less likely to
+     * be killed when the system is running low on memory and will have the same priority as your
+     * app's main process.
      *
-     * Use with {@link #setRendererPriorityPolicy}.
+     * <p>It's still possible for the renderer process to be killed when the system is running low
+     * on memory, however specifying this priority makes this situation less likely. It's also still
+     * possible for the renderer process to crash for other reasons. You may optionally still choose
+     * to handle {@link WebViewClient#onRenderProcessGone} in order to recover from a killed or
+     * crashed renderer process.
+     *
+     * @see #setRendererPriorityPolicy
+     * @see #getRendererPriorityPolicy
+     * @see RenderProcessGoneDetail#rendererPriorityAtExit
      */
     public static final int RENDERER_PRIORITY_IMPORTANT = 2;
 
@@ -2316,7 +2343,7 @@
      * process renderer should be considered to be a target for OOM
      * killing.
      *
-     * Because a renderer can be associated with more than one
+     * <p>Because a renderer can be associated with more than one
      * WebView, the final priority it is computed as the maximum of
      * any attached WebViews. When a WebView is destroyed it will
      * cease to be considerered when calculating the renderer
@@ -2324,7 +2351,7 @@
      * the priority of the renderer will be reduced to
      * {@link #RENDERER_PRIORITY_WAIVED}.
      *
-     * The default policy is to set the priority to
+     * <p>The default policy is to set the priority to
      * {@link #RENDERER_PRIORITY_IMPORTANT} regardless of visibility,
      * and this should not be changed unless the caller also handles
      * renderer crashes with
@@ -2338,6 +2365,8 @@
      *        when this WebView is not visible, it will be treated as
      *        if it had requested a priority of
      *        {@link #RENDERER_PRIORITY_WAIVED}.
+     * @see #getRendererPriorityPolicy
+     * @see RenderProcessGoneDetail#rendererPriorityAtExit
      */
     public void setRendererPriorityPolicy(
             @RendererPriority int rendererRequestedPriority,
@@ -2349,6 +2378,8 @@
      * Get the requested renderer priority for this WebView.
      *
      * @return the requested renderer priority policy.
+     * @see #setRendererPriorityPolicy
+     * @see RenderProcessGoneDetail#rendererPriorityAtExit
      */
     @InspectableProperty(hasAttributeId = false, enumMapping = {
             @InspectableProperty.EnumEntry(name = "waived", value = RENDERER_PRIORITY_WAIVED),
diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java
index 8162540..696b7b8 100644
--- a/core/java/android/window/DesktopModeFlags.java
+++ b/core/java/android/window/DesktopModeFlags.java
@@ -61,6 +61,8 @@
     ENABLE_DESKTOP_COMPAT_UI_VISIBILITY_STATUS(Flags::enableCompatUiVisibilityStatus, true),
     ENABLE_DESKTOP_INDICATOR_IN_SEPARATE_THREAD_BUGFIX(
             Flags::enableDesktopIndicatorInSeparateThreadBugfix, false),
+    ENABLE_DESKTOP_OPENING_DEEPLINK_MINIMIZE_ANIMATION_BUGFIX(
+            Flags::enableDesktopOpeningDeeplinkMinimizeAnimationBugfix, false),
     ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX(
             Flags::enableDesktopRecentsTransitionsCornersBugfix, false),
     ENABLE_DESKTOP_SKIP_COMPAT_UI_EDUCATION_IN_DESKTOP_MODE_BUGFIX(
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 9f768f0..f2efa20 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -152,4 +152,15 @@
     metadata {
         purpose: PURPOSE_BUGFIX
     }
-}
\ No newline at end of file
+}
+
+flag {
+    namespace: "windowing_sdk"
+    name: "cleanup_dispatch_pending_transactions_remote_exception"
+    description: "Refactor to cleanup for RemoteException from dispatchPendingTransactions"
+    bug: "323801078"
+    is_fixed_read_only: true
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
index ac78e87..f75a72d 100644
--- a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
+++ b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
@@ -414,16 +414,23 @@
     @Test
     @DisabledOnRavenwood(reason = "SystemProperties doesn't have permission check")
     public void testPermissionFailure() {
-        // Create a cache that will write a system nonce.
-        TestCache sysCache = new TestCache(MODULE_SYSTEM, "mode1");
         try {
-            // Invalidate the cache, which writes the system property.  There must be a permission
-            // failure.
-            sysCache.invalidateCache();
-            fail("expected permission failure");
-        } catch (RuntimeException e) {
-            // The expected exception is a bare RuntimeException.  The test does not attempt to
-            // validate the text of the exception message.
+            // Disable the test mode for this test, but ensure that it will be enabled when the
+            // test exits.
+            PropertyInvalidatedCache.setTestMode(false);
+            // Create a cache that will write a system nonce.
+            TestCache sysCache = new TestCache(MODULE_SYSTEM, "mode1");
+            try {
+                // Invalidate the cache, which writes the system property.  There must be a
+                // permission failure.
+                sysCache.invalidateCache();
+                fail("expected permission failure");
+            } catch (RuntimeException e) {
+                // The expected exception is a bare RuntimeException.  The test does not attempt
+                // to validate the text of the exception message.
+            }
+        } finally {
+            PropertyInvalidatedCache.setTestMode(true);
         }
     }
 
diff --git a/core/tests/coretests/src/android/os/IpcDataCacheTest.java b/core/tests/coretests/src/android/os/IpcDataCacheTest.java
index 74b32a1..791ec5d 100644
--- a/core/tests/coretests/src/android/os/IpcDataCacheTest.java
+++ b/core/tests/coretests/src/android/os/IpcDataCacheTest.java
@@ -452,22 +452,28 @@
         assertTrue(ec.isDisabled());
     }
 
-
     // Verify that invalidating the cache from an app process would fail due to lack of permissions.
     @Test
     @android.platform.test.annotations.DisabledOnRavenwood(
             reason = "SystemProperties doesn't have permission check")
     public void testPermissionFailure() {
-        // Create a cache that will write a system nonce.
-        TestCache sysCache = new TestCache(IpcDataCache.MODULE_SYSTEM, "mode1");
         try {
-            // Invalidate the cache, which writes the system property.  There must be a permission
-            // failure.
-            sysCache.invalidateCache();
-            fail("expected permission failure");
-        } catch (RuntimeException e) {
-            // The expected exception is a bare RuntimeException.  The test does not attempt to
-            // validate the text of the exception message.
+            // Disable test mode for this test.  Guarantee that the mode is enabled before the
+            // test exits.
+            IpcDataCache.setTestMode(false);
+            // Create a cache that will write a system nonce.
+            TestCache sysCache = new TestCache(IpcDataCache.MODULE_SYSTEM, "mode1");
+            try {
+                // Invalidate the cache, which writes the system property.  There must be a
+                // permission failure.
+                sysCache.invalidateCache();
+                fail("expected permission failure");
+            } catch (RuntimeException e) {
+                // The expected exception is a bare RuntimeException.  The test does not attempt
+                // to validate the text of the exception message.
+            }
+        } finally {
+            IpcDataCache.setTestMode(true);
         }
     }
 
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index f5d1e7a..39f3d33 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import static android.app.UiModeManager.MODE_NIGHT_NO;
+import static android.app.UiModeManager.MODE_NIGHT_YES;
 import static android.util.SequenceUtils.getInitSeq;
 import static android.view.HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING;
 import static android.view.InputDevice.SOURCE_ROTARY_ENCODER;
@@ -67,8 +69,10 @@
 import android.annotation.NonNull;
 import android.app.Instrumentation;
 import android.app.UiModeManager;
+import android.app.UiModeManager.ForceInvertType;
 import android.content.Context;
 import android.graphics.ForceDarkType;
+import android.graphics.ForceDarkType.ForceDarkTypeDef;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManagerGlobal;
 import android.os.Binder;
@@ -93,9 +97,12 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.ShellIdentityUtils;
+import com.android.compatibility.common.util.TestUtils;
 import com.android.cts.input.BlockingQueueEventVerifier;
 import com.android.window.flags.Flags;
 
+import com.google.common.truth.Expect;
+
 import org.hamcrest.Matcher;
 import org.junit.After;
 import org.junit.AfterClass;
@@ -124,6 +131,8 @@
 
     @Rule
     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+    @Rule
+    public final Expect mExpect = Expect.create();
 
     private ViewRootImpl mViewRootImpl;
     private View mView;
@@ -1507,49 +1516,34 @@
     }
 
     @Test
-    public void forceInvertOffDarkThemeOff_forceDarkModeDisabled() {
-        mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
-        ShellIdentityUtils.invokeWithShellPermissions(() -> {
-            Settings.Secure.putInt(
-                    sContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
-                    /* value= */ 0
-            );
-            var uiModeManager = sContext.getSystemService(UiModeManager.class);
-            uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
-        });
+    @RequiresFlagsEnabled(FLAG_FORCE_INVERT_COLOR)
+    public void updateConfiguration_returnsExpectedForceDarkMode() {
+        waitForSystemNightModeActivated(true);
 
-        sInstrumentation.runOnMainSync(() ->
-                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
-        );
+        verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ true,
+                UiModeManager.FORCE_INVERT_TYPE_DARK, ForceDarkType.FORCE_INVERT_COLOR_DARK);
+        verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ false,
+                UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
+        verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ true,
+                UiModeManager.FORCE_INVERT_TYPE_DARK, ForceDarkType.FORCE_INVERT_COLOR_DARK);
+        verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ false,
+                UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
 
-        assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.NONE);
+        waitForSystemNightModeActivated(false);
+
+        verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ true,
+                UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
+        verifyForceDarkType(/* isAppInNightMode= */ true, /* isForceInvertEnabled= */ false,
+                UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
+        verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ true,
+                UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
+        verifyForceDarkType(/* isAppInNightMode= */ false, /* isForceInvertEnabled= */ false,
+                UiModeManager.FORCE_INVERT_TYPE_OFF, ForceDarkType.NONE);
     }
 
     @Test
-    public void forceInvertOnDarkThemeOff_forceDarkModeEnabled() {
-        mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
-        ShellIdentityUtils.invokeWithShellPermissions(() -> {
-            Settings.Secure.putInt(
-                    sContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
-                    /* value= */ 1
-            );
-            var uiModeManager = sContext.getSystemService(UiModeManager.class);
-            uiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
-        });
-
-        sInstrumentation.runOnMainSync(() ->
-                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
-        );
-
-        assertThat(mViewRootImpl.determineForceDarkType())
-                .isEqualTo(ForceDarkType.FORCE_INVERT_COLOR_DARK);
-    }
-
-    @Test
+    @EnableFlags(FLAG_FORCE_INVERT_COLOR)
     public void forceInvertOffForceDarkOff_forceDarkModeDisabled() {
-        mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
         ShellIdentityUtils.invokeWithShellPermissions(() -> {
             Settings.Secure.putInt(
                     sContext.getContentResolver(),
@@ -1562,15 +1556,14 @@
         });
 
         sInstrumentation.runOnMainSync(() ->
-                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
-        );
+                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
 
         assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.NONE);
     }
 
     @Test
+    @EnableFlags(FLAG_FORCE_INVERT_COLOR)
     public void forceInvertOffForceDarkOn_forceDarkModeEnabled() {
-        mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR);
         ShellIdentityUtils.invokeWithShellPermissions(() -> {
             Settings.Secure.putInt(
                     sContext.getContentResolver(),
@@ -1582,8 +1575,7 @@
         });
 
         sInstrumentation.runOnMainSync(() ->
-                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId())
-        );
+                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
 
         assertThat(mViewRootImpl.determineForceDarkType()).isEqualTo(ForceDarkType.FORCE_DARK);
     }
@@ -1790,4 +1782,39 @@
                     () -> view.getViewTreeObserver().removeOnDrawListener(listener));
         }
     }
+
+    private void waitForSystemNightModeActivated(boolean active) {
+        ShellIdentityUtils.invokeWithShellPermissions(() ->
+                sInstrumentation.runOnMainSync(() -> {
+                    var uiModeManager = sContext.getSystemService(UiModeManager.class);
+                    uiModeManager.setNightModeActivated(active);
+                }));
+        sInstrumentation.waitForIdleSync();
+    }
+
+    private void verifyForceDarkType(boolean isAppInNightMode, boolean isForceInvertEnabled,
+            @ForceInvertType int expectedForceInvertType,
+            @ForceDarkTypeDef int expectedForceDarkType) {
+        var uiModeManager = sContext.getSystemService(UiModeManager.class);
+        ShellIdentityUtils.invokeWithShellPermissions(() -> {
+            uiModeManager.setApplicationNightMode(
+                    isAppInNightMode ? MODE_NIGHT_YES : MODE_NIGHT_NO);
+            Settings.Secure.putInt(
+                    sContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
+                    isForceInvertEnabled ? 1 : 0);
+        });
+
+        sInstrumentation.runOnMainSync(() ->
+                mViewRootImpl.updateConfiguration(sContext.getDisplayNoVerify().getDisplayId()));
+        try {
+            TestUtils.waitUntil("Waiting for force invert state changed",
+                    () -> (uiModeManager.getForceInvertState() == expectedForceInvertType));
+        } catch (Exception e) {
+            Log.e(TAG, "Unexpected error trying to apply force invert state. " + e);
+            e.printStackTrace();
+        }
+
+        mExpect.that(mViewRootImpl.determineForceDarkType()).isEqualTo(expectedForceDarkType);
+    }
 }
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index a0ca098..05e23a0 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -2206,26 +2206,21 @@
      * @param fontVariationOverride font variation override. You can pass null or empty string for
      *                              clearing font variation override.
      *
-     * @return true if the provided font variation settings is valid. Otherwise returns false.
-     *
+     * @throws IllegalArgumentException If given string is not a valid font variation settings
+     *                                  format
      * @see #getFontVariationSettings()
      * @see #setFontVariationSettings(String)
      * @see #getFontVariationOverride()
      * @see FontVariationAxis
      */
     @FlaggedApi(FLAG_TYPEFACE_REDESIGN_READONLY)
-    public boolean setFontVariationOverride(@Nullable String fontVariationOverride) {
+    public void setFontVariationOverride(@Nullable String fontVariationOverride) {
         if (Objects.equals(fontVariationOverride, mFontVariationOverride)) {
-            return true;
+            return;
         }
 
-        List<FontVariationAxis> axes;
-        try {
-            axes = FontVariationAxis.fromFontVariationSettingsForList(fontVariationOverride);
-        } catch (IllegalArgumentException e) {
-            Log.i(TAG, "failed to parse font variation settings.", e);
-            return false;
-        }
+        List<FontVariationAxis> axes =
+                FontVariationAxis.fromFontVariationSettingsForList(fontVariationOverride);
         long builderPtr = nCreateFontVariationBuilder(axes.size());
         for (int i = 0; i < axes.size(); ++i) {
             FontVariationAxis axis = axes.get(i);
@@ -2234,7 +2229,6 @@
         }
         nSetFontVariationOverride(mNativePaint, builderPtr);
         mFontVariationOverride = fontVariationOverride;
-        return true;
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 305fcdd..be22402 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -117,6 +117,7 @@
 import com.android.wm.shell.shared.annotations.ShellMainThread;
 import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper;
 import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation.UpdateSource;
 import com.android.wm.shell.shared.bubbles.BubbleBarUpdate;
 import com.android.wm.shell.shared.bubbles.BubbleDropTargetBoundsProvider;
 import com.android.wm.shell.shared.bubbles.DeviceConfig;
@@ -795,7 +796,7 @@
      * Update bubble bar location and trigger and update to listeners
      */
     public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation,
-            @BubbleBarLocation.UpdateSource int source) {
+            @UpdateSource int source) {
         if (isShowingAsBubbleBar()) {
             updateExpandedViewForBubbleBarLocation(bubbleBarLocation, source);
             BubbleBarUpdate bubbleBarUpdate = new BubbleBarUpdate();
@@ -805,7 +806,7 @@
     }
 
     private void updateExpandedViewForBubbleBarLocation(BubbleBarLocation bubbleBarLocation,
-            @BubbleBarLocation.UpdateSource int source) {
+            @UpdateSource int source) {
         if (isShowingAsBubbleBar()) {
             BubbleBarLocation previousLocation = mBubblePositioner.getBubbleBarLocation();
             mBubblePositioner.setBubbleBarLocation(bubbleBarLocation);
@@ -818,7 +819,7 @@
 
     private void logBubbleBarLocationIfChanged(BubbleBarLocation location,
             BubbleBarLocation previous,
-            @BubbleBarLocation.UpdateSource int source) {
+            @UpdateSource int source) {
         if (mLayerView == null) {
             return;
         }
@@ -830,25 +831,25 @@
             return;
         }
         switch (source) {
-            case BubbleBarLocation.UpdateSource.DRAG_BAR:
-            case BubbleBarLocation.UpdateSource.A11Y_ACTION_BAR:
+            case UpdateSource.DRAG_BAR:
+            case UpdateSource.A11Y_ACTION_BAR:
                 mLogger.log(onLeft ? BubbleLogger.Event.BUBBLE_BAR_MOVED_LEFT_DRAG_BAR
                         : BubbleLogger.Event.BUBBLE_BAR_MOVED_RIGHT_DRAG_BAR);
                 break;
-            case BubbleBarLocation.UpdateSource.DRAG_BUBBLE:
-            case BubbleBarLocation.UpdateSource.A11Y_ACTION_BUBBLE:
+            case UpdateSource.DRAG_BUBBLE:
+            case UpdateSource.A11Y_ACTION_BUBBLE:
                 mLogger.log(onLeft ? BubbleLogger.Event.BUBBLE_BAR_MOVED_LEFT_DRAG_BUBBLE
                         : BubbleLogger.Event.BUBBLE_BAR_MOVED_RIGHT_DRAG_BUBBLE);
                 break;
-            case BubbleBarLocation.UpdateSource.DRAG_EXP_VIEW:
-            case BubbleBarLocation.UpdateSource.A11Y_ACTION_EXP_VIEW:
+            case UpdateSource.DRAG_EXP_VIEW:
+            case UpdateSource.A11Y_ACTION_EXP_VIEW:
                 // TODO(b/349845968): move logging from BubbleBarLayerView to here
                 break;
-            case BubbleBarLocation.UpdateSource.APP_ICON_DRAG:
+            case UpdateSource.APP_ICON_DRAG:
                 mLogger.log(onLeft ? BubbleLogger.Event.BUBBLE_BAR_MOVED_LEFT_APP_ICON_DROP
                         : BubbleLogger.Event.BUBBLE_BAR_MOVED_RIGHT_APP_ICON_DROP);
                 break;
-            case BubbleBarLocation.UpdateSource.DRAG_TASK:
+            case UpdateSource.DRAG_TASK:
                 mLogger.log(onLeft ? BubbleLogger.Event.BUBBLE_BAR_MOVED_LEFT_DRAG_TASK
                         : BubbleLogger.Event.BUBBLE_BAR_MOVED_RIGHT_DRAG_TASK);
                 break;
@@ -872,10 +873,7 @@
         if (bubbleBarLocation == null) return;
         if (isShowingAsBubbleBar() && BubbleAnythingFlagHelper.enableCreateAnyBubble()) {
             mBubbleStateListener.onDragItemOverBubbleBarDragZone(bubbleBarLocation);
-            ensureBubbleViewsAndWindowCreated();
-            if (mLayerView != null) {
-                mLayerView.showBubbleBarExtendedViewDropTarget(bubbleBarLocation);
-            }
+            showBubbleBarExpandedViewDropTarget(bubbleBarLocation);
         }
     }
 
@@ -921,6 +919,13 @@
         return result;
     }
 
+    private void showBubbleBarExpandedViewDropTarget(BubbleBarLocation bubbleBarLocation) {
+        ensureBubbleViewsAndWindowCreated();
+        if (mLayerView != null) {
+            mLayerView.showBubbleBarExtendedViewDropTarget(bubbleBarLocation);
+        }
+    }
+
     private void hideBubbleBarExpandedViewDropTarget() {
         if (mLayerView != null) {
             mLayerView.hideBubbleBarExpandedViewDropTarget();
@@ -1541,20 +1546,9 @@
     public void expandStackAndSelectBubble(ShortcutInfo info,
             @Nullable BubbleBarLocation bubbleBarLocation) {
         if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) return;
-        BubbleBarLocation updateLocation = isShowingAsBubbleBar() ? bubbleBarLocation : null;
-        if (updateLocation != null) {
-            updateExpandedViewForBubbleBarLocation(updateLocation,
-                    BubbleBarLocation.UpdateSource.APP_ICON_DRAG);
-        }
         Bubble b = mBubbleData.getOrCreateBubble(info); // Removes from overflow
         ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - shortcut=%s", info);
-        if (b.isInflated()) {
-            mBubbleData.setSelectedBubbleAndExpandStack(b, updateLocation);
-        } else {
-            b.enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
-            inflateAndAdd(b, /* suppressFlyout= */ true, /* showInShade= */ false,
-                    updateLocation);
-        }
+        expandStackAndSelectAppBubble(b, bubbleBarLocation, UpdateSource.APP_ICON_DRAG);
     }
 
     /**
@@ -1562,16 +1556,12 @@
      *
      * @param intent the intent for the bubble.
      */
-    public void expandStackAndSelectBubble(Intent intent, UserHandle user) {
+    public void expandStackAndSelectBubble(Intent intent, UserHandle user,
+            @Nullable BubbleBarLocation bubbleBarLocation) {
         if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) return;
         Bubble b = mBubbleData.getOrCreateBubble(intent, user); // Removes from overflow
         ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - intent=%s", intent);
-        if (b.isInflated()) {
-            mBubbleData.setSelectedBubbleAndExpandStack(b);
-        } else {
-            b.enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
-            inflateAndAdd(b, /* suppressFlyout= */ true, /* showInShade= */ false);
-        }
+        expandStackAndSelectAppBubble(b, bubbleBarLocation, UpdateSource.APP_ICON_DRAG);
     }
 
     /**
@@ -1583,14 +1573,19 @@
     public void expandStackAndSelectBubble(PendingIntent pendingIntent, UserHandle user,
             @Nullable BubbleBarLocation bubbleBarLocation) {
         if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) return;
-        BubbleBarLocation updateLocation = isShowingAsBubbleBar() ? bubbleBarLocation : null;
-        if (updateLocation != null) {
-            updateExpandedViewForBubbleBarLocation(updateLocation,
-                    BubbleBarLocation.UpdateSource.APP_ICON_DRAG);
-        }
-        Bubble b = mBubbleData.getOrCreateBubble(pendingIntent, user);
+        Bubble b = mBubbleData.getOrCreateBubble(pendingIntent, user); // Removes from overflow
         ProtoLog.v(WM_SHELL_BUBBLES, "expandStackAndSelectBubble - pendingIntent=%s",
                 pendingIntent);
+        expandStackAndSelectAppBubble(b, bubbleBarLocation, UpdateSource.APP_ICON_DRAG);
+    }
+
+    private void expandStackAndSelectAppBubble(Bubble b,
+            @Nullable BubbleBarLocation bubbleBarLocation, @UpdateSource int source) {
+        if (!BubbleAnythingFlagHelper.enableCreateAnyBubble()) return;
+        BubbleBarLocation updateLocation = isShowingAsBubbleBar() ? bubbleBarLocation : null;
+        if (updateLocation != null) {
+            updateExpandedViewForBubbleBarLocation(updateLocation, source);
+        }
         if (b.isInflated()) {
             mBubbleData.setSelectedBubbleAndExpandStack(b, updateLocation);
         } else {
@@ -1623,7 +1618,7 @@
             }
         } else {
             if (location != null) {
-                setBubbleBarLocation(location, BubbleBarLocation.UpdateSource.DRAG_TASK);
+                setBubbleBarLocation(location, UpdateSource.DRAG_TASK);
             }
             b.enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
             // Lazy init stack view when a bubble is created
@@ -2840,14 +2835,16 @@
         }
 
         @Override
-        public void showShortcutBubble(ShortcutInfo info) {
+        public void showShortcutBubble(ShortcutInfo info, @Nullable BubbleBarLocation location) {
             mMainExecutor.execute(() -> mController
-                    .expandStackAndSelectBubble(info, /* bubbleBarLocation = */ null));
+                    .expandStackAndSelectBubble(info, location));
         }
 
         @Override
-        public void showAppBubble(Intent intent, UserHandle user) {
-            mMainExecutor.execute(() -> mController.expandStackAndSelectBubble(intent, user));
+        public void showAppBubble(Intent intent, UserHandle user,
+                @Nullable BubbleBarLocation location) {
+            mMainExecutor.execute(
+                    () -> mController.expandStackAndSelectBubble(intent, user, location));
         }
 
         @Override
@@ -2900,7 +2897,7 @@
 
         @Override
         public void setBubbleBarLocation(BubbleBarLocation location,
-                @BubbleBarLocation.UpdateSource int source) {
+                @UpdateSource int source) {
             mMainExecutor.execute(() ->
                     mController.setBubbleBarLocation(location, source));
         }
@@ -2921,6 +2918,17 @@
                 }
             });
         }
+
+        @Override
+        public void showDropTarget(boolean show, BubbleBarLocation location) {
+            mMainExecutor.execute(() -> {
+                if (show) {
+                    showBubbleBarExpandedViewDropTarget(location);
+                } else {
+                    hideBubbleBarExpandedViewDropTarget();
+                }
+            });
+        }
     }
 
     private class BubblesImpl implements Bubbles {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
index 0a4d79a..ae1b407 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
@@ -51,9 +51,11 @@
 
     oneway void stopBubbleDrag(in BubbleBarLocation location, in int topOnScreen) = 11;
 
-    oneway void showShortcutBubble(in ShortcutInfo info) = 12;
+    oneway void showShortcutBubble(in ShortcutInfo info, in @nullable BubbleBarLocation location) = 12;
 
-    oneway void showAppBubble(in Intent intent, in UserHandle user) = 13;
+    oneway void showAppBubble(in Intent intent, in UserHandle user, in @nullable BubbleBarLocation location) = 13;
 
     oneway void showExpandedView() = 14;
+
+    oneway void showDropTarget(in boolean show, in @nullable BubbleBarLocation location) = 15;
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt
index 6034299..70a648f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt
@@ -35,7 +35,7 @@
             desktopRepository.removeTask(taskInfo.displayId, taskInfo.taskId)
             return
         }
-        if (isFreeformTask(taskInfo)) {
+        if (isFreeformTask(taskInfo) && !desktopRepository.isActiveTask(taskInfo.taskId)) {
             desktopRepository.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible)
         }
     }
@@ -44,23 +44,33 @@
         logD("onTaskChanging for taskId=%d, displayId=%d", taskInfo.taskId, taskInfo.displayId)
         val desktopRepository: DesktopRepository =
             desktopUserRepositories.getProfile(taskInfo.userId)
-        if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
-
         // TODO: b/394281403 - with multiple desks, it's possible to have a non-freeform task
         //  inside a desk, so this should be decoupled from windowing mode.
         //  Also, changes in/out of desks are handled by the [DesksTransitionObserver], which has
         //  more specific information about the desk involved in the transition, which might be
         //  more accurate than assuming it's always the default/active desk in the display, as this
         //  method does.
-        // Case 1: Freeform task is changed in Desktop Mode.
-        if (isFreeformTask(taskInfo)) {
-            if (taskInfo.isVisible) {
-                desktopRepository.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible)
+        // Case 1: When the task change is from a task in the desktop repository which is now
+        // fullscreen,
+        // remove the task from the desktop repository since it is no longer a freeform task.
+        if (!isFreeformTask(taskInfo)) {
+            if (desktopRepository.isActiveTask(taskInfo.taskId)) {
+                desktopRepository.removeTask(taskInfo.displayId, taskInfo.taskId)
             }
-            desktopRepository.updateTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible)
-        } else {
-            // Case 2: Freeform task is changed outside Desktop Mode.
-            desktopRepository.removeTask(taskInfo.displayId, taskInfo.taskId)
+        } else { // Task change is a freeform task
+            if (!desktopRepository.isActiveTask(taskInfo.taskId)) {
+                // Case 2: When the task change is a freeform visible task, but the task is not
+                // yet active in the desktop repository, adds task to desktop repository.
+                desktopRepository.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible)
+            } else {
+                // Case 3: When the task change is a freeform task which already exists as an active
+                // task in the desktop repository, updates the task state.
+                desktopRepository.updateTask(
+                    taskInfo.displayId,
+                    taskInfo.taskId,
+                    taskInfo.isVisible,
+                )
+            }
         }
     }
 
@@ -82,14 +92,22 @@
         logD("onTaskMovingToFront for taskId=%d, displayId=%d", taskInfo.taskId, taskInfo.displayId)
         val desktopRepository: DesktopRepository =
             desktopUserRepositories.getProfile(taskInfo.userId)
-        if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
-        if (!isFreeformTask(taskInfo)) {
+        // When the task change is from a task in the desktop repository which is now fullscreen,
+        // remove the task from the desktop repository since it is no longer a freeform task.
+        if (!isFreeformTask(taskInfo) && desktopRepository.isActiveTask(taskInfo.taskId)) {
             desktopRepository.removeTask(taskInfo.displayId, taskInfo.taskId)
         }
-        desktopRepository.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible)
+        if (isFreeformTask(taskInfo)) {
+            // If the task is already active in the repository, then it only moves the task to the
+            // front.
+            desktopRepository.addTask(taskInfo.displayId, taskInfo.taskId, taskInfo.isVisible)
+        }
     }
 
     override fun onTaskMovingToBack(taskInfo: RunningTaskInfo) {
+        val desktopRepository: DesktopRepository =
+            desktopUserRepositories.getProfile(taskInfo.userId)
+        if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
         logD("onTaskMovingToBack for taskId=%d, displayId=%d", taskInfo.taskId, taskInfo.displayId)
         // TODO: b/367268953 - Connect this with DesktopRepository.
     }
@@ -101,7 +119,7 @@
         if (!desktopRepository.isActiveTask(taskInfo.taskId)) return
         // TODO: b/370038902 - Handle Activity#finishAndRemoveTask.
         if (
-            !DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue() ||
+            !DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue ||
                 desktopRepository.isClosingTask(taskInfo.taskId)
         ) {
             // A task that's vanishing should be removed:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 9302347..a3a808d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -2080,8 +2080,8 @@
                             Math.max(topLeftBounds.top, 0);
                     bottomRightBounds.right =
                             Math.min(bottomRightBounds.right, mSplitLayout.getDisplayWidth());
-                    bottomRightBounds.top =
-                            Math.min(bottomRightBounds.top, mSplitLayout.getDisplayHeight());
+                    bottomRightBounds.bottom =
+                            Math.min(bottomRightBounds.bottom, mSplitLayout.getDisplayHeight());
 
                     // TODO (b/349828130): Can change to getState() fully after brief soak time.
                     if (mSplitState.get() != currentSnapPosition) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 3652a16..bf58003 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -95,7 +95,6 @@
 import android.util.ArrayMap;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
-import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
 import android.window.TransitionInfo;
 import android.window.TransitionMetrics;
@@ -835,9 +834,8 @@
                 a = mTransitionAnimation.loadVoiceActivityExitAnimation(enter, userId);
             }
         } else if (changeMode == TRANSIT_CHANGE) {
-            // In the absence of a specific adapter, we just want to keep everything stationary.
-            a = new AlphaAnimation(1.f, 1.f);
-            a.setDuration(TransitionAnimation.DEFAULT_APP_TRANSITION_DURATION);
+            // Apply end state directly by default.
+            return null;
         } else if (type == TRANSIT_RELAUNCH) {
             a = mTransitionAnimation.createRelaunchAnimation(endBounds, mInsets, endBounds);
         } else if (overrideType == ANIM_CUSTOM
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
index 4c443d7..d73d08c 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
@@ -498,9 +498,9 @@
                         it.remove(VisibleLayersShownMoreThanOneConsecutiveEntry())
                     } +
                     listOf(
-                        AppWindowOnTopAtStart(DESKTOP_MODE_APP),
                         AppWindowBecomesInvisible(DESKTOP_MODE_APP),
                         AppWindowOnTopAtEnd(LAUNCHER),
+                        AppWindowIsInvisibleAtEnd(DESKTOP_WALLPAPER),
                     ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING })
             )
         val OPEN_UNLIMITED_APPS =
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt
index d054de4..cc37c44 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt
@@ -26,7 +26,6 @@
 import android.platform.test.annotations.EnableFlags
 import android.provider.Settings
 import android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS
-import android.testing.AndroidTestingRunner
 import android.view.Display.DEFAULT_DISPLAY
 import android.view.IWindowManager
 import android.view.WindowManager.TRANSIT_CHANGE
@@ -43,6 +42,8 @@
 import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider
 import com.android.wm.shell.transition.Transitions
 import com.google.common.truth.Truth.assertThat
+import com.google.testing.junit.testparameterinjector.TestParameter
+import com.google.testing.junit.testparameterinjector.TestParameterInjector
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -62,7 +63,7 @@
  * Usage: atest WMShellUnitTests:DesktopDisplayModeControllerTest
  */
 @SmallTest
-@RunWith(AndroidTestingRunner::class)
+@RunWith(TestParameterInjector::class)
 class DesktopDisplayModeControllerTest : ShellTestCase() {
     private val transitions = mock<Transitions>()
     private val rootTaskDisplayAreaOrganizer = mock<RootTaskDisplayAreaOrganizer>()
@@ -143,41 +144,24 @@
 
     @Test
     @DisableFlags(Flags.FLAG_ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING)
-    fun displayWindowingModeSwitchOnDisplayConnected_fullscreenDisplay_flagDisabled() {
+    fun displayWindowingModeSwitchOnDisplayConnected_flagDisabled(
+        @TestParameter param: ModeSwitchTestCase
+    ) {
         testDisplayWindowingModeSwitch(
-            defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
-            extendedDisplayEnabled = true,
+            param.defaultWindowingMode,
+            param.extendedDisplayEnabled,
+            // When the flag is disabled, never switch.
             expectToSwitch = false,
         )
     }
 
     @Test
     @EnableFlags(Flags.FLAG_ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING)
-    fun displayWindowingModeSwitchOnDisplayConnected_extendedDisplayDisabled() {
+    fun displayWindowingModeSwitchOnDisplayConnected(@TestParameter param: ModeSwitchTestCase) {
         testDisplayWindowingModeSwitch(
-            defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
-            extendedDisplayEnabled = false,
-            expectToSwitch = false,
-        )
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING)
-    fun displayWindowingModeSwitchOnDisplayConnected_fullscreenDisplay() {
-        testDisplayWindowingModeSwitch(
-            defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
-            extendedDisplayEnabled = true,
-            expectToSwitch = true,
-        )
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING)
-    fun displayWindowingModeSwitchOnDisplayConnected_freeformDisplay() {
-        testDisplayWindowingModeSwitch(
-            defaultWindowingMode = WINDOWING_MODE_FREEFORM,
-            extendedDisplayEnabled = true,
-            expectToSwitch = false,
+            param.defaultWindowingMode,
+            param.extendedDisplayEnabled,
+            param.expectToSwitchByDefault,
         )
     }
 
@@ -249,7 +233,34 @@
         }
     }
 
-    private companion object {
+    companion object {
         const val EXTERNAL_DISPLAY_ID = 100
+
+        enum class ModeSwitchTestCase(
+            val defaultWindowingMode: Int,
+            val extendedDisplayEnabled: Boolean,
+            val expectToSwitchByDefault: Boolean,
+        ) {
+            FULLSCREEN_DISPLAY(
+                defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
+                extendedDisplayEnabled = true,
+                expectToSwitchByDefault = true,
+            ),
+            FULLSCREEN_DISPLAY_MIRRORING(
+                defaultWindowingMode = WINDOWING_MODE_FULLSCREEN,
+                extendedDisplayEnabled = false,
+                expectToSwitchByDefault = false,
+            ),
+            FREEFORM_DISPLAY(
+                defaultWindowingMode = WINDOWING_MODE_FREEFORM,
+                extendedDisplayEnabled = true,
+                expectToSwitchByDefault = false,
+            ),
+            FREEFORM_DISPLAY_MIRRORING(
+                defaultWindowingMode = WINDOWING_MODE_FREEFORM,
+                extendedDisplayEnabled = false,
+                expectToSwitchByDefault = false,
+            ),
+        }
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt
index 50590f0..6b0ee5b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListenerTest.kt
@@ -56,7 +56,7 @@
     }
 
     @Test
-    fun onTaskOpening_fullscreenTask_notActiveDesktopTask_noop() {
+    fun onTaskOpening_fullscreenTask_nonActiveDesktopTask_noop() {
         val task = createFullscreenTask().apply { isVisible = true }
         whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(false)
 
@@ -68,7 +68,7 @@
     }
 
     @Test
-    fun onTaskOpening_freeformTask_activeDesktopTask_removesTaskFromRepo() {
+    fun onTaskOpening_fullscreenTask_taskIsActiveInDesktopRepo_removesTaskFromDesktopRepo() {
         val task = createFullscreenTask().apply { isVisible = true }
         whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
 
@@ -78,8 +78,19 @@
     }
 
     @Test
-    fun onTaskOpening_freeformTask_visibleDesktopTask_addsTaskToRepository() {
+    fun onTaskOpening_freeformTask_activeInDesktopRepository_noop() {
         val task = createFreeformTask().apply { isVisible = true }
+        whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
+
+        desktopTaskChangeListener.onTaskOpening(task)
+
+        verify(desktopUserRepositories.current, never())
+            .addTask(task.displayId, task.taskId, task.isVisible)
+    }
+
+    @Test
+    fun onTaskOpening_freeformTask_notActiveInDesktopRepo_addsTaskToRepository() {
+        val task = createFreeformTask().apply { isVisible = false }
         whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(false)
 
         desktopTaskChangeListener.onTaskOpening(task)
@@ -88,17 +99,7 @@
     }
 
     @Test
-    fun onTaskOpening_freeformTask_nonVisibleDesktopTask_addsTaskToRepository() {
-        val task = createFreeformTask().apply { isVisible = false }
-        whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
-
-        desktopTaskChangeListener.onTaskOpening(task)
-
-        verify(desktopUserRepositories.current).addTask(task.displayId, task.taskId, task.isVisible)
-    }
-
-    @Test
-    fun onTaskChanging_freeformTaskOutsideDesktop_removesTaskFromRepo() {
+    fun onTaskChanging_fullscreenTask_activeInDesktopRepository_removesTaskFromRepo() {
         val task = createFullscreenTask().apply { isVisible = true }
         whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
 
@@ -108,7 +109,27 @@
     }
 
     @Test
-    fun onTaskChanging_visibleTaskInDesktop_updatesTaskVisibility() {
+    fun onTaskChanging_fullscreenTask_nonActiveInDesktopRepo_noop() {
+        val task = createFullscreenTask().apply { isVisible = true }
+        whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(false)
+
+        desktopTaskChangeListener.onTaskChanging(task)
+
+        verify(desktopUserRepositories.current, never()).removeTask(task.displayId, task.taskId)
+    }
+
+    @Test
+    fun onTaskChanging_freeformTask_nonActiveTaskInDesktopRepo_addsTaskToDesktopRepo() {
+        val task = createFreeformTask().apply { isVisible = true }
+        whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(false)
+
+        desktopTaskChangeListener.onTaskChanging(task)
+
+        verify(desktopUserRepositories.current).addTask(task.displayId, task.taskId, task.isVisible)
+    }
+
+    @Test
+    fun onTaskChanging_freeformTask_activeVisibleTaskInDesktopRepo_updatesTaskVisibility() {
         val task = createFreeformTask().apply { isVisible = true }
         whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
 
@@ -119,7 +140,7 @@
     }
 
     @Test
-    fun onTaskChanging_nonVisibleTask_updatesTaskVisibility() {
+    fun onTaskChanging_freeformTask_activeNonVisibleTask_updatesTaskVisibility() {
         val task = createFreeformTask().apply { isVisible = false }
         whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
 
@@ -130,7 +151,7 @@
     }
 
     @Test
-    fun onTaskMovingToFront_freeformTaskOutsideDesktop_removesTaskFromRepo() {
+    fun onTaskMovingToFront_fullscreenTask_activeTaskInDesktopRepo_removesTaskFromRepo() {
         val task = createFullscreenTask().apply { isVisible = true }
         whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
 
@@ -140,9 +161,18 @@
     }
 
     @Test
-    fun onTaskMovingToFront_freeformTaskOutsideDesktop_addsTaskToRepo() {
+    fun onTaskMovingToFront_fullscreenTask_nonActiveTaskInDesktopRepo_noop() {
         val task = createFullscreenTask().apply { isVisible = true }
-        whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
+        whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(false)
+
+        desktopTaskChangeListener.onTaskMovingToFront(task)
+
+        verify(desktopUserRepositories.current, never()).removeTask(task.displayId, task.taskId)
+    }
+
+    @Test
+    fun onTaskMovingToFront_freeformTask_addsTaskToRepo() {
+        val task = createFreeformTask().apply { isVisible = true }
 
         desktopTaskChangeListener.onTaskMovingToFront(task)
 
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index fb89973..66de8c7 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -27,8 +27,6 @@
 import android.telephony.emergency.EmergencyNumber;
 import android.util.Log;
 
-import com.android.internal.annotations.KeepForWeakReference;
-
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -94,7 +92,6 @@
 
     // The internal implementation of TelephonyManager uses WeakReference so we have to keep a
     // reference here.
-    @KeepForWeakReference
     private final EmergencyCallListener mEmergencyCallListener = new EmergencyCallListener();
 
     private final EmergencyCallCallback mEmergencyCallCallback;
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 9bb31d0..4e86eac 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1223,8 +1223,14 @@
         private static final String TAG = "CodecCapabilities";
 
         // NEW-STYLE CAPABILITIES
+        // Capabilities for an audio codec.
+        @Nullable
         private AudioCapabilities mAudioCaps;
+        // Capabilities for a video codec.
+        @Nullable
         private VideoCapabilities mVideoCaps;
+        // Capabilities specific to an encoder (vs. a decoder).
+        @Nullable
         private EncoderCapabilities mEncoderCaps;
         private MediaFormat mDefaultFormat;
 
@@ -1262,6 +1268,7 @@
         /**
          * Returns the audio capabilities or {@code null} if this is not an audio codec.
          */
+        @Nullable
         public AudioCapabilities getAudioCapabilities() {
             return mAudioCaps;
         }
@@ -1273,6 +1280,7 @@
         /**
          * Returns the encoding capabilities or {@code null} if this is not an encoder.
          */
+        @Nullable
         public EncoderCapabilities getEncoderCapabilities() {
             return mEncoderCaps;
         }
@@ -1284,6 +1292,7 @@
         /**
          * Returns the video capabilities or {@code null} if this is not a video codec.
          */
+        @Nullable
         public VideoCapabilities getVideoCapabilities() {
             return mVideoCaps;
         }
diff --git a/media/java/android/media/Utils.java b/media/java/android/media/Utils.java
index d6e27b0..9db527b 100644
--- a/media/java/android/media/Utils.java
+++ b/media/java/android/media/Utils.java
@@ -18,6 +18,8 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.TestApi;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
@@ -61,16 +63,30 @@
  *
  * @hide
  */
+@TestApi
+@SuppressLint({"UnflaggedApi", "StaticUtils"}) // Test API
 public class Utils {
     private static final String TAG = "Utils";
 
+    /** @hide
+     * The vibration uri key parameter
+     */
+    @TestApi
+    @SuppressLint("UnflaggedApi") // Test API
     public static final String VIBRATION_URI_PARAM = "vibration_uri";
 
+    /** @hide
+     * Indicates the synchronized vibration
+     */
+    @TestApi
+    @SuppressLint("UnflaggedApi") // Test API
     public static final String SYNCHRONIZED_VIBRATION = "synchronized";
 
     /**
      * Sorts distinct (non-intersecting) range array in ascending order.
      * @throws java.lang.IllegalArgumentException if ranges are not distinct
+     *
+     * @hide
      */
     public static <T extends Comparable<? super T>> void sortDistinctRanges(Range<T>[] ranges) {
         Arrays.sort(ranges, new Comparator<Range<T>>() {
@@ -92,6 +108,8 @@
      * @param one a sorted set of non-intersecting ranges in ascending order
      * @param another another sorted set of non-intersecting ranges in ascending order
      * @return the intersection of the two sets, sorted in ascending order
+     *
+     * @hide
      */
     public static <T extends Comparable<? super T>>
             Range<T>[] intersectSortedDistinctRanges(Range<T>[] one, Range<T>[] another) {
@@ -124,6 +142,8 @@
      * @return if the value is in one of the ranges, it returns the index of that range.  Otherwise,
      * the return value is {@code (-1-index)} for the {@code index} of the range that is
      * immediately following {@code value}.
+     *
+     * @hide
      */
     public static <T extends Comparable<? super T>>
             int binarySearchDistinctRanges(Range<T>[] ranges, T value) {
@@ -358,6 +378,8 @@
      * @param fileName desired name for the file.
      * @param mimeType MIME type of the file to create.
      * @return the File object in the storage, or null if an error occurs.
+     *
+     * @hide
      */
     public static File getUniqueExternalFile(Context context, String subdirectory, String fileName,
             String mimeType) {
@@ -676,6 +698,8 @@
      * Must match the implementation of BluetoothUtils.toAnonymizedAddress()
      * @param address MAC address to be anonymized
      * @return anonymized MAC address
+     *
+     * @hide
      */
     public static @Nullable String anonymizeBluetoothAddress(@Nullable String address) {
         if (address == null) {
@@ -693,6 +717,8 @@
      * @param deviceType the internal type of the audio device
      * @param address MAC address to be anonymized
      * @return anonymized MAC address
+     *
+     * @hide
      */
     public static @Nullable String anonymizeBluetoothAddress(
             int deviceType, @Nullable String address) {
@@ -707,6 +733,8 @@
      *
      * @param context the {@link Context}
      * @return {@code true} if the device supports ringtone vibration
+     *
+     * @hide
      */
     public static boolean isRingtoneVibrationSettingsSupported(Context context) {
         final Resources res = context.getResources();
@@ -719,6 +747,8 @@
      *
      * @param ringtoneUri the ringtone Uri
      * @return {@code true} if the Uri has vibration parameter
+     *
+     * @hide
      */
     public static boolean hasVibration(Uri ringtoneUri) {
         if (ringtoneUri == null) {
@@ -734,6 +764,8 @@
      * @param ringtoneUri the ringtone Uri
      * @return parsed {@link Uri} of vibration parameter, {@code null} if the vibration parameter
      * is not found.
+     *
+     * @hide
      */
     public static @Nullable Uri getVibrationUri(Uri ringtoneUri) {
         if (ringtoneUri == null) {
@@ -751,6 +783,8 @@
      *
      * @param vibrator the vibrator to resolve the vibration file
      * @param vibrationUri the vibration file Uri to represent a vibration
+     *
+     * @hide
      */
     @SuppressWarnings("FlaggedApi") // VibrationXmlParser is available internally as hidden APIs.
     public static VibrationEffect parseVibrationEffect(Vibrator vibrator, Uri vibrationUri) {
diff --git a/native/webview/TEST_MAPPING b/native/webview/TEST_MAPPING
index 3858059..c9b5476 100644
--- a/native/webview/TEST_MAPPING
+++ b/native/webview/TEST_MAPPING
@@ -17,15 +17,6 @@
           "exclude-annotation": "android.test.FlakyTest"
         }
       ]
-    },
-    {
-      "name": "GtsWebViewHostTestCases",
-      "keywords": ["internal"],
-      "options": [
-        {
-          "exclude-annotation": "android.test.FlakyTest"
-        }
-      ]
     }
   ]
 }
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_content_layout.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_content_layout.xml
index 6221659..3db0ac6 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_content_layout.xml
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/layout-v36/settingslib_expressive_collapsing_toolbar_content_layout.xml
@@ -41,6 +41,7 @@
                 android:id="@+id/action_bar"
                 android:layout_width="match_parent"
                 android:layout_height="?attr/actionBarSize"
+                android:layout_marginStart="@dimen/settingslib_expressive_space_extrasmall4"
                 android:theme="?android:attr/actionBarTheme"
                 android:transitionName="shared_element_view"
                 app:layout_collapseMode="pin"/>
diff --git a/packages/SettingsLib/OWNERS b/packages/SettingsLib/OWNERS
index 04df308..7348920 100644
--- a/packages/SettingsLib/OWNERS
+++ b/packages/SettingsLib/OWNERS
@@ -8,6 +8,7 @@
 evanlaird@google.com
 jiannan@google.com
 juliacr@google.com
+millchen@google.com
 ykhung@google.com
 
 # Exempt resource files (because they are in a flat directory and too hard to manage via OWNERS)
diff --git a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/NormalPaddingMixin.kt b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/NormalPaddingMixin.kt
new file mode 100644
index 0000000..5035542
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/NormalPaddingMixin.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.widget
+
+/**
+ * A base interface to indicate that a Preference should have normal paddings.
+ *
+ * Preferences implementing this interface will be treated as has normal paddings both inside and
+ * outside.
+ */
+interface NormalPaddingMixin
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt
index a04fce7..2672787 100644
--- a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt
+++ b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsPreferenceGroupAdapter.kt
@@ -177,14 +177,32 @@
         val v = holder.itemView
         // Update padding
         if (SettingsThemeHelper.isExpressiveTheme(context)) {
-            val paddingStart = if (backgroundRes == 0) mNormalPaddingStart else mGroupPaddingStart
-            val paddingEnd = if (backgroundRes == 0) mNormalPaddingEnd else mGroupPaddingEnd
+            val (paddingStart, paddingEnd) = getStartEndPadding(position, backgroundRes)
             v.setPaddingRelative(paddingStart, v.paddingTop, paddingEnd, v.paddingBottom)
+            v.clipToOutline = backgroundRes != 0
         }
         // Update background
         v.setBackgroundResource(backgroundRes)
     }
 
+    private fun getStartEndPadding(position: Int, backgroundRes: Int): Pair<Int, Int> {
+        val item = getItem(position)
+        return when {
+            // This item handles edge to edge itself
+            item is NormalPaddingMixin && item is GroupSectionDividerMixin -> 0 to 0
+
+            // According to mappingPreferenceGroup(), backgroundRes == 0 means this item is
+            // GroupSectionDividerMixin or PreferenceCategory, which is design to have normal
+            // padding.
+            // NormalPaddingMixin items are also designed to have normal padding.
+            backgroundRes == 0 || item is NormalPaddingMixin ->
+                mNormalPaddingStart to mNormalPaddingEnd
+
+            // Other items are suppose to have group padding.
+            else -> mGroupPaddingStart to mGroupPaddingEnd
+        }
+    }
+
     @DrawableRes
     protected fun getRoundCornerDrawableRes(position: Int, isSelected: Boolean): Int {
         return getRoundCornerDrawableRes(position, isSelected, false)
diff --git a/packages/SettingsLib/SliderPreference/src/com/android/settingslib/widget/SliderPreference.java b/packages/SettingsLib/SliderPreference/src/com/android/settingslib/widget/SliderPreference.java
index 4315238..fe8e8b6 100644
--- a/packages/SettingsLib/SliderPreference/src/com/android/settingslib/widget/SliderPreference.java
+++ b/packages/SettingsLib/SliderPreference/src/com/android/settingslib/widget/SliderPreference.java
@@ -22,6 +22,7 @@
 import android.content.res.TypedArray;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -72,6 +73,7 @@
     private int mSliderIncrement;
     private boolean mAdjustable;
     private boolean mTrackingTouch;
+    private CharSequence mSliderContentDescription;
 
     /**
      * Listener reacting to the user pressing DPAD left/right keys if {@code
@@ -143,6 +145,7 @@
             @Nullable AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         setLayoutResource(R.layout.settingslib_expressive_preference_slider);
+        setSelectable(false);
 
         TypedArray a = context.obtainStyledAttributes(
                 attrs, androidx.preference.R.styleable.SeekBarPreference, defStyleAttr,
@@ -265,6 +268,14 @@
         } else {
             mSliderIncrement = (int) (mSlider.getStepSize());
         }
+        final CharSequence title = getTitle();
+        if (!TextUtils.isEmpty(mSliderContentDescription)) {
+            mSlider.setContentDescription(mSliderContentDescription);
+        } else if (!TextUtils.isEmpty(title)) {
+            mSlider.setContentDescription(title);
+        } else {
+            mSlider.setContentDescription(null);
+        }
         mSlider.setValueFrom(mMin);
         mSlider.setValueTo(mMax);
         mSlider.setValue(mSliderValue);
@@ -273,6 +284,8 @@
         mSlider.clearOnChangeListeners();
         mSlider.addOnChangeListener(mChangeListener);
         mSlider.setEnabled(isEnabled());
+        mSlider.setFocusable(isSelectable());
+        mSlider.setClickable(isSelectable());
 
         // Set up slider color
         mSlider.setTrackActiveTintList(mTrackActiveColor);
@@ -471,6 +484,19 @@
         setValueInternal(sliderValue, true);
     }
 
+
+    /**
+     * Sets the content description of the {@link Slider}.
+     *
+     * @param contentDescription The content description of the {@link Slider}
+     */
+    public void setSliderContentDescription(@Nullable CharSequence contentDescription) {
+        mSliderContentDescription = contentDescription;
+        if (mSlider != null) {
+            mSlider.setContentDescription(contentDescription);
+        }
+    }
+
     @Override
     protected void onSetInitialValue(@Nullable Object defaultValue) {
         if (defaultValue == null) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
index 2c6d09a..2d03e2b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
@@ -23,7 +23,6 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.layout.Measurable
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntRect
@@ -35,7 +34,6 @@
 import com.android.systemui.communal.ui.compose.section.AmbientStatusBarSection
 import com.android.systemui.communal.ui.compose.section.CommunalLockSection
 import com.android.systemui.communal.ui.compose.section.CommunalPopupSection
-import com.android.systemui.communal.ui.compose.section.CommunalToDreamButtonSection
 import com.android.systemui.communal.ui.compose.section.HubOnboardingSection
 import com.android.systemui.communal.ui.view.layout.sections.CommunalAppWidgetSection
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
@@ -61,7 +59,6 @@
     private val ambientStatusBarSection: AmbientStatusBarSection,
     private val communalPopupSection: CommunalPopupSection,
     private val widgetSection: CommunalAppWidgetSection,
-    private val communalToDreamButtonSection: CommunalToDreamButtonSection,
     private val hubOnboardingSection: HubOnboardingSection,
 ) {
 
@@ -103,13 +100,11 @@
                             Modifier.element(Communal.Elements.IndicationArea).fillMaxWidth()
                         )
                     }
-                    with(communalToDreamButtonSection) { Button() }
                 },
             ) { measurables, constraints ->
                 val communalGridMeasurable = measurables[0]
                 val lockIconMeasurable = measurables[1]
                 val bottomAreaMeasurable = measurables[2]
-                val screensaverButtonMeasurable: Measurable? = measurables.getOrNull(3)
 
                 val noMinConstraints = constraints.copy(minWidth = 0, minHeight = 0)
 
@@ -152,9 +147,6 @@
 
                 val bottomAreaPlaceable = bottomAreaMeasurable.measure(noMinConstraints)
 
-                val screensaverButtonPlaceable =
-                    screensaverButtonMeasurable?.measure(noMinConstraints)
-
                 val communalGridPlaceable =
                     communalGridMeasurable.measure(
                         noMinConstraints.copy(maxHeight = lockIconBounds.top)
@@ -166,26 +158,12 @@
 
                     val bottomAreaTop = constraints.maxHeight - bottomAreaPlaceable.height
                     bottomAreaPlaceable.place(x = 0, y = bottomAreaTop)
-
-                    val screensaverButtonPaddingInt = screensaverButtonPadding.roundToPx()
-                    screensaverButtonPlaceable?.place(
-                        x =
-                            constraints.maxWidth -
-                                screensaverButtonPaddingInt -
-                                screensaverButtonPlaceable.width,
-                        y =
-                            constraints.maxHeight -
-                                screensaverButtonPaddingInt -
-                                screensaverButtonPlaceable.height,
-                    )
                 }
             }
         }
     }
 
     companion object {
-        private val screensaverButtonPadding: Dp = 24.dp
-
         // TODO(b/382739998): Remove these hardcoded values once lock icon size and bottom area
         // position are sorted.
         private val lockIconSize: Dp = 54.dp
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalToDreamButtonSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalToDreamButtonSection.kt
deleted file mode 100644
index acaf43a..0000000
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalToDreamButtonSection.kt
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.communal.ui.compose.section
-
-import androidx.compose.animation.AnimatedVisibility
-import androidx.compose.animation.core.MutableTransitionState
-import androidx.compose.animation.expandVertically
-import androidx.compose.animation.fadeIn
-import androidx.compose.animation.fadeOut
-import androidx.compose.animation.shrinkVertically
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.layout.widthIn
-import androidx.compose.foundation.shape.CornerSize
-import androidx.compose.material3.IconButtonDefaults
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Surface
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.CornerRadius
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.RoundRect
-import androidx.compose.ui.geometry.Size
-import androidx.compose.ui.geometry.toRect
-import androidx.compose.ui.graphics.Outline
-import androidx.compose.ui.graphics.Path
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.res.dimensionResource
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.unit.dp
-import com.android.compose.PlatformIconButton
-import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
-import com.android.systemui.communal.ui.compose.extensions.observeTaps
-import com.android.systemui.communal.ui.viewmodel.CommunalToDreamButtonViewModel
-import com.android.systemui.lifecycle.rememberViewModel
-import com.android.systemui.res.R
-import javax.inject.Inject
-import kotlin.time.Duration.Companion.seconds
-import kotlinx.coroutines.delay
-
-class CommunalToDreamButtonSection
-@Inject
-constructor(
-    private val communalSettingsInteractor: CommunalSettingsInteractor,
-    private val viewModelFactory: CommunalToDreamButtonViewModel.Factory,
-) {
-    @Composable
-    fun Button() {
-        if (!communalSettingsInteractor.isV2FlagEnabled()) {
-            return
-        }
-
-        val viewModel =
-            rememberViewModel("CommunalToDreamButtonSection") { viewModelFactory.create() }
-
-        if (!viewModel.shouldShowDreamButtonOnHub) {
-            return
-        }
-
-        val buttonSize = dimensionResource(R.dimen.communal_to_dream_button_size)
-
-        if (viewModel.shouldShowTooltip) {
-            val tooltipVisibleState = remember { MutableTransitionState(false) }
-
-            Column(
-                modifier =
-                    Modifier.widthIn(max = tooltipMaxWidth).pointerInput(Unit) {
-                        observeTaps {
-                            if (tooltipVisibleState.isCurrentlyVisible()) {
-                                tooltipVisibleState.targetState = false
-                            }
-                        }
-                    }
-            ) {
-                var waitingToShowTooltip by remember { mutableStateOf(true) }
-
-                LaunchedEffect(tooltipVisibleState.targetState) {
-                    delay(3.seconds)
-                    tooltipVisibleState.targetState = true
-                    waitingToShowTooltip = false
-                }
-
-                // This LaunchedEffect is used to wait for the tooltip dismiss animation to
-                // complete before setting the tooltip dismissed. Otherwise, the composable would
-                // be removed before the animation can start.
-                LaunchedEffect(
-                    tooltipVisibleState.currentState,
-                    tooltipVisibleState.isIdle,
-                    waitingToShowTooltip,
-                ) {
-                    if (
-                        !waitingToShowTooltip &&
-                            !tooltipVisibleState.currentState &&
-                            tooltipVisibleState.isIdle
-                    ) {
-                        viewModel.setDreamButtonTooltipDismissed()
-                    }
-                }
-
-                AnimatedVisibility(
-                    visibleState = tooltipVisibleState,
-                    enter = fadeIn() + expandVertically(expandFrom = Alignment.Bottom),
-                    exit = fadeOut() + shrinkVertically(shrinkTowards = Alignment.Bottom),
-                ) {
-                    Tooltip(
-                        pointerOffsetDp = buttonSize.div(2),
-                        text = stringResource(R.string.glanceable_hub_to_dream_button_tooltip),
-                    )
-                }
-
-                GoToDreamButton(
-                    modifier = Modifier.width(buttonSize).height(buttonSize).align(Alignment.End)
-                ) {
-                    viewModel.onShowDreamButtonTap()
-                }
-            }
-        } else {
-            GoToDreamButton(modifier = Modifier.width(buttonSize).height(buttonSize)) {
-                viewModel.onShowDreamButtonTap()
-            }
-        }
-    }
-
-    private fun MutableTransitionState<Boolean>.isCurrentlyVisible() = currentState && isIdle
-
-    companion object {
-        private val tooltipMaxWidth = 350.dp
-    }
-}
-
-@Composable
-private fun GoToDreamButton(modifier: Modifier, onClick: () -> Unit) {
-    PlatformIconButton(
-        modifier = modifier,
-        onClick = onClick,
-        iconResource = R.drawable.ic_screensaver_auto,
-        contentDescription = stringResource(R.string.accessibility_glanceable_hub_to_dream_button),
-        colors =
-            IconButtonDefaults.filledIconButtonColors(
-                contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
-                containerColor = MaterialTheme.colorScheme.primaryContainer,
-            ),
-    )
-}
-
-@Composable
-private fun Tooltip(pointerOffsetDp: Dp, text: String) {
-    Surface(
-        color = MaterialTheme.colorScheme.surface,
-        shape = TooltipShape(pointerSizeDp = 12.dp, pointerOffsetDp = pointerOffsetDp),
-    ) {
-        Text(
-            modifier = Modifier.padding(start = 32.dp, top = 16.dp, end = 32.dp, bottom = 32.dp),
-            color = MaterialTheme.colorScheme.onSurface,
-            text = text,
-        )
-    }
-
-    Spacer(modifier = Modifier.height(4.dp))
-}
-
-private class TooltipShape(private val pointerSizeDp: Dp, private val pointerOffsetDp: Dp) : Shape {
-
-    override fun createOutline(
-        size: Size,
-        layoutDirection: LayoutDirection,
-        density: Density,
-    ): Outline {
-
-        val pointerSizePx = with(density) { pointerSizeDp.toPx() }
-        val pointerOffsetPx = with(density) { pointerOffsetDp.toPx() }
-        val cornerRadius = CornerRadius(CornerSize(16.dp).toPx(size, density))
-        val bubbleSize = size.copy(height = size.height - pointerSizePx)
-
-        val path =
-            Path().apply {
-                addRoundRect(
-                    RoundRect(
-                        rect = bubbleSize.toRect(),
-                        topLeft = cornerRadius,
-                        topRight = cornerRadius,
-                        bottomRight = cornerRadius,
-                        bottomLeft = cornerRadius,
-                    )
-                )
-                addPath(
-                    Path().apply {
-                        moveTo(0f, 0f)
-                        lineTo(pointerSizePx / 2f, pointerSizePx)
-                        lineTo(pointerSizePx, 0f)
-                        close()
-                    },
-                    offset =
-                        Offset(
-                            x = bubbleSize.width - pointerOffsetPx - pointerSizePx / 2f,
-                            y = bubbleSize.height,
-                        ),
-                )
-            }
-
-        return Outline.Generic(path)
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt
deleted file mode 100644
index 2f3073e..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.communal.ui.viewmodel
-
-import android.content.pm.UserInfo
-import android.platform.test.annotations.EnableFlags
-import android.provider.Settings
-import android.service.dream.dreamManager
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.internal.logging.uiEventLoggerFake
-import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.communal.data.repository.fakeCommunalPrefsRepository
-import com.android.systemui.communal.domain.interactor.HubOnboardingInteractorTest.Companion.MAIN_USER
-import com.android.systemui.communal.shared.log.CommunalUiEvent
-import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
-import com.android.systemui.flags.fakeFeatureFlagsClassic
-import com.android.systemui.kosmos.runCurrent
-import com.android.systemui.kosmos.runTest
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.lifecycle.activateIn
-import com.android.systemui.plugins.activityStarter
-import com.android.systemui.settings.fakeUserTracker
-import com.android.systemui.statusbar.policy.batteryController
-import com.android.systemui.statusbar.policy.fake
-import com.android.systemui.testKosmos
-import com.android.systemui.user.data.repository.fakeUserRepository
-import com.android.systemui.util.settings.fakeSettings
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mockito.verify
-import org.mockito.kotlin.any
-
-@SmallTest
-@EnableFlags(FLAG_GLANCEABLE_HUB_V2)
-@RunWith(AndroidJUnit4::class)
-class CommunalToDreamButtonViewModelTest : SysuiTestCase() {
-    private val kosmos = testKosmos()
-    private val testScope = kosmos.testScope
-    private val underTest: CommunalToDreamButtonViewModel by lazy {
-        kosmos.communalToDreamButtonViewModel
-    }
-
-    @Before
-    fun setUp() {
-        kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
-        underTest.activateIn(testScope)
-    }
-
-    @Test
-    fun shouldShowDreamButtonOnHub_trueWhenPluggedIn() =
-        with(kosmos) {
-            runTest {
-                batteryController.fake._isPluggedIn = true
-                runCurrent()
-
-                assertThat(underTest.shouldShowDreamButtonOnHub).isTrue()
-            }
-        }
-
-    @Test
-    fun shouldShowDreamButtonOnHub_falseWhenNotPluggedIn() =
-        with(kosmos) {
-            runTest {
-                batteryController.fake._isPluggedIn = false
-
-                assertThat(underTest.shouldShowDreamButtonOnHub).isFalse()
-            }
-        }
-
-    @Test
-    fun onShowDreamButtonTap_dreamsEnabled_startsDream() =
-        with(kosmos) {
-            runTest {
-                val currentUser = fakeUserRepository.asMainUser()
-                kosmos.fakeSettings.putIntForUser(
-                    Settings.Secure.SCREENSAVER_ENABLED,
-                    1,
-                    currentUser.id,
-                )
-                runCurrent()
-
-                underTest.onShowDreamButtonTap()
-                runCurrent()
-
-                verify(dreamManager).startDream()
-            }
-        }
-
-    @Test
-    fun onShowDreamButtonTap_dreamsDisabled_startsActivity() =
-        with(kosmos) {
-            runTest {
-                val currentUser = fakeUserRepository.asMainUser()
-                kosmos.fakeSettings.putIntForUser(
-                    Settings.Secure.SCREENSAVER_ENABLED,
-                    0,
-                    currentUser.id,
-                )
-                runCurrent()
-
-                underTest.onShowDreamButtonTap()
-                runCurrent()
-
-                verify(activityStarter).postStartActivityDismissingKeyguard(any(), anyInt())
-            }
-        }
-
-    @Test
-    fun shouldShowDreamButtonTooltip_trueWhenNotDismissedAndHubOnboardingDismissed() =
-        kosmos.runTest {
-            setSelectedUser(MAIN_USER)
-            fakeCommunalPrefsRepository.setHubOnboardingDismissed(MAIN_USER)
-            runCurrent()
-
-            assertThat(underTest.shouldShowTooltip).isTrue()
-        }
-
-    @Test
-    fun shouldShowDreamButtonTooltip_falseWhenNotDismissedAndHubOnboardingNotDismissed() =
-        kosmos.runTest {
-            runCurrent()
-            assertThat(underTest.shouldShowTooltip).isFalse()
-        }
-
-    @Test
-    fun shouldShowDreamButtonTooltip_falseWhenDismissed() =
-        kosmos.runTest {
-            setSelectedUser(MAIN_USER)
-            fakeCommunalPrefsRepository.setDreamButtonTooltipDismissed(MAIN_USER)
-            runCurrent()
-
-            assertThat(underTest.shouldShowTooltip).isFalse()
-        }
-
-    @Test
-    fun onShowDreamButtonTap_eventLogged() =
-        with(kosmos) {
-            runTest {
-                underTest.onShowDreamButtonTap()
-                runCurrent()
-
-                assertThat(uiEventLoggerFake[0].eventId)
-                    .isEqualTo(CommunalUiEvent.COMMUNAL_HUB_SHOW_DREAM_BUTTON_TAP.id)
-            }
-        }
-
-    private suspend fun setSelectedUser(user: UserInfo) {
-        with(kosmos.fakeUserRepository) {
-            setUserInfos(listOf(user))
-            setSelectedUserInfo(user)
-        }
-        kosmos.fakeUserTracker.set(userInfos = listOf(user), selectedUserIndex = 0)
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimatorTest.kt
index 56cd72e..0bb4737 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimatorTest.kt
@@ -15,19 +15,22 @@
  */
 package com.android.systemui.statusbar.notification
 
+import android.animation.AnimatorTestRule
 import android.util.FloatProperty
 import android.util.Property
 import android.view.View
-import androidx.dynamicanimation.animation.DynamicAnimation
+
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.internal.dynamicanimation.animation.DynamicAnimation
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.notification.stack.AnimationProperties
 import com.android.systemui.statusbar.notification.stack.ViewState
 import org.junit.Assert
 import org.junit.Before
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mockito
@@ -50,6 +53,8 @@
                 return _value
             }
         }
+    @get:Rule
+    val animatorTestRule = AnimatorTestRule(this)
     private val property: PhysicsProperty =
         PhysicsProperty(R.id.scale_x_animator_tag, effectiveProperty)
     private var finishListener: DynamicAnimation.OnAnimationEndListener? = null
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
index 2853264..fa185bc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
@@ -18,6 +18,7 @@
 
 import android.app.Flags
 import android.app.NotificationChannel
+import android.app.NotificationChannel.SYSTEM_RESERVED_IDS
 import android.app.NotificationManager.IMPORTANCE_DEFAULT
 import android.app.NotificationManager.IMPORTANCE_HIGH
 import android.app.NotificationManager.IMPORTANCE_LOW
@@ -124,6 +125,14 @@
     }
 
     @Test
+    fun testPrioritySectioner_doesNotClaim_classifiedConversation() {
+        val sectioner = coordinator.priorityPeopleSectioner
+        for (id in SYSTEM_RESERVED_IDS) {
+            assertFalse(sectioner.isInSection(makeClassifiedConversation(id)))
+        }
+    }
+
+    @Test
     fun testPromotesImportantConversations() {
         assertTrue(promoter.shouldPromoteToTopLevel(makeEntryOfPeopleType(TYPE_IMPORTANT_PERSON)))
         assertFalse(promoter.shouldPromoteToTopLevel(makeEntryOfPeopleType(TYPE_FULL_PERSON)))
@@ -166,6 +175,14 @@
     }
 
     @Test
+    fun testAlertingSectioner_doesNotClaim_classifiedConversation() {
+        val sectioner = coordinator.peopleAlertingSectioner
+        for (id in SYSTEM_RESERVED_IDS) {
+            assertFalse(sectioner.isInSection(makeClassifiedConversation(id)))
+        }
+    }
+
+    @Test
     fun testInAlertingPeopleSectionWhenTheImportanceIsAtLeastDefault() {
         // GIVEN
         val alertingEntry = makeEntryOfPeopleType(TYPE_PERSON) { setImportance(IMPORTANCE_DEFAULT) }
@@ -186,6 +203,15 @@
 
     @Test
     @DisableFlags(Flags.FLAG_SORT_SECTION_BY_TIME)
+    fun testSilentSectioner_doesNotClaim_classifiedConversation() {
+        val sectioner = coordinator.peopleSilentSectioner
+        for (id in SYSTEM_RESERVED_IDS) {
+            assertFalse(sectioner.isInSection(makeClassifiedConversation(id)))
+        }
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_SORT_SECTION_BY_TIME)
     fun testInSilentPeopleSectionWhenTheImportanceIsLowerThanDefault() {
         // GIVEN
         val silentEntry = makeEntryOfPeopleType(TYPE_PERSON) { setImportance(IMPORTANCE_LOW) }
@@ -280,4 +306,17 @@
         assertEquals(type, peopleNotificationIdentifier.getPeopleNotificationType(entry))
         return entry
     }
+
+    private fun makeClassifiedConversation(channelId: String): NotificationEntry {
+        val channel = NotificationChannel(channelId, channelId, IMPORTANCE_LOW)
+        val entry =
+            NotificationEntryBuilder()
+                .updateRanking {
+                    it.setIsConversation(true)
+                    it.setShortcutInfo(mock())
+                    it.setChannel(channel)
+                }
+                .build()
+        return entry
+    }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt
index 961616c..3d1fdee 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelTest.kt
@@ -22,6 +22,8 @@
 import com.android.systemui.accessibility.data.repository.FakeAccessibilityRepository
 import com.android.systemui.accessibility.domain.interactor.AccessibilityInteractor
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.testKosmos
+import com.android.systemui.window.domain.interactor.windowRootViewBlurInteractor
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
@@ -32,12 +34,16 @@
 @SmallTest
 class ActivatableNotificationViewModelTest : SysuiTestCase() {
 
+    private val kosmos = testKosmos()
+
     // fakes
     private val a11yRepo = FakeAccessibilityRepository()
 
     // real impls
     private val a11yInteractor = AccessibilityInteractor(a11yRepo)
-    private val underTest = ActivatableNotificationViewModel(a11yInteractor)
+    private val windowRootViewBlurInteractor = kosmos.windowRootViewBlurInteractor
+    private val underTest = ActivatableNotificationViewModel(a11yInteractor,
+        windowRootViewBlurInteractor)
 
     @Test
     fun isTouchable_whenA11yTouchExplorationDisabled() = runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
index 4a761917..cb4642c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
@@ -18,9 +18,11 @@
 
 import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.AnimatorTestRule
 import com.android.systemui.res.R
@@ -44,6 +46,7 @@
 import org.mockito.Mockito.description
 import org.mockito.Mockito.eq
 import org.mockito.Mockito.verify
+import org.mockito.kotlin.doNothing
 
 private const val VIEW_HEIGHT = 100
 private const val FULL_SHADE_APPEAR_TRANSLATION = 300
@@ -53,18 +56,20 @@
 @RunWith(AndroidJUnit4::class)
 @RunWithLooper
 class StackStateAnimatorTest : SysuiTestCase() {
+
+    @get:Rule val setFlagsRule = SetFlagsRule()
     @get:Rule val animatorTestRule = AnimatorTestRule(this)
 
     private lateinit var stackStateAnimator: StackStateAnimator
     private lateinit var headsUpAnimator: HeadsUpAnimator
     private val stackScroller: NotificationStackScrollLayout = mock()
     private val view: ExpandableView = mock()
-    private val viewState: ExpandableViewState =
-        ExpandableViewState().apply { height = VIEW_HEIGHT }
+    private lateinit var viewState: ExpandableViewState
     private val runnableCaptor: ArgumentCaptor<Runnable> = argumentCaptor()
 
     @Before
     fun setUp() {
+        viewState = ExpandableViewState().apply { height = VIEW_HEIGHT }
         overrideResource(
             R.dimen.go_to_full_shade_appearing_translation,
             FULL_SHADE_APPEAR_TRANSLATION,
@@ -153,6 +158,7 @@
             )
     }
 
+    @DisableFlags(Flags.FLAG_PHYSICAL_NOTIFICATION_MOVEMENT)
     @Test
     @EnableFlags(NotificationsHunSharedAnimationValues.FLAG_NAME)
     fun startAnimationForEvents_headsUpFromBottom_startsHeadsUpAppearAnim_flagOn() {
@@ -238,6 +244,32 @@
             .removeFromTransientContainer()
     }
 
+    @EnableFlags(Flags.FLAG_PHYSICAL_NOTIFICATION_MOVEMENT)
+    @Test
+    fun startAnimationForEvents_startsHeadsUpDisappearAnim_physical() {
+        val disappearDuration = ANIMATION_DURATION_HEADS_UP_DISAPPEAR.toLong()
+        val event = AnimationEvent(view, AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR)
+        clearInvocations(view)
+        stackStateAnimator.startAnimationForEvents(arrayListOf(event), 0)
+
+        verify(view)
+            .performRemoveAnimation(
+                /* duration= */ eq(disappearDuration),
+                /* delay= */ eq(0L),
+                /* translationDirection= */ eq(0f),
+                /* isHeadsUpAnimation= */ eq(true),
+                /* isHeadsUpCycling= */ eq(false),
+                /* onStartedRunnable= */ any(),
+                /* onFinishedRunnable= */ runnableCaptor.capture(),
+                /* animationListener= */ any(),
+                /* clipSide= */ eq(ExpandableView.ClipSide.BOTTOM),
+            )
+
+        runnableCaptor.value.run() // execute the end runnable
+        verify(view, description("should be called at the end of the disappear animation"))
+            .removeFromTransientContainer()
+    }
+
     @Test
     fun initView_updatesResources() {
         // Given: the resource values are initialized in the SSA
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
index ef415c9..6ee1c4d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ViewStateTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.stack
 
+import android.animation.AnimatorTestRule
 import android.animation.ValueAnimator
 import android.view.View
 import androidx.test.annotation.UiThreadTest
@@ -28,6 +29,7 @@
 import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator.Companion.TAG_ANIMATOR_TRANSLATION_Y
 import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator.Companion.Y_TRANSLATION
 import org.junit.Assert
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import kotlin.math.log2
@@ -38,6 +40,8 @@
 @UiThreadTest
 class ViewStateTest : SysuiTestCase() {
     private val viewState = ViewState(true /* usePhysicsForMovement */)
+    @get:Rule
+    val animatorTestRule = AnimatorTestRule(this)
 
     @Suppress("DIVISION_BY_ZERO")
     @Test
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6ff1240..43ea2c3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1024,6 +1024,12 @@
     <string name="hearing_devices_ambient_control_left">Left</string>
     <!-- QuickSettings: The text to show the control is for right side device. [CHAR LIMIT=30] -->
     <string name="hearing_devices_ambient_control_right">Right</string>
+    <!-- QuickSettings: Content description for unified ambient control slider. [CHAR LIMIT=NONE] -->
+    <string name="hearing_devices_ambient_control_description">Surroundings</string>
+    <!-- QuickSettings: Content description for left ambient control slider. [CHAR LIMIT=NONE] -->
+    <string name="hearing_devices_ambient_control_left_description">Left surroundings</string>
+    <!-- QuickSettings: Content description for left ambient control slider. [CHAR LIMIT=NONE] -->
+    <string name="hearing_devices_ambient_control_right_description">Right surroundings</string>
     <!-- QuickSettings: Content description for a button, that expands ambient volume sliders [CHAR_LIMIT=NONE] -->
     <string name="hearing_devices_ambient_expand_controls">Expand to left and right separated controls</string>
     <!-- QuickSettings: Content description for a button, that collapses ambient volume sliders [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 5b96e50..4431dda 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -871,6 +871,7 @@
     </style>
 
     <style name="MediaPlayer.SessionAction.Primary" parent="MediaPlayer.SessionAction">
+        <item name="android:tint">@android:color/system_on_primary_dark</item>
         <item name="android:background">@drawable/qs_media_round_button_background</item>
         <item name="android:backgroundTint">@color/media_player_solid_button_bg</item>
     </style>
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java
index 5247acc..33c9eb1 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java
@@ -327,8 +327,19 @@
         slider.addOnChangeListener(mSliderOnChangeListener);
         if (side == SIDE_LEFT) {
             slider.setTitle(mContext.getString(R.string.hearing_devices_ambient_control_left));
+            slider.setContentDescription(
+                    mContext.getString(R.string.hearing_devices_ambient_control_left));
+            slider.setSliderContentDescription(
+                    mContext.getString(R.string.hearing_devices_ambient_control_left_description));
         } else if (side == SIDE_RIGHT) {
             slider.setTitle(mContext.getString(R.string.hearing_devices_ambient_control_right));
+            slider.setContentDescription(
+                    mContext.getString(R.string.hearing_devices_ambient_control_right));
+            slider.setSliderContentDescription(
+                    mContext.getString(R.string.hearing_devices_ambient_control_right_description));
+        } else {
+            slider.setSliderContentDescription(
+                    mContext.getString(R.string.hearing_devices_ambient_control_description));
         }
         mSideToSliderMap.put(side, slider);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSlider.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSlider.java
index 1a068c4..5c0ad3d 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSlider.java
@@ -92,6 +92,11 @@
         mSlider = requireViewById(R.id.ambient_volume_slider);
         mSlider.addOnSliderTouchListener(mSliderTouchListener);
         mSlider.addOnChangeListener(mSliderChangeListener);
+
+        setFocusable(false);
+        setClickable(false);
+        mSlider.setFocusable(false);
+        mSlider.setClickable(false);
     }
 
     /**
@@ -178,6 +183,13 @@
         return (int) Math.ceil((value - min) / levelGap);
     }
 
+    /** Sets the content description to the ambient volume slider. */
+    public void setSliderContentDescription(CharSequence contentDescription) {
+        if (mSlider != null) {
+            mSlider.setContentDescription(contentDescription);
+        }
+    }
+
     /** Interface definition for a callback invoked when a slider's value is changed. */
     public interface OnChangeListener {
         /** Called when the finger is take off from the slider. */
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt
deleted file mode 100644
index b531d15..0000000
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.communal.ui.viewmodel
-
-import android.annotation.SuppressLint
-import android.app.DreamManager
-import android.content.Intent
-import android.provider.Settings
-import androidx.compose.runtime.getValue
-import com.android.internal.logging.UiEventLogger
-import com.android.systemui.communal.domain.interactor.CommunalPrefsInteractor
-import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
-import com.android.systemui.communal.shared.log.CommunalUiEvent
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.lifecycle.ExclusiveActivatable
-import com.android.systemui.lifecycle.Hydrator
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.statusbar.policy.BatteryController
-import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
-import com.android.systemui.util.kotlin.BooleanFlowOperators.not
-import com.android.systemui.util.kotlin.isDevicePluggedIn
-import com.android.systemui.util.kotlin.sample
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
-import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.awaitCancellation
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.flow.collectLatest
-import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.receiveAsFlow
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-
-class CommunalToDreamButtonViewModel
-@AssistedInject
-constructor(
-    @Background private val backgroundContext: CoroutineContext,
-    batteryController: BatteryController,
-    private val prefsInteractor: CommunalPrefsInteractor,
-    private val settingsInteractor: CommunalSettingsInteractor,
-    private val activityStarter: ActivityStarter,
-    private val dreamManager: DreamManager,
-    private val uiEventLogger: UiEventLogger,
-) : ExclusiveActivatable() {
-
-    private val hydrator = Hydrator("CommunalToDreamButtonViewModel.hydrator")
-    private val _requests = Channel<Unit>(Channel.BUFFERED)
-
-    /** Whether we should show a button on hub to switch to dream. */
-    val shouldShowDreamButtonOnHub: Boolean by
-        hydrator.hydratedStateOf(
-            traceName = "shouldShowDreamButtonOnHub",
-            initialValue = false,
-            source = batteryController.isDevicePluggedIn().distinctUntilChanged(),
-        )
-
-    /** Return whether to show the dream button tooltip. */
-    val shouldShowTooltip: Boolean by
-        hydrator.hydratedStateOf(
-            traceName = "shouldShowTooltip",
-            initialValue = false,
-            source =
-                allOf(
-                    not(prefsInteractor.isDreamButtonTooltipDismissed),
-                    prefsInteractor.isHubOnboardingDismissed,
-                ),
-        )
-
-    /** Set the dream button tooltip to be dismissed. */
-    fun setDreamButtonTooltipDismissed() {
-        prefsInteractor.setDreamButtonTooltipDismissed()
-    }
-
-    /** Handle a tap on the "show dream" button. */
-    fun onShowDreamButtonTap() {
-        uiEventLogger.log(CommunalUiEvent.COMMUNAL_HUB_SHOW_DREAM_BUTTON_TAP)
-        _requests.trySend(Unit)
-    }
-
-    @SuppressLint("MissingPermission")
-    override suspend fun onActivated(): Nothing = coroutineScope {
-        launch {
-            _requests
-                .receiveAsFlow()
-                .sample(settingsInteractor.isScreensaverEnabled)
-                .collectLatest { enabled ->
-                    withContext(backgroundContext) {
-                        if (enabled) {
-                            dreamManager.startDream()
-                        } else {
-                            activityStarter.postStartActivityDismissingKeyguard(
-                                Intent(Settings.ACTION_DREAM_SETTINGS),
-                                0,
-                            )
-                        }
-                    }
-                }
-        }
-
-        launch { hydrator.activate() }
-
-        awaitCancellation()
-    }
-
-    @AssistedFactory
-    interface Factory {
-        fun create(): CommunalToDreamButtonViewModel
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt
index 9b443f5..5d62c02 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt
@@ -90,15 +90,16 @@
 
     fun logCarouselVisible() = buffer.log(TAG, LogLevel.DEBUG, {}, { "showing carousel" })
 
-    fun logMediaHostVisibility(location: Int, visible: Boolean) {
+    fun logMediaHostVisibility(location: Int, visible: Boolean, oldState: Boolean) {
         buffer.log(
             TAG,
             LogLevel.DEBUG,
             {
                 int1 = location
                 bool1 = visible
+                bool2 = oldState
             },
-            { "media host visibility changed location=$location, visible:$visible" },
+            { "media host visibility changed location=$location, visible:$visible, was:$oldState" },
         )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
index c689408..69006c6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
@@ -1129,10 +1129,11 @@
         traceSection("MediaHierarchyManager#updateHostAttachment") {
             if (SceneContainerFlag.isEnabled) {
                 // No need to manage transition states - just update the desired location directly
-                logger.logMediaHostAttachment(desiredLocation)
+                val host = getHost(desiredLocation)
+                logger.logMediaHostAttachment(desiredLocation, host?.visible)
                 mediaCarouselController.onDesiredLocationChanged(
                     desiredLocation = desiredLocation,
-                    desiredHostState = getHost(desiredLocation),
+                    desiredHostState = host,
                     animate = false,
                 )
                 return
@@ -1169,7 +1170,8 @@
                     // that and directly set the mediaFrame's bounds within the premeasured host.
                     targetHost.addView(mediaFrame)
                 }
-                logger.logMediaHostAttachment(currentAttachmentLocation)
+                val host = getHost(currentAttachmentLocation)
+                logger.logMediaHostAttachment(currentAttachmentLocation, host?.visible)
                 if (isCrossFadeAnimatorRunning) {
                     // When cross-fading with an animation, we only notify the media carousel of the
                     // location change, once the view is reattached to the new place and not
@@ -1313,6 +1315,7 @@
                 isHomeScreenShadeVisibleToUser() ||
                 isGlanceableHubVisibleToUser()
         val mediaVisible = qsExpanded || hasActiveMediaOrRecommendation
+        logger.logUserVisibilityChange(shadeVisible, mediaVisible)
         mediaCarouselController.mediaCarouselScrollHandler.visibleToUser =
             shadeVisible && mediaVisible
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewLogger.kt
index 1514db3..089d16b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewLogger.kt
@@ -36,7 +36,7 @@
                 int1 = width
                 int2 = height
             },
-            { "size ($str1): $int1 x $int2" }
+            { "size ($str1): $int1 x $int2" },
         )
     }
 
@@ -49,11 +49,31 @@
                 int1 = startLocation
                 int2 = endLocation
             },
-            { "location ($str1): $int1 -> $int2" }
+            { "location ($str1): $int1 -> $int2" },
         )
     }
 
-    fun logMediaHostAttachment(host: Int) {
-        buffer.log(TAG, LogLevel.DEBUG, { int1 = host }, { "Host (updateHostAttachment): $int1" })
+    fun logMediaHostAttachment(host: Int, visible: Boolean?) {
+        buffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            {
+                int1 = host
+                str1 = visible.toString()
+            },
+            { "Host (updateHostAttachment): $int1 visible $str1" },
+        )
+    }
+
+    fun logUserVisibilityChange(shadeVisible: Boolean, mediaVisible: Boolean) {
+        buffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            {
+                bool1 = shadeVisible
+                bool2 = mediaVisible
+            },
+            { "User visibility shade: $shadeVisible media: $mediaVisible" },
+        )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt
index 11251cd..a518349 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt
@@ -208,6 +208,7 @@
      * the visibility has changed
      */
     fun updateViewVisibility() {
+        val oldState = state.visible
         state.visible =
             if (mediaCarouselController.isLockedAndHidden()) {
                 false
@@ -217,9 +218,9 @@
                 mediaDataManager.hasAnyMediaOrRecommendation()
             }
         val newVisibility = if (visible) View.VISIBLE else View.GONE
-        if (newVisibility != hostView.visibility) {
+        if (oldState != state.visible || newVisibility != hostView.visibility) {
             hostView.visibility = newVisibility
-            debugLogger.logMediaHostVisibility(location, visible)
+            debugLogger.logMediaHostVisibility(location, visible, oldState)
             visibleChangedListeners.forEach { it.invoke(visible) }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
index 4bb12e5..6ebe024 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
@@ -57,6 +57,12 @@
     private static final VisibilityApplicator VISIBILITY_APPLICATOR = new VisibilityApplicator();
     private static final VisibilityApplicator APP_NAME_APPLICATOR = new AppNameApplicator();
     private static final ResultApplicator LEFT_ICON_APPLICATOR = new LeftIconApplicator();
+    private static final DataExtractor ICON_EXTRACTOR = new DataExtractor() {
+        @Override
+        public Object extractData(ExpandableNotificationRow row) {
+            return row.getEntry().getSbn().getNotification();
+        }
+    };
 
     private final ExpandableNotificationRow mRow;
     private final ArrayList<Processor> mProcessors = new ArrayList<>();
@@ -103,26 +109,31 @@
         // To hide the icons if they are the same and the color is the same
         mProcessors.add(new Processor(mRow,
                 com.android.internal.R.id.icon,
+                ICON_EXTRACTOR,
                 iconVisibilityComparator,
                 VISIBILITY_APPLICATOR));
         // To grey out the icons when they are not the same, or they have the same color
         mProcessors.add(new Processor(mRow,
                 com.android.internal.R.id.status_bar_latest_event_content,
+                ICON_EXTRACTOR,
                 greyComparator,
                 greyApplicator));
         // To show the large icon on the left side instead if all the small icons are the same
         mProcessors.add(new Processor(mRow,
                 com.android.internal.R.id.status_bar_latest_event_content,
+                ICON_EXTRACTOR,
                 iconVisibilityComparator,
                 LEFT_ICON_APPLICATOR));
         // To only show the work profile icon in the group header
         mProcessors.add(new Processor(mRow,
                 com.android.internal.R.id.profile_badge,
+                null /* Extractor */,
                 BADGE_COMPARATOR,
                 VISIBILITY_APPLICATOR));
         // To hide the app name in group children
         mProcessors.add(new Processor(mRow,
                 com.android.internal.R.id.app_name_text,
+                null,
                 APP_NAME_COMPARATOR,
                 APP_NAME_APPLICATOR));
         // To hide the header text if it's the same
@@ -242,20 +253,23 @@
 
     private static class Processor {
         private final int mId;
+        private final DataExtractor mExtractor;
         private final ViewComparator mComparator;
         private final ResultApplicator mApplicator;
         private final ExpandableNotificationRow mParentRow;
         private boolean mApply;
         private View mParentView;
+        private Object mParentData;
 
         public static Processor forTextView(ExpandableNotificationRow row, int id) {
-            return new Processor(row, id, TEXT_VIEW_COMPARATOR, VISIBILITY_APPLICATOR);
+            return new Processor(row, id, null, TEXT_VIEW_COMPARATOR, VISIBILITY_APPLICATOR);
         }
 
-        Processor(ExpandableNotificationRow row, int id,
+        Processor(ExpandableNotificationRow row, int id, DataExtractor extractor,
                 ViewComparator comparator,
                 ResultApplicator applicator) {
             mId = id;
+            mExtractor = extractor;
             mApplicator = applicator;
             mComparator = comparator;
             mParentRow = row;
@@ -265,6 +279,7 @@
             NotificationViewWrapper wrapper = mParentRow.getNotificationViewWrapper();
             View header = wrapper == null ? null : wrapper.getNotificationHeader();
             mParentView = header == null ? null : header.findViewById(mId);
+            mParentData = mExtractor == null ? null : mExtractor.extractData(mParentRow);
             mApply = !mComparator.isEmpty(mParentView);
         }
 
@@ -282,7 +297,9 @@
                 // when for example showing an undo notification
                 return;
             }
-            mApply = mComparator.compare(mParentView, ownView);
+            Object childData = mExtractor == null ? null : mExtractor.extractData(row);
+            mApply = mComparator.compare(mParentView, ownView,
+                    mParentData, childData);
         }
 
         public void apply(ExpandableNotificationRow row) {
@@ -314,9 +331,11 @@
         /**
          * @param parent     the view with the given id in the group header
          * @param child      the view with the given id in the child notification
+         * @param parentData optional data for the parent
+         * @param childData  optional data for the child
          * @return whether to views are the same
          */
-        boolean compare(View parent, View child);
+        boolean compare(View parent, View child, Object parentData, Object childData);
 
         boolean isEmpty(View view);
     }
@@ -327,7 +346,7 @@
 
     private static class BadgeComparator implements ViewComparator {
         @Override
-        public boolean compare(View parent, View child) {
+        public boolean compare(View parent, View child, Object parentData, Object childData) {
             return parent.getVisibility() != View.GONE;
         }
 
@@ -345,7 +364,7 @@
 
     private static class TextViewComparator implements ViewComparator {
         @Override
-        public boolean compare(View parent, View child) {
+        public boolean compare(View parent, View child, Object parentData, Object childData) {
             TextView parentView = (TextView) parent;
             CharSequence parentText = parentView == null ? "" : parentView.getText();
             TextView childView = (TextView) child;
@@ -361,7 +380,7 @@
 
     private abstract static class IconComparator implements ViewComparator {
         @Override
-        public boolean compare(View parent, View child) {
+        public boolean compare(View parent, View child, Object parentData, Object childData) {
             return false;
         }
 
@@ -421,14 +440,14 @@
 
     private static class AppNameComparator extends TextViewComparator {
         @Override
-        public boolean compare(View parent, View child) {
+        public boolean compare(View parent, View child, Object parentData, Object childData) {
             if (isEmpty(child)) {
                 // In headerless notifications the AppName view exists but is usually GONE (and not
                 // populated).  We need to treat this case as equal to the header in order to
                 // deduplicate the view.
                 return true;
             }
-            return super.compare(parent, child);
+            return super.compare(parent, child, parentData, childData);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimator.kt
index 74faf25..0a24d7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PhysicsPropertyAnimator.kt
@@ -15,12 +15,12 @@
  */
 package com.android.systemui.statusbar.notification
 
+import android.util.FloatProperty
 import android.util.Property
 import android.view.View
-import androidx.dynamicanimation.animation.DynamicAnimation
-import androidx.dynamicanimation.animation.FloatPropertyCompat
-import androidx.dynamicanimation.animation.SpringAnimation
-import androidx.dynamicanimation.animation.SpringForce
+import com.android.internal.dynamicanimation.animation.DynamicAnimation
+import com.android.internal.dynamicanimation.animation.SpringAnimation
+import com.android.internal.dynamicanimation.animation.SpringForce
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.notification.PhysicsPropertyAnimator.Companion.createDefaultSpring
 import com.android.systemui.statusbar.notification.stack.AnimationProperties
@@ -33,8 +33,8 @@
  */
 data class PhysicsProperty(val tag: Int, val property: Property<View, Float>) {
     val offsetProperty =
-        object : FloatPropertyCompat<View>(property.name) {
-            override fun getValue(view: View): Float {
+        object : FloatProperty<View>(property.name) {
+            override fun get(view: View): Float {
                 return property.get(view)
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
index 248b528..28923b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.collection.coordinator
 
+import android.app.NotificationChannel.SYSTEM_RESERVED_IDS
 import com.android.systemui.statusbar.notification.collection.GroupEntry
 import com.android.systemui.statusbar.notification.collection.PipelineEntry
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
@@ -89,6 +90,7 @@
             object : NotifSectioner("Priority People", BUCKET_PRIORITY_PEOPLE) {
                 override fun isInSection(entry: PipelineEntry): Boolean {
                     return getPeopleType(entry) == TYPE_IMPORTANT_PERSON
+                            && entry.representativeEntry?.channel?.id !in SYSTEM_RESERVED_IDS
                 }
             }
 
@@ -96,10 +98,12 @@
     val peopleAlertingSectioner = object : NotifSectioner("People(alerting)", BUCKET_PEOPLE) {
         override fun isInSection(entry: PipelineEntry): Boolean  {
             if (SortBySectionTimeFlag.isEnabled) {
-                return highPriorityProvider.isHighPriorityConversation(entry)
-                        || isConversation(entry)
+                return (highPriorityProvider.isHighPriorityConversation(entry)
+                        || isConversation(entry))
+                        && entry.representativeEntry?.channel?.id !in SYSTEM_RESERVED_IDS
             } else {
                 return highPriorityProvider.isHighPriorityConversation(entry)
+                        && entry.representativeEntry?.channel?.id !in SYSTEM_RESERVED_IDS
             }
         }
 
@@ -111,11 +115,12 @@
     }
 
     val peopleSilentSectioner = object : NotifSectioner("People(silent)", BUCKET_PEOPLE) {
-        // Because the peopleAlertingSectioner is above this one, it will claim all conversations that are alerting.
-        // All remaining conversations must be silent.
+        // Because the peopleAlertingSectioner is above this one, it will claim all conversations
+        // that are alerting. All remaining conversations must be silent.
         override fun isInSection(entry: PipelineEntry): Boolean {
             SortBySectionTimeFlag.assertInLegacyMode()
             return isConversation(entry)
+                    && entry.representativeEntry?.channel?.id !in SYSTEM_RESERVED_IDS
         }
 
         override fun getComparator(): NotifComparator {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt
index 7959e99..2a01a14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AODPromotedNotification.kt
@@ -20,6 +20,7 @@
 import android.app.Flags.notificationsRedesignTemplates
 import android.app.Notification
 import android.graphics.PorterDuff
+import android.util.Log
 import android.view.LayoutInflater
 import android.view.View
 import android.view.View.GONE
@@ -80,9 +81,13 @@
     val content = viewModel.content ?: return
     val audiblyAlertedIconVisible = viewModel.audiblyAlertedIconVisible
 
-    key(content.identity) {
-        val layoutResource = content.layoutResource ?: return
+    val layoutResource = content.layoutResource
+    if (layoutResource == null) {
+        Log.w(TAG, "not displaying promoted notif with ineligible style on AOD")
+        return
+    }
 
+    key(content.identity) {
         val sidePaddings = dimensionResource(systemuiR.dimen.notification_side_paddings)
         val sidePaddingValues = PaddingValues(horizontal = sidePaddings, vertical = 0.dp)
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index a081ad5..6837cb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -119,6 +119,7 @@
     protected Point mTargetPoint;
     private boolean mDismissed;
     private boolean mRefocusOnDismiss;
+    protected boolean mIsBlurSupported;
 
     public ActivatableNotificationView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -128,12 +129,13 @@
     }
 
     private void updateColors() {
-        if (notificationRowTransparency()) {
+        if (usesTransparentBackground()) {
             mNormalColor = SurfaceEffectColors.surfaceEffect1(getContext());
         } else {
             mNormalColor = mContext.getColor(
                     com.android.internal.R.color.materialColorSurfaceContainerHigh);
         }
+        setBackgroundToNormalColor();
         mTintedRippleColor = mContext.getColor(
                 R.color.notification_ripple_tinted_color);
         mNormalRippleColor = mContext.getColor(
@@ -144,6 +146,12 @@
         mOverrideAmount = 0.0f;
     }
 
+    private void setBackgroundToNormalColor() {
+        if (mBackgroundNormal != null) {
+            mBackgroundNormal.setNormalColor(mNormalColor);
+        }
+    }
+
     /**
      * Reload background colors from resources and invalidate views.
      */
@@ -173,6 +181,7 @@
         mBackgroundNormal = findViewById(R.id.backgroundNormal);
         mFakeShadow = findViewById(R.id.fake_shadow);
         mShadowHidden = mFakeShadow.getVisibility() != VISIBLE;
+        setBackgroundToNormalColor();
         initBackground();
         updateBackgroundTint();
         updateOutlineAlpha();
@@ -326,6 +335,21 @@
         mBackgroundNormal.setBottomAmountClips(!isChildInGroup());
     }
 
+    public void setIsBlurSupported(boolean isBlurSupported) {
+        if (!notificationRowTransparency()) {
+            return;
+        }
+        boolean usedTransparentBackground = usesTransparentBackground();
+        mIsBlurSupported = isBlurSupported;
+        if (usedTransparentBackground != usesTransparentBackground()) {
+            updateBackgroundColors();
+        }
+    }
+
+    protected boolean usesTransparentBackground() {
+        return mIsBlurSupported && notificationRowTransparency();
+    }
+
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 179951f..3ef1fd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -20,8 +20,8 @@
 import static android.app.Notification.Action.SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY;
 import static android.service.notification.NotificationListenerService.REASON_CANCEL;
 
-import static com.android.systemui.Flags.notificationsPinnedHunInShade;
 import static com.android.systemui.Flags.notificationRowTransparency;
+import static com.android.systemui.Flags.notificationsPinnedHunInShade;
 import static com.android.systemui.flags.Flags.ENABLE_NOTIFICATIONS_SIMULATE_SLOW_MEASURE;
 import static com.android.systemui.statusbar.notification.NotificationUtils.logKey;
 import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.PARENT_DISMISSED;
@@ -1678,14 +1678,15 @@
         if (view != null) {
             view.setBackgroundTintColor(color);
         }
-        if (notificationRowTransparency()
-                && (mBackgroundNormal != null)) {
+        if (notificationRowTransparency() && mBackgroundNormal != null) {
             if (NotificationBundleUi.isEnabled()) {
-                mBackgroundNormal.setBgIsColorized(mEntryAdapter.isColorized());
+                mBackgroundNormal.setBgIsColorized(
+                        usesTransparentBackground() && mEntryAdapter.isColorized());
             } else {
                 if (mEntry != null) {
                     mBackgroundNormal.setBgIsColorized(
-                            mEntry.getSbn().getNotification().isColorized());
+                            usesTransparentBackground()
+                                    && mEntry.getSbn().getNotification().isColorized());
                 }
             }
         }
@@ -3021,6 +3022,7 @@
 
         mUserLocked = userLocked;
         mPrivateLayout.setUserExpanding(userLocked);
+        mPublicLayout.setUserExpanding(userLocked);
         // This is intentionally not guarded with mIsSummaryWithChildren since we might have had
         // children but not anymore.
         if (mChildrenContainer != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
index 4978fa4..e1219e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
@@ -73,7 +73,7 @@
     private int mDrawableAlpha = 255;
     private final ColorStateList mLightColoredStatefulColors;
     private final ColorStateList mDarkColoredStatefulColors;
-    private final int mNormalColor;
+    private int mNormalColor;
     private boolean mBgIsColorized = false;
     private boolean mForceOpaque = false;
     private final int convexR = 9;
@@ -89,15 +89,13 @@
                 R.color.notification_state_color_light);
         mDarkColoredStatefulColors = getResources().getColorStateList(
                 R.color.notification_state_color_dark);
-        if (notificationRowTransparency()) {
-            mNormalColor = SurfaceEffectColors.surfaceEffect1(getContext());
-        } else  {
-            mNormalColor = mContext.getColor(
-                    com.android.internal.R.color.materialColorSurfaceContainerHigh);
-        }
         mFocusOverlayStroke = getResources().getDimension(R.dimen.notification_focus_stroke_width);
     }
 
+    public void setNormalColor(int color) {
+        mNormalColor = color;
+    }
+
     @Override
     public void onTargetVisibilityChanged(boolean targetVisible) {
         if (NotificationAddXOnHoverToDismiss.isUnexpectedlyInLegacyMode()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt
index f0b5c36..8984f2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt
@@ -50,6 +50,15 @@
                 view.registerListenersWhileAttached(touchHandler)
             }
         }
+        view.repeatWhenAttached {
+            repeatOnLifecycle(Lifecycle.State.STARTED) {
+                launch {
+                    viewModel.isBlurSupported.collect { supported ->
+                        view.setIsBlurSupported(supported)
+                    }
+                }
+            }
+        }
     }
 
     private suspend fun ActivatableNotificationView.registerListenersWhileAttached(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModel.kt
index f46d424..9a86ffb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModel.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.row.ui.viewmodel
 
 import com.android.systemui.accessibility.domain.interactor.AccessibilityInteractor
+import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
 import dagger.Module
 import dagger.Provides
 import kotlinx.coroutines.flow.Flow
@@ -26,25 +27,34 @@
 interface ActivatableNotificationViewModel : ExpandableOutlineViewModel {
     /** Does the view react to touches? */
     val isTouchable: Flow<Boolean>
+    val isBlurSupported: Flow<Boolean>
 
     companion object {
         operator fun invoke(
             a11yInteractor: AccessibilityInteractor,
-        ): ActivatableNotificationViewModel = ActivatableNotificationViewModelImpl(a11yInteractor)
+            windowRootViewBlurInteractor: WindowRootViewBlurInteractor
+        ): ActivatableNotificationViewModel =
+            ActivatableNotificationViewModelImpl(a11yInteractor, windowRootViewBlurInteractor)
     }
 }
 
 private class ActivatableNotificationViewModelImpl(
     a11yInteractor: AccessibilityInteractor,
+    windowRootViewBlurInteractor: WindowRootViewBlurInteractor,
 ) : ActivatableNotificationViewModel {
     override val isTouchable: Flow<Boolean> =
         // If a11y touch exploration is enabled, then the activatable view should ignore touches
         a11yInteractor.isTouchExplorationEnabled.map { !it }
+    override val isBlurSupported: Flow<Boolean> =
+        windowRootViewBlurInteractor.isBlurCurrentlySupported
 }
 
 @Module
 object ActivatableNotificationViewModelModule {
     @Provides
-    fun provideViewModel(interactor: AccessibilityInteractor) =
-        ActivatableNotificationViewModel(interactor)
+    fun provideViewModel(
+        a11yInteractor: AccessibilityInteractor,
+        windowRootViewBlurInteractor: WindowRootViewBlurInteractor
+    ) =
+        ActivatableNotificationViewModel(a11yInteractor, windowRootViewBlurInteractor)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java
index 3d60092..4d01cbd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationProperties.java
@@ -23,7 +23,7 @@
 import android.view.View;
 import android.view.animation.Interpolator;
 
-import androidx.dynamicanimation.animation.DynamicAnimation;
+import com.android.internal.dynamicanimation.animation.DynamicAnimation;
 
 import java.util.function.Consumer;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 9a5cf9c..19abfa8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -32,10 +32,9 @@
 import android.util.Property;
 import android.view.View;
 
-import androidx.dynamicanimation.animation.DynamicAnimation;
-
 import com.android.app.animation.Interpolators;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.dynamicanimation.animation.DynamicAnimation;
 import com.android.systemui.res.R;
 import com.android.systemui.shared.clocks.AnimatableClockView;
 import com.android.systemui.statusbar.NotificationShelf;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
index 2ef6f36..29dbeb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -30,10 +30,9 @@
 import android.view.View;
 import android.view.animation.Interpolator;
 
-import androidx.dynamicanimation.animation.DynamicAnimation;
-import androidx.dynamicanimation.animation.SpringAnimation;
-
 import com.android.app.animation.Interpolators;
+import com.android.internal.dynamicanimation.animation.DynamicAnimation;
+import com.android.internal.dynamicanimation.animation.SpringAnimation;
 import com.android.systemui.Dumpable;
 import com.android.systemui.res.R;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelKosmos.kt
deleted file mode 100644
index 43d3eb7..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelKosmos.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.communal.ui.viewmodel
-
-import android.service.dream.dreamManager
-import com.android.internal.logging.uiEventLogger
-import com.android.systemui.communal.domain.interactor.communalPrefsInteractor
-import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.testDispatcher
-import com.android.systemui.plugins.activityStarter
-import com.android.systemui.statusbar.policy.batteryController
-
-val Kosmos.communalToDreamButtonViewModel by
-    Kosmos.Fixture {
-        CommunalToDreamButtonViewModel(
-            backgroundContext = testDispatcher,
-            batteryController = batteryController,
-            prefsInteractor = communalPrefsInteractor,
-            settingsInteractor = communalSettingsInteractor,
-            activityStarter = activityStarter,
-            dreamManager = dreamManager,
-            uiEventLogger = uiEventLogger,
-        )
-    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelKosmos.kt
index 2523975..7ccbdb7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ActivatableNotificationViewModelKosmos.kt
@@ -19,9 +19,11 @@
 import com.android.systemui.accessibility.domain.interactor.accessibilityInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.window.domain.interactor.windowRootViewBlurInteractor
 
 val Kosmos.activatableNotificationViewModel by Fixture {
     ActivatableNotificationViewModel.invoke(
         a11yInteractor = accessibilityInteractor,
+        windowRootViewBlurInteractor = windowRootViewBlurInteractor,
     )
 }
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
index 735635c..b41ce0f 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -268,18 +268,45 @@
 }
 
 /**
+ * Write bytecode to pop the 2 uninitialized instances out of the stack
+ * after performing constructor redirection.
+ */
+fun adjustStackForConstructorRedirection(writer: MethodVisitor) {
+    // Stack: { uninitialized, uninitialized, obj }
+    writer.visitInsn(Opcodes.SWAP)
+    // Stack: { uninitialized, obj, uninitialized }
+    writer.visitInsn(Opcodes.POP)
+    // Stack: { uninitialized, obj }
+    writer.visitInsn(Opcodes.SWAP)
+    // Stack: { obj, uninitialized }
+    writer.visitInsn(Opcodes.POP)
+    // Stack: { obj }
+
+    // We end up with only the desired object on the stack
+}
+
+/**
  * Given a method descriptor, insert an [argType] as the first argument to it.
  */
 fun prependArgTypeToMethodDescriptor(methodDescriptor: String, classInternalName: String): String {
     val returnType = Type.getReturnType(methodDescriptor)
     val argTypes = Type.getArgumentTypes(methodDescriptor).toMutableList()
 
-    argTypes.add(0, Type.getType("L" + classInternalName + ";"))
+    argTypes.add(0, Type.getType("L$classInternalName;"))
 
     return Type.getMethodDescriptor(returnType, *argTypes.toTypedArray())
 }
 
 /**
+ * Given a method descriptor, change the return type to [classInternalName].
+ */
+fun changeMethodDescriptorReturnType(methodDescriptor: String, classInternalName: String): String {
+    val argTypes = Type.getArgumentTypes(methodDescriptor)
+    val returnType = Type.getType("L$classInternalName;")
+    return Type.getMethodDescriptor(returnType, *argTypes)
+}
+
+/**
  * Return the "visibility" modifier from an `access` integer.
  *
  * (see https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1)
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
index d0c97c0..dd353e9 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
@@ -100,7 +100,6 @@
         methodName: String,
         methodDesc: String,
         replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec,
-        policy: FilterPolicyWithReason,
     )
 }
 
@@ -286,9 +285,10 @@
             methodName: String,
             methodDesc: String,
             replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec,
-            policy: FilterPolicyWithReason,
         ) {
-            imf.setPolicyForMethod(className, methodName, methodDesc, policy)
+            // Keep the source method, because the target method may call it.
+            imf.setPolicyForMethod(className, methodName, methodDesc,
+                FilterPolicy.Keep.withReason(FILTER_REASON))
             methodReplaceSpec.add(replaceSpec)
         }
     }
@@ -642,7 +642,6 @@
                     methodName,
                     signature,
                     spec,
-                    policyWithReason,
                 )
             } else {
                 // It's an in-class replace.
diff --git a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
index 70e7d46..b8a3576 100644
--- a/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
+++ b/ravenwood/tools/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
@@ -17,7 +17,10 @@
 
 import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC
 import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME
+import com.android.hoststubgen.asm.CTOR_NAME
 import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.adjustStackForConstructorRedirection
+import com.android.hoststubgen.asm.changeMethodDescriptorReturnType
 import com.android.hoststubgen.asm.prependArgTypeToMethodDescriptor
 import com.android.hoststubgen.asm.writeByteCodeToPushArguments
 import com.android.hoststubgen.asm.writeByteCodeToReturn
@@ -33,6 +36,7 @@
 import org.objectweb.asm.MethodVisitor
 import org.objectweb.asm.Opcodes
 import org.objectweb.asm.Opcodes.INVOKEINTERFACE
+import org.objectweb.asm.Opcodes.INVOKESPECIAL
 import org.objectweb.asm.Opcodes.INVOKESTATIC
 import org.objectweb.asm.Opcodes.INVOKEVIRTUAL
 import org.objectweb.asm.Type
@@ -376,53 +380,90 @@
         val callerMethodName: String,
         next: MethodVisitor?,
     ) : MethodVisitor(OPCODE_VERSION, next) {
-        override fun visitMethodInsn(
+
+        private fun doReplace(
             opcode: Int,
-            owner: String?,
-            name: String?,
-            descriptor: String?,
-            isInterface: Boolean,
-        ) {
+            owner: String,
+            name: String,
+            descriptor: String,
+        ): Boolean {
             when (opcode) {
                 INVOKESTATIC, INVOKEVIRTUAL, INVOKEINTERFACE -> {}
-                else -> {
-                    // Don't touch other opcodes.
-                    super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
-                    return
-                }
+                // We only support INVOKESPECIAL when replacing constructors.
+                INVOKESPECIAL -> if (name != CTOR_NAME) return false
+                // Don't touch other opcodes.
+                else -> return false
             }
+
             val to = filter.getMethodCallReplaceTo(
-                currentClassName, callerMethodName, owner!!, name!!, descriptor!!
+                currentClassName, callerMethodName, owner, name, descriptor
             )
 
             if (to == null
                 // Don't replace if the target is the callsite.
                 || (to.className == currentClassName && to.methodName == callerMethodName)
             ) {
-                super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
-                return
+                return false
             }
 
-            // Replace the method call with a (static) call to the target method.
-            // If it's a non-static call, the target method's first argument will receive "this".
-            // (Because of that, we don't need to manipulate the stack. Just replace the
-            // method call.)
+            if (opcode != INVOKESPECIAL) {
+                // It's either a static method call or virtual method call.
+                // Either way, we don't manipulate the stack and send the original arguments
+                // as is to the target method.
+                //
+                // If the call is a virtual call (INVOKEVIRTUAL or INVOKEINTERFACE), then
+                // the first argument in the stack is the "this" object, so the target
+                // method must have an extra argument as the first argument to receive it.
+                // We update the method descriptor with prependArgTypeToMethodDescriptor()
+                // to absorb this difference.
 
-            val toDesc = if (opcode == INVOKESTATIC) {
-                // Static call to static call, no need to change the desc.
-                descriptor
+                val toDesc = if (opcode == INVOKESTATIC) {
+                    descriptor
+                } else {
+                    prependArgTypeToMethodDescriptor(descriptor, owner)
+                }
+
+                mv.visitMethodInsn(
+                    INVOKESTATIC,
+                    to.className,
+                    to.methodName,
+                    toDesc,
+                    false
+                )
             } else {
-                // Need to prepend the "this" type to the descriptor.
-                prependArgTypeToMethodDescriptor(descriptor, owner)
+                // Because an object initializer does not return a value, the newly created
+                // but uninitialized object will be dup-ed at the bottom of the stack.
+                // We first call the target method to consume the constructor arguments at the top.
+
+                val toDesc = changeMethodDescriptorReturnType(descriptor, owner)
+
+                // Before stack: { uninitialized, uninitialized, args... }
+                mv.visitMethodInsn(
+                    INVOKESTATIC,
+                    to.className,
+                    to.methodName,
+                    toDesc,
+                    false
+                )
+                // After stack: { uninitialized, uninitialized, obj }
+
+                // Next we pop the 2 uninitialized instances out of the stack.
+                adjustStackForConstructorRedirection(mv)
             }
 
-            mv.visitMethodInsn(
-                INVOKESTATIC,
-                to.className,
-                to.methodName,
-                toDesc,
-                false
-            )
+            return true
+        }
+
+        override fun visitMethodInsn(
+            opcode: Int,
+            owner: String,
+            name: String,
+            descriptor: String,
+            isInterface: Boolean,
+        ) {
+            if (!doReplace(opcode, owner, name, descriptor)) {
+                super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
+            }
         }
     }
 }
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt
index e846d6e..2b942a9 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -1883,6 +1883,42 @@
 InnerClasses:
   public static #x= #x of #x;          // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
   public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester.class
+  Compiled from "TinyFrameworkMethodCallReplace.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester
+  minor version: 0
+  major version: 65
+  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+  super_class: #x                         // java/lang/Object
+  interfaces: 0, fields: 1, methods: 1, attributes: 3
+Constant pool:
+{
+  public int i;
+    descriptor: I
+    flags: (0x0001) ACC_PUBLIC
+
+  public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester(int);
+    descriptor: (I)V
+    flags: (0x0001) ACC_PUBLIC
+    Code:
+      stack=2, locals=2, args_size=2
+         x: aload_0
+         x: invokespecial #x                  // Method java/lang/Object."<init>":()V
+         x: aload_0
+         x: iload_1
+         x: putfield      #x                  // Field i:I
+         x: return
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+            0      10     1     i   I
+}
+SourceFile: "TinyFrameworkMethodCallReplace.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+InnerClasses:
+  public static #x= #x of #x;           // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
   Compiled from "TinyFrameworkMethodCallReplace.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
@@ -1891,7 +1927,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                         // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 3, attributes: 3
+  interfaces: 0, fields: 0, methods: 4, attributes: 3
 Constant pool:
 {
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo();
@@ -1937,10 +1973,28 @@
         Start  Length  Slot  Name   Signature
             0       4     0     a   I
             0       4     1     b   I
+
+  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester newConstructorTester(int);
+    descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=1, args_size=1
+         x: new           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+         x: dup
+         x: iload_0
+         x: iconst_1
+         x: iadd
+         x: invokespecial #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+        x: areturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0      11     0     i   I
 }
 SourceFile: "TinyFrameworkMethodCallReplace.java"
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 InnerClasses:
+  public static #x= #x of #x;          // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static #x= #x of #x;          // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class
   Compiled from "TinyFrameworkMethodCallReplace.java"
@@ -1950,7 +2004,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                         // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 5, attributes: 5
+  interfaces: 0, fields: 0, methods: 6, attributes: 5
 Constant pool:
 {
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace();
@@ -2008,6 +2062,21 @@
          x: ireturn
       LineNumberTable:
 
+  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester constructorReplaceTester(int);
+    descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=3, locals=1, args_size=1
+         x: new           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+         x: dup
+         x: iload_0
+         x: invokespecial #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+         x: areturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0       9     0     i   I
+
   private static int originalAdd(int, int);
     descriptor: (II)I
     flags: (0x000a) ACC_PRIVATE, ACC_STATIC
@@ -2046,6 +2115,7 @@
     android.hosttest.annotation.HostSideTestWholeClassKeep
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+  com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
 BootstrapMethods:
   x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
     Method arguments:
@@ -2053,8 +2123,9 @@
       #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.lambda$nonStaticMethodCallReplaceTester$0:(Ljava/util/concurrent/atomic/AtomicBoolean;)V
       #x ()V
 InnerClasses:
+  public static #x= #x of #x;          // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static #x= #x of #x;          // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-  public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
+  public static final #x= #x of #x;   // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
   Compiled from "TinyFrameworkNative.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/03-hoststubgen-test-tiny-framework-host-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/03-hoststubgen-test-tiny-framework-host-dump.txt
index be95fe0..d493ad1 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/03-hoststubgen-test-tiny-framework-host-dump.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/03-hoststubgen-test-tiny-framework-host-dump.txt
@@ -2002,6 +2002,51 @@
       #x ()Ljava/lang/Integer;
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester.class
+  Compiled from "TinyFrameworkMethodCallReplace.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester
+  minor version: 0
+  major version: 65
+  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+  super_class: #x                         // java/lang/Object
+  interfaces: 0, fields: 1, methods: 1, attributes: 4
+Constant pool:
+{
+  public int i;
+    descriptor: I
+    flags: (0x0001) ACC_PUBLIC
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester(int);
+    descriptor: (I)V
+    flags: (0x0001) ACC_PUBLIC
+    Code:
+      stack=2, locals=2, args_size=2
+         x: aload_0
+         x: invokespecial #x                 // Method java/lang/Object."<init>":()V
+         x: aload_0
+         x: iload_1
+         x: putfield      #x                 // Field i:I
+         x: return
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+            0      10     1     i   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+}
+InnerClasses:
+  public static #x= #x of #x;             // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+SourceFile: "TinyFrameworkMethodCallReplace.java"
+RuntimeVisibleAnnotations:
+  x: #x()
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
   Compiled from "TinyFrameworkMethodCallReplace.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
@@ -2010,7 +2055,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 3, attributes: 4
+  interfaces: 0, fields: 0, methods: 4, attributes: 4
 Constant pool:
 {
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo();
@@ -2065,9 +2110,30 @@
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester newConstructorTester(int);
+    descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=1, args_size=1
+         x: new           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+         x: dup
+         x: iload_0
+         x: iconst_1
+         x: iadd
+         x: invokespecial #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+        x: areturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0      11     0     i   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
-  public static #x= #x of #x;             // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+  public static #x= #x of #x;           // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+  public static #x= #x of #x;            // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 SourceFile: "TinyFrameworkMethodCallReplace.java"
 RuntimeVisibleAnnotations:
   x: #x()
@@ -2081,7 +2147,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 4, attributes: 6
+  interfaces: 0, fields: 0, methods: 6, attributes: 6
 Constant pool:
 {
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace();
@@ -2148,6 +2214,48 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
+  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester constructorReplaceTester(int);
+    descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=3, locals=1, args_size=1
+         x: new           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+         x: dup
+         x: iload_0
+         x: invokestatic  #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.newConstructorTester:(I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+         x: swap
+         x: pop
+        x: swap
+        x: pop
+        x: areturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0      13     0     i   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  private static int originalAdd(int, int);
+    descriptor: (II)I
+    flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+    Code:
+      stack=2, locals=2, args_size=2
+         x: iload_0
+         x: iload_1
+         x: iadd
+         x: iconst_1
+         x: isub
+         x: ireturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0       6     0     a   I
+            0       6     1     b   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
   private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
     descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
     flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
@@ -2167,6 +2275,7 @@
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
+  public static #x= #x of #x;           // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static #x= #x of #x;            // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
 SourceFile: "TinyFrameworkMethodCallReplace.java"
@@ -2184,6 +2293,7 @@
       #x ()V
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+  com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
   Compiled from "TinyFrameworkNative.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/13-hoststubgen-test-tiny-framework-host-ext-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
index 667981f..8978a7a 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output.RELEASE_TARGET_JAVA_21/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
@@ -2413,6 +2413,66 @@
       #x ()Ljava/lang/Integer;
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester.class
+  Compiled from "TinyFrameworkMethodCallReplace.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester
+  minor version: 0
+  major version: 65
+  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+  super_class: #x                         // java/lang/Object
+  interfaces: 0, fields: 1, methods: 2, attributes: 4
+Constant pool:
+{
+  public int i;
+    descriptor: I
+    flags: (0x0001) ACC_PUBLIC
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  private static {};
+    descriptor: ()V
+    flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+    Code:
+      stack=2, locals=0, args_size=0
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+         x: return
+
+  public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester(int);
+    descriptor: (I)V
+    flags: (0x0001) ACC_PUBLIC
+    Code:
+      stack=4, locals=2, args_size=2
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+         x: ldc           #x                 // String <init>
+         x: ldc           #x                 // String (I)V
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: aload_0
+        x: invokespecial #x                 // Method java/lang/Object."<init>":()V
+        x: aload_0
+        x: iload_1
+        x: putfield      #x                 // Field i:I
+        x: return
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+           11      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+           11      10     1     i   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+}
+InnerClasses:
+  public static #x= #x of #x;           // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+SourceFile: "TinyFrameworkMethodCallReplace.java"
+RuntimeVisibleAnnotations:
+  x: #x()
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
   Compiled from "TinyFrameworkMethodCallReplace.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
@@ -2421,7 +2481,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 4, attributes: 4
+  interfaces: 0, fields: 0, methods: 5, attributes: 4
 Constant pool:
 {
   private static {};
@@ -2501,8 +2561,34 @@
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester newConstructorTester(int);
+    descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=1, args_size=1
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+         x: ldc           #x                 // String newConstructorTester
+         x: ldc           #x                 // String (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: new           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+        x: dup
+        x: iload_0
+        x: iconst_1
+        x: iadd
+        x: invokespecial #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+        x: areturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+           11      11     0     i   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
+  public static #x= #x of #x;          // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static #x= #x of #x;           // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 SourceFile: "TinyFrameworkMethodCallReplace.java"
 RuntimeVisibleAnnotations:
@@ -2517,7 +2603,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 5, attributes: 6
+  interfaces: 0, fields: 0, methods: 7, attributes: 6
 Constant pool:
 {
   private static {};
@@ -2609,18 +2695,70 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
+  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester constructorReplaceTester(int);
+    descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=1, args_size=1
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+         x: ldc           #x                 // String constructorReplaceTester
+         x: ldc           #x                // String (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: new           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+        x: dup
+        x: iload_0
+        x: invokestatic  #x                // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.newConstructorTester:(I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+        x: swap
+        x: pop
+        x: swap
+        x: pop
+        x: areturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+           11      13     0     i   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  private static int originalAdd(int, int);
+    descriptor: (II)I
+    flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+    Code:
+      stack=4, locals=2, args_size=2
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+         x: ldc           #x                // String originalAdd
+         x: ldc           #x                // String (II)I
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: iload_0
+        x: iload_1
+        x: iadd
+        x: iconst_1
+        x: isub
+        x: ireturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+           11       6     0     a   I
+           11       6     1     b   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
   private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
     descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
     flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
     Code:
       stack=4, locals=1, args_size=1
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-         x: ldc           #x                 // String lambda$nonStaticMethodCallReplaceTester$0
-         x: ldc           #x                 // String (Ljava/util/concurrent/atomic/AtomicBoolean;)V
+         x: ldc           #x                // String lambda$nonStaticMethodCallReplaceTester$0
+         x: ldc           #x                // String (Ljava/util/concurrent/atomic/AtomicBoolean;)V
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
         x: aload_0
-        x: invokestatic  #x                 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
+        x: invokestatic  #x                // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
         x: invokevirtual #x                // Method java/lang/Thread.isDaemon:()Z
         x: invokevirtual #x                // Method java/util/concurrent/atomic/AtomicBoolean.set:(Z)V
         x: return
@@ -2633,6 +2771,7 @@
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
+  public static #x= #x of #x;           // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static #x= #x of #x;           // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
 SourceFile: "TinyFrameworkMethodCallReplace.java"
@@ -2650,6 +2789,7 @@
       #x ()V
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+  com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
   Compiled from "TinyFrameworkNative.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
index 8f56f0e..406c611 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -1883,6 +1883,42 @@
 InnerClasses:
   public static #x= #x of #x;          // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
   public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester.class
+  Compiled from "TinyFrameworkMethodCallReplace.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester
+  minor version: 0
+  major version: 61
+  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+  super_class: #x                         // java/lang/Object
+  interfaces: 0, fields: 1, methods: 1, attributes: 3
+Constant pool:
+{
+  public int i;
+    descriptor: I
+    flags: (0x0001) ACC_PUBLIC
+
+  public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester(int);
+    descriptor: (I)V
+    flags: (0x0001) ACC_PUBLIC
+    Code:
+      stack=2, locals=2, args_size=2
+         x: aload_0
+         x: invokespecial #x                  // Method java/lang/Object."<init>":()V
+         x: aload_0
+         x: iload_1
+         x: putfield      #x                  // Field i:I
+         x: return
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+            0      10     1     i   I
+}
+SourceFile: "TinyFrameworkMethodCallReplace.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+InnerClasses:
+  public static #x= #x of #x;           // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
   Compiled from "TinyFrameworkMethodCallReplace.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
@@ -1891,7 +1927,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                         // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 3, attributes: 3
+  interfaces: 0, fields: 0, methods: 4, attributes: 3
 Constant pool:
 {
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo();
@@ -1937,10 +1973,28 @@
         Start  Length  Slot  Name   Signature
             0       4     0     a   I
             0       4     1     b   I
+
+  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester newConstructorTester(int);
+    descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=1, args_size=1
+         x: new           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+         x: dup
+         x: iload_0
+         x: iconst_1
+         x: iadd
+         x: invokespecial #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+        x: areturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0      11     0     i   I
 }
 SourceFile: "TinyFrameworkMethodCallReplace.java"
 NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 InnerClasses:
+  public static #x= #x of #x;          // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static #x= #x of #x;          // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class
   Compiled from "TinyFrameworkMethodCallReplace.java"
@@ -1950,7 +2004,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                         // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 5, attributes: 5
+  interfaces: 0, fields: 0, methods: 6, attributes: 5
 Constant pool:
 {
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace();
@@ -2008,6 +2062,21 @@
          x: ireturn
       LineNumberTable:
 
+  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester constructorReplaceTester(int);
+    descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=3, locals=1, args_size=1
+         x: new           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+         x: dup
+         x: iload_0
+         x: invokespecial #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+         x: areturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0       9     0     i   I
+
   private static int originalAdd(int, int);
     descriptor: (II)I
     flags: (0x000a) ACC_PRIVATE, ACC_STATIC
@@ -2046,6 +2115,7 @@
     android.hosttest.annotation.HostSideTestWholeClassKeep
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+  com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
 BootstrapMethods:
   x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
     Method arguments:
@@ -2053,8 +2123,9 @@
       #x REF_invokeStatic com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.lambda$nonStaticMethodCallReplaceTester$0:(Ljava/util/concurrent/atomic/AtomicBoolean;)V
       #x ()V
 InnerClasses:
+  public static #x= #x of #x;          // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static #x= #x of #x;          // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-  public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
+  public static final #x= #x of #x;   // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
   Compiled from "TinyFrameworkNative.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
index c918bf8..6a8e488 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
@@ -2002,6 +2002,51 @@
       #x ()Ljava/lang/Integer;
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester.class
+  Compiled from "TinyFrameworkMethodCallReplace.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester
+  minor version: 0
+  major version: 61
+  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+  super_class: #x                         // java/lang/Object
+  interfaces: 0, fields: 1, methods: 1, attributes: 4
+Constant pool:
+{
+  public int i;
+    descriptor: I
+    flags: (0x0001) ACC_PUBLIC
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester(int);
+    descriptor: (I)V
+    flags: (0x0001) ACC_PUBLIC
+    Code:
+      stack=2, locals=2, args_size=2
+         x: aload_0
+         x: invokespecial #x                 // Method java/lang/Object."<init>":()V
+         x: aload_0
+         x: iload_1
+         x: putfield      #x                 // Field i:I
+         x: return
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+            0      10     1     i   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+}
+InnerClasses:
+  public static #x= #x of #x;             // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+SourceFile: "TinyFrameworkMethodCallReplace.java"
+RuntimeVisibleAnnotations:
+  x: #x()
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
   Compiled from "TinyFrameworkMethodCallReplace.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
@@ -2010,7 +2055,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 3, attributes: 4
+  interfaces: 0, fields: 0, methods: 4, attributes: 4
 Constant pool:
 {
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo();
@@ -2065,9 +2110,30 @@
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester newConstructorTester(int);
+    descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=1, args_size=1
+         x: new           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+         x: dup
+         x: iload_0
+         x: iconst_1
+         x: iadd
+         x: invokespecial #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+        x: areturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0      11     0     i   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
-  public static #x= #x of #x;             // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+  public static #x= #x of #x;           // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+  public static #x= #x of #x;            // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 SourceFile: "TinyFrameworkMethodCallReplace.java"
 RuntimeVisibleAnnotations:
   x: #x()
@@ -2081,7 +2147,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 4, attributes: 6
+  interfaces: 0, fields: 0, methods: 6, attributes: 6
 Constant pool:
 {
   public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace();
@@ -2148,6 +2214,48 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
+  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester constructorReplaceTester(int);
+    descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=3, locals=1, args_size=1
+         x: new           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+         x: dup
+         x: iload_0
+         x: invokestatic  #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.newConstructorTester:(I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+         x: swap
+         x: pop
+        x: swap
+        x: pop
+        x: areturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0      13     0     i   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  private static int originalAdd(int, int);
+    descriptor: (II)I
+    flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+    Code:
+      stack=2, locals=2, args_size=2
+         x: iload_0
+         x: iload_1
+         x: iadd
+         x: iconst_1
+         x: isub
+         x: ireturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+            0       6     0     a   I
+            0       6     1     b   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
   private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
     descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
     flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
@@ -2167,6 +2275,7 @@
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
+  public static #x= #x of #x;           // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static #x= #x of #x;            // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
 SourceFile: "TinyFrameworkMethodCallReplace.java"
@@ -2184,6 +2293,7 @@
       #x ()V
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+  com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
   Compiled from "TinyFrameworkNative.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
index 28065bf..d8e7632 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
@@ -2413,6 +2413,66 @@
       #x ()Ljava/lang/Integer;
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester.class
+  Compiled from "TinyFrameworkMethodCallReplace.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester
+  minor version: 0
+  major version: 61
+  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+  this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+  super_class: #x                         // java/lang/Object
+  interfaces: 0, fields: 1, methods: 2, attributes: 4
+Constant pool:
+{
+  public int i;
+    descriptor: I
+    flags: (0x0001) ACC_PUBLIC
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  private static {};
+    descriptor: ()V
+    flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+    Code:
+      stack=2, locals=0, args_size=0
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+         x: ldc           #x                  // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+         x: return
+
+  public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester(int);
+    descriptor: (I)V
+    flags: (0x0001) ACC_PUBLIC
+    Code:
+      stack=4, locals=2, args_size=2
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+         x: ldc           #x                 // String <init>
+         x: ldc           #x                 // String (I)V
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: aload_0
+        x: invokespecial #x                 // Method java/lang/Object."<init>":()V
+        x: aload_0
+        x: iload_1
+        x: putfield      #x                 // Field i:I
+        x: return
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+           11      10     0  this   Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+           11      10     1     i   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+}
+InnerClasses:
+  public static #x= #x of #x;           // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+SourceFile: "TinyFrameworkMethodCallReplace.java"
+RuntimeVisibleAnnotations:
+  x: #x()
+    com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
   Compiled from "TinyFrameworkMethodCallReplace.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
@@ -2421,7 +2481,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 4, attributes: 4
+  interfaces: 0, fields: 0, methods: 5, attributes: 4
 Constant pool:
 {
   private static {};
@@ -2501,8 +2561,34 @@
     RuntimeVisibleAnnotations:
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester newConstructorTester(int);
+    descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=1, args_size=1
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+         x: ldc           #x                 // String newConstructorTester
+         x: ldc           #x                 // String (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: new           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+        x: dup
+        x: iload_0
+        x: iconst_1
+        x: iadd
+        x: invokespecial #x                 // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester."<init>":(I)V
+        x: areturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+           11      11     0     i   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
+  public static #x= #x of #x;          // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static #x= #x of #x;           // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
 SourceFile: "TinyFrameworkMethodCallReplace.java"
 RuntimeVisibleAnnotations:
@@ -2517,7 +2603,7 @@
   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
   this_class: #x                          // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   super_class: #x                         // java/lang/Object
-  interfaces: 0, fields: 0, methods: 5, attributes: 6
+  interfaces: 0, fields: 0, methods: 7, attributes: 6
 Constant pool:
 {
   private static {};
@@ -2609,18 +2695,70 @@
       x: #x()
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 
+  public static com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester constructorReplaceTester(int);
+    descriptor: (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+    Code:
+      stack=4, locals=1, args_size=1
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+         x: ldc           #x                 // String constructorReplaceTester
+         x: ldc           #x                // String (I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: new           #x                 // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
+        x: dup
+        x: iload_0
+        x: invokestatic  #x                // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.newConstructorTester:(I)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester;
+        x: swap
+        x: pop
+        x: swap
+        x: pop
+        x: areturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+           11      13     0     i   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+  private static int originalAdd(int, int);
+    descriptor: (II)I
+    flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+    Code:
+      stack=4, locals=2, args_size=2
+         x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+         x: ldc           #x                // String originalAdd
+         x: ldc           #x                // String (II)I
+         x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+         x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+        x: iload_0
+        x: iload_1
+        x: iadd
+        x: iconst_1
+        x: isub
+        x: ireturn
+      LineNumberTable:
+      LocalVariableTable:
+        Start  Length  Slot  Name   Signature
+           11       6     0     a   I
+           11       6     1     b   I
+    RuntimeVisibleAnnotations:
+      x: #x()
+        com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
   private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
     descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
     flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
     Code:
       stack=4, locals=1, args_size=1
          x: ldc           #x                  // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-         x: ldc           #x                 // String lambda$nonStaticMethodCallReplaceTester$0
-         x: ldc           #x                 // String (Ljava/util/concurrent/atomic/AtomicBoolean;)V
+         x: ldc           #x                // String lambda$nonStaticMethodCallReplaceTester$0
+         x: ldc           #x                // String (Ljava/util/concurrent/atomic/AtomicBoolean;)V
          x: ldc           #x                 // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
          x: invokestatic  #x                 // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
         x: aload_0
-        x: invokestatic  #x                 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
+        x: invokestatic  #x                // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
         x: invokevirtual #x                // Method java/lang/Thread.isDaemon:()Z
         x: invokevirtual #x                // Method java/util/concurrent/atomic/AtomicBoolean.set:(Z)V
         x: return
@@ -2633,6 +2771,7 @@
         com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
 }
 InnerClasses:
+  public static #x= #x of #x;           // ConstructorTester=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static #x= #x of #x;           // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
   public static final #x= #x of #x;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
 SourceFile: "TinyFrameworkMethodCallReplace.java"
@@ -2650,6 +2789,7 @@
       #x ()V
 NestMembers:
   com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
+  com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ConstructorTester
 ## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
   Compiled from "TinyFrameworkNative.java"
 public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt b/ravenwood/tools/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
index 1f64a3c..cbaad2e 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
@@ -68,6 +68,10 @@
 class java.lang.Thread keep
   method start ()V @com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo.startThread
 
+# Used to test constructor replacement.
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ConstructorTester keepclass
+  method <init> (I)V @com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo.newConstructorTester
+
 
 # "rename" takes a type internal name, so '/'s is used as a separator.
 # The leading / in the prefix is not needed (it'll be stripped), but it's added to make
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java
index 57c69a3..d850be8 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java
@@ -41,10 +41,23 @@
         return originalAdd(1, 2);
     }
 
+    public static ConstructorTester constructorReplaceTester(int i) {
+        // This object construction will be replaced with ReplaceTo.newConstructorTester().
+        return new ConstructorTester(i);
+    }
+
     private static int originalAdd(int a, int b) {
         return a + b - 1; // Original is broken.
     }
 
+    public static class ConstructorTester {
+        public int i;
+
+        public ConstructorTester(int i) {
+            this.i = i;
+        }
+    }
+
     public static class ReplaceTo {
         public static void startThread(Thread thread) {
             thread.setDaemon(true);
@@ -54,5 +67,9 @@
         public static int add(int a, int b) {
             return a + b;
         }
+
+        public static ConstructorTester newConstructorTester(int i) {
+            return new ConstructorTester(i + 1);
+        }
     }
 }
diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
index b8d6be4..89fcd30 100644
--- a/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
+++ b/ravenwood/tools/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
@@ -323,4 +323,10 @@
         assertThat(TinyFrameworkMethodCallReplace.staticMethodCallReplaceTester())
                 .isEqualTo(3);
     }
+
+    @Test
+    public void testConstructorCallReplace() throws Exception {
+        assertThat(TinyFrameworkMethodCallReplace.constructorReplaceTester(5).i)
+                .isEqualTo(6);
+    }
 }
diff --git a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt
index b6089ea..a7f481a 100644
--- a/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt
+++ b/ravenwood/tools/ravenhelper/src/com/android/platform/test/ravenwood/ravenhelper/policytoannot/PtaProcessor.kt
@@ -449,7 +449,6 @@
             methodName: String,
             methodDesc: String,
             replaceSpec: TextFilePolicyMethodReplaceFilter.MethodCallReplaceSpec,
-            policy: FilterPolicyWithReason
         ) {
             // This can't be converted to an annotation.
             classHasMember = true
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 4187ee2..5395d2a 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2625,6 +2625,13 @@
                     }
                     notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
                     r.foregroundNoti = notification;
+                    if (r.isForeground && foregroundServiceType != previousFgsType) {
+                        // An already foreground service is being started with a different fgs type
+                        // which results in the type changing without typical startForeground
+                        // logging.
+                        Slog.w(TAG_SERVICE, "FGS type change for " + r.shortInstanceName
+                                + " from " + previousFgsType + " to " + foregroundServiceType);
+                    }
                     mAm.mProcessStateController.setForegroundServiceType(r, foregroundServiceType);
                     if (!r.isForeground) {
                         final ServiceMap smap = getServiceMapLocked(r.userId);
@@ -9191,7 +9198,9 @@
         } else {
             synchronized (mAm.mPidsSelfLocked) {
                 callerApp = mAm.mPidsSelfLocked.get(callingPid);
-                caller = callerApp.getThread();
+                if (callerApp != null) {
+                    caller = callerApp.getThread();
+                }
             }
         }
         if (callerApp == null) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index c8b8909..f7d7ed5 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -3006,7 +3006,7 @@
             UidState uidState = getUidStateLocked(uid, false);
             if (uidState != null) {
                 int rawUidMode = mAppOpsCheckingService.getUidMode(
-                        uidState.uid, getPersistentId(virtualDeviceId), code);
+                        uidState.uid, getPersistentDeviceIdForOp(virtualDeviceId, code), code);
 
                 if (rawUidMode != AppOpsManager.opToDefaultMode(code)) {
                     return raw ? rawUidMode :
@@ -3069,7 +3069,7 @@
 
             int switchCode = AppOpsManager.opToSwitch(code);
             int rawUidMode = mAppOpsCheckingService.getUidMode(uid,
-                    getPersistentId(virtualDeviceId), switchCode);
+                    getPersistentDeviceIdForOp(virtualDeviceId, switchCode), switchCode);
 
             if (rawUidMode != AppOpsManager.opToDefaultMode(switchCode)) {
                 return raw ? rawUidMode : evaluateForegroundMode(uid, switchCode, rawUidMode);
@@ -3396,7 +3396,7 @@
             }
             final Op op = getOpLocked(ops, code, uid, true);
             final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag,
-                    getPersistentId(virtualDeviceId));
+                    getPersistentDeviceIdForOp(virtualDeviceId, code));
             if (attributedOp.isRunning()) {
                 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName + " code "
                         + code + " startTime of in progress event="
@@ -3418,15 +3418,15 @@
 
                 // If there is a non-default per UID policy (we set UID op mode only if
                 // non-default) it takes over, otherwise use the per package policy.
-            } else if (mAppOpsCheckingService.getUidMode(
-                            uidState.uid, getPersistentId(virtualDeviceId), switchCode)
+            } else if (mAppOpsCheckingService.getUidMode(uidState.uid,
+                    getPersistentDeviceIdForOp(virtualDeviceId, switchCode), switchCode)
                     != AppOpsManager.opToDefaultMode(switchCode)) {
                 final int uidMode =
                         uidState.evalMode(
                                 code,
                                 mAppOpsCheckingService.getUidMode(
                                         uidState.uid,
-                                        getPersistentId(virtualDeviceId),
+                                        getPersistentDeviceIdForOp(virtualDeviceId, switchCode),
                                         switchCode));
                 if (uidMode != AppOpsManager.MODE_ALLOWED) {
                     if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
@@ -3478,7 +3478,8 @@
                     virtualDeviceId, flags, AppOpsManager.MODE_ALLOWED);
 
             attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag,
-                    getPersistentId(proxyVirtualDeviceId), uidState.getState(), flags, notedCount);
+                    getPersistentDeviceIdForOp(proxyVirtualDeviceId, code), uidState.getState(),
+                    flags, notedCount);
 
             if (shouldCollectAsyncNotedOp) {
                 collectAsyncNotedOp(uid, packageName, code, attributionTag, flags, message,
@@ -4045,7 +4046,7 @@
             }
             final Op op = getOpLocked(ops, code, uid, true);
             final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag,
-                    getPersistentId(virtualDeviceId));
+                    getPersistentDeviceIdForOp(virtualDeviceId, code));
             final UidState uidState = ops.uidState;
             isRestricted = isOpRestrictedLocked(uid, code, packageName, attributionTag,
                     virtualDeviceId, pvr.bypass, false);
@@ -4058,8 +4059,9 @@
                 // If there is a non-default per UID policy (we set UID op mode only if
                 // non-default) it takes over, otherwise use the per package policy.
             } else if ((rawUidMode =
-                            mAppOpsCheckingService.getUidMode(
-                                    uidState.uid, getPersistentId(virtualDeviceId), switchCode))
+                    mAppOpsCheckingService.getUidMode(
+                            uidState.uid, getPersistentDeviceIdForOp(virtualDeviceId, switchCode),
+                            switchCode))
                     != AppOpsManager.opToDefaultMode(switchCode)) {
                 final int uidMode = uidState.evalMode(code, rawUidMode);
                 if (!shouldStartForMode(uidMode, startIfModeDefault)) {
@@ -4107,11 +4109,13 @@
             try {
                 if (isRestricted) {
                     attributedOp.createPaused(clientId, virtualDeviceId, proxyUid, proxyPackageName,
-                            proxyAttributionTag, getPersistentId(proxyVirtualDeviceId),
+                            proxyAttributionTag,
+                            getPersistentDeviceIdForOp(proxyVirtualDeviceId, code),
                             uidState.getState(), flags, attributionFlags, attributionChainId);
                 } else {
                     attributedOp.started(clientId, virtualDeviceId, proxyUid, proxyPackageName,
-                            proxyAttributionTag, getPersistentId(proxyVirtualDeviceId),
+                            proxyAttributionTag,
+                            getPersistentDeviceIdForOp(proxyVirtualDeviceId, code),
                             uidState.getState(), flags, attributionFlags, attributionChainId);
                     startType = START_TYPE_STARTED;
                 }
@@ -4179,15 +4183,15 @@
             final int switchCode = AppOpsManager.opToSwitch(code);
             // If there is a non-default mode per UID policy (we set UID op mode only if
             // non-default) it takes over, otherwise use the per package policy.
-            if (mAppOpsCheckingService.getUidMode(
-                            uidState.uid, getPersistentId(virtualDeviceId), switchCode)
+            if (mAppOpsCheckingService.getUidMode(uidState.uid,
+                    getPersistentDeviceIdForOp(virtualDeviceId, switchCode), switchCode)
                     != AppOpsManager.opToDefaultMode(switchCode)) {
                 final int uidMode =
                         uidState.evalMode(
                                 code,
                                 mAppOpsCheckingService.getUidMode(
                                         uidState.uid,
-                                        getPersistentId(virtualDeviceId),
+                                        getPersistentDeviceIdForOp(virtualDeviceId, switchCode),
                                         switchCode));
                 if (!shouldStartForMode(uidMode, startIfModeDefault)) {
                     if (DEBUG) {
@@ -4350,7 +4354,8 @@
                 return;
             }
             final AttributedOp attributedOp =
-                    op.mDeviceAttributedOps.getOrDefault(getPersistentId(virtualDeviceId),
+                    op.mDeviceAttributedOps.getOrDefault(
+                            getPersistentDeviceIdForOp(virtualDeviceId, code),
                             new ArrayMap<>()).get(attributionTag);
             if (attributedOp == null) {
                 Slog.e(TAG, "Attribution not found: uid=" + uid + " pkg=" + packageName + "("
@@ -4641,7 +4646,8 @@
             return true;
         }
         if (mVirtualDeviceManagerInternal == null) {
-            return true;
+            Slog.w(TAG, "VirtualDeviceManagerInternal is null when device Id is non-default");
+            return false;
         }
         if (mVirtualDeviceManagerInternal.isValidVirtualDeviceId(virtualDeviceId)) {
             mKnownDeviceIds.put(virtualDeviceId,
@@ -7310,7 +7316,13 @@
         return packageNames;
     }
 
-    @NonNull private String getPersistentId(int virtualDeviceId) {
+    // For ops associated with device aware permissions, if virtual device id is non-default, we
+    // will return string version of that id provided the virtual device has corresponding camera or
+    // audio policy.
+    @NonNull private String getPersistentDeviceIdForOp(int virtualDeviceId, int op) {
+        virtualDeviceId = PermissionManager.resolveDeviceIdForPermissionCheck(mContext,
+                virtualDeviceId, AppOpsManager.opToPermission(op));
+
         if (virtualDeviceId == Context.DEVICE_ID_DEFAULT) {
             return PERSISTENT_DEVICE_ID_DEFAULT;
         }
@@ -7319,6 +7331,7 @@
         }
         String persistentId =
                 mVirtualDeviceManagerInternal.getPersistentIdForDevice(virtualDeviceId);
+
         if (persistentId == null) {
             persistentId = mKnownDeviceIds.get(virtualDeviceId);
         }
diff --git a/services/core/java/com/android/server/display/mode/ModeChangeObserver.java b/services/core/java/com/android/server/display/mode/ModeChangeObserver.java
index bbc13cc..2751835 100644
--- a/services/core/java/com/android/server/display/mode/ModeChangeObserver.java
+++ b/services/core/java/com/android/server/display/mode/ModeChangeObserver.java
@@ -23,8 +23,6 @@
 import android.view.DisplayAddress;
 import android.view.DisplayEventReceiver;
 
-import com.android.internal.annotations.KeepForWeakReference;
-
 import java.util.HashSet;
 import java.util.Set;
 
@@ -35,7 +33,6 @@
     private final DisplayModeDirector.Injector mInjector;
 
     @SuppressWarnings("unused")
-    @KeepForWeakReference
     private DisplayEventReceiver mModeChangeListener;
     private final SparseArray<Set<Integer>> mRejectedModesByDisplay = new SparseArray<>();
     private Looper mLooper;
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index f96846c..acdc79f 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -1067,6 +1067,9 @@
     void doPostDexopt(List<ReconciledPackage> reconciledPackages,
             List<InstallRequest> requests, Map<String, Boolean> createdAppId,
             MoveInfo moveInfo, long acquireTime) {
+        for (InstallRequest request : requests) {
+            request.onWaitDexoptFinished();
+        }
         boolean success = false;
         try {
             if (commitInstallPackages(reconciledPackages)) {
@@ -1218,6 +1221,7 @@
             CompletableFuture<Void> future =
                     DexOptHelper.performDexoptIfNeededAsync(request, mDexManager);
             completableFutures.add(future);
+            request.onWaitDexoptStarted();
         }
 
         if (!completableFutures.isEmpty()) {
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index fbf5db5..7349204 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -1028,6 +1028,18 @@
         }
     }
 
+    public void onWaitDexoptStarted() {
+        if (mPackageMetrics != null) {
+            mPackageMetrics.onStepStarted(PackageMetrics.STEP_WAIT_DEXOPT);
+        }
+    }
+
+    public void onWaitDexoptFinished() {
+        if (mPackageMetrics != null) {
+            mPackageMetrics.onStepFinished(PackageMetrics.STEP_WAIT_DEXOPT);
+        }
+    }
+
     public void onDexoptFinished(DexoptResult dexoptResult) {
         // Only report external profile warnings when installing from adb. The goal is to warn app
         // developers if they have provided bad external profiles, so it's not beneficial to report
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index 994ee42..22da3b2 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -73,6 +73,7 @@
     public static final int STEP_DEXOPT = 5;
     public static final int STEP_FREEZE_INSTALL = 6;
     public static final int STEP_RESTORE = 7;
+    public static final int STEP_WAIT_DEXOPT = 8;
 
     @IntDef(prefix = {"STEP_"}, value = {
             STEP_PREPARE,
@@ -81,7 +82,8 @@
             STEP_COMMIT,
             STEP_DEXOPT,
             STEP_FREEZE_INSTALL,
-            STEP_RESTORE
+            STEP_RESTORE,
+            STEP_WAIT_DEXOPT
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface StepInt {
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 12f5534..58534b9 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -712,13 +712,17 @@
             if (!isMagnifierActivated) {
                 return;
             }
-            // All opening/closing situations.
+            // All opening/closing/recents transitions
+            boolean notify = (flags & TRANSIT_FLAG_IS_RECENTS) != 0;
             switch (type) {
                 case WindowManager.TRANSIT_OPEN:
                 case WindowManager.TRANSIT_TO_FRONT:
                 case WindowManager.TRANSIT_CLOSE:
                 case WindowManager.TRANSIT_TO_BACK:
-                    mUserContextChangedNotifier.onWMTransition(type, flags);
+                    notify = true;
+            }
+            if (notify) {
+                mUserContextChangedNotifier.onWMTransition(type, flags);
             }
         }
 
@@ -1088,8 +1092,7 @@
             // causing the notifying, or the recents/home window is removed, then we won't need the
             // delayed notification anymore.
             void onWMTransition(@TransitionType int type, @TransitionFlags int flags) {
-                if (type == WindowManager.TRANSIT_TO_FRONT
-                        && (flags & TRANSIT_FLAG_IS_RECENTS) != 0) {
+                if ((flags & TRANSIT_FLAG_IS_RECENTS) != 0) {
                     // Delay the recents to front transition notification then send after if needed.
                     mHasDelayedNotificationForRecentsToFrontTransition = true;
                 } else {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 247264f..bdde5fe 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -58,6 +58,7 @@
 import static android.security.Flags.preventIntentRedirectAbortOrThrowException;
 import static android.security.Flags.preventIntentRedirectShowToast;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.TRANSIT_FLAG_AVOID_MOVE_TO_FRONT;
 import static android.view.WindowManager.TRANSIT_NONE;
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -1841,6 +1842,9 @@
             // no-user-leaving implies not entering PiP.
             transition.setCanPipOnFinish(false /* canPipOnFinish */);
         }
+        if (avoidMoveToFront() && transition != null) {
+            transition.addFlag(TRANSIT_FLAG_AVOID_MOVE_TO_FRONT);
+        }
         if (isIndependentLaunch && transition != null) {
             transitionController.requestStartTransition(transition,
                     mTargetTask == null ? started.getTask() : mTargetTask,
diff --git a/services/core/java/com/android/server/wm/ClientLifecycleManager.java b/services/core/java/com/android/server/wm/ClientLifecycleManager.java
index d291d99..98e453b 100644
--- a/services/core/java/com/android/server/wm/ClientLifecycleManager.java
+++ b/services/core/java/com/android/server/wm/ClientLifecycleManager.java
@@ -25,6 +25,7 @@
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
 import android.os.Build;
+import android.os.DeadObjectException;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.Trace;
@@ -66,64 +67,80 @@
     /**
      * Schedules a transaction, which may consist of multiple callbacks and a lifecycle request.
      * @param transaction A sequence of client transaction items.
-     * @throws RemoteException
-     *
+     * @return {@code false} if the transaction failed because of {@link RemoteException}.
      * @see ClientTransaction
      */
     @VisibleForTesting
-    void scheduleTransaction(@NonNull ClientTransaction transaction) throws RemoteException {
-        final IApplicationThread client = transaction.getClient();
-        try {
-            transaction.schedule();
-        } catch (RemoteException e) {
-            Slog.w(TAG, "Failed to deliver transaction for " + client
-                            + "\ntransaction=" + transaction);
-            throw e;
+    boolean scheduleTransaction(@NonNull ClientTransaction transaction) {
+        final RemoteException e = transaction.schedule();
+        if (e != null) {
+            final WindowProcessController wpc = mWms.mAtmService.getProcessController(
+                    transaction.getClient());
+            Slog.w(TAG, "Failed to deliver transaction for " + wpc + "\ntransaction=" + this, e);
+            return false;
         }
+        return true;
     }
 
     /**
      * Similar to {@link #scheduleTransactionItem}, but it sends the transaction immediately and
      * it can be called without WM lock.
      *
+     * @return {@code false} if the transaction failed because of {@link RemoteException}.
      * @see WindowProcessController#setReportedProcState(int)
      */
-    void scheduleTransactionItemNow(@NonNull IApplicationThread client,
+    boolean scheduleTransactionItemNow(@NonNull IApplicationThread client,
             @NonNull ClientTransactionItem transactionItem) throws RemoteException {
         final ClientTransaction clientTransaction = new ClientTransaction(client);
         clientTransaction.addTransactionItem(transactionItem);
-        scheduleTransaction(clientTransaction);
+        final boolean res = scheduleTransaction(clientTransaction);
+        if (!com.android.window.flags.Flags.cleanupDispatchPendingTransactionsRemoteException()
+                && !res) {
+            throw new DeadObjectException();
+        }
+        return res;
     }
 
     /**
-     * Schedules a transaction with the given item, delivery to client application.
+     * Schedules a transaction with the given item, delivery to client application, which may be
+     * queued to dispatched later.
      *
-     * @throws RemoteException
+     * @return {@code false} if the transaction was dispatched immediately, but failed because of
+     *         {@link RemoteException}. If the transaction is queued, any failure will be ignored.
      * @see ClientTransactionItem
      */
-    void scheduleTransactionItem(@NonNull IApplicationThread client,
+    boolean scheduleTransactionItem(@NonNull IApplicationThread client,
             @NonNull ClientTransactionItem item) throws RemoteException {
         // Wait until RootWindowContainer#performSurfacePlacementNoTrace to dispatch all pending
         // transactions at once.
         final ClientTransaction clientTransaction = getOrCreatePendingTransaction(client);
         clientTransaction.addTransactionItem(item);
 
-        onClientTransactionItemScheduled(clientTransaction, false /* shouldDispatchImmediately */);
+        final boolean res = onClientTransactionItemScheduled(clientTransaction,
+                false /* shouldDispatchImmediately */);
+        if (!com.android.window.flags.Flags.cleanupDispatchPendingTransactionsRemoteException()
+                && !res) {
+            throw new DeadObjectException();
+        }
+        return res;
     }
 
     /**
-     * Schedules a transaction with the given items, delivery to client application.
+     * Schedules a transaction with the given items, delivery to client application, which may be
+     * queued to dispatched later.
      *
-     * @throws RemoteException
+     * @return {@code false} if the transaction was dispatched immediately, but failed because of
+     *         {@link RemoteException}. If the transaction is queued, any failure will be ignored.
      * @see ClientTransactionItem
      */
-    void scheduleTransactionItems(@NonNull IApplicationThread client,
+    boolean scheduleTransactionItems(@NonNull IApplicationThread client,
             @NonNull ClientTransactionItem... items) throws RemoteException {
-        scheduleTransactionItems(client, false /* shouldDispatchImmediately */, items);
+        return scheduleTransactionItems(client, false /* shouldDispatchImmediately */, items);
     }
 
     /**
-     * Schedules a transaction with the given items, delivery to client application.
+     * Schedules a transaction with the given items, delivery to client application, which may be
+     * queued to dispatched later.
      *
      * @param shouldDispatchImmediately whether or not to dispatch the transaction immediately. This
      *                                  should only be {@code true} when it is important to know the
@@ -131,11 +148,11 @@
      *                                  launches an app, the server needs to know if the transaction
      *                                  is dispatched successfully, and may restart the process if
      *                                  not.
-     *
-     * @throws RemoteException
+     * @return {@code false} if the transaction was dispatched immediately, but failed because of
+     *         {@link RemoteException}. If the transaction is queued, any failure will be ignored.
      * @see ClientTransactionItem
      */
-    void scheduleTransactionItems(@NonNull IApplicationThread client,
+    boolean scheduleTransactionItems(@NonNull IApplicationThread client,
             boolean shouldDispatchImmediately,
             @NonNull ClientTransactionItem... items) throws RemoteException {
         // Wait until RootWindowContainer#performSurfacePlacementNoTrace to dispatch all pending
@@ -147,7 +164,13 @@
             clientTransaction.addTransactionItem(items[i]);
         }
 
-        onClientTransactionItemScheduled(clientTransaction, shouldDispatchImmediately);
+        final boolean res = onClientTransactionItemScheduled(clientTransaction,
+                shouldDispatchImmediately);
+        if (!com.android.window.flags.Flags.cleanupDispatchPendingTransactionsRemoteException()
+                && !res) {
+            throw new DeadObjectException();
+        }
+        return res;
     }
 
     /** Executes all the pending transactions. */
@@ -159,12 +182,7 @@
         final int size = mPendingTransactions.size();
         for (int i = 0; i < size; i++) {
             final ClientTransaction transaction = mPendingTransactions.valueAt(i);
-            try {
-                scheduleTransaction(transaction);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to deliver pending transaction", e);
-                // TODO(b/323801078): apply cleanup for individual transaction item if needed.
-            }
+            scheduleTransaction(transaction);
         }
         mPendingTransactions.clear();
         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
@@ -174,12 +192,7 @@
     void dispatchPendingTransaction(@NonNull IApplicationThread client) {
         final ClientTransaction pendingTransaction = mPendingTransactions.remove(client.asBinder());
         if (pendingTransaction != null) {
-            try {
-                scheduleTransaction(pendingTransaction);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to deliver pending transaction", e);
-                // TODO(b/323801078): apply cleanup for individual transaction item if needed.
-            }
+            scheduleTransaction(pendingTransaction);
         }
     }
 
@@ -211,15 +224,22 @@
         return transaction;
     }
 
-    /** Must only be called with WM lock. */
-    private void onClientTransactionItemScheduled(
+    /**
+     * Must only be called with WM lock.
+     * If the transaction should not be queued, it will be dispatched immediately.
+     *
+     * @return {@code false} if the transaction was dispatched immediately, but failed because of
+     *         {@link RemoteException}.
+     */
+    private boolean onClientTransactionItemScheduled(
             @NonNull ClientTransaction clientTransaction,
-            boolean shouldDispatchImmediately) throws RemoteException {
+            boolean shouldDispatchImmediately) {
         if (shouldDispatchImmediately || shouldDispatchPendingTransactionsImmediately()) {
             // Dispatch the pending transaction immediately.
             mPendingTransactions.remove(clientTransaction.getClient().asBinder());
-            scheduleTransaction(clientTransaction);
+            return scheduleTransaction(clientTransaction);
         }
+        return true;
     }
 
     /** Must only be called with WM lock. */
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 301a754..9d4fe9e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -41,8 +41,8 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.pm.ApplicationInfo.CATEGORY_SOCIAL;
 import static android.content.pm.ApplicationInfo.CATEGORY_GAME;
+import static android.content.pm.ApplicationInfo.CATEGORY_SOCIAL;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.content.res.Configuration.UI_MODE_TYPE_DESK;
@@ -66,7 +66,6 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
@@ -196,7 +195,7 @@
         // Because the booted state is set, avoid starting real home if there is no task.
         doReturn(false).when(mRootWindowContainer).resumeHomeActivity(any(), anyString(), any());
         // Do not execute the transaction, because we can't verify the parameter after it recycles.
-        doNothing().when(mClientLifecycleManager).scheduleTransaction(any());
+        doReturn(true).when(mClientLifecycleManager).scheduleTransaction(any());
     }
 
     private TestStartingWindowOrganizer registerTestStartingWindowOrganizer() {
@@ -266,7 +265,7 @@
                     break;
                 }
             }
-            return null;
+            return true;
         }).when(mClientLifecycleManager).scheduleTransaction(any());
 
         activity.setState(STOPPED, "testPausingWhenVisibleFromStopped");
diff --git a/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java b/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
index 02ad9db..8d214dd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
@@ -16,11 +16,13 @@
 
 package com.android.server.wm;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -32,17 +34,19 @@
 import android.app.servertransaction.ActivityLifecycleItem;
 import android.app.servertransaction.ClientTransaction;
 import android.app.servertransaction.ClientTransactionItem;
+import android.os.DeadObjectException;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.window.flags.Flags;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -60,15 +64,11 @@
     @Mock
     private IApplicationThread mClient;
     @Mock
-    private IApplicationThread.Stub mNonBinderClient;
-    @Mock
     private ClientTransaction mTransaction;
     @Mock
     private ClientTransactionItem mTransactionItem;
     @Mock
     private ActivityLifecycleItem mLifecycleItem;
-    @Captor
-    private ArgumentCaptor<ClientTransaction> mTransactionCaptor;
 
     private WindowManagerService mWms;
     private ClientLifecycleManager mLifecycleManager;
@@ -83,7 +83,6 @@
 
         doReturn(true).when(mLifecycleItem).isActivityLifecycleItem();
         doReturn(mClientBinder).when(mClient).asBinder();
-        doReturn(mNonBinderClient).when(mNonBinderClient).asBinder();
     }
 
     @Test
@@ -91,13 +90,11 @@
         spyOn(mWms.mWindowPlacerLocked);
         doReturn(true).when(mWms.mWindowPlacerLocked).isTraversalScheduled();
 
-        // Use non binder client to get non-recycled ClientTransaction.
-        mLifecycleManager.scheduleTransactionItem(mNonBinderClient, mTransactionItem);
+        mLifecycleManager.scheduleTransactionItem(mClient, mTransactionItem);
 
         // When there is traversal scheduled, add transaction items to pending.
         assertEquals(1, mLifecycleManager.mPendingTransactions.size());
-        ClientTransaction transaction =
-                mLifecycleManager.mPendingTransactions.get(mNonBinderClient);
+        ClientTransaction transaction = mLifecycleManager.mPendingTransactions.get(mClientBinder);
         assertEquals(1, transaction.getTransactionItems().size());
         assertEquals(mTransactionItem, transaction.getTransactionItems().get(0));
         // TODO(b/324203798): cleanup after remove UnsupportedAppUsage
@@ -108,10 +105,10 @@
 
         // Add new transaction item to the existing pending.
         clearInvocations(mLifecycleManager);
-        mLifecycleManager.scheduleTransactionItem(mNonBinderClient, mLifecycleItem);
+        mLifecycleManager.scheduleTransactionItem(mClient, mLifecycleItem);
 
         assertEquals(1, mLifecycleManager.mPendingTransactions.size());
-        transaction = mLifecycleManager.mPendingTransactions.get(mNonBinderClient);
+        transaction = mLifecycleManager.mPendingTransactions.get(mClientBinder);
         assertEquals(2, transaction.getTransactionItems().size());
         assertEquals(mTransactionItem, transaction.getTransactionItems().get(0));
         assertEquals(mLifecycleItem, transaction.getTransactionItems().get(1));
@@ -124,8 +121,7 @@
 
     @Test
     public void testScheduleTransactionItemNow() throws RemoteException {
-        // Use non binder client to get non-recycled ClientTransaction.
-        mLifecycleManager.scheduleTransactionItemNow(mNonBinderClient, mTransactionItem);
+        mLifecycleManager.scheduleTransactionItemNow(mClient, mTransactionItem);
 
         // Dispatch immediately.
         assertTrue(mLifecycleManager.mPendingTransactions.isEmpty());
@@ -137,13 +133,11 @@
         spyOn(mWms.mWindowPlacerLocked);
         doReturn(true).when(mWms.mWindowPlacerLocked).isTraversalScheduled();
 
-        // Use non binder client to get non-recycled ClientTransaction.
-        mLifecycleManager.scheduleTransactionItems(mNonBinderClient, mTransactionItem,
-                mLifecycleItem);
+        mLifecycleManager.scheduleTransactionItems(mClient, mTransactionItem, mLifecycleItem);
 
         assertEquals(1, mLifecycleManager.mPendingTransactions.size());
         final ClientTransaction transaction =
-                mLifecycleManager.mPendingTransactions.get(mNonBinderClient);
+                mLifecycleManager.mPendingTransactions.get(mClientBinder);
         assertEquals(2, transaction.getTransactionItems().size());
         assertEquals(mTransactionItem, transaction.getTransactionItems().get(0));
         assertEquals(mLifecycleItem, transaction.getTransactionItems().get(1));
@@ -160,8 +154,8 @@
         spyOn(mWms.mWindowPlacerLocked);
         doReturn(true).when(mWms.mWindowPlacerLocked).isTraversalScheduled();
 
-        // Use non binder client to get non-recycled ClientTransaction.
-        mLifecycleManager.scheduleTransactionItems(mNonBinderClient,
+        mLifecycleManager.scheduleTransactionItems(
+                mClient,
                 true /* shouldDispatchImmediately */,
                 mTransactionItem, mLifecycleItem);
 
@@ -187,7 +181,7 @@
         doReturn(true).when(mWms.mWindowPlacerLocked).isLayoutDeferred();
 
         // Queue transactions during layout deferred.
-        mLifecycleManager.scheduleTransactionItem(mNonBinderClient, mLifecycleItem);
+        mLifecycleManager.scheduleTransactionItem(mClient, mLifecycleItem);
 
         verify(mLifecycleManager, never()).scheduleTransaction(any());
 
@@ -203,4 +197,42 @@
 
         verify(mLifecycleManager).scheduleTransaction(any());
     }
+
+    @EnableFlags(Flags.FLAG_CLEANUP_DISPATCH_PENDING_TRANSACTIONS_REMOTE_EXCEPTION)
+    @Test
+    public void testOnRemoteException_returnTrueOnSuccess() throws RemoteException {
+        final boolean res = mLifecycleManager.scheduleTransactionItemNow(mClient, mTransactionItem);
+
+        assertTrue(res);
+    }
+
+    @EnableFlags(Flags.FLAG_CLEANUP_DISPATCH_PENDING_TRANSACTIONS_REMOTE_EXCEPTION)
+    @Test
+    public void testOnRemoteException_returnFalseOnFailure() throws RemoteException {
+        final DeadObjectException e = new DeadObjectException();
+        doThrow(e).when(mClient).scheduleTransaction(any());
+
+        // No exception when flag enabled.
+        final boolean res = mLifecycleManager.scheduleTransactionItemNow(mClient, mTransactionItem);
+
+        assertFalse(res);
+    }
+
+    @EnableFlags(Flags.FLAG_CLEANUP_DISPATCH_PENDING_TRANSACTIONS_REMOTE_EXCEPTION)
+    @Test
+    public void testOnRemoteException_returnTrueForQueueing() throws RemoteException {
+        spyOn(mWms.mWindowPlacerLocked);
+        doReturn(true).when(mWms.mWindowPlacerLocked).isLayoutDeferred();
+        final DeadObjectException e = new DeadObjectException();
+        doThrow(e).when(mClient).scheduleTransaction(any());
+
+        final boolean res = mLifecycleManager.scheduleTransactionItem(mClient, mTransactionItem);
+
+        assertTrue(res);
+
+        doReturn(false).when(mWms.mWindowPlacerLocked).isLayoutDeferred();
+        mLifecycleManager.onLayoutContinued();
+
+        verify(mLifecycleManager).scheduleTransaction(any());
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index d228970..9dc7026 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -24,7 +24,6 @@
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -295,7 +294,7 @@
 
     @Test
     public void testCachedStateConfigurationChange() throws RemoteException {
-        doNothing().when(mClientLifecycleManager).scheduleTransactionItemNow(any(), any());
+        doReturn(true).when(mClientLifecycleManager).scheduleTransactionItemNow(any(), any());
         final IApplicationThread thread = mWpc.getThread();
         final Configuration newConfig = new Configuration(mWpc.getConfiguration());
         newConfig.densityDpi += 100;
diff --git a/tests/AppJankTest/src/android/app/jank/tests/JankTrackerTest.java b/tests/AppJankTest/src/android/app/jank/tests/JankTrackerTest.java
index 1bdf019..9d87fbd 100644
--- a/tests/AppJankTest/src/android/app/jank/tests/JankTrackerTest.java
+++ b/tests/AppJankTest/src/android/app/jank/tests/JankTrackerTest.java
@@ -18,10 +18,12 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 import android.app.jank.Flags;
 import android.app.jank.JankTracker;
 import android.app.jank.StateTracker;
+import android.content.Context;
 import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -55,10 +57,9 @@
      * Start an empty activity so decore view is not null when creating the JankTracker instance.
      */
     private static ActivityScenario<EmptyActivity> sEmptyActivityRule;
-
     private static String sActivityName;
-
     private static View sActivityDecorView;
+    private static Context sContext;
 
     @BeforeClass
     public static void classSetup() {
@@ -66,6 +67,7 @@
         sEmptyActivityRule.onActivity(activity -> {
             sActivityDecorView = activity.getWindow().getDecorView();
             sActivityName = activity.toString();
+            sContext = activity.getApplicationContext();
         });
     }
 
@@ -168,4 +170,14 @@
 
         assertNotNull(jankTracker);
     }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API)
+    public void jankTracker_IsNull_WhenViewNotInHierarchy() {
+        TestWidget testWidget = new TestWidget(sContext);
+        JankTracker jankTracker = testWidget.getJankTracker();
+
+        assertNull(jankTracker);
+    }
+
 }