Merge "Fix fingerprint on lockscreen preivew" into udc-dev
diff --git a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
index ce381b6..e08200b 100644
--- a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
+++ b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
@@ -22,7 +22,6 @@
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.PackageOps;
 import android.app.IActivityManager;
-import android.app.UidObserver;
 import android.app.usage.UsageStatsManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -54,6 +53,7 @@
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.StatLogger;
+import com.android.modules.expresslog.Counter;
 import com.android.server.AppStateTrackerProto.ExemptedPackage;
 import com.android.server.AppStateTrackerProto.RunAnyInBackgroundRestrictedPackages;
 import com.android.server.usage.AppStandbyInternal;
@@ -79,6 +79,9 @@
 public class AppStateTrackerImpl implements AppStateTracker {
     private static final boolean DEBUG = false;
 
+    private static final String APP_RESTRICTION_COUNTER_METRIC_ID =
+            "battery.value_app_background_restricted";
+
     private final Object mLock = new Object();
     private final Context mContext;
 
@@ -748,6 +751,9 @@
             } catch (RemoteException e) {
                 // Shouldn't happen
             }
+            if (restricted) {
+                Counter.logIncrementWithUid(APP_RESTRICTION_COUNTER_METRIC_ID, uid);
+            }
             synchronized (mLock) {
                 if (updateForcedAppStandbyUidPackageLocked(uid, packageName, restricted)) {
                     mHandler.notifyRunAnyAppOpsChanged(uid, packageName);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index c540517..0a7bffc 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -49,8 +49,10 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.BitUtils;
+import com.android.modules.expresslog.Histogram;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.IoThread;
 import com.android.server.job.JobSchedulerInternal.JobStorePersistStats;
 import com.android.server.job.controllers.JobStatus;
@@ -94,6 +96,7 @@
 
     /** Threshold to adjust how often we want to write to the db. */
     private static final long JOB_PERSIST_DELAY = 2000L;
+    private static final long SCHEDULED_JOB_HIGH_WATER_MARK_PERIOD_MS = 30 * 60_000L;
     @VisibleForTesting
     static final String JOB_FILE_SPLIT_PREFIX = "jobs_";
     private static final int ALL_UIDS = -1;
@@ -131,6 +134,30 @@
 
     private JobStorePersistStats mPersistInfo = new JobStorePersistStats();
 
+    /**
+     * Separately updated value of the JobSet size to avoid recalculating it frequently for logging
+     * purposes. Continue to use {@link JobSet#size()} for the up-to-date and accurate value.
+     */
+    private int mCurrentJobSetSize = 0;
+    private int mScheduledJob30MinHighWaterMark = 0;
+    private static final Histogram sScheduledJob30MinHighWaterMarkLogger = new Histogram(
+            "job_scheduler.value_hist_scheduled_job_30_min_high_water_mark",
+            new Histogram.ScaledRangeOptions(15, 1, 99, 1.5f));
+    private final Runnable mScheduledJobHighWaterMarkLoggingRunnable = new Runnable() {
+        @Override
+        public void run() {
+            AppSchedulingModuleThread.getHandler().removeCallbacks(this);
+            synchronized (mLock) {
+                sScheduledJob30MinHighWaterMarkLogger.logSample(mScheduledJob30MinHighWaterMark);
+                mScheduledJob30MinHighWaterMark = mJobSet.size();
+            }
+            // The count doesn't need to be logged at exact times. Logging based on system uptime
+            // should be fine.
+            AppSchedulingModuleThread.getHandler()
+                    .postDelayed(this, SCHEDULED_JOB_HIGH_WATER_MARK_PERIOD_MS);
+        }
+    };
+
     /** Used by the {@link JobSchedulerService} to instantiate the JobStore. */
     static JobStore get(JobSchedulerService jobManagerService) {
         synchronized (sSingletonLock) {
@@ -183,6 +210,9 @@
         mXmlTimestamp = mJobsFile.exists()
                 ? mJobsFile.getLastModifiedTime() : mJobFileDirectory.lastModified();
         mRtcGood = (sSystemClock.millis() > mXmlTimestamp);
+
+        AppSchedulingModuleThread.getHandler().postDelayed(
+                mScheduledJobHighWaterMarkLoggingRunnable, SCHEDULED_JOB_HIGH_WATER_MARK_PERIOD_MS);
     }
 
     private void init() {
@@ -252,7 +282,10 @@
      * @param jobStatus Job to add.
      */
     public void add(JobStatus jobStatus) {
-        mJobSet.add(jobStatus);
+        if (mJobSet.add(jobStatus)) {
+            mCurrentJobSetSize++;
+            maybeUpdateHighWaterMark();
+        }
         if (jobStatus.isPersisted()) {
             mPendingJobWriteUids.put(jobStatus.getUid(), true);
             maybeWriteStatusToDiskAsync();
@@ -267,7 +300,10 @@
      */
     @VisibleForTesting
     public void addForTesting(JobStatus jobStatus) {
-        mJobSet.add(jobStatus);
+        if (mJobSet.add(jobStatus)) {
+            mCurrentJobSetSize++;
+            maybeUpdateHighWaterMark();
+        }
         if (jobStatus.isPersisted()) {
             mPendingJobWriteUids.put(jobStatus.getUid(), true);
         }
@@ -303,6 +339,7 @@
             }
             return false;
         }
+        mCurrentJobSetSize--;
         if (removeFromPersisted && jobStatus.isPersisted()) {
             mPendingJobWriteUids.put(jobStatus.getUid(), true);
             maybeWriteStatusToDiskAsync();
@@ -315,7 +352,9 @@
      */
     @VisibleForTesting
     public void removeForTesting(JobStatus jobStatus) {
-        mJobSet.remove(jobStatus);
+        if (mJobSet.remove(jobStatus)) {
+            mCurrentJobSetSize--;
+        }
         if (jobStatus.isPersisted()) {
             mPendingJobWriteUids.put(jobStatus.getUid(), true);
         }
@@ -327,6 +366,7 @@
      */
     public void removeJobsOfUnlistedUsers(int[] keepUserIds) {
         mJobSet.removeJobsOfUnlistedUsers(keepUserIds);
+        mCurrentJobSetSize = mJobSet.size();
     }
 
     /** Note a change in the specified JobStatus that necessitates writing job state to disk. */
@@ -342,6 +382,7 @@
     public void clear() {
         mJobSet.clear();
         mPendingJobWriteUids.put(ALL_UIDS, true);
+        mCurrentJobSetSize = 0;
         maybeWriteStatusToDiskAsync();
     }
 
@@ -352,6 +393,7 @@
     public void clearForTesting() {
         mJobSet.clear();
         mPendingJobWriteUids.put(ALL_UIDS, true);
+        mCurrentJobSetSize = 0;
     }
 
     void setUseSplitFiles(boolean useSplitFiles) {
@@ -442,6 +484,12 @@
         mJobSet.forEachJobForSourceUid(sourceUid, functor);
     }
 
+    private void maybeUpdateHighWaterMark() {
+        if (mScheduledJob30MinHighWaterMark < mCurrentJobSetSize) {
+            mScheduledJob30MinHighWaterMark = mCurrentJobSetSize;
+        }
+    }
+
     /** Version of the db schema. */
     private static final int JOBS_FILE_VERSION = 1;
     /**
@@ -1125,6 +1173,12 @@
             if (needFileMigration) {
                 migrateJobFilesAsync();
             }
+
+            // Log the count immediately after loading from boot.
+            mCurrentJobSetSize = numJobs;
+            mScheduledJob30MinHighWaterMark = mCurrentJobSetSize;
+            mScheduledJobHighWaterMarkLoggingRunnable.run();
+
             if (mCompletionLatch != null) {
                 mCompletionLatch.countDown();
             }
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 9346223..e42e526 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2367,6 +2367,7 @@
     method public static boolean isApp(int);
     field public static final int MIN_SECONDARY_USER_ID = 10; // 0xa
     field public static final int USER_ALL = -1; // 0xffffffff
+    field public static final int USER_CURRENT = -2; // 0xfffffffe
     field public static final int USER_NULL = -10000; // 0xffffd8f0
     field public static final int USER_SYSTEM = 0; // 0x0
   }
@@ -2375,10 +2376,12 @@
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createProfileForUser(@Nullable String, @NonNull String, int, int, @Nullable String[]);
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createRestrictedProfile(@Nullable String);
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createUser(@Nullable String, @NonNull String, int);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.content.pm.UserInfo> getAliveUsers();
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle getBootUser();
     method public int getMainDisplayIdAssignedToUser();
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.Set<java.lang.String> getPreInstallableSystemPackages(@NonNull String);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public String getUserType();
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.content.pm.UserInfo> getUsers();
     method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.content.pm.UserInfo> getUsers(boolean, boolean, boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean hasBaseUserRestriction(@NonNull String, @NonNull android.os.UserHandle);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean isUserTypeEnabled(@NonNull String);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 9e59ee4..0e5cbe2 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -60,13 +60,16 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.DeviceConfig;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.LongSparseLongArray;
 import android.util.Pools;
+import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
@@ -179,6 +182,8 @@
  */
 @SystemService(Context.APP_OPS_SERVICE)
 public class AppOpsManager {
+    private static final String LOG_TAG = "AppOpsManager";
+
     /**
      * This is a subtle behavior change to {@link #startWatchingMode}.
      *
@@ -7517,6 +7522,7 @@
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setUidMode(int code, int uid, @Mode int mode) {
+        logAnySeriousModeChanges(code, uid, null, mode);
         try {
             mService.setUidMode(code, uid, mode);
         } catch (RemoteException e) {
@@ -7537,6 +7543,7 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setUidMode(@NonNull String appOp, int uid, @Mode int mode) {
+        logAnySeriousModeChanges(strOpToOp(appOp), uid, null, mode);
         try {
             mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
         } catch (RemoteException e) {
@@ -7572,11 +7579,32 @@
         }
     }
 
+    private void logAnySeriousModeChanges(int code, int uid, String packageName, @Mode int mode) {
+        // TODO (b/280869337): Remove this once we have the required data.
+        if (code != OP_RUN_ANY_IN_BACKGROUND || mode == MODE_ALLOWED) {
+            return;
+        }
+        final StringBuilder log = new StringBuilder("Attempt to change RUN_ANY_IN_BACKGROUND to ")
+                .append(modeToName(mode))
+                .append(" for uid: ")
+                .append(UserHandle.formatUid(uid))
+                .append(" package: ")
+                .append(packageName)
+                .append(" by: ")
+                .append(mContext.getOpPackageName());
+        if (Process.myUid() == Process.SYSTEM_UID) {
+            Slog.wtfStack(LOG_TAG, log.toString());
+        } else {
+            Log.w(LOG_TAG, log.toString());
+        }
+    }
+
     /** @hide */
     @UnsupportedAppUsage
     @TestApi
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setMode(int code, int uid, String packageName, @Mode int mode) {
+        logAnySeriousModeChanges(code, uid, packageName, mode);
         try {
             mService.setMode(code, uid, packageName, mode);
         } catch (RemoteException e) {
@@ -7599,6 +7627,7 @@
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setMode(@NonNull String op, int uid, @Nullable String packageName,
             @Mode int mode) {
+        logAnySeriousModeChanges(strOpToOp(op), uid, packageName, mode);
         try {
             mService.setMode(strOpToOp(op), uid, packageName, mode);
         } catch (RemoteException e) {
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 27270d9..d6592d5 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -765,10 +765,6 @@
     @Nullable
     public PendingIntent getMainActivityLaunchIntent(@NonNull ComponentName component,
             @Nullable Bundle startActivityOptions, @NonNull UserHandle user) {
-        if (mContext.checkSelfPermission(android.Manifest.permission.START_TASKS_FROM_RECENTS)
-                != PackageManager.PERMISSION_GRANTED) {
-            Log.w(TAG, "Only allowed for recents.");
-        }
         logErrorForInvalidProfileAccess(user);
         if (DEBUG) {
             Log.i(TAG, "GetMainActivityLaunchIntent " + component + " " + user);
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index a89d17b..50be5c4 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -91,7 +91,7 @@
     /**
      * The version name of this package, as specified by the &lt;manifest&gt;
      * tag's {@link android.R.styleable#AndroidManifest_versionName versionName}
-     * attribute.
+     * attribute, or null if there was none.
      */
     public String versionName;
 
diff --git a/core/java/android/credentials/ui/RequestInfo.java b/core/java/android/credentials/ui/RequestInfo.java
index 9ebb058..3fc3be5 100644
--- a/core/java/android/credentials/ui/RequestInfo.java
+++ b/core/java/android/credentials/ui/RequestInfo.java
@@ -52,6 +52,12 @@
     @NonNull public static final String TYPE_UNDEFINED = "android.credentials.ui.TYPE_UNDEFINED";
     /** Type value for a getCredential request. */
     @NonNull public static final String TYPE_GET = "android.credentials.ui.TYPE_GET";
+    /** Type value for a getCredential request that utilizes the credential registry.
+     *
+     * @hide
+     **/
+    @NonNull public static final String TYPE_GET_VIA_REGISTRY =
+            "android.credentials.ui.TYPE_GET_VIA_REGISTRY";
     /** Type value for a createCredential request. */
     @NonNull public static final String TYPE_CREATE = "android.credentials.ui.TYPE_CREATE";
 
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index 069c264..dcf1a47 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -1136,7 +1136,10 @@
         Printer indentedPrinter = PrefixPrinter.create(printer, "    ");
         synchronized (mLock) {
             if (directories != null) {
-                directories.add(new File(mConfiguration.path).getParent());
+                String parent = new File(mConfiguration.path).getParent();
+                if (parent != null) {
+                    directories.add(parent);
+                }
             }
             boolean isCompatibilityWalEnabled = mConfiguration.isLegacyCompatibilityWalEnabled();
             printer.println("Connection pool for " + mConfiguration.path + ":");
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index 6cd32ff..17bbe14 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -233,7 +233,7 @@
      */
     public static boolean useTouchpadNaturalScrolling(@NonNull Context context) {
         return Settings.System.getIntForUser(context.getContentResolver(),
-                Settings.System.TOUCHPAD_NATURAL_SCROLLING, 0, UserHandle.USER_CURRENT) == 1;
+                Settings.System.TOUCHPAD_NATURAL_SCROLLING, 1, UserHandle.USER_CURRENT) == 1;
     }
 
     /**
diff --git a/core/java/android/hardware/radio/TunerCallbackAdapter.java b/core/java/android/hardware/radio/TunerCallbackAdapter.java
index 22f5902..f9a2dbb 100644
--- a/core/java/android/hardware/radio/TunerCallbackAdapter.java
+++ b/core/java/android/hardware/radio/TunerCallbackAdapter.java
@@ -144,6 +144,9 @@
 
         int errorCode;
         switch (status) {
+            case RadioTuner.TUNER_RESULT_CANCELED:
+                errorCode = RadioTuner.ERROR_CANCELLED;
+                break;
             case RadioManager.STATUS_PERMISSION_DENIED:
             case RadioManager.STATUS_DEAD_OBJECT:
                 errorCode = RadioTuner.ERROR_SERVER_DIED;
@@ -152,10 +155,16 @@
             case RadioManager.STATUS_NO_INIT:
             case RadioManager.STATUS_BAD_VALUE:
             case RadioManager.STATUS_INVALID_OPERATION:
+            case RadioTuner.TUNER_RESULT_INTERNAL_ERROR:
+            case RadioTuner.TUNER_RESULT_INVALID_ARGUMENTS:
+            case RadioTuner.TUNER_RESULT_INVALID_STATE:
+            case RadioTuner.TUNER_RESULT_NOT_SUPPORTED:
+            case RadioTuner.TUNER_RESULT_UNKNOWN_ERROR:
                 Log.i(TAG, "Got an error with no mapping to the legacy API (" + status
                         + "), doing a best-effort conversion to ERROR_SCAN_TIMEOUT");
             // fall through
             case RadioManager.STATUS_TIMED_OUT:
+            case RadioTuner.TUNER_RESULT_TIMEOUT:
             default:
                 errorCode = RadioTuner.ERROR_SCAN_TIMEOUT;
         }
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 301b412..bfff4db 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -2306,7 +2306,7 @@
         Looper looper = handler != null ? handler.getLooper() : Looper.getMainLooper();
         try {
             return new SoundTriggerModule(getService(), moduleId, listener, looper,
-                    middlemanIdentity, originatorIdentity);
+                    middlemanIdentity, originatorIdentity, false);
         } catch (Exception e) {
             Log.e(TAG, "", e);
             return null;
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
index 48d4ea4..8813a17 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
@@ -83,7 +83,8 @@
      */
     public SoundTriggerModule(@NonNull ISoundTriggerMiddlewareService service,
             int moduleId, @NonNull SoundTrigger.StatusListener listener, @NonNull Looper looper,
-            @NonNull Identity middlemanIdentity, @NonNull Identity originatorIdentity) {
+            @NonNull Identity middlemanIdentity, @NonNull Identity originatorIdentity,
+            boolean isTrusted) {
         mId = moduleId;
         mEventHandlerDelegate = new EventHandlerDelegate(listener, looper);
 
@@ -91,7 +92,8 @@
             try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                 mService = service.attachAsMiddleman(moduleId, middlemanIdentity,
                         originatorIdentity,
-                        mEventHandlerDelegate);
+                        mEventHandlerDelegate,
+                        isTrusted);
             }
             mService.asBinder().linkToDeath(mEventHandlerDelegate, 0);
         } catch (RemoteException e) {
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 2c31e32..94971b8 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -107,42 +107,22 @@
     private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER = 2;
     private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_OFF = 3;
 
-    // System properties related to ANGLE and legacy GLES graphics drivers.
-    private static final String PROPERTY_EGL_SYSTEM_DRIVER = "ro.hardware.egl";
-    // TODO (b/224558229): Properly add this to the list of system properties for a device:
-    private static final String PROPERTY_EGL_LEGACY_DRIVER = "ro.hardware.egl_legacy";
-
     // Values for ANGLE_GL_DRIVER_ALL_ANGLE
     private static final int ANGLE_GL_DRIVER_ALL_ANGLE_ON = 1;
     private static final int ANGLE_GL_DRIVER_ALL_ANGLE_OFF = 0;
-    private static final int ANGLE_GL_DRIVER_ALL_LEGACY = -1;
 
     // Values for ANGLE_GL_DRIVER_SELECTION_VALUES
     private static final String ANGLE_GL_DRIVER_CHOICE_DEFAULT = "default";
     private static final String ANGLE_GL_DRIVER_CHOICE_ANGLE = "angle";
-    private static final String ANGLE_GL_DRIVER_CHOICE_LEGACY = "legacy";
-    // The following value is a deprecated choice for "legacy"
     private static final String ANGLE_GL_DRIVER_CHOICE_NATIVE = "native";
 
-    // Values returned by getDriverForPackage() and getDefaultDriverToUse() (avoid returning
-    // strings for performance reasons)
-    private static final int ANGLE_GL_DRIVER_TO_USE_LEGACY = 0;
-    private static final int ANGLE_GL_DRIVER_TO_USE_ANGLE = 1;
-
     private ClassLoader mClassLoader;
     private String mLibrarySearchPaths;
     private String mLibraryPermittedPaths;
     private GameManager mGameManager;
 
-    private boolean mAngleIsSystemDriver = false;
-    private boolean mNoLegacyDriver = false;
-    // When ANGLE is the system driver, this is the name of the legacy driver.
-    //
-    // TODO (b/224558229): This is temporarily set to a value that works for testing, until
-    // PROPERTY_EGL_LEGACY_DRIVER has been properly plumbed and this becomes broadly available.
-    private String mEglLegacyDriver = "mali";
-
     private int mAngleOptInIndex = -1;
+    private boolean mEnabledByGameMode = false;
 
     /**
      * Set up GraphicsEnvironment
@@ -159,24 +139,6 @@
         setupGpuLayers(context, coreSettings, pm, packageName, appInfoWithMetaData);
         Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
 
-        // Determine if ANGLE is the system driver, as this will determine other logic
-        final String eglSystemDriver = SystemProperties.get(PROPERTY_EGL_SYSTEM_DRIVER);
-        Log.v(TAG, "GLES system driver is '" + eglSystemDriver + "'");
-        mAngleIsSystemDriver = eglSystemDriver.equals(ANGLE_DRIVER_NAME);
-        if (mAngleIsSystemDriver) {
-            // Lookup the legacy driver, to send down to the EGL loader
-            final String eglLegacyDriver = SystemProperties.get(PROPERTY_EGL_LEGACY_DRIVER);
-            if (eglLegacyDriver.isEmpty()) {
-                mNoLegacyDriver = true;
-                // TBD/TODO: Do we need this?:
-                mEglLegacyDriver = eglSystemDriver;
-            }
-        } else {
-            // TBD/TODO: Do we need this?:
-            mEglLegacyDriver = eglSystemDriver;
-        }
-        Log.v(TAG, "Legacy GLES driver is '" + mEglLegacyDriver + "'");
-
         // Setup ANGLE and pass down ANGLE details to the C++ code
         Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setupAngle");
         boolean useAngle = false;
@@ -185,10 +147,6 @@
                 useAngle = true;
                 setGpuStats(ANGLE_DRIVER_NAME, ANGLE_DRIVER_VERSION_NAME, ANGLE_DRIVER_VERSION_CODE,
                         0, packageName, getVulkanVersion(pm));
-            } else if (mNoLegacyDriver) {
-                // TBD: The following should never happen--does it?
-                Log.e(TAG, "Unexpected problem with the ANGLE for use with: '" + packageName + "'");
-                useAngle = true;
             }
         }
         Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
@@ -242,12 +200,10 @@
     private boolean shouldUseAngle(Context context, Bundle coreSettings, String packageName) {
         if (TextUtils.isEmpty(packageName)) {
             Log.v(TAG, "No package name specified; use the system driver");
-            return mAngleIsSystemDriver ? true : false;
+            return false;
         }
 
-        final int driverToUse = getDriverForPackage(context, coreSettings, packageName);
-        boolean yesOrNo = driverToUse == ANGLE_GL_DRIVER_TO_USE_ANGLE;
-        return yesOrNo;
+        return shouldUseAngleInternal(context, coreSettings, packageName);
     }
 
     private int getVulkanVersion(PackageManager pm) {
@@ -455,43 +411,25 @@
         return ai;
     }
 
-    /**
-     * Return the appropriate "default" driver, unless overridden by isAngleEnabledByGameMode().
-     */
-    private int getDefaultDriverToUse(Context context, String packageName) {
-        if (mAngleIsSystemDriver || isAngleEnabledByGameMode(context, packageName)) {
-            return ANGLE_GL_DRIVER_TO_USE_ANGLE;
-        } else {
-            return ANGLE_GL_DRIVER_TO_USE_LEGACY;
-        }
-    }
-
     /*
      * Determine which GLES "driver" should be used for the package, taking into account the
      * following factors (in priority order):
      *
      * 1) The semi-global switch (i.e. Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE; which is set by
      *    the "angle_gl_driver_all_angle" setting; which forces a driver for all processes that
-     *    start after the Java run time is up), if it forces a choice; otherwise ...
+     *    start after the Java run time is up), if it forces a choice;
      * 2) The per-application switch (i.e. Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS and
      *    Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES; which corresponds to the
      *    “angle_gl_driver_selection_pkgs” and “angle_gl_driver_selection_values” settings); if it
      *    forces a choice;
-     *      - Workaround Note: ANGLE and Vulkan currently have issues with applications that use YUV
-     *        target functionality.  The ANGLE broadcast receiver code will apply a "deferlist" at
-     *        the first boot of a newly-flashed device.  However, there is a gap in time between
-     *        when applications can start and when the deferlist is applied.  For now, assume that
-     *        if ANGLE is the system driver and Settings.Global.ANGLE_DEFERLIST is empty, that the
-     *        deferlist has not yet been applied.  In this case, select the Legacy driver.
-     *    otherwise ...
-     * 3) Use ANGLE if isAngleEnabledByGameMode() returns true; otherwise ...
-     * 4) The global switch (i.e. use the system driver, whether ANGLE or legacy;
-     *    a.k.a. mAngleIsSystemDriver, which is set by the device’s “ro.hardware.egl” property)
-     *
-     * Factors 1 and 2 are decided by this method.  Factors 3 and 4 are decided by
-     * getDefaultDriverToUse().
+     * 3) Use ANGLE if isAngleEnabledByGameMode() returns true;
      */
-    private int getDriverForPackage(Context context, Bundle bundle, String packageName) {
+    private boolean shouldUseAngleInternal(Context context, Bundle bundle, String packageName) {
+        // Make sure we have a good package name
+        if (TextUtils.isEmpty(packageName)) {
+            return false;
+        }
+
         // Check the semi-global switch (i.e. once system has booted enough) for whether ANGLE
         // should be forced on or off for "all appplications"
         final int allUseAngle;
@@ -504,16 +442,7 @@
         }
         if (allUseAngle == ANGLE_GL_DRIVER_ALL_ANGLE_ON) {
             Log.v(TAG, "Turn on ANGLE for all applications.");
-            return ANGLE_GL_DRIVER_TO_USE_ANGLE;
-        }
-        if (allUseAngle == ANGLE_GL_DRIVER_ALL_LEGACY) {
-            Log.v(TAG, "Disable ANGLE for all applications.");
-            return ANGLE_GL_DRIVER_TO_USE_LEGACY;
-        }
-
-        // Make sure we have a good package name
-        if (TextUtils.isEmpty(packageName)) {
-            return getDefaultDriverToUse(context, packageName);
+            return true;
         }
 
         // Get the per-application settings lists
@@ -522,61 +451,46 @@
                 contentResolver, bundle, Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS);
         final List<String> optInValues = getGlobalSettingsString(
                 contentResolver, bundle, Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES);
-        final List<String> angleDeferlist = getGlobalSettingsString(
-                contentResolver, bundle, Settings.Global.ANGLE_DEFERLIST);
         Log.v(TAG, "Currently set values for:");
-        Log.v(TAG, "    angle_gl_driver_selection_pkgs =" + optInPackages);
-        Log.v(TAG, "  angle_gl_driver_selection_values =" + optInValues);
+        Log.v(TAG, "  angle_gl_driver_selection_pkgs=" + optInPackages);
+        Log.v(TAG, "  angle_gl_driver_selection_values=" + optInValues);
 
-        // If ANGLE is the system driver AND the deferlist has not yet been applied, select the
-        // Legacy driver
-        if (mAngleIsSystemDriver && angleDeferlist.size() == 0) {
-            Log.v(TAG, "ANGLE deferlist (" + Settings.Global.ANGLE_DEFERLIST + ") has not been "
-                           + "applied, defaulting to legacy driver");
-            return ANGLE_GL_DRIVER_TO_USE_LEGACY;
-        }
+        mEnabledByGameMode = isAngleEnabledByGameMode(context, packageName);
 
         // Make sure we have good settings to use
         if (optInPackages.size() != optInValues.size()) {
-            Log.w(TAG,
+            Log.v(TAG,
                     "Global.Settings values are invalid: "
                         + "number of packages: "
                             + optInPackages.size() + ", "
                         + "number of values: "
                             + optInValues.size());
-            return getDefaultDriverToUse(context, packageName);
+            return mEnabledByGameMode;
         }
 
-        // See if this application is listed in the per-application settings lists
+        // See if this application is listed in the per-application settings list
         final int pkgIndex = getPackageIndex(packageName, optInPackages);
 
         if (pkgIndex < 0) {
-            // The application is NOT listed in the per-application settings lists; and so use the
-            // system driver (i.e. either ANGLE or the Legacy driver)
-            Log.v(TAG, "getDriverForPackage(): No per-application setting");
-            return getDefaultDriverToUse(context, packageName);
+            Log.v(TAG, packageName + " is not listed in per-application setting");
+            return mEnabledByGameMode;
         }
         mAngleOptInIndex = pkgIndex;
 
-        Log.v(TAG,
-                "getDriverForPackage(): using per-application switch: "
-                        + optInValues.get(pkgIndex));
-        // The application IS listed in the per-application settings lists; and so use the
-        // setting--choosing the current system driver if the setting is "default" (i.e. either
-        // ANGLE or the Legacy driver)
-        String rtnValue = optInValues.get(pkgIndex);
+        // The application IS listed in the per-application settings list; and so use the
+        // setting--choosing the current system driver if the setting is "default"
+        String optInValue = optInValues.get(pkgIndex);
         Log.v(TAG,
                 "ANGLE Developer option for '" + packageName + "' "
-                        + "set to: '" + rtnValue + "'");
-        if (rtnValue.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE)) {
-            return ANGLE_GL_DRIVER_TO_USE_ANGLE;
-        } else if (rtnValue.equals(ANGLE_GL_DRIVER_CHOICE_NATIVE)
-                || rtnValue.equals(ANGLE_GL_DRIVER_CHOICE_LEGACY)) {
-            return ANGLE_GL_DRIVER_TO_USE_LEGACY;
+                        + "set to: '" + optInValue + "'");
+        if (optInValue.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE)) {
+            return true;
+        } else if (optInValue.equals(ANGLE_GL_DRIVER_CHOICE_NATIVE)) {
+            return false;
         } else {
             // The user either chose default or an invalid value; go with the default driver or what
-            // the game dashboard indicates
-            return getDefaultDriverToUse(context, packageName);
+            // the game mode indicates
+            return mEnabledByGameMode;
         }
     }
 
@@ -631,9 +545,7 @@
      * the C++ GraphicsEnv class.
      *
      * If ANGLE will be used, GraphicsEnv::setAngleInfo() will be called to enable ANGLE to be
-     * properly used.  Otherwise, GraphicsEnv::setLegacyDriverInfo() will be called to
-     * enable the legacy GLES driver (e.g. when ANGLE is the system driver) to be identified and
-     * used.
+     * properly used.
      *
      * @param context
      * @param bundle
@@ -646,7 +558,6 @@
             String packageName) {
 
         if (!shouldUseAngle(context, bundle, packageName)) {
-            setLegacyDriverInfo(packageName, mAngleIsSystemDriver, mEglLegacyDriver);
             return false;
         }
 
@@ -655,13 +566,13 @@
         // If the developer has specified a debug package over ADB, attempt to find it
         String anglePkgName = getAngleDebugPackage(context, bundle);
         if (!anglePkgName.isEmpty()) {
-            Log.i(TAG, "ANGLE debug package enabled: " + anglePkgName);
+            Log.v(TAG, "ANGLE debug package enabled: " + anglePkgName);
             try {
                 // Note the debug package does not have to be pre-installed
                 angleInfo = pm.getApplicationInfo(anglePkgName, 0);
             } catch (PackageManager.NameNotFoundException e) {
-                Log.w(TAG, "ANGLE debug package '" + anglePkgName + "' not installed");
-                setLegacyDriverInfo(packageName, mAngleIsSystemDriver, mEglLegacyDriver);
+                // If the debug package is specified but not found, abort.
+                Log.v(TAG, "ANGLE debug package '" + anglePkgName + "' not installed");
                 return false;
             }
         }
@@ -670,8 +581,7 @@
         if (angleInfo == null) {
             anglePkgName = getAnglePackageName(pm);
             if (TextUtils.isEmpty(anglePkgName)) {
-                Log.w(TAG, "Failed to find ANGLE package.");
-                setLegacyDriverInfo(packageName, mAngleIsSystemDriver, mEglLegacyDriver);
+                Log.v(TAG, "Failed to find ANGLE package.");
                 return false;
             }
 
@@ -681,8 +591,7 @@
                 angleInfo = pm.getApplicationInfo(anglePkgName,
                         PackageManager.MATCH_SYSTEM_ONLY);
             } catch (PackageManager.NameNotFoundException e) {
-                Log.w(TAG, "ANGLE package '" + anglePkgName + "' not installed");
-                setLegacyDriverInfo(packageName, mAngleIsSystemDriver, mEglLegacyDriver);
+                Log.v(TAG, "ANGLE package '" + anglePkgName + "' not installed");
                 return false;
             }
         }
@@ -697,14 +606,13 @@
                 + abi;
 
         if (DEBUG) {
-            Log.v(TAG, "ANGLE package libs: " + paths);
+            Log.d(TAG, "ANGLE package libs: " + paths);
         }
 
         // If we make it to here, ANGLE will be used.  Call setAngleInfo() with the package name,
         // and features to use.
         final String[] features = getAngleEglFeatures(context, bundle);
-        setAngleInfo(
-                paths, packageName, mAngleIsSystemDriver, ANGLE_GL_DRIVER_CHOICE_ANGLE, features);
+        setAngleInfo(paths, packageName, ANGLE_GL_DRIVER_CHOICE_ANGLE, features);
 
         return true;
     }
@@ -994,9 +902,7 @@
     private static native void setGpuStats(String driverPackageName, String driverVersionName,
             long driverVersionCode, long driverBuildTime, String appPackageName, int vulkanVersion);
     private static native void setAngleInfo(String path, String appPackage,
-            boolean angleIsSystemDriver, String devOptIn, String[] features);
-    private static native void setLegacyDriverInfo(
-            String appPackage, boolean angleIsSystemDriver, String legacyDriverName);
+            String devOptIn, String[] features);
     private static native boolean getShouldUseAngle(String packageName);
     private static native boolean setInjectLayersPrSetDumpable();
     private static native void nativeToggleAngleAsSystemDriver(boolean enabled);
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 4ce9184..ef39010 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -56,6 +56,7 @@
 
     /** @hide A user id to indicate the currently active user */
     @UnsupportedAppUsage
+    @TestApi
     public static final @UserIdInt int USER_CURRENT = -2;
 
     /** @hide A user handle to indicate the current user of the device */
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 5bcbaa1..8606687 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -4224,7 +4224,8 @@
             android.Manifest.permission.MANAGE_USERS,
             android.Manifest.permission.CREATE_USERS
     })
-    public List<UserInfo> getUsers() {
+    @TestApi
+    public @NonNull List<UserInfo> getUsers() {
         return getUsers(/*excludePartial= */ true, /* excludeDying= */ false,
                 /* excludePreCreated= */ true);
     }
@@ -4245,6 +4246,7 @@
             android.Manifest.permission.MANAGE_USERS,
             android.Manifest.permission.CREATE_USERS
     })
+    @TestApi
     public @NonNull List<UserInfo> getAliveUsers() {
         return getUsers(/*excludePartial= */ true, /* excludeDying= */ true,
                 /* excludePreCreated= */ true);
@@ -4271,8 +4273,7 @@
      * Returns information for all users on this device, based on the filtering parameters.
      *
      * @deprecated Pre-created users are deprecated and no longer supported.
-     *             Use {@link #getUsers()}, {@link #getUsers(boolean)}, or {@link #getAliveUsers()}
-     *             instead.
+     *             Use {@link #getUsers()}, or {@link #getAliveUsers()} instead.
      * @hide
      */
     @Deprecated
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 77c0067..ac6b2b2 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -1293,7 +1293,8 @@
                 USER_MISSED_NO_VIBRATE,
                 USER_MISSED_CALL_SCREENING_SERVICE_SILENCED,
                 USER_MISSED_CALL_FILTERS_TIMEOUT,
-                USER_MISSED_NEVER_RANG
+                USER_MISSED_NEVER_RANG,
+                USER_MISSED_NOT_RUNNING
         })
         @Retention(RetentionPolicy.SOURCE)
         public @interface MissedReason {}
@@ -1391,6 +1392,13 @@
         public static final long USER_MISSED_NEVER_RANG = 1 << 23;
 
         /**
+         * When {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE}, set this bit when
+         * the user receiving the call is not running (i.e. work profile paused).
+         * @hide
+         */
+        public static final long USER_MISSED_NOT_RUNNING = 1 << 24;
+
+        /**
          * Where the {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#MISSED_TYPE},
          * indicates factors which may have lead the user to miss the call.
          * <P>Type: INTEGER</P>
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 196bac2..cd76754 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -1106,6 +1106,16 @@
                     mTransformedTextUpdate.before = before;
                     mTransformedTextUpdate.after = after;
                 }
+                // When there is a transformed text, we have to reflow the DynamicLayout based on
+                // the transformed indices instead of the range in base text.
+                // For example,
+                //   base text:         abcd    >   abce
+                //   updated range:     where = 3, before = 1, after = 1
+                //   transformed text:  abxxcd  >   abxxce
+                //   updated range:     where = 5, before = 1, after = 1
+                //
+                // Because the transformedText is udapted simultaneously with the base text,
+                // the range must be transformed before the base text changes.
                 transformedText.originalToTransformed(mTransformedTextUpdate);
             }
         }
@@ -1113,9 +1123,20 @@
         public void onTextChanged(CharSequence s, int where, int before, int after) {
             final DynamicLayout dynamicLayout = mLayout.get();
             if (dynamicLayout != null && dynamicLayout.mDisplay instanceof OffsetMapping) {
-                where = mTransformedTextUpdate.where;
-                before = mTransformedTextUpdate.before;
-                after = mTransformedTextUpdate.after;
+                if (mTransformedTextUpdate != null && mTransformedTextUpdate.where >= 0) {
+                    where = mTransformedTextUpdate.where;
+                    before = mTransformedTextUpdate.before;
+                    after = mTransformedTextUpdate.after;
+                    // Set where to -1 so that we know if beforeTextChanged is called.
+                    mTransformedTextUpdate.where = -1;
+                } else {
+                    // onTextChanged is called without beforeTextChanged. Reflow the entire text.
+                    where = 0;
+                    // We can't get the before length from the text, use the line end of the
+                    // last line instead.
+                    before = dynamicLayout.getLineEnd(dynamicLayout.getLineCount() - 1);
+                    after = dynamicLayout.mDisplay.length();
+                }
             }
             reflow(s, where, before, after);
         }
diff --git a/core/java/android/text/method/InsertModeTransformationMethod.java b/core/java/android/text/method/InsertModeTransformationMethod.java
index 0c933d9..59b80f3 100644
--- a/core/java/android/text/method/InsertModeTransformationMethod.java
+++ b/core/java/android/text/method/InsertModeTransformationMethod.java
@@ -37,6 +37,8 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
 
+import java.lang.reflect.Array;
+
 /**
  * The transformation method used by handwriting insert mode.
  * This transformation will insert a placeholder string to the original text at the given
@@ -309,26 +311,51 @@
                 return ArrayUtils.emptyArray(type);
             }
 
-            final T[] spansOriginal;
+            T[] spansOriginal = null;
             if (mSpannedOriginal != null) {
                 final int originalStart =
                         transformedToOriginal(start, OffsetMapping.MAP_STRATEGY_CURSOR);
                 final int originalEnd =
                         transformedToOriginal(end, OffsetMapping.MAP_STRATEGY_CURSOR);
+                // We can't simply call SpannedString.getSpans(originalStart, originalEnd) here.
+                // When start == end SpannedString.getSpans returns spans whose spanEnd == start.
+                // For example,
+                //   text: abcd  span: [1, 3)
+                // getSpan(3, 3) will return the span [1, 3) but getSpan(3, 4) returns no span.
+                //
+                // This creates some special cases when originalStart == originalEnd.
+                // For example:
+                //   original text: abcd    span1: [1, 3) span2: [3, 4) span3: [3, 3)
+                //   transformed text: abc\n\nd    span1: [1, 3) span2: [5, 6) span3: [3, 3)
+                // Case 1:
+                // When start = 3 and end = 4, transformedText#getSpan(3, 4) should return span3.
+                // However, because originalStart == originalEnd == 3, originalText#getSpan(3, 3)
+                // returns span1, span2 and span3.
+                //
+                // Case 2:
+                // When start == end == 4, transformedText#getSpan(4, 4) should return nothing.
+                // However, because originalStart == originalEnd == 3, originalText#getSpan(3, 3)
+                // return span1, span2 and span3.
+                //
+                // Case 3:
+                // When start == end == 5, transformedText#getSpan(5, 5) should return span2.
+                // However, because originalStart == originalEnd == 3, originalText#getSpan(3, 3)
+                // return span1,  span2 and span3.
+                //
+                // To handle the issue, we need to filter out the invalid spans.
                 spansOriginal = mSpannedOriginal.getSpans(originalStart, originalEnd, type);
-            } else {
-                spansOriginal = null;
+                spansOriginal = ArrayUtils.filter(spansOriginal,
+                        size -> (T[]) Array.newInstance(type, size),
+                        span -> intersect(getSpanStart(span), getSpanEnd(span), start, end));
             }
 
-            final T[] spansPlaceholder;
+            T[] spansPlaceholder = null;
             if (mSpannedPlaceholder != null
                     && intersect(start, end, mEnd, mEnd + mPlaceholder.length())) {
-                final int placeholderStart = Math.max(start - mEnd, 0);
-                final int placeholderEnd = Math.min(end - mEnd, mPlaceholder.length());
+                int placeholderStart = Math.max(start - mEnd, 0);
+                int placeholderEnd = Math.min(end - mEnd, mPlaceholder.length());
                 spansPlaceholder =
                         mSpannedPlaceholder.getSpans(placeholderStart, placeholderEnd, type);
-            } else {
-                spansPlaceholder = null;
             }
 
             // TODO: sort the spans based on their priority.
@@ -340,7 +367,10 @@
             if (mSpannedOriginal != null) {
                 final int index = mSpannedOriginal.getSpanStart(tag);
                 if (index >= 0) {
-                    if (index < mEnd) {
+                    // When originalSpanStart == originalSpanEnd == mEnd, the span should be
+                    // considered "before" the placeholder text. So we return the originalSpanStart.
+                    if (index < mEnd
+                            || (index == mEnd && mSpannedOriginal.getSpanEnd(tag) == index)) {
                         return index;
                     }
                     return index + mPlaceholder.length();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9670735..705a2ce0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -25074,7 +25074,7 @@
         int viewStateIndex = 0;
         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
-        if (isFocused() && hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
+        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 34fe935..6c84f35 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11808,8 +11808,17 @@
     public boolean hasSelection() {
         final int selectionStart = getSelectionStart();
         final int selectionEnd = getSelectionEnd();
+        final int selectionMin;
+        final int selectionMax;
+        if (selectionStart < selectionEnd) {
+            selectionMin = selectionStart;
+            selectionMax = selectionEnd;
+        } else {
+            selectionMin = selectionEnd;
+            selectionMax = selectionStart;
+        }
 
-        return selectionStart >= 0 && selectionEnd > 0 && selectionStart != selectionEnd;
+        return selectionMin >= 0 && selectionMax > 0 && selectionMin != selectionMax;
     }
 
     String getSelectedText() {
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 617519b..fdcb87f 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -1468,6 +1468,11 @@
         mHistoryLastLastWritten.setTo(mHistoryLastWritten);
         final boolean hasTags = mHistoryLastWritten.tagsFirstOccurrence || cur.tagsFirstOccurrence;
         mHistoryLastWritten.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur);
+        if (mHistoryLastWritten.time < mHistoryLastLastWritten.time - 60000) {
+            Slog.wtf(TAG, "Significantly earlier event written to battery history:"
+                    + " time=" + mHistoryLastWritten.time
+                    + " previous=" + mHistoryLastLastWritten.time);
+        }
         mHistoryLastWritten.tagsFirstOccurrence = hasTags;
         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
         mLastHistoryElapsedRealtimeMs = elapsedRealtimeMs;
@@ -1908,12 +1913,6 @@
             in.setDataPosition(curPos + bufSize);
         }
 
-        if (DEBUG) {
-            StringBuilder sb = new StringBuilder(128);
-            sb.append("****************** OLD mHistoryBaseTimeMs: ");
-            TimeUtils.formatDuration(mHistoryBaseTimeMs, sb);
-            Slog.i(TAG, sb.toString());
-        }
         mHistoryBaseTimeMs = historyBaseTime;
         if (DEBUG) {
             StringBuilder sb = new StringBuilder(128);
@@ -1922,11 +1921,10 @@
             Slog.i(TAG, sb.toString());
         }
 
-        // We are just arbitrarily going to insert 1 minute from the sample of
-        // the last run until samples in this run.
         if (mHistoryBaseTimeMs > 0) {
-            long oldnow = mClock.elapsedRealtime();
-            mHistoryBaseTimeMs = mHistoryBaseTimeMs - oldnow + 1;
+            long elapsedRealtimeMs = mClock.elapsedRealtime();
+            mLastHistoryElapsedRealtimeMs = elapsedRealtimeMs;
+            mHistoryBaseTimeMs = mHistoryBaseTimeMs - elapsedRealtimeMs + 1;
             if (DEBUG) {
                 StringBuilder sb = new StringBuilder(128);
                 sb.append("****************** ADJUSTED mHistoryBaseTimeMs: ");
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index d9152d6..01dbceb 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -50,7 +50,7 @@
 }
 
 void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName,
-                         jboolean angleIsSystemDriver, jstring devOptIn, jobjectArray featuresObj) {
+                         jstring devOptIn, jobjectArray featuresObj) {
     ScopedUtfChars pathChars(env, path);
     ScopedUtfChars appNameChars(env, appName);
     ScopedUtfChars devOptInChars(env, devOptIn);
@@ -74,18 +74,7 @@
     }
 
     android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(),
-                                                     angleIsSystemDriver, devOptInChars.c_str(),
-                                                     features);
-}
-
-void setLegacyDriverInfo_native(JNIEnv* env, jobject clazz, jstring appName,
-                                jboolean angleIsSystemDriver, jstring legacyDriverName) {
-    ScopedUtfChars appNameChars(env, appName);
-    ScopedUtfChars legacyDriverNameChars(env, legacyDriverName);
-
-    android::GraphicsEnv::getInstance().setLegacyDriverInfo(appNameChars.c_str(),
-                                                            angleIsSystemDriver,
-                                                            legacyDriverNameChars.c_str());
+                                                     devOptInChars.c_str(), features);
 }
 
 bool shouldUseAngle_native(JNIEnv* env, jobject clazz, jstring appName) {
@@ -135,10 +124,8 @@
         {"setInjectLayersPrSetDumpable", "()Z",
          reinterpret_cast<void*>(setInjectLayersPrSetDumpable_native)},
         {"setAngleInfo",
-         "(Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;[Ljava/lang/String;)V",
+         "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V",
          reinterpret_cast<void*>(setAngleInfo_native)},
-        {"setLegacyDriverInfo", "(Ljava/lang/String;ZLjava/lang/String;)V",
-         reinterpret_cast<void*>(setLegacyDriverInfo_native)},
         {"getShouldUseAngle", "(Ljava/lang/String;)Z",
          reinterpret_cast<void*>(shouldUseAngle_native)},
         {"setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V",
diff --git a/core/jni/android_window_WindowInfosListener.cpp b/core/jni/android_window_WindowInfosListener.cpp
index 850755a..55995df 100644
--- a/core/jni/android_window_WindowInfosListener.cpp
+++ b/core/jni/android_window_WindowInfosListener.cpp
@@ -21,6 +21,7 @@
 #include <android_runtime/Log.h>
 #include <gui/DisplayInfo.h>
 #include <gui/SurfaceComposerClient.h>
+#include <gui/WindowInfosUpdate.h>
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedLocalFrame.h>
 #include <utils/Log.h>
@@ -91,8 +92,7 @@
     WindowInfosListener(JNIEnv* env, jobject listener)
           : mListener(env->NewWeakGlobalRef(listener)) {}
 
-    void onWindowInfosChanged(const std::vector<WindowInfo>& windowInfos,
-                              const std::vector<DisplayInfo>& displayInfos) override {
+    void onWindowInfosChanged(const gui::WindowInfosUpdate& update) override {
         JNIEnv* env = AndroidRuntime::getJNIEnv();
         LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onWindowInfoChanged.");
 
@@ -103,8 +103,10 @@
             return;
         }
 
-        ScopedLocalRef<jobjectArray> jWindowHandlesArray(env, fromWindowInfos(env, windowInfos));
-        ScopedLocalRef<jobjectArray> jDisplayInfoArray(env, fromDisplayInfos(env, displayInfos));
+        ScopedLocalRef<jobjectArray> jWindowHandlesArray(env,
+                                                         fromWindowInfos(env, update.windowInfos));
+        ScopedLocalRef<jobjectArray> jDisplayInfoArray(env,
+                                                       fromDisplayInfos(env, update.displayInfos));
 
         env->CallVoidMethod(listener, gListenerClassInfo.onWindowInfosChanged,
                             jWindowHandlesArray.get(), jDisplayInfoArray.get());
diff --git a/core/proto/android/server/windowmanagertransitiontrace.proto b/core/proto/android/server/windowmanagertransitiontrace.proto
index a776bd2..a950a79 100644
--- a/core/proto/android/server/windowmanagertransitiontrace.proto
+++ b/core/proto/android/server/windowmanagertransitiontrace.proto
@@ -23,7 +23,7 @@
 option java_multiple_files = true;
 
 /* Represents a file full of transition entries.
-   Encoded, it should start with 0x09 0x54 0x52 0x4E 0x54 0x52 0x41 0x43 0x45 (TRNTRACE), such
+   Encoded, it should start with 0x09 0x54 0x52 0x4E 0x54 0x52 0x41 0x43 0x45 (.TRNTRACE), such
    that it can be easily identified. */
 message TransitionTraceProto {
 
@@ -38,28 +38,24 @@
 
   // Must be the first field, set to value in MagicNumber
   required fixed64 magic_number = 1;
-  // Transitions that don't have a finish time are considered aborted
-  repeated Transition finished_transitions = 2;
-
-  // Additional debugging info only collected and dumped when explicitly requested to trace
-  repeated TransitionState transition_states = 3;
-  repeated TransitionInfo transition_info = 4;
+  repeated Transition transitions = 2;
 
   /* offset between real-time clock and elapsed time clock in nanoseconds.
    Calculated as: 1000000 * System.currentTimeMillis() - SystemClock.elapsedRealtimeNanos() */
-  optional fixed64 real_to_elapsed_time_offset_nanos = 5;
+  optional fixed64 real_to_elapsed_time_offset_nanos = 3;
 }
 
 message Transition {
-  optional int32 id = 1; // Not dumped in always on tracing
-  required uint64 start_transaction_id = 2;
-  required uint64 finish_transaction_id = 3;
-  required int64 create_time_ns = 4;
-  required int64 send_time_ns = 5;
-  optional int64 finish_time_ns = 6; // consider aborted if not provided
-  required int32 type = 7;
+  required int32 id = 1;
+  optional uint64 start_transaction_id = 2;
+  optional uint64 finish_transaction_id = 3;
+  optional int64 create_time_ns = 4;
+  optional int64 send_time_ns = 5;
+  optional int64 finish_time_ns = 6;
+  optional int32 type = 7;
   repeated Target targets = 8;
   optional int32 flags = 9;
+  optional int64 abort_time_ns = 10;
 }
 
 message Target {
@@ -68,40 +64,3 @@
   optional int32 window_id = 3;  // Not dumped in always on tracing
   optional int32 flags = 4;
 }
-
-message TransitionState {
-  enum State {
-    COLLECTING = 0;
-    PENDING = -1;
-    STARTED = 1;
-    PLAYING = 2;
-    ABORT = 3;
-    FINISHED = 4;
-  }
-
-  required int64 time_ns = 1;
-  required int32 transition_id = 2;
-  required int32 transition_type = 3;
-  required State state = 4;
-  required int32 flags = 5;
-  repeated ChangeInfo change = 6;
-  repeated com.android.server.wm.IdentifierProto participants = 7;
-}
-
-message ChangeInfo {
-  required com.android.server.wm.IdentifierProto window_identifier = 1;
-  required int32 transit_mode = 2;
-  required bool has_changed = 3;
-  required int32 change_flags = 4;
-  required int32 windowing_mode = 5;
-}
-
-message TransitionInfo {
-  required int32 transition_id = 1;
-  repeated TransitionInfoChange change = 2;
-}
-
-message TransitionInfoChange {
-  required int32 layer_id = 1;
-  required int32 mode = 2;
-}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index fefa79f..7e0a36d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4976,11 +4976,11 @@
         android:protectionLevel="signature" />
 
     <!-- Allows an application to subscribe to keyguard locked (i.e., showing) state.
-         <p>Protection level: internal|role
-         <p>Intended for use by ROLE_ASSISTANT only.
+         <p>Protection level: signature|role
+         <p>Intended for use by ROLE_ASSISTANT and signature apps only.
     -->
     <permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE"
-                android:protectionLevel="internal|role"/>
+                android:protectionLevel="signature|role"/>
 
     <!-- Must be required by a {@link android.service.autofill.AutofillService},
          to ensure that only the system can bind to it.
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 7de36a71..6f7bc53 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2791,7 +2791,7 @@
             <flag name="noExcludeDescendants" value="0x8" />
         </attr>
 
-        <!-- Boolean that hints the Android System that the view is credntial and associated with
+        <!-- Boolean that hints the Android System that the view is credential and associated with
              CredentialManager -->
         <attr name="isCredential" format="boolean" />
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index bf141b5..17d8402 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -774,11 +774,6 @@
          we rely on gravity to determine the effective orientation. -->
     <bool name="config_deskDockEnablesAccelerometer">true</bool>
 
-    <!-- Control whether nosensor and locked orientation requests are respected from the app when
-         config_deskDockEnablesAccelerometer is set to false.
-         TODO(b/274763533): Consider making true by default and removing this. -->
-    <bool name="config_deskRespectsNoSensorAndLockedWithoutAccelerometer">false</bool>
-
     <!-- Car dock behavior -->
 
     <!-- The number of degrees to rotate the display when the device is in a car dock.
@@ -6440,4 +6435,8 @@
     <bool name="config_persistBrightnessNitsForDefaultDisplay">false</bool>
     <!-- Whether to request the approval before commit sessions. -->
     <bool name="config_isPreApprovalRequestAvailable">true</bool>
+
+    <!-- Whether the AOSP support for app cloning building blocks is to be enabled for the
+         device. -->
+    <bool name="config_enableAppCloningBuildingBlocks">true</bool>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c91e3cb..e3697bb 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -480,6 +480,7 @@
   <java-symbol type="bool" name="config_multiuserDelayUserDataLocking" />
   <java-symbol type="bool" name="config_multiuserVisibleBackgroundUsers" />
   <java-symbol type="bool" name="config_multiuserVisibleBackgroundUsersOnDefaultDisplay" />
+  <java-symbol type="bool" name="config_enableAppCloningBuildingBlocks" />
   <java-symbol type="bool" name="config_enableTimeoutToDockUserWhenDocked" />
   <java-symbol type="integer" name="config_userTypePackageWhitelistMode"/>
   <java-symbol type="xml" name="config_user_types" />
@@ -1698,7 +1699,6 @@
   <java-symbol type="bool" name="config_carDockEnablesAccelerometer" />
   <java-symbol type="bool" name="config_customUserSwitchUi" />
   <java-symbol type="bool" name="config_deskDockEnablesAccelerometer" />
-  <java-symbol type="bool" name="config_deskRespectsNoSensorAndLockedWithoutAccelerometer" />
   <java-symbol type="bool" name="config_disableMenuKeyInLockScreen" />
   <java-symbol type="bool" name="config_enableCarDockHomeLaunch" />
   <java-symbol type="bool" name="config_enableLockBeforeUnlockScreen" />
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java
index c7b82b1..6a6a951 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java
@@ -750,6 +750,15 @@
     }
 
     @Test
+    public void onTuneFailed_withCanceledResult() throws Exception {
+        mTunerCallback.onTuneFailed(RadioTuner.TUNER_RESULT_CANCELED, FM_SELECTOR);
+
+        verify(mCallbackMock, timeout(CALLBACK_TIMEOUT_MS)).onTuneFailed(
+                RadioTuner.TUNER_RESULT_CANCELED, FM_SELECTOR);
+        verify(mCallbackMock, timeout(CALLBACK_TIMEOUT_MS)).onError(RadioTuner.ERROR_CANCELLED);
+    }
+
+    @Test
     public void onProgramListChanged_forTunerCallbackAdapter() throws Exception {
         mTunerCallback.onProgramListChanged();
 
diff --git a/core/tests/coretests/src/android/text/DynamicLayoutOffsetMappingTest.java b/core/tests/coretests/src/android/text/DynamicLayoutOffsetMappingTest.java
index 76f4171..5939c06 100644
--- a/core/tests/coretests/src/android/text/DynamicLayoutOffsetMappingTest.java
+++ b/core/tests/coretests/src/android/text/DynamicLayoutOffsetMappingTest.java
@@ -119,6 +119,86 @@
         assertLineRange(layout, /* lineBreaks */ 0, 5, 6, 8);
     }
 
+    @Test
+    public void textWithOffsetMapping_blockBeforeTextChanged_deletion() {
+        final String text = "abcdef";
+        final SpannableStringBuilder spannable = new TestNoBeforeTextChangeSpannableString(text);
+        final CharSequence transformedText =
+                new TestOffsetMapping(spannable, 5, "\n\n");
+
+        final DynamicLayout layout = DynamicLayout.Builder.obtain(spannable, sTextPaint, WIDTH)
+                .setAlignment(ALIGN_NORMAL)
+                .setIncludePad(false)
+                .setDisplayText(transformedText)
+                .build();
+
+        // delete "cd", original text becomes "abef"
+        spannable.delete(2, 4);
+        assertThat(transformedText.toString()).isEqualTo("abe\n\nf");
+        assertLineRange(layout, /* lineBreaks */ 0, 4, 5, 6);
+
+        // delete "abe", original text becomes "f"
+        spannable.delete(0, 3);
+        assertThat(transformedText.toString()).isEqualTo("\n\nf");
+        assertLineRange(layout, /* lineBreaks */ 0, 1, 2, 3);
+    }
+
+    @Test
+    public void textWithOffsetMapping_blockBeforeTextChanged_insertion() {
+        final String text = "abcdef";
+        final SpannableStringBuilder spannable = new TestNoBeforeTextChangeSpannableString(text);
+        final CharSequence transformedText = new TestOffsetMapping(spannable, 3, "\n\n");
+
+        final DynamicLayout layout = DynamicLayout.Builder.obtain(spannable, sTextPaint, WIDTH)
+                .setAlignment(ALIGN_NORMAL)
+                .setIncludePad(false)
+                .setDisplayText(transformedText)
+                .build();
+
+        spannable.insert(3, "x");
+        assertThat(transformedText.toString()).isEqualTo("abcx\n\ndef");
+        assertLineRange(layout, /* lineBreaks */ 0, 5, 6, 9);
+
+        spannable.insert(5, "x");
+        assertThat(transformedText.toString()).isEqualTo("abcx\n\ndxef");
+        assertLineRange(layout, /* lineBreaks */ 0, 5, 6, 10);
+    }
+
+    @Test
+    public void textWithOffsetMapping_blockBeforeTextChanged_replace() {
+        final String text = "abcdef";
+        final SpannableStringBuilder spannable = new TestNoBeforeTextChangeSpannableString(text);
+        final CharSequence transformedText = new TestOffsetMapping(spannable, 3, "\n\n");
+
+        final DynamicLayout layout = DynamicLayout.Builder.obtain(spannable, sTextPaint, WIDTH)
+                .setAlignment(ALIGN_NORMAL)
+                .setIncludePad(false)
+                .setDisplayText(transformedText)
+                .build();
+
+        spannable.replace(2, 4, "xx");
+        assertThat(transformedText.toString()).isEqualTo("abxx\n\nef");
+        assertLineRange(layout, /* lineBreaks */ 0, 5, 6, 8);
+    }
+
+    @Test
+    public void textWithOffsetMapping_onlyCallOnTextChanged_notCrash() {
+        String text = "abcdef";
+        SpannableStringBuilder spannable = new SpannableStringBuilder(text);
+        CharSequence transformedText = new TestOffsetMapping(spannable, 3, "\n\n");
+
+        DynamicLayout.Builder.obtain(spannable, sTextPaint, WIDTH)
+                .setAlignment(ALIGN_NORMAL)
+                .setIncludePad(false)
+                .setDisplayText(transformedText)
+                .build();
+
+        TextWatcher[] textWatcher = spannable.getSpans(0, spannable.length(), TextWatcher.class);
+        assertThat(textWatcher.length).isEqualTo(1);
+
+        textWatcher[0].onTextChanged(spannable, 0, 2, 2);
+    }
+
     private void assertLineRange(Layout layout, int... lineBreaks) {
         final int lineCount = lineBreaks.length - 1;
         assertThat(layout.getLineCount()).isEqualTo(lineCount);
@@ -129,6 +209,50 @@
     }
 
     /**
+     * A test SpannableStringBuilder that doesn't call beforeTextChanged. It's used to test
+     * DynamicLayout against some special cases where beforeTextChanged callback is not properly
+     * called.
+     */
+    private static class TestNoBeforeTextChangeSpannableString extends SpannableStringBuilder {
+
+        TestNoBeforeTextChangeSpannableString(CharSequence text) {
+            super(text);
+        }
+
+        @Override
+        public void setSpan(Object what, int start, int end, int flags) {
+            if (what instanceof TextWatcher) {
+                super.setSpan(new TestNoBeforeTextChangeWatcherWrapper((TextWatcher) what), start,
+                        end, flags);
+            } else {
+                super.setSpan(what, start, end, flags);
+            }
+        }
+    }
+
+    /** A TextWatcherWrapper that blocks beforeTextChanged callback. */
+    private static class TestNoBeforeTextChangeWatcherWrapper implements TextWatcher {
+        private final TextWatcher mTextWatcher;
+
+        TestNoBeforeTextChangeWatcherWrapper(TextWatcher textWatcher) {
+            mTextWatcher = textWatcher;
+        }
+
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+            mTextWatcher.onTextChanged(s, start, before, count);
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+            mTextWatcher.afterTextChanged(s);
+        }
+    }
+
+    /**
      * A test TransformedText that inserts some text at the given offset.
      */
     private static class TestOffsetMapping implements OffsetMapping, CharSequence {
diff --git a/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java b/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java
index 7706d9a..9ef137b 100644
--- a/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java
+++ b/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java
@@ -224,6 +224,12 @@
         assertThat(spans0to2.length).isEqualTo(1);
         assertThat(spans0to2[0]).isEqualTo(span1);
 
+        // only span2 is in the range of [3, 4).
+        // note: span1 [0, 3) is not in the range because [3, 4) is not collapsed.
+        final TestSpan[] spans3to4 = transformedText.getSpans(3, 4, TestSpan.class);
+        assertThat(spans3to4.length).isEqualTo(1);
+        assertThat(spans3to4[0]).isEqualTo(span2);
+
         // span1 and span2 are in the range of [1, 6).
         final TestSpan[] spans1to6 = transformedText.getSpans(1, 6, TestSpan.class);
         assertThat(spans1to6.length).isEqualTo(2);
@@ -262,7 +268,7 @@
         text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 
-        // In the transformedText, the new ranges of the spans are:
+        // In the transformedText "abc\uFFFD def", the new ranges of the spans are:
         // span1: [0, 3)
         // span2: [2, 5)
         // span3: [5, 6)
@@ -277,6 +283,12 @@
         assertThat(spans0to2.length).isEqualTo(1);
         assertThat(spans0to2[0]).isEqualTo(span1);
 
+        // only span2 is in the range of [3, 4).
+        // note: span1 [0, 3) is not in the range because [3, 4) is not collapsed.
+        final TestSpan[] spans3to4 = transformedText.getSpans(3, 4, TestSpan.class);
+        assertThat(spans3to4.length).isEqualTo(1);
+        assertThat(spans3to4[0]).isEqualTo(span2);
+
         // span1 and span2 are in the range of [1, 5).
         final TestSpan[] spans1to4 = transformedText.getSpans(1, 4, TestSpan.class);
         assertThat(spans1to4.length).isEqualTo(2);
@@ -318,20 +330,143 @@
     }
 
     @Test
-    public void transformedText_getSpanStartAndEnd() {
+    public void transformedText_getSpans_collapsedRange() {
         final SpannableString text = new SpannableString(TEXT);
         final TestSpan span1 = new TestSpan();
         final TestSpan span2 = new TestSpan();
         final TestSpan span3 = new TestSpan();
 
         text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        text.setSpan(span2, 3, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        text.setSpan(span3, 3, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+        // In the transformedText "abc\n\n def", the new ranges of the spans are:
+        // span1: [0, 3)
+        // span2: [3, 3)
+        // span3: [5, 6)
+        final InsertModeTransformationMethod transformationMethod =
+                new InsertModeTransformationMethod(3, false, null);
+        final Spanned transformedText =
+                (Spanned) transformationMethod.getTransformation(text, sView);
+
+        // only span1 is in the range of [0, 0).
+        final TestSpan[] spans0to0 = transformedText.getSpans(0, 0, TestSpan.class);
+        assertThat(spans0to0.length).isEqualTo(1);
+        assertThat(spans0to0[0]).isEqualTo(span1);
+
+        // span1 and span 2 are in the range of [3, 3).
+        final TestSpan[] spans3to3 = transformedText.getSpans(3, 3, TestSpan.class);
+        assertThat(spans3to3.length).isEqualTo(2);
+        assertThat(spans3to3[0]).isEqualTo(span1);
+        assertThat(spans3to3[1]).isEqualTo(span2);
+
+        // only the span2 with collapsed range is in the range of [3, 4).
+        final TestSpan[] spans3to4 = transformedText.getSpans(3, 4, TestSpan.class);
+        assertThat(spans3to4.length).isEqualTo(1);
+        assertThat(spans3to4[0]).isEqualTo(span2);
+
+        // no span is in the range of [4, 5). (span2 is not mistakenly included.)
+        final TestSpan[] spans4to5 = transformedText.getSpans(4, 5, TestSpan.class);
+        assertThat(spans4to5).isEmpty();
+
+        // only span3 is in the range of [4, 6). (span2 is not mistakenly included.)
+        final TestSpan[] spans4to6 = transformedText.getSpans(4, 6, TestSpan.class);
+        assertThat(spans4to6.length).isEqualTo(1);
+        assertThat(spans4to6[0]).isEqualTo(span3);
+
+        // no span is in the range of [4, 4).
+        final TestSpan[] spans4to4 = transformedText.getSpans(4, 4, TestSpan.class);
+        assertThat(spans4to4.length).isEqualTo(0);
+
+        // span3 is in the range of [5, 5).
+        final TestSpan[] spans5to5 = transformedText.getSpans(5, 5, TestSpan.class);
+        assertThat(spans5to5.length).isEqualTo(1);
+        assertThat(spans5to5[0]).isEqualTo(span3);
+
+        // span3 is in the range of [6, 6).
+        final TestSpan[] spans6to6 = transformedText.getSpans(6, 6, TestSpan.class);
+        assertThat(spans6to6.length).isEqualTo(1);
+        assertThat(spans6to6[0]).isEqualTo(span3);
+    }
+
+    @Test
+    public void transformedText_getSpans_collapsedRange_singleLine() {
+        final SpannableString text = new SpannableString(TEXT);
+        final TestSpan span1 = new TestSpan();
+        final TestSpan span2 = new TestSpan();
+        final TestSpan span3 = new TestSpan();
+
+        text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        text.setSpan(span2, 3, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        text.setSpan(span3, 3, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+        // In the transformedText "abc\uFFFD def", the new ranges of the spans are:
+        // span1: [0, 3)
+        // span2: [3, 3)
+        // span3: [4, 5)
+        final InsertModeTransformationMethod transformationMethod =
+                new InsertModeTransformationMethod(3, true, null);
+        final Spanned transformedText =
+                (Spanned) transformationMethod.getTransformation(text, sView);
+
+        // only span1 is in the range of [0, 0).
+        final TestSpan[] spans0to0 = transformedText.getSpans(0, 0, TestSpan.class);
+        assertThat(spans0to0.length).isEqualTo(1);
+        assertThat(spans0to0[0]).isEqualTo(span1);
+
+        // span1 and span2 are in the range of [3, 3).
+        final TestSpan[] spans3to3 = transformedText.getSpans(3, 3, TestSpan.class);
+        assertThat(spans3to3.length).isEqualTo(2);
+        assertThat(spans3to3[0]).isEqualTo(span1);
+        assertThat(spans3to3[1]).isEqualTo(span2);
+
+        // only the span2 with collapsed range is in the range of [3, 4).
+        final TestSpan[] spans3to4 = transformedText.getSpans(3, 4, TestSpan.class);
+        assertThat(spans3to4.length).isEqualTo(1);
+        assertThat(spans3to4[0]).isEqualTo(span2);
+
+        // span3 is in the range of [4, 5). (span2 is not mistakenly included.)
+        final TestSpan[] spans4to5 = transformedText.getSpans(4, 5, TestSpan.class);
+        assertThat(spans4to5.length).isEqualTo(1);
+        assertThat(spans4to5[0]).isEqualTo(span3);
+
+        // only span3 is in the range of [4, 6). (span2 is not mistakenly included.)
+        final TestSpan[] spans4to6 = transformedText.getSpans(4, 6, TestSpan.class);
+        assertThat(spans4to6.length).isEqualTo(1);
+        assertThat(spans4to6[0]).isEqualTo(span3);
+
+        // span3 is in the range of [4, 4).
+        final TestSpan[] spans4to4 = transformedText.getSpans(4, 4, TestSpan.class);
+        assertThat(spans4to4.length).isEqualTo(1);
+        assertThat(spans4to4[0]).isEqualTo(span3);
+
+        // span3 is in the range of [5, 5).
+        final TestSpan[] spans5to5 = transformedText.getSpans(5, 5, TestSpan.class);
+        assertThat(spans5to5.length).isEqualTo(1);
+        assertThat(spans5to5[0]).isEqualTo(span3);
+    }
+
+    @Test
+    public void transformedText_getSpanStartAndEnd() {
+        final SpannableString text = new SpannableString(TEXT);
+        final TestSpan span1 = new TestSpan();
+        final TestSpan span2 = new TestSpan();
+        final TestSpan span3 = new TestSpan();
+        final TestSpan span4 = new TestSpan();
+        final TestSpan span5 = new TestSpan();
+
+        text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        text.setSpan(span4, 3, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        text.setSpan(span5, 3, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 
         // In the transformedText, the new ranges of the spans are:
         // span1: [0, 3)
         // span2: [2, 6)
         // span3: [6, 7)
+        // span4: [3, 3)
+        // span5: [5, 6)
         final InsertModeTransformationMethod transformationMethod =
                 new InsertModeTransformationMethod(3, false, null);
         final Spanned transformedText =
@@ -345,6 +480,12 @@
 
         assertThat(transformedText.getSpanStart(span3)).isEqualTo(6);
         assertThat(transformedText.getSpanEnd(span3)).isEqualTo(7);
+
+        assertThat(transformedText.getSpanStart(span4)).isEqualTo(3);
+        assertThat(transformedText.getSpanEnd(span4)).isEqualTo(3);
+
+        assertThat(transformedText.getSpanStart(span5)).isEqualTo(5);
+        assertThat(transformedText.getSpanEnd(span5)).isEqualTo(6);
     }
 
     @Test
@@ -353,15 +494,21 @@
         final TestSpan span1 = new TestSpan();
         final TestSpan span2 = new TestSpan();
         final TestSpan span3 = new TestSpan();
+        final TestSpan span4 = new TestSpan();
+        final TestSpan span5 = new TestSpan();
 
         text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        text.setSpan(span4, 3, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        text.setSpan(span5, 3, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 
         // In the transformedText, the new ranges of the spans are:
         // span1: [0, 3)
         // span2: [2, 5)
         // span3: [5, 6)
+        // span4: [3. 3)
+        // span5: [4, 5)
         final InsertModeTransformationMethod transformationMethod =
                 new InsertModeTransformationMethod(3, true, null);
         final Spanned transformedText =
@@ -376,6 +523,12 @@
         assertThat(transformedText.getSpanStart(span3)).isEqualTo(5);
         assertThat(transformedText.getSpanEnd(span3)).isEqualTo(6);
 
+        assertThat(transformedText.getSpanStart(span4)).isEqualTo(3);
+        assertThat(transformedText.getSpanEnd(span4)).isEqualTo(3);
+
+        assertThat(transformedText.getSpanStart(span5)).isEqualTo(4);
+        assertThat(transformedText.getSpanEnd(span5)).isEqualTo(5);
+
         final ReplacementSpan[] replacementSpans =
                 transformedText.getSpans(0, 8, ReplacementSpan.class);
         assertThat(transformedText.getSpanStart(replacementSpans[0])).isEqualTo(3);
diff --git a/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto b/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto
index 6e01101..c82a70c 100644
--- a/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto
+++ b/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto
@@ -37,6 +37,9 @@
     required fixed64 magic_number = 1;
     repeated Transition transitions = 2;
     repeated HandlerMapping handlerMappings = 3;
+    /* offset between real-time clock and elapsed time clock in nanoseconds.
+    Calculated as: 1000000 * System.currentTimeMillis() - SystemClock.elapsedRealtimeNanos() */
+    optional fixed64 real_to_elapsed_time_offset_nanos = 4;
 }
 
 message Transition {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
index 19eff0e..1793a3d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
@@ -255,7 +255,7 @@
     private boolean shouldShowBackdrop(@NonNull TransitionInfo info,
             @NonNull TransitionInfo.Change change) {
         final Animation a = loadAttributeAnimation(info, change, WALLPAPER_TRANSITION_NONE,
-                mTransitionAnimation);
+                mTransitionAnimation, false);
         return a != null && a.getShowBackdrop();
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index e8014af..adc0c9c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -479,7 +479,7 @@
     void applyThemeAttrs() {
         final TypedArray ta = mContext.obtainStyledAttributes(new int[]{
                 android.R.attr.dialogCornerRadius,
-                android.R.attr.colorBackgroundFloating});
+                com.android.internal.R.attr.materialColorSurfaceBright});
         boolean supportsRoundedCorners = ScreenDecorationsUtils.supportsRoundedCornersOnWindows(
                 mContext.getResources());
         mCornerRadius = supportsRoundedCorners ? ta.getDimensionPixelSize(0, 0) : 0;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index e7dede7..2832c55 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -412,7 +412,10 @@
 
     /** Releases and re-inflates {@link DividerView} on the root surface. */
     public void update(SurfaceControl.Transaction t) {
-        if (!mInitialized) return;
+        if (!mInitialized) {
+            init();
+            return;
+        }
         mSplitWindowManager.release(t);
         mImePositionProcessor.reset();
         mSplitWindowManager.init(this, mInsetsState);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index 838e37a..2bbd870 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -47,6 +47,8 @@
 import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.transition.Transitions;
 
+import dagger.Lazy;
+
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -55,8 +57,6 @@
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 
-import dagger.Lazy;
-
 /**
  * Controller to show/update compat UI components on Tasks based on whether the foreground
  * activities are in compatibility mode.
@@ -284,13 +284,18 @@
             ShellTaskOrganizer.TaskListener taskListener) {
         CompatUIWindowManager layout = mActiveCompatLayouts.get(taskInfo.taskId);
         if (layout != null) {
-            // UI already exists, update the UI layout.
-            if (!layout.updateCompatInfo(taskInfo, taskListener,
-                    showOnDisplay(layout.getDisplayId()))) {
-                // The layout is no longer eligible to be shown, remove from active layouts.
+            if (layout.needsToBeRecreated(taskInfo, taskListener)) {
                 mActiveCompatLayouts.remove(taskInfo.taskId);
+                layout.release();
+            } else {
+                // UI already exists, update the UI layout.
+                if (!layout.updateCompatInfo(taskInfo, taskListener,
+                        showOnDisplay(layout.getDisplayId()))) {
+                    // The layout is no longer eligible to be shown, remove from active layouts.
+                    mActiveCompatLayouts.remove(taskInfo.taskId);
+                }
+                return;
             }
-            return;
         }
 
         // Create a new UI layout.
@@ -433,13 +438,18 @@
     private void createOrUpdateReachabilityEduLayout(TaskInfo taskInfo,
             ShellTaskOrganizer.TaskListener taskListener) {
         if (mActiveReachabilityEduLayout != null) {
-            // UI already exists, update the UI layout.
-            if (!mActiveReachabilityEduLayout.updateCompatInfo(taskInfo, taskListener,
-                    showOnDisplay(mActiveReachabilityEduLayout.getDisplayId()))) {
-                // The layout is no longer eligible to be shown, remove from active layouts.
+            if (mActiveReachabilityEduLayout.needsToBeRecreated(taskInfo, taskListener)) {
+                mActiveReachabilityEduLayout.release();
                 mActiveReachabilityEduLayout = null;
+            } else {
+                // UI already exists, update the UI layout.
+                if (!mActiveReachabilityEduLayout.updateCompatInfo(taskInfo, taskListener,
+                        showOnDisplay(mActiveReachabilityEduLayout.getDisplayId()))) {
+                    // The layout is no longer eligible to be shown, remove from active layouts.
+                    mActiveReachabilityEduLayout = null;
+                }
+                return;
             }
-            return;
         }
         // Create a new UI layout.
         final Context context = getOrCreateDisplayContext(taskInfo.displayId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
index 6592292..d4778fa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java
@@ -22,7 +22,6 @@
 import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
 import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.TaskInfo;
 import android.app.TaskInfo.CameraCompatControlState;
@@ -53,9 +52,6 @@
 
     private final Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> mOnRestartButtonClicked;
 
-    @NonNull
-    private TaskInfo mTaskInfo;
-
     // Remember the last reported states in case visibility changes due to keyguard or IME updates.
     @VisibleForTesting
     boolean mHasSizeCompat;
@@ -77,7 +73,6 @@
             CompatUIHintsState compatUIHintsState, CompatUIConfiguration compatUIConfiguration,
             Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> onRestartButtonClicked) {
         super(context, taskInfo, syncQueue, taskListener, displayLayout);
-        mTaskInfo = taskInfo;
         mCallback = callback;
         mHasSizeCompat = taskInfo.topActivityInSizeCompat;
         mCameraCompatControlState = taskInfo.cameraCompatControlState;
@@ -129,7 +124,6 @@
     @Override
     public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener,
             boolean canShow) {
-        mTaskInfo = taskInfo;
         final boolean prevHasSizeCompat = mHasSizeCompat;
         final int prevCameraCompatControlState = mCameraCompatControlState;
         mHasSizeCompat = taskInfo.topActivityInSizeCompat;
@@ -149,7 +143,7 @@
 
     /** Called when the restart button is clicked. */
     void onRestartButtonClicked() {
-        mOnRestartButtonClicked.accept(Pair.create(mTaskInfo, getTaskListener()));
+        mOnRestartButtonClicked.accept(Pair.create(getLastTaskInfo(), getTaskListener()));
     }
 
     /** Called when the camera treatment button is clicked. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
index 9c4e79c..180498c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
@@ -26,6 +26,7 @@
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.TaskInfo;
 import android.content.Context;
@@ -65,6 +66,9 @@
     private DisplayLayout mDisplayLayout;
     private final Rect mStableBounds;
 
+    @NonNull
+    private TaskInfo mTaskInfo;
+
     /**
      * Utility class for adding and releasing a View hierarchy for this {@link
      * WindowlessWindowManager} to {@code mLeash}.
@@ -83,6 +87,7 @@
             SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener,
             DisplayLayout displayLayout) {
         super(taskInfo.configuration, null /* rootSurface */, null /* hostInputToken */);
+        mTaskInfo = taskInfo;
         mContext = context;
         mSyncQueue = syncQueue;
         mTaskConfig = taskInfo.configuration;
@@ -95,6 +100,17 @@
     }
 
     /**
+     * @return {@code true} if the instance of the specific {@link CompatUIWindowManagerAbstract}
+     * for the current task id needs to be recreated loading the related resources. This happens
+     * if the user switches between Light/Dark mode, if the device is docked/undocked or if the
+     * user switches between multi-window mode to fullscreen where the
+     * {@link ShellTaskOrganizer.TaskListener} implementation is different.
+     */
+    boolean needsToBeRecreated(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) {
+        return hasUiModeChanged(mTaskInfo, taskInfo) || hasTaskListenerChanged(taskListener);
+    }
+
+    /**
      * Returns the z-order of this window which will be passed to the {@link SurfaceControl} once
      * {@link #attachToParentSurface} is called.
      *
@@ -195,6 +211,7 @@
     @VisibleForTesting(visibility = PROTECTED)
     public boolean updateCompatInfo(TaskInfo taskInfo,
             ShellTaskOrganizer.TaskListener taskListener, boolean canShow) {
+        mTaskInfo = taskInfo;
         final Configuration prevTaskConfig = mTaskConfig;
         final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener;
         mTaskConfig = taskInfo.configuration;
@@ -315,6 +332,11 @@
         updateSurfacePosition();
     }
 
+    @Nullable
+    protected TaskInfo getLastTaskInfo() {
+        return mTaskInfo;
+    }
+
     /**
      * Called following a change in the task bounds, display layout stable bounds, or the layout
      * direction.
@@ -402,4 +424,12 @@
     protected final String getTag() {
         return getClass().getSimpleName();
     }
+
+    protected boolean hasTaskListenerChanged(ShellTaskOrganizer.TaskListener newTaskListener) {
+        return !mTaskListener.equals(newTaskListener);
+    }
+
+    protected static boolean hasUiModeChanged(TaskInfo currentTaskInfo, TaskInfo newTaskInfo) {
+        return currentTaskInfo.configuration.uiMode != newTaskInfo.configuration.uiMode;
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java
index 959c50d..9a67258 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java
@@ -19,7 +19,6 @@
 import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING;
 import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.TaskInfo;
 import android.content.Context;
@@ -69,9 +68,6 @@
     @VisibleForTesting
     LetterboxEduDialogLayout mLayout;
 
-    @NonNull
-    private TaskInfo mTaskInfo;
-
     /**
      * The vertical margin between the dialog container and the task stable bounds (excluding
      * insets).
@@ -99,7 +95,6 @@
             DialogAnimationController<LetterboxEduDialogLayout> animationController,
             DockStateReader dockStateReader, CompatUIConfiguration compatUIConfiguration) {
         super(context, taskInfo, syncQueue, taskListener, displayLayout);
-        mTaskInfo = taskInfo;
         mTransitions = transitions;
         mOnDismissCallback = onDismissCallback;
         mAnimationController = animationController;
@@ -197,7 +192,7 @@
         mLayout.setDismissOnClickListener(null);
         mAnimationController.startExitAnimation(mLayout, () -> {
             release();
-            mOnDismissCallback.accept(Pair.create(mTaskInfo, getTaskListener()));
+            mOnDismissCallback.accept(Pair.create(getLastTaskInfo(), getTaskListener()));
         });
     }
 
@@ -210,7 +205,6 @@
     @Override
     public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener,
             boolean canShow) {
-        mTaskInfo = taskInfo;
         mEligibleForLetterboxEducation = taskInfo.topActivityEligibleForLetterboxEducation;
 
         return super.updateCompatInfo(taskInfo, taskListener, canShow);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java
index a18ab91..95bb1fe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java
@@ -20,7 +20,6 @@
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.TaskInfo;
 import android.content.Context;
@@ -52,9 +51,6 @@
 
     private final ShellExecutor mMainExecutor;
 
-    @NonNull
-    private TaskInfo mTaskInfo;
-
     private boolean mIsActivityLetterboxed;
 
     private int mLetterboxVerticalPosition;
@@ -86,7 +82,6 @@
             ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout,
             CompatUIConfiguration compatUIConfiguration, ShellExecutor mainExecutor) {
         super(context, taskInfo, syncQueue, taskListener, displayLayout);
-        mTaskInfo = taskInfo;
         mIsActivityLetterboxed = taskInfo.isLetterboxDoubleTapEnabled;
         mLetterboxVerticalPosition = taskInfo.topActivityLetterboxVerticalPosition;
         mLetterboxHorizontalPosition = taskInfo.topActivityLetterboxHorizontalPosition;
@@ -136,7 +131,6 @@
     @Override
     public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener,
             boolean canShow) {
-        mTaskInfo = taskInfo;
         final boolean prevIsActivityLetterboxed = mIsActivityLetterboxed;
         final int prevLetterboxVerticalPosition = mLetterboxVerticalPosition;
         final int prevLetterboxHorizontalPosition = mLetterboxHorizontalPosition;
@@ -222,14 +216,14 @@
         if (mLayout == null) {
             return;
         }
-
+        final TaskInfo lastTaskInfo = getLastTaskInfo();
         final boolean eligibleForDisplayHorizontalEducation = mForceUpdate
-                || !mCompatUIConfiguration.hasSeenHorizontalReachabilityEducation(mTaskInfo)
+                || !mCompatUIConfiguration.hasSeenHorizontalReachabilityEducation(lastTaskInfo)
                 || (mHasUserDoubleTapped
                     && (mLetterboxHorizontalPosition == REACHABILITY_LEFT_OR_UP_POSITION
                         || mLetterboxHorizontalPosition == REACHABILITY_RIGHT_OR_BOTTOM_POSITION));
         final boolean eligibleForDisplayVerticalEducation = mForceUpdate
-                || !mCompatUIConfiguration.hasSeenVerticalReachabilityEducation(mTaskInfo)
+                || !mCompatUIConfiguration.hasSeenVerticalReachabilityEducation(lastTaskInfo)
                 || (mHasUserDoubleTapped
                     && (mLetterboxVerticalPosition == REACHABILITY_LEFT_OR_UP_POSITION
                         || mLetterboxVerticalPosition == REACHABILITY_RIGHT_OR_BOTTOM_POSITION));
@@ -241,7 +235,7 @@
             mLayout.handleVisibility(eligibleForDisplayHorizontalEducation,
                     eligibleForDisplayVerticalEducation,
                     mLetterboxVerticalPosition, mLetterboxHorizontalPosition, availableWidth,
-                    availableHeight, mCompatUIConfiguration, mTaskInfo);
+                    availableHeight, mCompatUIConfiguration, lastTaskInfo);
             if (!mHasLetterboxSizeChanged) {
                 updateHideTime();
                 mMainExecutor.executeDelayed(this::hideReachability, DISAPPEAR_DELAY_MS);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
index 51e5141..a770da2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
@@ -19,7 +19,6 @@
 import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING;
 import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.TaskInfo;
 import android.content.Context;
@@ -67,9 +66,6 @@
      */
     private final int mDialogVerticalMargin;
 
-    @NonNull
-    private TaskInfo mTaskInfo;
-
     @Nullable
     @VisibleForTesting
     RestartDialogLayout mLayout;
@@ -95,7 +91,6 @@
             DialogAnimationController<RestartDialogLayout> animationController,
             CompatUIConfiguration compatUIConfiguration) {
         super(context, taskInfo, syncQueue, taskListener, displayLayout);
-        mTaskInfo = taskInfo;
         mTransitions = transitions;
         mOnDismissCallback = onDismissCallback;
         mOnRestartCallback = onRestartCallback;
@@ -125,7 +120,7 @@
     protected boolean eligibleToShowLayout() {
         // We don't show this dialog if the user has explicitly selected so clicking on a checkbox.
         return mRequestRestartDialog && !isTaskbarEduShowing() && (mLayout != null
-                || mCompatUIConfiguration.shouldShowRestartDialogAgain(mTaskInfo));
+                || mCompatUIConfiguration.shouldShowRestartDialogAgain(getLastTaskInfo()));
     }
 
     @Override
@@ -143,18 +138,6 @@
         mRequestRestartDialog = enabled;
     }
 
-    @Override
-    public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener,
-            boolean canShow) {
-        mTaskInfo = taskInfo;
-        return super.updateCompatInfo(taskInfo, taskListener, canShow);
-    }
-
-    boolean needsToBeRecreated(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) {
-        return taskInfo.configuration.uiMode != mTaskInfo.configuration.uiMode
-                || !getTaskListener().equals(taskListener);
-    }
-
     private void updateDialogMargins() {
         if (mLayout == null) {
             return;
@@ -191,6 +174,7 @@
             // Dialog has already been released.
             return;
         }
+        final TaskInfo lastTaskInfo = getLastTaskInfo();
         mLayout.setDismissOnClickListener(this::onDismiss);
         mLayout.setRestartOnClickListener(dontShowAgain -> {
             if (mLayout != null) {
@@ -200,9 +184,9 @@
                 });
             }
             if (dontShowAgain) {
-                mCompatUIConfiguration.setDontShowRestartDialogAgain(mTaskInfo);
+                mCompatUIConfiguration.setDontShowRestartDialogAgain(lastTaskInfo);
             }
-            mOnRestartCallback.accept(Pair.create(mTaskInfo, getTaskListener()));
+            mOnRestartCallback.accept(Pair.create(lastTaskInfo, getTaskListener()));
         });
         // Focus on the dialog title for accessibility.
         mLayout.getDialogTitle().sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
@@ -216,7 +200,7 @@
         mLayout.setDismissOnClickListener(null);
         mAnimationController.startExitAnimation(mLayout, () -> {
             release();
-            mOnDismissCallback.accept(Pair.create(mTaskInfo, getTaskListener()));
+            mOnDismissCallback.accept(Pair.create(getLastTaskInfo(), getTaskListener()));
         });
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt
index 00cc57f..3ab175d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt
@@ -23,6 +23,8 @@
 import androidx.core.util.forEach
 import androidx.core.util.keyIterator
 import androidx.core.util.valueIterator
+import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
+import com.android.wm.shell.util.KtProtoLog
 import java.util.concurrent.Executor
 import java.util.function.Consumer
 
@@ -140,6 +142,12 @@
 
         val added = displayData.getOrCreate(displayId).activeTasks.add(taskId)
         if (added) {
+            KtProtoLog.d(
+                WM_SHELL_DESKTOP_MODE,
+                "DesktopTaskRepo: add active task=%d displayId=%d",
+                taskId,
+                displayId
+            )
             activeTasksListeners.onEach { it.onActiveTasksChanged(displayId) }
         }
         return added
@@ -158,6 +166,9 @@
                 result = true
             }
         }
+        if (result) {
+            KtProtoLog.d(WM_SHELL_DESKTOP_MODE, "DesktopTaskRepo: remove active task=%d", taskId)
+        }
         return result
     }
 
@@ -221,6 +232,17 @@
             displayData[displayId]?.visibleTasks?.remove(taskId)
         }
         val newCount = getVisibleTaskCount(displayId)
+
+        if (prevCount != newCount) {
+            KtProtoLog.d(
+                WM_SHELL_DESKTOP_MODE,
+                "DesktopTaskRepo: update task visibility taskId=%d visible=%b displayId=%d",
+                taskId,
+                visible,
+                displayId
+            )
+        }
+
         // Check if count changed and if there was no tasks or this is the first task
         if (prevCount != newCount && (prevCount == 0 || newCount == 0)) {
             notifyVisibleTaskListeners(displayId, newCount > 0)
@@ -244,6 +266,11 @@
      * Add (or move if it already exists) the task to the top of the ordered list.
      */
     fun addOrMoveFreeformTaskToTop(taskId: Int) {
+        KtProtoLog.d(
+            WM_SHELL_DESKTOP_MODE,
+            "DesktopTaskRepo: add or move task to top taskId=%d",
+            taskId
+        )
         if (freeformTasksInZOrder.contains(taskId)) {
             freeformTasksInZOrder.remove(taskId)
         }
@@ -254,6 +281,11 @@
      * Remove the task from the ordered list.
      */
     fun removeFreeformTask(taskId: Int) {
+        KtProtoLog.d(
+            WM_SHELL_DESKTOP_MODE,
+            "DesktopTaskRepo: remove freeform task from ordered list taskId=%d",
+            taskId
+        )
         freeformTasksInZOrder.remove(taskId)
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index b310938..91bb155 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -39,7 +39,6 @@
 import android.window.WindowContainerToken
 import android.window.WindowContainerTransaction
 import androidx.annotation.BinderThread
-import com.android.internal.protolog.common.ProtoLog
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer
 import com.android.wm.shell.ShellTaskOrganizer
 import com.android.wm.shell.common.DisplayController
@@ -56,6 +55,7 @@
 import com.android.wm.shell.sysui.ShellInit
 import com.android.wm.shell.sysui.ShellSharedConstants
 import com.android.wm.shell.transition.Transitions
+import com.android.wm.shell.util.KtProtoLog
 import java.util.concurrent.Executor
 import java.util.function.Consumer
 
@@ -91,7 +91,7 @@
     }
 
     private fun onInit() {
-        ProtoLog.d(WM_SHELL_DESKTOP_MODE, "Initialize DesktopTasksController")
+        KtProtoLog.d(WM_SHELL_DESKTOP_MODE, "Initialize DesktopTasksController")
         shellController.addExternalInterface(
             ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE,
             { createExternalInterface() },
@@ -102,7 +102,7 @@
 
     /** Show all tasks, that are part of the desktop, on top of launcher */
     fun showDesktopApps(displayId: Int) {
-        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "showDesktopApps")
+        KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: showDesktopApps")
         val wct = WindowContainerTransaction()
         // TODO(b/278084491): pass in display id
         bringDesktopAppsToFront(displayId, wct)
@@ -130,8 +130,11 @@
 
     /** Move a task to desktop */
     fun moveToDesktop(task: RunningTaskInfo) {
-        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToDesktop: %d", task.taskId)
-
+        KtProtoLog.v(
+            WM_SHELL_DESKTOP_MODE,
+            "DesktopTasksController: moveToDesktop taskId=%d",
+            task.taskId
+        )
         val wct = WindowContainerTransaction()
         // Bring other apps to front first
         bringDesktopAppsToFront(task.displayId, wct)
@@ -147,10 +150,12 @@
      * Moves a single task to freeform and sets the taskBounds to the passed in bounds,
      * startBounds
      */
-    fun moveToFreeform(
-            taskInfo: RunningTaskInfo,
-            startBounds: Rect
-    ) {
+    fun moveToFreeform(taskInfo: RunningTaskInfo, startBounds: Rect) {
+        KtProtoLog.v(
+            WM_SHELL_DESKTOP_MODE,
+            "DesktopTasksController: moveToFreeform with bounds taskId=%d",
+            taskInfo.taskId
+        )
         val wct = WindowContainerTransaction()
         moveHomeTaskToFront(wct)
         addMoveToDesktopChanges(wct, taskInfo.getToken())
@@ -165,10 +170,12 @@
     }
 
     /** Brings apps to front and sets freeform task bounds */
-    private fun moveToDesktopWithAnimation(
-            taskInfo: RunningTaskInfo,
-            freeformBounds: Rect
-    ) {
+    private fun moveToDesktopWithAnimation(taskInfo: RunningTaskInfo, freeformBounds: Rect) {
+        KtProtoLog.v(
+            WM_SHELL_DESKTOP_MODE,
+            "DesktopTasksController: moveToDesktop with animation taskId=%d",
+            taskInfo.taskId
+        )
         val wct = WindowContainerTransaction()
         bringDesktopAppsToFront(taskInfo.displayId, wct)
         addMoveToDesktopChanges(wct, taskInfo.getToken())
@@ -190,7 +197,11 @@
 
     /** Move a task to fullscreen */
     fun moveToFullscreen(task: RunningTaskInfo) {
-        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToFullscreen: %d", task.taskId)
+        KtProtoLog.v(
+            WM_SHELL_DESKTOP_MODE,
+            "DesktopTasksController: moveToFullscreen taskId=%d",
+            task.taskId
+        )
 
         val wct = WindowContainerTransaction()
         addMoveToFullscreenChanges(wct, task.token)
@@ -206,6 +217,11 @@
      * status bar area
      */
     fun cancelMoveToFreeform(task: RunningTaskInfo, position: Point) {
+        KtProtoLog.v(
+                WM_SHELL_DESKTOP_MODE,
+                "DesktopTasksController: cancelMoveToFreeform taskId=%d",
+                task.taskId
+        )
         val wct = WindowContainerTransaction()
         addMoveToFullscreenChanges(wct, task.token)
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
@@ -218,6 +234,11 @@
     }
 
     private fun moveToFullscreenWithAnimation(task: RunningTaskInfo, position: Point) {
+        KtProtoLog.v(
+                WM_SHELL_DESKTOP_MODE,
+                "DesktopTasksController: moveToFullscreen with animation taskId=%d",
+                task.taskId
+        )
         val wct = WindowContainerTransaction()
         addMoveToFullscreenChanges(wct, task.token)
 
@@ -230,8 +251,14 @@
         }
     }
 
-    /** Move a task to the front **/
+    /** Move a task to the front */
     fun moveTaskToFront(taskInfo: RunningTaskInfo) {
+        KtProtoLog.v(
+            WM_SHELL_DESKTOP_MODE,
+            "DesktopTasksController: moveTaskToFront taskId=%d",
+            taskInfo.taskId
+        )
+
         val wct = WindowContainerTransaction()
         wct.reorder(taskInfo.token, true)
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
@@ -255,10 +282,10 @@
     fun moveToNextDisplay(taskId: Int) {
         val task = shellTaskOrganizer.getRunningTaskInfo(taskId)
         if (task == null) {
-            ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d not found", taskId)
+            KtProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d not found", taskId)
             return
         }
-        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d taskDisplayId=%d",
+        KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d taskDisplayId=%d",
                 taskId, task.displayId)
 
         val displayIds = rootTaskDisplayAreaOrganizer.displayIds.sorted()
@@ -269,7 +296,7 @@
             newDisplayId = displayIds.firstOrNull { displayId -> displayId < task.displayId }
         }
         if (newDisplayId == null) {
-            ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: next display not found")
+            KtProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: next display not found")
             return
         }
         moveToDisplay(task, newDisplayId)
@@ -281,17 +308,17 @@
      * No-op if task is already on that display per [RunningTaskInfo.displayId].
      */
     private fun moveToDisplay(task: RunningTaskInfo, displayId: Int) {
-        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToDisplay: taskId=%d displayId=%d",
+        KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToDisplay: taskId=%d displayId=%d",
                 task.taskId, displayId)
 
         if (task.displayId == displayId) {
-            ProtoLog.d(WM_SHELL_DESKTOP_MODE, "moveToDisplay: task already on display")
+            KtProtoLog.d(WM_SHELL_DESKTOP_MODE, "moveToDisplay: task already on display")
             return
         }
 
         val displayAreaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId)
         if (displayAreaInfo == null) {
-            ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToDisplay: display not found")
+            KtProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToDisplay: display not found")
             return
         }
 
@@ -316,7 +343,7 @@
     }
 
     private fun bringDesktopAppsToFront(displayId: Int, wct: WindowContainerTransaction) {
-        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront")
+        KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "DesktopTasksController: bringDesktopAppsToFront")
         val activeTasks = desktopModeTaskRepository.getActiveTasks(displayId)
 
         // First move home to front and then other tasks on top of it
@@ -397,9 +424,9 @@
         if (task.windowingMode == WINDOWING_MODE_FULLSCREEN) {
             // If there are any visible desktop tasks, switch the task to freeform
             if (activeTasks.any { desktopModeTaskRepository.isVisibleTask(it) }) {
-                ProtoLog.d(
+                KtProtoLog.d(
                     WM_SHELL_DESKTOP_MODE,
-                    "DesktopTasksController#handleRequest: switch fullscreen task to freeform," +
+                    "DesktopTasksController: switch fullscreen task to freeform on transition" +
                         " taskId=%d",
                     task.taskId
                 )
@@ -414,9 +441,9 @@
             // If no visible desktop tasks, switch this task to freeform as the transition came
             // outside of this controller
             if (activeTasks.none { desktopModeTaskRepository.isVisibleTask(it) }) {
-                ProtoLog.d(
+                KtProtoLog.d(
                     WM_SHELL_DESKTOP_MODE,
-                    "DesktopTasksController#handleRequest: switch freeform task to fullscreen," +
+                    "DesktopTasksController: switch freeform task to fullscreen oon transition" +
                         " taskId=%d",
                     task.taskId
                 )
@@ -627,8 +654,6 @@
         }
     }
 
-
-
     /** The interface for calls from outside the host process. */
     @BinderThread
     private class IDesktopModeImpl(private var controller: DesktopTasksController?) :
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
index ccbb9cf..a3803ed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
@@ -1,3 +1,4 @@
 # WM shell sub-module freeform owners
 [email protected]
[email protected]
 [email protected]
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
index 24d0b99..f51eb52 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
@@ -180,6 +180,35 @@
         return null;
     }
 
+
+    /**
+     * Returns the source hint rect if it is valid (if provided and is contained by the current
+     * task bounds, while not smaller than the destination bounds).
+     */
+    @Nullable
+    public static Rect getValidSourceHintRect(PictureInPictureParams params, Rect sourceBounds,
+            Rect destinationBounds) {
+        Rect sourceRectHint = getValidSourceHintRect(params, sourceBounds);
+        if (!isSourceRectHintValidForEnterPip(sourceRectHint, destinationBounds)) {
+            sourceRectHint = null;
+        }
+        return sourceRectHint;
+    }
+
+    /**
+     * This is a situation in which the source rect hint on at least one axis is smaller
+     * than the destination bounds, which represents a problem because we would have to scale
+     * up that axis to fit the bounds. So instead, just fallback to the non-source hint
+     * animation in this case.
+     *
+     * @return {@code false} if the given source is too small to use for the entering animation.
+     */
+    static boolean isSourceRectHintValidForEnterPip(Rect sourceRectHint, Rect destinationBounds) {
+        return sourceRectHint != null
+                && sourceRectHint.width() > destinationBounds.width()
+                && sourceRectHint.height() > destinationBounds.height();
+    }
+
     public float getDefaultAspectRatio() {
         return mDefaultAspectRatio;
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 6cedcf5..363d675 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -1657,8 +1657,8 @@
                     "%s: Abort animation, invalid leash", TAG);
             return null;
         }
-        if (isInPipDirection(direction)
-                && !isSourceRectHintValidForEnterPip(sourceHintRect, destinationBounds)) {
+        if (isInPipDirection(direction) && !PipBoundsAlgorithm
+                .isSourceRectHintValidForEnterPip(sourceHintRect, destinationBounds)) {
             // The given source rect hint is too small for enter PiP animation, reset it to null.
             sourceHintRect = null;
         }
@@ -1757,20 +1757,6 @@
     }
 
     /**
-     * This is a situation in which the source rect hint on at least one axis is smaller
-     * than the destination bounds, which represents a problem because we would have to scale
-     * up that axis to fit the bounds. So instead, just fallback to the non-source hint
-     * animation in this case.
-     *
-     * @return {@code false} if the given source is too small to use for the entering animation.
-     */
-    private boolean isSourceRectHintValidForEnterPip(Rect sourceRectHint, Rect destinationBounds) {
-        return sourceRectHint != null
-                && sourceRectHint.width() > destinationBounds.width()
-                && sourceRectHint.height() > destinationBounds.height();
-    }
-
-    /**
      * Sync with {@link SplitScreenController} on destination bounds if PiP is going to
      * split screen.
      *
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 98db707..6b8108a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -764,7 +764,7 @@
         final Rect currentBounds = taskInfo.configuration.windowConfiguration.getBounds();
         int rotationDelta = deltaRotation(startRotation, endRotation);
         Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
-                taskInfo.pictureInPictureParams, currentBounds);
+                taskInfo.pictureInPictureParams, currentBounds, destinationBounds);
         if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) {
             // Need to get the bounds of new rotation in old rotation for fixed rotation,
             computeEnterPipRotatedBounds(rotationDelta, startRotation, endRotation, taskInfo,
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 5c2f1438..b8373f3 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
@@ -1538,7 +1538,7 @@
     }
 
     void finishEnterSplitScreen(SurfaceControl.Transaction t) {
-        mSplitLayout.init();
+        mSplitLayout.update(t);
         setDividerVisibility(true, t);
         // Ensure divider surface are re-parented back into the hierarchy at the end of the
         // transition. See Transition#buildFinishTransaction for more detail.
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 1ee52ae..dfad8b9 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
@@ -24,6 +24,7 @@
 import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
 import static android.app.admin.DevicePolicyManager.EXTRA_RESOURCE_TYPE;
@@ -329,6 +330,8 @@
         @ColorInt int backgroundColorForTransition = 0;
         final int wallpaperTransit = getWallpaperTransitType(info);
         boolean isDisplayRotationAnimationStarted = false;
+        final boolean isDreamTransition = isDreamTransition(info);
+
         for (int i = info.getChanges().size() - 1; i >= 0; --i) {
             final TransitionInfo.Change change = info.getChanges().get(i);
             if (change.hasAllFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY
@@ -424,7 +427,7 @@
             // Don't animate anything that isn't independent.
             if (!TransitionInfo.isIndependent(change, info)) continue;
 
-            Animation a = loadAnimation(info, change, wallpaperTransit);
+            Animation a = loadAnimation(info, change, wallpaperTransit, isDreamTransition);
             if (a != null) {
                 if (isTask) {
                     final @TransitionType int type = info.getType();
@@ -519,6 +522,18 @@
         return true;
     }
 
+    private static boolean isDreamTransition(@NonNull TransitionInfo info) {
+        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+            final TransitionInfo.Change change = info.getChanges().get(i);
+            if (change.getTaskInfo() != null
+                    && change.getTaskInfo().topActivityType == ACTIVITY_TYPE_DREAM) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     @Override
     public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
             @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
@@ -572,7 +587,8 @@
 
     @Nullable
     private Animation loadAnimation(@NonNull TransitionInfo info,
-            @NonNull TransitionInfo.Change change, int wallpaperTransit) {
+            @NonNull TransitionInfo.Change change, int wallpaperTransit,
+            boolean isDreamTransition) {
         Animation a;
 
         final int type = info.getType();
@@ -630,7 +646,8 @@
             // If there's a scene-transition, then jump-cut.
             return null;
         } else {
-            a = loadAttributeAnimation(info, change, wallpaperTransit, mTransitionAnimation);
+            a = loadAttributeAnimation(
+                    info, change, wallpaperTransit, mTransitionAnimation, isDreamTransition);
         }
 
         if (a != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java
index 0cede90..e27e4f9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java
@@ -28,7 +28,6 @@
 import android.util.Log;
 
 import com.android.internal.util.TraceBuffer;
-import com.android.wm.shell.nano.HandlerMapping;
 import com.android.wm.shell.sysui.ShellCommandHandler;
 
 import com.google.protobuf.nano.MessageNano;
@@ -41,6 +40,7 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Queue;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Helper class to collect and dump transition traces.
@@ -241,6 +241,10 @@
                     new com.android.wm.shell.nano.WmShellTransitionTraceProto();
             proto.magicNumber = MAGIC_NUMBER_VALUE;
             writeHandlerMappingToProto(proto);
+            long timeOffsetNs =
+                    TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis())
+                            - SystemClock.elapsedRealtimeNanos();
+            proto.realToElapsedTimeOffsetNanos = timeOffsetNs;
             int pid = android.os.Process.myPid();
             LogAndPrintln.i(pw, "Writing file to " + file.getAbsolutePath()
                     + " from process " + pid);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
index 0f4645c..19d8384 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
@@ -18,7 +18,6 @@
 
 import static android.app.ActivityOptions.ANIM_FROM_STYLE;
 import static android.app.ActivityOptions.ANIM_NONE;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
@@ -63,7 +62,7 @@
     @Nullable
     public static Animation loadAttributeAnimation(@NonNull TransitionInfo info,
             @NonNull TransitionInfo.Change change, int wallpaperTransit,
-            @NonNull TransitionAnimation transitionAnimation) {
+            @NonNull TransitionAnimation transitionAnimation, boolean isDreamTransition) {
         final int type = info.getType();
         final int changeMode = change.getMode();
         final int changeFlags = change.getFlags();
@@ -71,11 +70,9 @@
         final boolean isTask = change.getTaskInfo() != null;
         final TransitionInfo.AnimationOptions options = info.getAnimationOptions();
         final int overrideType = options != null ? options.getType() : ANIM_NONE;
-        final boolean isDream =
-                isTask && change.getTaskInfo().topActivityType == ACTIVITY_TYPE_DREAM;
         int animAttr = 0;
         boolean translucent = false;
-        if (isDream) {
+        if (isDreamTransition) {
             if (type == TRANSIT_OPEN) {
                 animAttr = enter
                         ? R.styleable.WindowAnimation_dreamActivityOpenEnterAnimation
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt
new file mode 100644
index 0000000..9b48a54
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.util
+
+import android.util.Log
+import com.android.internal.protolog.common.IProtoLogGroup
+import com.android.wm.shell.protolog.ShellProtoLogImpl
+
+/**
+ * Log messages using an API similar to [com.android.internal.protolog.common.ProtoLog]. Useful for
+ * logging from Kotlin classes as ProtoLog does not have support for Kotlin.
+ *
+ * All messages are logged to logcat if logging is enabled for that [IProtoLogGroup].
+ */
+// TODO(b/168581922): remove once ProtoLog adds support for Kotlin
+class KtProtoLog {
+    companion object {
+        /** @see [com.android.internal.protolog.common.ProtoLog.d] */
+        fun d(group: IProtoLogGroup, messageString: String, vararg args: Any) {
+            if (ShellProtoLogImpl.isEnabled(group)) {
+                Log.d(group.tag, String.format(messageString, *args))
+            }
+        }
+
+        /** @see [com.android.internal.protolog.common.ProtoLog.v] */
+        fun v(group: IProtoLogGroup, messageString: String, vararg args: Any) {
+            if (ShellProtoLogImpl.isEnabled(group)) {
+                Log.v(group.tag, String.format(messageString, *args))
+            }
+        }
+
+        /** @see [com.android.internal.protolog.common.ProtoLog.i] */
+        fun i(group: IProtoLogGroup, messageString: String, vararg args: Any) {
+            if (ShellProtoLogImpl.isEnabled(group)) {
+                Log.i(group.tag, String.format(messageString, *args))
+            }
+        }
+
+        /** @see [com.android.internal.protolog.common.ProtoLog.w] */
+        fun w(group: IProtoLogGroup, messageString: String, vararg args: Any) {
+            if (ShellProtoLogImpl.isEnabled(group)) {
+                Log.w(group.tag, String.format(messageString, *args))
+            }
+        }
+
+        /** @see [com.android.internal.protolog.common.ProtoLog.e] */
+        fun e(group: IProtoLogGroup, messageString: String, vararg args: Any) {
+            if (ShellProtoLogImpl.isEnabled(group)) {
+                Log.e(group.tag, String.format(messageString, *args))
+            }
+        }
+
+        /** @see [com.android.internal.protolog.common.ProtoLog.wtf] */
+        fun wtf(group: IProtoLogGroup, messageString: String, vararg args: Any) {
+            if (ShellProtoLogImpl.isEnabled(group)) {
+                Log.wtf(group.tag, String.format(messageString, *args))
+            }
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/OWNERS b/libs/WindowManager/Shell/tests/OWNERS
index 64dfc3e..deebad5 100644
--- a/libs/WindowManager/Shell/tests/OWNERS
+++ b/libs/WindowManager/Shell/tests/OWNERS
@@ -8,3 +8,4 @@
 [email protected]
 [email protected]
 [email protected]
[email protected]
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
index 4de5298..55781f1b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java
@@ -37,6 +37,7 @@
 
 import android.app.ActivityManager;
 import android.app.TaskInfo;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.testing.AndroidTestingRunner;
 import android.util.Pair;
@@ -455,12 +456,21 @@
         verify(mLayout).setCameraCompatHintVisibility(/* show= */ true);
     }
 
+    @Test
+    public void testWhenDockedStateHasChanged_needsToBeRecreated() {
+        ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo();
+        newTaskInfo.configuration.uiMode |= Configuration.UI_MODE_TYPE_DESK;
+
+        Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener));
+    }
+
     private static TaskInfo createTaskInfo(boolean hasSizeCompat,
             @TaskInfo.CameraCompatControlState int cameraCompatControlState) {
         ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
         taskInfo.taskId = TASK_ID;
         taskInfo.topActivityInSizeCompat = hasSizeCompat;
         taskInfo.cameraCompatControlState = cameraCompatControlState;
+        taskInfo.configuration.uiMode &= ~Configuration.UI_MODE_TYPE_DESK;
         return taskInfo;
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java
index 5bcc72e..973a99c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java
@@ -21,6 +21,7 @@
 
 import android.app.ActivityManager;
 import android.app.TaskInfo;
+import android.content.res.Configuration;
 import android.testing.AndroidTestingRunner;
 
 import androidx.test.filters.SmallTest;
@@ -31,6 +32,8 @@
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.SyncTransactionQueue;
 
+import junit.framework.Assert;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -46,63 +49,61 @@
 @RunWith(AndroidTestingRunner.class)
 @SmallTest
 public class ReachabilityEduWindowManagerTest extends ShellTestCase {
-
-    private static final int USER_ID = 1;
-    private static final int TASK_ID = 1;
-
     @Mock
     private SyncTransactionQueue mSyncTransactionQueue;
     @Mock
     private ShellTaskOrganizer.TaskListener mTaskListener;
     @Mock
-    private CompatUIController.CompatUICallback mCallback;
-    @Mock
     private CompatUIConfiguration mCompatUIConfiguration;
     @Mock
     private DisplayLayout mDisplayLayout;
-
     private TestShellExecutor mExecutor;
+    private TaskInfo mTaskInfo;
+    private ReachabilityEduWindowManager mWindowManager;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mExecutor = new TestShellExecutor();
+        mTaskInfo = new ActivityManager.RunningTaskInfo();
+        mTaskInfo.configuration.uiMode =
+                (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK)
+                        | Configuration.UI_MODE_NIGHT_NO;
+        mTaskInfo.configuration.uiMode =
+                (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_TYPE_MASK)
+                        | Configuration.UI_MODE_TYPE_NORMAL;
+        mWindowManager = createReachabilityEduWindowManager(mTaskInfo);
     }
 
     @Test
     public void testCreateLayout_notEligible_doesNotCreateLayout() {
-        final ReachabilityEduWindowManager windowManager = createReachabilityEduWindowManager(
-                createTaskInfo(/* userId= */ USER_ID, /*isLetterboxDoubleTapEnabled  */ false));
+        assertFalse(mWindowManager.createLayout(/* canShow= */ true));
 
-        assertFalse(windowManager.createLayout(/* canShow= */ true));
+        assertNull(mWindowManager.mLayout);
+    }
 
-        assertNull(windowManager.mLayout);
+    @Test
+    public void testWhenDockedStateHasChanged_needsToBeRecreated() {
+        ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo();
+        newTaskInfo.configuration.uiMode =
+                (newTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_TYPE_MASK)
+                        | Configuration.UI_MODE_TYPE_DESK;
+
+        Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener));
+    }
+
+    @Test
+    public void testWhenDarkLightThemeHasChanged_needsToBeRecreated() {
+        ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo();
+        mTaskInfo.configuration.uiMode =
+                (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK)
+                        | Configuration.UI_MODE_NIGHT_YES;
+
+        Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener));
     }
 
     private ReachabilityEduWindowManager createReachabilityEduWindowManager(TaskInfo taskInfo) {
         return new ReachabilityEduWindowManager(mContext, taskInfo, mSyncTransactionQueue,
                 mTaskListener, mDisplayLayout, mCompatUIConfiguration, mExecutor);
     }
-
-    private static TaskInfo createTaskInfo(int userId, boolean isLetterboxDoubleTapEnabled) {
-        return createTaskInfo(userId, /* isLetterboxDoubleTapEnabled */ isLetterboxDoubleTapEnabled,
-                /* topActivityLetterboxVerticalPosition */ -1,
-                /* topActivityLetterboxHorizontalPosition */ -1,
-                /* topActivityLetterboxWidth */ -1,
-                /* topActivityLetterboxHeight */ -1);
-    }
-
-    private static TaskInfo createTaskInfo(int userId, boolean isLetterboxDoubleTapEnabled,
-            int topActivityLetterboxVerticalPosition, int topActivityLetterboxHorizontalPosition,
-            int topActivityLetterboxWidth, int topActivityLetterboxHeight) {
-        ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
-        taskInfo.userId = userId;
-        taskInfo.taskId = TASK_ID;
-        taskInfo.isLetterboxDoubleTapEnabled = isLetterboxDoubleTapEnabled;
-        taskInfo.topActivityLetterboxVerticalPosition = topActivityLetterboxVerticalPosition;
-        taskInfo.topActivityLetterboxHorizontalPosition = topActivityLetterboxHorizontalPosition;
-        taskInfo.topActivityLetterboxWidth = topActivityLetterboxWidth;
-        taskInfo.topActivityLetterboxHeight = topActivityLetterboxHeight;
-        return taskInfo;
-    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/RestartDialogWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/RestartDialogWindowManagerTest.java
new file mode 100644
index 0000000..9f109a1
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/RestartDialogWindowManagerTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.compatui;
+
+import android.app.ActivityManager;
+import android.app.TaskInfo;
+import android.content.res.Configuration;
+import android.testing.AndroidTestingRunner;
+import android.util.Pair;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.transition.Transitions;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.Consumer;
+
+/**
+ * Tests for {@link RestartDialogWindowManager}.
+ *
+ * Build/Install/Run:
+ *  atest WMShellUnitTests:RestartDialogWindowManagerTest
+ */
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class RestartDialogWindowManagerTest extends ShellTestCase {
+
+    @Mock
+    private SyncTransactionQueue mSyncTransactionQueue;
+    @Mock private ShellTaskOrganizer.TaskListener mTaskListener;
+    @Mock private CompatUIConfiguration mCompatUIConfiguration;
+    @Mock private Transitions mTransitions;
+    @Mock private  Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> mOnRestartCallback;
+    @Mock private  Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> mOnDismissCallback;
+    private RestartDialogWindowManager mWindowManager;
+    private TaskInfo mTaskInfo;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mTaskInfo = new ActivityManager.RunningTaskInfo();
+        mTaskInfo.configuration.uiMode =
+                (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK)
+                        | Configuration.UI_MODE_NIGHT_NO;
+        mTaskInfo.configuration.uiMode =
+                (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_TYPE_MASK)
+                        | Configuration.UI_MODE_TYPE_NORMAL;
+        mWindowManager = new RestartDialogWindowManager(mContext, mTaskInfo, mSyncTransactionQueue,
+                mTaskListener, new DisplayLayout(), mTransitions, mOnRestartCallback,
+                mOnDismissCallback, mCompatUIConfiguration);
+    }
+
+    @Test
+    public void testWhenDockedStateHasChanged_needsToBeRecreated() {
+        ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo();
+        newTaskInfo.configuration.uiMode =
+                (newTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_TYPE_MASK)
+                        | Configuration.UI_MODE_TYPE_DESK;
+
+        Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener));
+    }
+
+    @Test
+    public void testWhenDarkLightThemeHasChanged_needsToBeRecreated() {
+        ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo();
+        mTaskInfo.configuration.uiMode =
+                (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK)
+                        | Configuration.UI_MODE_NIGHT_YES;
+
+        Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener));
+    }
+}
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 88e3519..e21d6fb 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -45,14 +45,13 @@
 // --- PointerController::DisplayInfoListener ---
 
 void PointerController::DisplayInfoListener::onWindowInfosChanged(
-        const std::vector<android::gui::WindowInfo>&,
-        const std::vector<android::gui::DisplayInfo>& displayInfos) {
+        const gui::WindowInfosUpdate& update) {
     std::scoped_lock lock(mLock);
     if (mPointerController == nullptr) return;
 
     // PointerController uses DisplayInfoListener's lock.
     base::ScopedLockAssertion assumeLocked(mPointerController->getLock());
-    mPointerController->onDisplayInfosChangedLocked(displayInfos);
+    mPointerController->onDisplayInfosChangedLocked(update.displayInfos);
 }
 
 void PointerController::DisplayInfoListener::onPointerControllerDestroyed() {
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index ca14b6e..62ee7433 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -19,6 +19,7 @@
 
 #include <PointerControllerInterface.h>
 #include <gui/DisplayEventReceiver.h>
+#include <gui/WindowInfosUpdate.h>
 #include <input/DisplayViewport.h>
 #include <input/Input.h>
 #include <utils/BitSet.h>
@@ -114,8 +115,7 @@
     class DisplayInfoListener : public gui::WindowInfosListener {
     public:
         explicit DisplayInfoListener(PointerController* pc) : mPointerController(pc){};
-        void onWindowInfosChanged(const std::vector<android::gui::WindowInfo>&,
-                                  const std::vector<android::gui::DisplayInfo>&) override;
+        void onWindowInfosChanged(const gui::WindowInfosUpdate&) override;
         void onPointerControllerDestroyed();
 
         // This lock is also used by PointerController. See PointerController::getLock().
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp
index 2378d42..8574751 100644
--- a/libs/input/tests/PointerController_test.cpp
+++ b/libs/input/tests/PointerController_test.cpp
@@ -343,7 +343,7 @@
         localListenerCopy = registeredListener;
     }
     EXPECT_EQ(nullptr, registeredListener) << "WindowInfosListener was not unregistered";
-    localListenerCopy->onWindowInfosChanged({}, {});
+    localListenerCopy->onWindowInfosChanged({{}, {}, 0, 0});
 }
 
 }  // namespace android
diff --git a/media/aidl/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl b/media/aidl/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl
index 531b3ae..bc6a259 100644
--- a/media/aidl/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl
+++ b/media/aidl/android/media/soundtrigger_middleware/ISoundTriggerMiddlewareService.aidl
@@ -80,14 +80,16 @@
      *   This implies that the caller must clear its caller identity to protect from the case where
      *   it resides in the same process as the callee.
      * - The identity of the entity on behalf of which module operations are to be performed.
-     *
+     * @param isTrusted - {@code true} if the middleware should not audit data delivery, since the
+     * callback is being delivered to another trusted component which will audit access.
      * listModules() must be called prior to calling this method and the provided handle must be
      * one of the handles from the returned list.
      */
     ISoundTriggerModule attachAsMiddleman(int handle,
                                           in Identity middlemanIdentity,
                                           in Identity originatorIdentity,
-                                          ISoundTriggerCallback callback);
+                                          ISoundTriggerCallback callback,
+                                          boolean isTrusted);
 
     /**
      * Attach an injection interface interface to the ST mock HAL.
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategy.java b/media/java/android/media/audiopolicy/AudioProductStrategy.java
index 0289aa3..3394dd0 100644
--- a/media/java/android/media/audiopolicy/AudioProductStrategy.java
+++ b/media/java/android/media/audiopolicy/AudioProductStrategy.java
@@ -203,10 +203,16 @@
 
         AudioProductStrategy thatStrategy = (AudioProductStrategy) o;
 
-        return mName == thatStrategy.mName && mId == thatStrategy.mId
+        return mId == thatStrategy.mId
+                && Objects.equals(mName, thatStrategy.mName)
                 && Arrays.equals(mAudioAttributesGroups, thatStrategy.mAudioAttributesGroups);
     }
 
+    @Override
+    public int hashCode() {
+        return Objects.hash(mId, mName, Arrays.hashCode(mAudioAttributesGroups));
+    }
+
     /**
      * @param name of the product strategy
      * @param id of the product strategy
@@ -460,6 +466,12 @@
                     && Arrays.equals(mAudioAttributes, thatAag.mAudioAttributes);
         }
 
+        @Override
+        public int hashCode() {
+            return Objects.hash(mVolumeGroupId, mLegacyStreamType,
+                    Arrays.hashCode(mAudioAttributes));
+        }
+
         public int getStreamType() {
             return mLegacyStreamType;
         }
diff --git a/media/java/android/media/tv/AdBuffer.java b/media/java/android/media/tv/AdBuffer.java
index 230d763..f2b772f 100644
--- a/media/java/android/media/tv/AdBuffer.java
+++ b/media/java/android/media/tv/AdBuffer.java
@@ -22,6 +22,8 @@
 import android.os.Parcelable;
 import android.os.SharedMemory;
 
+import java.io.IOException;
+
 /**
  * Buffer for advertisement data.
  */
@@ -57,6 +59,16 @@
         this.mFlags = flags;
     }
 
+    /** @hide **/
+    public static AdBuffer dupAdBuffer(AdBuffer buffer) throws IOException {
+        if (buffer == null) {
+            return null;
+        }
+        return new AdBuffer(buffer.mId, buffer.mMimeType,
+                SharedMemory.fromFileDescriptor(buffer.mBuffer.getFdDup()), buffer.mOffset,
+                buffer.mLength, buffer.mPresentationTimeUs, buffer.mFlags);
+    }
+
     /**
      * Gets corresponding AD request ID.
      *
diff --git a/media/java/android/media/tv/AdRequest.java b/media/java/android/media/tv/AdRequest.java
index d8cddfc..5f6b2b5 100644
--- a/media/java/android/media/tv/AdRequest.java
+++ b/media/java/android/media/tv/AdRequest.java
@@ -72,6 +72,22 @@
     private final Bundle mMetadata;
     private final Uri mUri;
 
+    /**
+     * The key for video metadata.
+     *
+     * @see #getMetadata()
+     * @hide
+     */
+    public static final String KEY_VIDEO_METADATA = "key_video_metadata";
+
+    /**
+     * The key for audio metadata.
+     *
+     * @see #getMetadata()
+     * @hide
+     */
+    public static final String KEY_AUDIO_METADATA = "key_audio_metadata";
+
     public AdRequest(int id, @RequestType int requestType,
             @Nullable ParcelFileDescriptor fileDescriptor, long startTime, long stopTime,
             long echoInterval, @Nullable String mediaFileType, @NonNull Bundle metadata) {
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index f344fd3..631ab9a 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -3737,6 +3737,10 @@
                 mService.notifyAdBufferReady(mToken, buffer, mUserId);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
+            } finally {
+                if (buffer != null) {
+                    buffer.getSharedMemory().close();
+                }
             }
         }
 
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
index 06d1acd..7cce84a 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
@@ -1608,6 +1608,10 @@
                 mService.notifyAdBufferConsumed(mToken, buffer, mUserId);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
+            } finally {
+                if (buffer != null) {
+                    buffer.getSharedMemory().close();
+                }
             }
         }
 
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
index 06dfe4f..ec85cc7 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
@@ -69,6 +69,7 @@
 
 import com.android.internal.os.SomeArgs;
 
+import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -1973,9 +1974,9 @@
                                     "notifyAdBufferReady(buffer=" + buffer + ")");
                         }
                         if (mSessionCallback != null) {
-                            mSessionCallback.onAdBufferReady(buffer);
+                            mSessionCallback.onAdBufferReady(AdBuffer.dupAdBuffer(buffer));
                         }
-                    } catch (RemoteException e) {
+                    } catch (RemoteException | IOException e) {
                         Log.w(TAG, "error in notifyAdBuffer", e);
                     }
                 }
diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioProductStrategyTest.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioProductStrategyTest.java
index b66545a..266faae 100644
--- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioProductStrategyTest.java
+++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioProductStrategyTest.java
@@ -29,11 +29,14 @@
 import android.media.AudioSystem;
 import android.media.audiopolicy.AudioProductStrategy;
 import android.media.audiopolicy.AudioVolumeGroup;
+import android.os.Parcel;
 import android.platform.test.annotations.Presubmit;
 import android.util.Log;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
+import com.google.common.testing.EqualsTester;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -231,4 +234,26 @@
             }
         }
     }
+
+    @Test
+    public void testEquals() {
+        final EqualsTester equalsTester = new EqualsTester();
+
+        AudioProductStrategy.getAudioProductStrategies().forEach(
+                strategy -> equalsTester.addEqualityGroup(strategy,
+                        writeToAndFromParcel(strategy)));
+
+        equalsTester.testEquals();
+    }
+
+    private static AudioProductStrategy writeToAndFromParcel(
+            AudioProductStrategy audioProductStrategy) {
+        Parcel parcel = Parcel.obtain();
+        audioProductStrategy.writeToParcel(parcel, /*flags=*/0);
+        parcel.setDataPosition(0);
+        AudioProductStrategy unmarshalledAudioProductStrategy =
+                AudioProductStrategy.CREATOR.createFromParcel(parcel);
+        parcel.recycle();
+        return unmarshalledAudioProductStrategy;
+    }
 }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index a35310c..b81339e8 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -213,7 +213,7 @@
                     }
                 }
             return com.android.credentialmanager.getflow.RequestDisplayInfo(
-                appName = originName
+                appName = originName?.ifEmpty { null }
                     ?: getAppLabel(context.packageManager, requestInfo.appPackageName)
                     ?: return null,
                 preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials,
@@ -286,7 +286,8 @@
                             pendingIntent = credentialEntry.pendingIntent,
                             fillInIntent = it.frameworkExtrasIntent,
                             credentialType = CredentialType.UNKNOWN,
-                            credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
+                            credentialTypeDisplayName =
+                            credentialEntry.typeDisplayName?.toString().orEmpty(),
                             userName = credentialEntry.title.toString(),
                             displayName = credentialEntry.subtitle?.toString(),
                             icon = credentialEntry.icon.loadDrawable(context),
@@ -461,7 +462,7 @@
             if (requestInfo == null) {
                 return null
             }
-            val appLabel = originName
+            val appLabel = originName?.ifEmpty { null }
                 ?: getAppLabel(context.packageManager, requestInfo.appPackageName)
                 ?: return null
             val createCredentialRequest = requestInfo.createCredentialRequest ?: return null
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index d16120f..a258984 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -436,7 +436,8 @@
                 },
             )
         }
-        if (createOptionInfo.footerDescription != null) {
+        val footerDescription = createOptionInfo.footerDescription
+        if (footerDescription != null && footerDescription.length > 0) {
             item {
                 Divider(
                     thickness = 1.dp,
@@ -446,7 +447,7 @@
             }
             item {
                 Row(modifier = Modifier.fillMaxWidth().wrapContentHeight()) {
-                    BodySmallText(text = createOptionInfo.footerDescription)
+                    BodySmallText(text = footerDescription)
                 }
             }
         }
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp b/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp
index e9000a8..df43863 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp
@@ -27,6 +27,7 @@
         "//apex_available:platform",
         "com.android.adservices",
         "com.android.cellbroadcast",
+        "com.android.devicelock",
         "com.android.extservices",
         "com.android.permission",
         "com.android.healthfitness",
diff --git a/packages/SettingsLib/SettingsTheme/Android.bp b/packages/SettingsLib/SettingsTheme/Android.bp
index d26ad1c..e6fb720 100644
--- a/packages/SettingsLib/SettingsTheme/Android.bp
+++ b/packages/SettingsLib/SettingsTheme/Android.bp
@@ -16,6 +16,7 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.cellbroadcast",
+        "com.android.devicelock",
         "com.android.extservices",
         "com.android.permission",
         "com.android.adservices",
diff --git a/packages/SettingsLib/SettingsTransition/Android.bp b/packages/SettingsLib/SettingsTransition/Android.bp
index 0f9f781..48cc75d 100644
--- a/packages/SettingsLib/SettingsTransition/Android.bp
+++ b/packages/SettingsLib/SettingsTransition/Android.bp
@@ -22,6 +22,7 @@
         "//apex_available:platform",
         "com.android.adservices",
         "com.android.cellbroadcast",
+        "com.android.devicelock",
         "com.android.extservices",
         "com.android.permission",
         "com.android.healthfitness",
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt
index 621e6ea..0f5862a 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt
@@ -20,6 +20,7 @@
 
 import android.content.Intent
 import android.os.Bundle
+import android.util.Log
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
 import androidx.annotation.VisibleForTesting
@@ -40,6 +41,7 @@
 import com.android.settingslib.spa.R
 import com.android.settingslib.spa.framework.common.LogCategory
 import com.android.settingslib.spa.framework.common.NullPageProvider
+import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.SettingsPageProviderRepository
 import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
@@ -51,7 +53,7 @@
 import com.android.settingslib.spa.framework.compose.localNavController
 import com.android.settingslib.spa.framework.compose.rememberAnimatedNavController
 import com.android.settingslib.spa.framework.theme.SettingsTheme
-import com.android.settingslib.spa.framework.util.PageWithEvent
+import com.android.settingslib.spa.framework.util.PageLogger
 import com.android.settingslib.spa.framework.util.getDestination
 import com.android.settingslib.spa.framework.util.getEntryId
 import com.android.settingslib.spa.framework.util.getSessionName
@@ -87,25 +89,50 @@
         setContent {
             SettingsTheme {
                 val sppRepository by spaEnvironment.pageProviderRepository
-                BrowseContent(sppRepository, intent)
+                BrowseContent(
+                    sppRepository = sppRepository,
+                    isPageEnabled = ::isPageEnabled,
+                    initialIntent = intent,
+                )
             }
         }
     }
+
+    open fun isPageEnabled(page: SettingsPage) = page.isEnabled()
 }
 
 @VisibleForTesting
 @Composable
-fun BrowseContent(sppRepository: SettingsPageProviderRepository, initialIntent: Intent? = null) {
+internal fun BrowseContent(
+    sppRepository: SettingsPageProviderRepository,
+    isPageEnabled: (SettingsPage) -> Boolean,
+    initialIntent: Intent?,
+) {
     val navController = rememberAnimatedNavController()
     CompositionLocalProvider(navController.localNavController()) {
         val controller = LocalNavController.current as NavControllerWrapperImpl
-        controller.NavContent(sppRepository.getAllProviders())
+        controller.NavContent(sppRepository.getAllProviders()) { page ->
+            if (remember { isPageEnabled(page) }) {
+                LaunchedEffect(Unit) {
+                    Log.d(TAG, "Launching page ${page.sppName}")
+                }
+                page.PageLogger()
+                page.UiLayout()
+            } else {
+                LaunchedEffect(Unit) {
+                    controller.navigateBack()
+                }
+            }
+        }
         controller.InitialDestination(initialIntent, sppRepository.getDefaultStartPage())
     }
 }
 
 @Composable
-private fun NavControllerWrapperImpl.NavContent(allProvider: Collection<SettingsPageProvider>) {
+private fun NavControllerWrapperImpl.NavContent(
+    allProvider: Collection<SettingsPageProvider>,
+    content: @Composable (SettingsPage) -> Unit,
+) {
     AnimatedNavHost(
         navController = navController,
         startDestination = NullPageProvider.name,
@@ -139,7 +166,7 @@
                 },
             ) { navBackStackEntry ->
                 val page = remember { spp.createSettingsPage(navBackStackEntry.arguments) }
-                page.PageWithEvent()
+                content(page)
             }
         }
     }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/PageLogger.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/PageLogger.kt
index dde4e04..a9e5e39 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/PageLogger.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/PageLogger.kt
@@ -29,14 +29,12 @@
 import com.android.settingslib.spa.framework.compose.NavControllerWrapper
 
 @Composable
-internal fun SettingsPage.PageWithEvent() {
-    if (!isEnabled()) return
+internal fun SettingsPage.PageLogger() {
     val navController = LocalNavController.current
     LifecycleEffect(
         onStart = { logPageEvent(LogEvent.PAGE_ENTER, navController) },
         onStop = { logPageEvent(LogEvent.PAGE_LEAVE, navController) },
     )
-    UiLayout()
 }
 
 private fun SettingsPage.logPageEvent(event: LogEvent, navController: NavControllerWrapper) {
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/BrowseActivityTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/BrowseActivityTest.kt
index 218f569..92d3411 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/BrowseActivityTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/BrowseActivityTest.kt
@@ -26,6 +26,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.settingslib.spa.framework.common.LogCategory
 import com.android.settingslib.spa.framework.common.LogEvent
+import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
 import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest
@@ -38,8 +39,6 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 
-const val WAIT_UNTIL_TIMEOUT = 1000L
-
 @RunWith(AndroidJUnit4::class)
 class BrowseActivityTest {
     @get:Rule
@@ -49,19 +48,26 @@
     private val spaLogger = SpaLoggerForTest()
 
     @Test
-    fun testBrowsePage() {
-        spaLogger.reset()
-        val spaEnvironment =
-            SpaEnvironmentForTest(context, listOf(SppHome.createSettingsPage()), logger = spaLogger)
+    fun browseContent_onNavigate_logPageEvent() {
+        val spaEnvironment = SpaEnvironmentForTest(
+            context = context,
+            rootPages = listOf(SppHome.createSettingsPage()),
+            logger = spaLogger,
+        )
         SpaEnvironmentFactory.reset(spaEnvironment)
-
         val sppRepository by spaEnvironment.pageProviderRepository
         val sppHome = sppRepository.getProviderOrNull("SppHome")!!
         val pageHome = sppHome.createSettingsPage()
         val sppLayer1 = sppRepository.getProviderOrNull("SppLayer1")!!
         val pageLayer1 = sppLayer1.createSettingsPage()
 
-        composeTestRule.setContent { BrowseContent(sppRepository) }
+        composeTestRule.setContent {
+            BrowseContent(
+                sppRepository = sppRepository,
+                isPageEnabled = SettingsPage::isEnabled,
+                initialIntent = null,
+            )
+        }
 
         composeTestRule.onNodeWithText(sppHome.getTitle(null)).assertIsDisplayed()
         spaLogger.verifyPageEvent(pageHome.id, 1, 0)
@@ -69,7 +75,7 @@
 
         // click to layer1 page
         composeTestRule.onNodeWithText("SppHome to Layer1").assertIsDisplayed().performClick()
-        waitUntil(WAIT_UNTIL_TIMEOUT) {
+        waitUntil {
             composeTestRule.onAllNodesWithText(sppLayer1.getTitle(null))
                 .fetchSemanticsNodes().size == 1
         }
@@ -78,18 +84,24 @@
     }
 
     @Test
-    fun testBrowseDisabledPage() {
-        spaLogger.reset()
+    fun browseContent_whenDisabled_noLogPageEvent() {
         val spaEnvironment = SpaEnvironmentForTest(
-            context, listOf(SppDisabled.createSettingsPage()), logger = spaLogger
+            context = context,
+            rootPages = listOf(SppDisabled.createSettingsPage()),
+            logger = spaLogger,
         )
         SpaEnvironmentFactory.reset(spaEnvironment)
-
         val sppRepository by spaEnvironment.pageProviderRepository
         val sppDisabled = sppRepository.getProviderOrNull("SppDisabled")!!
         val pageDisabled = sppDisabled.createSettingsPage()
 
-        composeTestRule.setContent { BrowseContent(sppRepository) }
+        composeTestRule.setContent {
+            BrowseContent(
+                sppRepository = sppRepository,
+                isPageEnabled = SettingsPage::isEnabled,
+                initialIntent = null,
+            )
+        }
 
         composeTestRule.onNodeWithText(sppDisabled.getTitle(null)).assertDoesNotExist()
         spaLogger.verifyPageEvent(pageDisabled.id, 0, 0)
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
index 338b16d..e9da88e 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
@@ -46,7 +46,7 @@
 ) : AppRecord
 
 abstract class AppOpPermissionListModel(
-    private val context: Context,
+    protected val context: Context,
     private val packageManagers: IPackageManagers = PackageManagers,
 ) : TogglePermissionAppListModel<AppOpPermissionRecord> {
 
diff --git a/packages/SettingsLib/TopIntroPreference/Android.bp b/packages/SettingsLib/TopIntroPreference/Android.bp
index eca1165..5d09a1a 100644
--- a/packages/SettingsLib/TopIntroPreference/Android.bp
+++ b/packages/SettingsLib/TopIntroPreference/Android.bp
@@ -23,6 +23,7 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.cellbroadcast",
+        "com.android.devicelock",
         "com.android.healthfitness",
     ],
 }
diff --git a/packages/SettingsLib/Utils/Android.bp b/packages/SettingsLib/Utils/Android.bp
index 33ba64a..dc2b52d 100644
--- a/packages/SettingsLib/Utils/Android.bp
+++ b/packages/SettingsLib/Utils/Android.bp
@@ -25,6 +25,7 @@
         "//apex_available:platform",
         "com.android.adservices",
         "com.android.cellbroadcast",
+        "com.android.devicelock",
         "com.android.extservices",
         "com.android.healthfitness",
         "com.android.permission",
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index e9aded0..2372c80 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -67,6 +67,8 @@
 
     <!-- SignalDrawable -->
     <dimen name="signal_icon_size">15dp</dimen>
+    <!-- The size of the roaming icon in the top-left corner of the signal icon. -->
+    <dimen name="signal_icon_size_roaming">8dp</dimen>
 
     <!-- Size of nearby icon -->
     <dimen name="bt_nearby_icon_size">24dp</dimen>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 214c903..4e75792 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -244,7 +244,7 @@
     <!-- Bluetooth settings.  The user-visible string that is used whenever referring to the Hearing Aid profile. -->
     <string name="bluetooth_profile_hearing_aid">Hearing Aids</string>
     <!-- Bluetooth settings.  The user-visible string that is used whenever referring to the LE audio profile. -->
-    <string name="bluetooth_profile_le_audio">LE audio</string>
+    <string name="bluetooth_profile_le_audio">LE audio (experimental)</string>
     <!-- Bluetooth settings.  Connection options screen.  The summary for the Hearing Aid checkbox preference when Hearing Aid is connected. -->
     <string name="bluetooth_hearing_aid_profile_summary_connected">Connected to Hearing Aids</string>
     <!-- Bluetooth settings.  Connection options screen.  The summary for the LE audio checkbox preference when LE audio is connected. -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index adaf4a1..c45d774 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -343,7 +343,12 @@
     }
 
     @Nullable
-    private WifiInfo getMainOrUnderlyingWifiInfo(NetworkCapabilities networkCapabilities) {
+    private WifiInfo getMainOrUnderlyingWifiInfo(
+            @Nullable NetworkCapabilities networkCapabilities) {
+        if (networkCapabilities == null) {
+            return null;
+        }
+
         WifiInfo mainWifiInfo = getMainWifiInfo(networkCapabilities);
         if (mainWifiInfo != null) {
             return mainWifiInfo;
@@ -376,7 +381,10 @@
     }
 
     @Nullable
-    private WifiInfo getMainWifiInfo(NetworkCapabilities networkCapabilities) {
+    private WifiInfo getMainWifiInfo(@Nullable NetworkCapabilities networkCapabilities) {
+        if (networkCapabilities == null) {
+            return null;
+        }
         boolean canHaveWifiInfo = networkCapabilities.hasTransport(TRANSPORT_WIFI)
                 || networkCapabilities.hasTransport(TRANSPORT_CELLULAR);
         if (!canHaveWifiInfo) {
@@ -402,7 +410,11 @@
                 getMainOrUnderlyingWifiInfo(networkCapabilities));
     }
 
-    private boolean connectionIsWifi(NetworkCapabilities networkCapabilities, WifiInfo wifiInfo) {
+    private boolean connectionIsWifi(
+            @Nullable NetworkCapabilities networkCapabilities, WifiInfo wifiInfo) {
+        if (networkCapabilities == null) {
+            return false;
+        }
         return wifiInfo != null || networkCapabilities.hasTransport(TRANSPORT_WIFI);
     }
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java
index 6e975cf..5a9a9d1 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java
@@ -305,4 +305,16 @@
 
         assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
     }
+
+    /** Regression test for b/280169520. */
+    @Test
+    public void networkCallbackNullCapabilities_noCrash() {
+        Network primaryNetwork = Mockito.mock(Network.class);
+
+        // WHEN the network capabilities are null
+        mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+                primaryNetwork, /* networkCapabilities= */ null);
+
+        // THEN there's no crash (no assert needed)
+    }
 }
diff --git a/packages/SystemUI/res-keyguard/layout/status_bar_mobile_signal_group_inner.xml b/packages/SystemUI/res-keyguard/layout/status_bar_mobile_signal_group_inner.xml
index 29832a0..f050a1e 100644
--- a/packages/SystemUI/res-keyguard/layout/status_bar_mobile_signal_group_inner.xml
+++ b/packages/SystemUI/res-keyguard/layout/status_bar_mobile_signal_group_inner.xml
@@ -78,6 +78,7 @@
                 android:id="@+id/mobile_roaming"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:layout_gravity="top|start"
                 android:src="@drawable/stat_sys_roaming"
                 android:contentDescription="@string/data_connection_roaming"
                 android:visibility="gone" />
diff --git a/packages/SystemUI/res/drawable/action_chip_background.xml b/packages/SystemUI/res/drawable/action_chip_background.xml
index 745470f..9492472 100644
--- a/packages/SystemUI/res/drawable/action_chip_background.xml
+++ b/packages/SystemUI/res/drawable/action_chip_background.xml
@@ -20,7 +20,7 @@
     android:color="@color/overlay_button_ripple">
     <item android:id="@android:id/background">
         <shape android:shape="rectangle">
-            <solid android:color="?androidprv:attr/colorAccentSecondary"/>
+            <solid android:color="?androidprv:attr/materialColorSecondary"/>
             <corners android:radius="@dimen/overlay_button_corner_radius"/>
         </shape>
     </item>
diff --git a/packages/SystemUI/res/drawable/action_chip_container_background.xml b/packages/SystemUI/res/drawable/action_chip_container_background.xml
index 36083f1..2ee2710 100644
--- a/packages/SystemUI/res/drawable/action_chip_container_background.xml
+++ b/packages/SystemUI/res/drawable/action_chip_container_background.xml
@@ -18,6 +18,6 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     android:shape="rectangle">
-    <solid android:color="?androidprv:attr/colorSurface"/>
+    <solid android:color="?androidprv:attr/materialColorSurfaceBright"/>
     <corners android:radius="@dimen/overlay_action_container_corner_radius"/>
 </shape>
diff --git a/packages/SystemUI/res/drawable/overlay_cancel.xml b/packages/SystemUI/res/drawable/circular_background.xml
similarity index 62%
rename from packages/SystemUI/res/drawable/overlay_cancel.xml
rename to packages/SystemUI/res/drawable/circular_background.xml
index 3fa12dd..4fef0d6 100644
--- a/packages/SystemUI/res/drawable/overlay_cancel.xml
+++ b/packages/SystemUI/res/drawable/circular_background.xml
@@ -16,14 +16,11 @@
   -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-        android:width="48dp"
-        android:height="48dp"
-        android:viewportWidth="32.0"
-        android:viewportHeight="32.0">
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
     <path
-        android:fillColor="?androidprv:attr/colorAccentTertiary"
-        android:pathData="M16,16m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0"/>
-    <path
-        android:fillColor="?attr/overlayButtonTextColor"
-        android:pathData="M23,10.41L21.59,9 16,14.59 10.41,9 9,10.41 14.59,16 9,21.59 10.41,23 16,17.41 21.59,23 23,21.59 17.41,16z"/>
-</vector>
+        android:fillColor="#ff000000"
+        android:pathData="M12,12m-12,0a12,12 0,1 1,24 0a12,12 0,1 1,-24 0"/>
+   </vector>
diff --git a/packages/SystemUI/res/drawable/overlay_border.xml b/packages/SystemUI/res/drawable/overlay_border.xml
index c1accdc..a59f923 100644
--- a/packages/SystemUI/res/drawable/overlay_border.xml
+++ b/packages/SystemUI/res/drawable/overlay_border.xml
@@ -18,6 +18,6 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     android:shape="rectangle">
-    <solid android:color="?androidprv:attr/colorSurface"/>
-    <corners android:radius="24dp"/>
+    <solid android:color="?androidprv:attr/materialColorSurfaceBright"/>
+    <corners android:radius="16dp"/>
 </shape>
diff --git a/packages/SystemUI/res/drawable/overlay_button_background.xml b/packages/SystemUI/res/drawable/overlay_button_background.xml
index c045048..4e5b8fb 100644
--- a/packages/SystemUI/res/drawable/overlay_button_background.xml
+++ b/packages/SystemUI/res/drawable/overlay_button_background.xml
@@ -17,12 +17,11 @@
 <!-- Button background for activities downstream of overlays
      (clipboard text editor, long screenshots) -->
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
         android:color="@color/overlay_button_ripple">
     <item android:id="@android:id/background">
         <inset android:insetTop="4dp" android:insetBottom="4dp">
             <shape android:shape="rectangle">
-                <solid android:color="?androidprv:attr/colorAccentPrimary"/>
+                <solid android:color="#fff"/>
                 <corners android:radius="20dp"/>
                 <size android:height="40dp"/>
             </shape>
@@ -31,7 +30,7 @@
     <item android:id="@android:id/mask">
         <inset android:insetTop="4dp" android:insetBottom="4dp">
             <shape android:shape="rectangle">
-                <solid android:color="?android:textColorPrimary"/>
+                <solid android:color="#000"/>
                 <corners android:radius="20dp"/>
                 <size android:height="40dp"/>
             </shape>
diff --git a/packages/SystemUI/res/drawable/overlay_button_outline.xml b/packages/SystemUI/res/drawable/overlay_button_outline.xml
new file mode 100644
index 0000000..4d91503
--- /dev/null
+++ b/packages/SystemUI/res/drawable/overlay_button_outline.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+<!-- Button background for activities downstream of overlays
+     (clipboard text editor, long screenshots) -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="@color/overlay_button_ripple">
+    <item android:id="@android:id/background">
+        <inset android:insetTop="4dp" android:insetBottom="4dp">
+            <shape android:shape="rectangle">
+                <solid android:color="@android:color/transparent" />
+                <stroke android:width="1dp" android:color="#fff"/>
+                <corners android:radius="20dp"/>
+                <size android:height="40dp"/>
+            </shape>
+        </inset>
+    </item>
+    <item android:id="@android:id/mask">
+        <inset android:insetTop="4dp" android:insetBottom="4dp">
+            <shape android:shape="rectangle">
+                <solid android:color="#000"/>
+                <corners android:radius="20dp"/>
+                <size android:height="40dp"/>
+            </shape>
+        </inset>
+    </item>
+</ripple>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/overlay_preview_background.xml b/packages/SystemUI/res/drawable/overlay_preview_background.xml
index 5adfaa13..d39d71e 100644
--- a/packages/SystemUI/res/drawable/overlay_preview_background.xml
+++ b/packages/SystemUI/res/drawable/overlay_preview_background.xml
@@ -17,5 +17,6 @@
 <shape
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <corners android:radius="20dp"/>
+    <!-- preview radius should be equal to [overlay border radius - overlay border width] -->
+    <corners android:radius="12dp"/>
 </shape>
diff --git a/packages/SystemUI/res/drawable/screenshot_edit_background.xml b/packages/SystemUI/res/drawable/screenshot_edit_background.xml
index a1185a2..07e5aff 100644
--- a/packages/SystemUI/res/drawable/screenshot_edit_background.xml
+++ b/packages/SystemUI/res/drawable/screenshot_edit_background.xml
@@ -20,13 +20,7 @@
         android:color="@color/overlay_button_ripple">
     <item android:id="@android:id/background">
         <shape android:shape="rectangle">
-            <solid android:color="?androidprv:attr/colorAccentPrimary"/>
-            <corners android:radius="16dp"/>
-        </shape>
-    </item>
-    <item android:id="@android:id/mask">
-        <shape android:shape="rectangle">
-            <solid android:color="?android:textColorPrimary"/>
+            <solid android:color="?androidprv:attr/materialColorSecondaryFixedDim"/>
             <corners android:radius="16dp"/>
         </shape>
     </item>
diff --git a/packages/SystemUI/res/drawable/stat_sys_roaming.xml b/packages/SystemUI/res/drawable/stat_sys_roaming.xml
index 0dd9f5a..2dd12ca 100644
--- a/packages/SystemUI/res/drawable/stat_sys_roaming.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_roaming.xml
@@ -14,10 +14,10 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="@dimen/signal_icon_size"
-        android:height="@dimen/signal_icon_size"
-        android:viewportWidth="17"
-        android:viewportHeight="17">
+        android:width="@dimen/signal_icon_size_roaming"
+        android:height="@dimen/signal_icon_size_roaming"
+        android:viewportWidth="8"
+        android:viewportHeight="8">
 
 <path
     android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/layout/app_clips_screenshot.xml b/packages/SystemUI/res/layout/app_clips_screenshot.xml
index 5155b77..2459eea 100644
--- a/packages/SystemUI/res/layout/app_clips_screenshot.xml
+++ b/packages/SystemUI/res/layout/app_clips_screenshot.xml
@@ -87,19 +87,4 @@
         tools:background="?android:colorBackground"
         tools:minHeight="100dp"
         tools:minWidth="100dp" />
-
-    <com.android.systemui.screenshot.MagnifierView
-        android:id="@+id/magnifier"
-        android:visibility="invisible"
-        android:layout_width="200dp"
-        android:layout_height="200dp"
-        android:elevation="2dp"
-        app:layout_constraintTop_toTopOf="@id/preview"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:handleThickness="@dimen/screenshot_crop_handle_thickness"
-        app:handleColor="?android:attr/colorAccent"
-        app:scrimColor="?android:colorBackgroundFloating"
-        app:scrimAlpha="128"
-        app:borderThickness="4dp"
-        app:borderColor="#fff" />
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml b/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml
index cb7f40f..ae24313 100644
--- a/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml
+++ b/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
@@ -15,6 +16,8 @@
         android:paddingHorizontal="16dp"
         android:background="@drawable/overlay_button_background"
         android:text="@string/clipboard_edit_text_done"
+        android:backgroundTint="?androidprv:attr/materialColorPrimary"
+        android:textColor="?androidprv:attr/materialColorOnPrimary"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent" />
 
diff --git a/packages/SystemUI/res/layout/clipboard_overlay.xml b/packages/SystemUI/res/layout/clipboard_overlay.xml
index 297cf2b..2500769 100644
--- a/packages/SystemUI/res/layout/clipboard_overlay.xml
+++ b/packages/SystemUI/res/layout/clipboard_overlay.xml
@@ -179,6 +179,10 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_margin="@dimen/overlay_dismiss_button_margin"
-            android:src="@drawable/overlay_cancel"/>
+            android:background="@drawable/circular_background"
+            android:backgroundTint="?androidprv:attr/materialColorPrimaryFixedDim"
+            android:tint="?androidprv:attr/materialColorOnPrimaryFixed"
+            android:padding="4dp"
+            android:src="@drawable/ic_close"/>
     </FrameLayout>
 </com.android.systemui.clipboardoverlay.ClipboardOverlayView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml
index 2927d6b..8a19c2e 100644
--- a/packages/SystemUI/res/layout/long_screenshot.xml
+++ b/packages/SystemUI/res/layout/long_screenshot.xml
@@ -16,9 +16,9 @@
   -->
 <androidx.constraintlayout.widget.ConstraintLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
-    android:background="?android:colorBackgroundFloating"
     android:id="@+id/root"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
@@ -32,7 +32,8 @@
         android:layout_marginStart="8dp"
         android:layout_marginTop="@dimen/long_screenshot_action_bar_top_margin"
         android:background="@drawable/overlay_button_background"
-        android:textColor="?android:textColorSecondary"
+        android:backgroundTint="?androidprv:attr/materialColorPrimary"
+        android:textColor="?androidprv:attr/materialColorOnPrimary"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toTopOf="@id/preview" />
@@ -45,8 +46,9 @@
         android:text="@android:string/cancel"
         android:layout_marginStart="6dp"
         android:layout_marginTop="@dimen/long_screenshot_action_bar_top_margin"
-        android:background="@drawable/overlay_button_background"
-        android:textColor="?android:textColorSecondary"
+        android:background="@drawable/overlay_button_outline"
+        android:backgroundTint="?androidprv:attr/materialColorPrimary"
+        android:textColor="?androidprv:attr/materialColorOnSurface"
         app:layout_constraintStart_toEndOf="@id/save"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toTopOf="@id/preview"
@@ -55,7 +57,7 @@
     <ImageButton
         android:id="@+id/share"
         style="@android:style/Widget.Material.Button.Borderless"
-        android:tint="?android:textColorPrimary"
+        android:tint="?androidprv:attr/materialColorOnSurface"
         android:layout_width="48dp"
         android:layout_height="48dp"
         android:layout_marginEnd="8dp"
@@ -112,10 +114,10 @@
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:handleThickness="@dimen/screenshot_crop_handle_thickness"
-        app:handleColor="?android:attr/colorAccent"
-        app:scrimColor="?android:colorBackgroundFloating"
+        app:handleColor="?androidprv:attr/materialColorSecondary"
+        app:scrimColor="?androidprv:attr/materialColorSurfaceContainer"
         app:scrimAlpha="128"
-        app:containerBackgroundColor="?android:colorBackgroundFloating"
+        app:containerBackgroundColor="?androidprv:attr/materialColorSurfaceContainer"
         tools:background="?android:colorBackground"
         tools:minHeight="100dp"
         tools:minWidth="100dp" />
@@ -129,12 +131,11 @@
         app:layout_constraintTop_toTopOf="@id/preview"
         app:layout_constraintLeft_toLeftOf="parent"
         app:handleThickness="@dimen/screenshot_crop_handle_thickness"
-        app:handleColor="?android:attr/colorAccent"
-        app:scrimColor="?android:colorBackgroundFloating"
+        app:handleColor="?androidprv:attr/materialColorSecondary"
+        app:scrimColor="?androidprv:attr/materialColorSurfaceContainer"
         app:scrimAlpha="128"
         app:borderThickness="4dp"
-        app:borderColor="#fff"
-        />
+        app:borderColor="?androidprv:attr/materialColorSurfaceBright" />
 
     <ImageButton
         android:id="@+id/edit"
@@ -146,12 +147,11 @@
         android:background="@drawable/screenshot_edit_background"
         android:src="@drawable/ic_screenshot_edit"
         android:contentDescription="@string/screenshot_edit_label"
-        android:tint="?android:textColorSecondary"
+        android:tint="?androidprv:attr/materialColorOnSecondaryFixed"
         android:padding="16dp"
         android:scaleType="fitCenter"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-    />
+        app:layout_constraintEnd_toEndOf="parent"/>
 
     <ImageView
         android:id="@+id/transition"
@@ -160,7 +160,6 @@
         app:layout_constraintTop_toTopOf="@id/preview"
         app:layout_constraintLeft_toLeftOf="parent"
         android:scaleType="centerCrop"
-        android:visibility="invisible"
-        />
+        android:visibility="invisible" />
 
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/layout/media_session_end_dialog.xml b/packages/SystemUI/res/layout/media_session_end_dialog.xml
new file mode 100644
index 0000000..e1050f6
--- /dev/null
+++ b/packages/SystemUI/res/layout/media_session_end_dialog.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/end_session_dialog"
+    android:layout_width="@dimen/large_dialog_width"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        style="@style/Widget.SliceView.Panel"
+        android:gravity="center_vertical|center_horizontal"
+        android:layout_marginTop="@dimen/dialog_top_padding"
+        android:layout_marginBottom="@dimen/dialog_bottom_padding"
+        android:orientation="vertical">
+
+        <ImageView
+            android:id="@+id/end_icon"
+            android:gravity="center_vertical|center_horizontal"
+            android:layout_width="36dp"
+            android:layout_height="36dp"
+            android:importantForAccessibility="no"/>
+
+        <TextView
+            android:id="@+id/end_session_dialog_title"
+            android:text="@string/media_output_end_session_dialog_summary"
+            android:layout_marginTop="16dp"
+            android:layout_marginBottom="@dimen/dialog_side_padding"
+            android:layout_marginStart="@dimen/dialog_side_padding"
+            android:layout_marginEnd="@dimen/dialog_bottom_padding"
+            android:ellipsize="end"
+            android:gravity="center_vertical|center_horizontal"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="?android:attr/textColorPrimary"
+            android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+            android:textSize="24sp"/>
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="end|center_vertical"
+        android:layout_marginTop="8dp"
+        android:layout_marginStart="@dimen/dialog_side_padding"
+        android:layout_marginEnd="@dimen/dialog_side_padding"
+        android:layout_marginBottom="@dimen/dialog_bottom_padding"
+        android:orientation="horizontal">
+        <Button
+            android:id="@+id/cancel_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="8dp"
+            android:text="@string/cancel"
+            android:ellipsize="end"
+            android:layout_gravity="end|center_vertical"
+            android:singleLine="true"
+            style="@style/Widget.Dialog.Button.BorderButton"
+            android:clickable="true"
+            android:focusable="true"/>
+        <Button
+            android:id="@+id/stop_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="end|center_vertical"
+            android:text="@string/media_output_end_session_dialog_stop"
+            style="@style/Widget.Dialog.Button"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:clickable="true"
+            android:focusable="true"/>
+    </LinearLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/overlay_action_chip.xml b/packages/SystemUI/res/layout/overlay_action_chip.xml
index e0c20ff..e7c382f 100644
--- a/packages/SystemUI/res/layout/overlay_action_chip.xml
+++ b/packages/SystemUI/res/layout/overlay_action_chip.xml
@@ -16,12 +16,12 @@
   -->
 <com.android.systemui.screenshot.OverlayActionChip
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/overlay_action_chip"
     android:theme="@style/FloatingOverlay"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_marginStart="@dimen/overlay_action_chip_margin_start"
-    android:paddingVertical="@dimen/overlay_action_chip_margin_vertical"
     android:layout_gravity="center"
     android:gravity="center"
     android:alpha="0.0">
@@ -33,7 +33,7 @@
         android:gravity="center">
         <ImageView
             android:id="@+id/overlay_action_chip_icon"
-            android:tint="?attr/overlayButtonTextColor"
+            android:tint="?androidprv:attr/materialColorOnSecondary"
             android:layout_width="@dimen/overlay_action_chip_icon_size"
             android:layout_height="@dimen/overlay_action_chip_icon_size"/>
         <TextView
@@ -42,6 +42,6 @@
             android:layout_height="wrap_content"
             android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
             android:textSize="@dimen/overlay_action_chip_text_size"
-            android:textColor="?attr/overlayButtonTextColor"/>
+            android:textColor="?androidprv:attr/materialColorOnSecondary"/>
     </LinearLayout>
 </com.android.systemui.screenshot.OverlayActionChip>
diff --git a/packages/SystemUI/res/layout/screenshot_static.xml b/packages/SystemUI/res/layout/screenshot_static.xml
index 7e9202c..3b728a9 100644
--- a/packages/SystemUI/res/layout/screenshot_static.xml
+++ b/packages/SystemUI/res/layout/screenshot_static.xml
@@ -16,6 +16,7 @@
   -->
 <com.android.systemui.screenshot.DraggableConstraintLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
@@ -68,7 +69,7 @@
         android:layout_marginTop="@dimen/overlay_border_width_neg"
         android:layout_marginEnd="@dimen/overlay_border_width_neg"
         android:layout_marginBottom="@dimen/overlay_preview_container_margin"
-        android:elevation="7dp"
+        android:elevation="8dp"
         android:alpha="0"
         android:background="@drawable/overlay_border"
         app:layout_constraintStart_toStartOf="@id/actions_container_background"
@@ -83,7 +84,7 @@
         android:layout_marginStart="@dimen/overlay_border_width"
         android:layout_marginBottom="@dimen/overlay_border_width"
         android:layout_gravity="center"
-        android:elevation="7dp"
+        android:elevation="8dp"
         android:contentDescription="@string/screenshot_edit_description"
         android:scaleType="fitEnd"
         android:background="@drawable/overlay_preview_background"
@@ -93,17 +94,17 @@
         app:layout_constraintBottom_toBottomOf="@id/screenshot_preview_border"/>
     <ImageView
         android:id="@+id/screenshot_badge"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
+        android:layout_width="56dp"
+        android:layout_height="56dp"
         android:visibility="gone"
-        android:elevation="8dp"
+        android:elevation="9dp"
         app:layout_constraintBottom_toBottomOf="@id/screenshot_preview_border"
         app:layout_constraintEnd_toEndOf="@id/screenshot_preview_border"/>
     <FrameLayout
         android:id="@+id/screenshot_dismiss_button"
         android:layout_width="@dimen/overlay_dismiss_button_tappable_size"
         android:layout_height="@dimen/overlay_dismiss_button_tappable_size"
-        android:elevation="10dp"
+        android:elevation="11dp"
         android:visibility="gone"
         app:layout_constraintStart_toEndOf="@id/screenshot_preview"
         app:layout_constraintEnd_toEndOf="@id/screenshot_preview"
@@ -115,7 +116,11 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_margin="@dimen/overlay_dismiss_button_margin"
-            android:src="@drawable/overlay_cancel"/>
+            android:background="@drawable/circular_background"
+            android:backgroundTint="?androidprv:attr/materialColorPrimary"
+            android:tint="?androidprv:attr/materialColorOnPrimary"
+            android:padding="4dp"
+            android:src="@drawable/ic_close"/>
     </FrameLayout>
     <ImageView
         android:id="@+id/screenshot_scrollable_preview"
@@ -150,8 +155,7 @@
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintWidth_max="450dp"
-        app:layout_constraintHorizontal_bias="0"
-        >
+        app:layout_constraintHorizontal_bias="0">
         <include layout="@layout/screenshot_work_profile_first_run" />
         <include layout="@layout/screenshot_detection_notice" />
     </FrameLayout>
diff --git a/packages/SystemUI/res/layout/screenshot_work_profile_first_run.xml b/packages/SystemUI/res/layout/screenshot_work_profile_first_run.xml
index 392d845..78cd718 100644
--- a/packages/SystemUI/res/layout/screenshot_work_profile_first_run.xml
+++ b/packages/SystemUI/res/layout/screenshot_work_profile_first_run.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/work_profile_first_run"
     android:layout_height="wrap_content"
     android:layout_width="match_parent"
@@ -33,9 +34,13 @@
         android:layout_height="@dimen/overlay_dismiss_button_tappable_size"
         android:contentDescription="@string/screenshot_dismiss_work_profile">
         <ImageView
-            android:layout_width="24dp"
-            android:layout_height="24dp"
+            android:layout_width="16dp"
+            android:layout_height="16dp"
             android:layout_gravity="center"
-            android:src="@drawable/overlay_cancel"/>
+            android:background="@drawable/circular_background"
+            android:backgroundTint="?androidprv:attr/materialColorSurfaceContainerHigh"
+            android:tint="?androidprv:attr/materialColorOnSurface"
+            android:padding="2dp"
+            android:src="@drawable/ic_close"/>
     </FrameLayout>
 </LinearLayout>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index aff0e80..bf0b8a6 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -342,23 +342,22 @@
 
 
     <dimen name="screenshot_crop_handle_thickness">3dp</dimen>
-    <dimen name="long_screenshot_action_bar_top_margin">8dp</dimen>
+    <dimen name="long_screenshot_action_bar_top_margin">4dp</dimen>
 
     <!-- Dimensions shared between "overlays" (clipboard and screenshot preview UIs) -->
     <!-- Constrained size of the floating overlay preview -->
     <dimen name="overlay_x_scale">80dp</dimen>
     <!-- Radius of the chip background on floating overlay actions -->
-    <dimen name="overlay_button_corner_radius">8dp</dimen>
+    <dimen name="overlay_button_corner_radius">16dp</dimen>
     <!-- Margin between successive chips -->
     <dimen name="overlay_action_chip_margin_start">8dp</dimen>
-    <!-- Padding to make tappable chip height 48dp (18+11+11+4+4) -->
-    <dimen name="overlay_action_chip_margin_vertical">4dp</dimen>
-    <dimen name="overlay_action_chip_padding_vertical">11dp</dimen>
-    <dimen name="overlay_action_chip_icon_size">18sp</dimen>
+    <dimen name="overlay_action_chip_padding_vertical">12dp</dimen>
+    <dimen name="overlay_action_chip_icon_size">24sp</dimen>
     <!-- Padding on each side of the icon for icon-only chips -->
-    <dimen name="overlay_action_chip_icon_only_padding_horizontal">14dp</dimen>
+    <dimen name="overlay_action_chip_icon_only_padding_horizontal">12dp</dimen>
     <!-- Padding at the edges of the chip for icon-and-text chips -->
-    <dimen name="overlay_action_chip_padding_horizontal">12dp</dimen>
+    <dimen name="overlay_action_chip_padding_start">12dp</dimen>
+    <dimen name="overlay_action_chip_padding_end">16dp</dimen>
     <!-- Spacing between chip icon and chip text -->
     <dimen name="overlay_action_chip_spacing">8dp</dimen>
     <dimen name="overlay_action_chip_text_size">14sp</dimen>
@@ -368,8 +367,8 @@
     <dimen name="overlay_action_container_margin_horizontal">8dp</dimen>
     <dimen name="overlay_action_container_margin_bottom">6dp</dimen>
     <dimen name="overlay_bg_protection_height">242dp</dimen>
-    <dimen name="overlay_action_container_corner_radius">18dp</dimen>
-    <dimen name="overlay_action_container_padding_vertical">4dp</dimen>
+    <dimen name="overlay_action_container_corner_radius">20dp</dimen>
+    <dimen name="overlay_action_container_padding_vertical">8dp</dimen>
     <dimen name="overlay_action_container_padding_right">8dp</dimen>
     <dimen name="overlay_action_container_padding_end">8dp</dimen>
     <dimen name="overlay_dismiss_button_tappable_size">48dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c57fef1..70fdc20 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2684,6 +2684,10 @@
     <string name="media_output_group_title_speakers_and_displays">Speakers &amp; Displays</string>
     <!-- Title for Suggested Devices group. [CHAR LIMIT=NONE] -->
     <string name="media_output_group_title_suggested_device">Suggested Devices</string>
+    <!-- Summary for end session dialog. [CHAR LIMIT=NONE] -->
+    <string name="media_output_end_session_dialog_summary">Stop your shared session to move media to another device</string>
+    <!-- Button text for stopping session [CHAR LIMIT=60] -->
+    <string name="media_output_end_session_dialog_stop">Stop</string>
 
 
     <!-- Media Output Broadcast Dialog -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 9d0cc11..cee2135 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -782,10 +782,12 @@
     </style>
 
     <style name="LongScreenshotActivity" parent="@android:style/Theme.DeviceDefault.DayNight">
+        <item name="android:colorBackground">?androidprv:attr/materialColorSurfaceContainer</item>
         <item name="android:windowNoTitle">true</item>
         <item name="android:windowLightStatusBar">true</item>
         <item name="android:windowLightNavigationBar">true</item>
-        <item name="android:navigationBarColor">?android:attr/colorBackgroundFloating</item>
+        <item name="android:statusBarColor">?androidprv:attr/materialColorSurfaceContainer</item>
+        <item name="android:navigationBarColor">?androidprv:attr/materialColorSurfaceContainerHighest</item>
         <item name="android:windowActivityTransitions">true</item>
     </style>
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index d8bf570..676f342 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -179,6 +179,20 @@
     }
 
     /**
+     * Set alpha directly to mView will clip clock, so we set alpha to clock face instead
+     */
+    public void setAlpha(float alpha) {
+        ClockController clock = getClock();
+        if (clock != null) {
+            clock.getLargeClock().getView().setAlpha(alpha);
+            clock.getSmallClock().getView().setAlpha(alpha);
+        }
+        if (mStatusArea != null) {
+            mStatusArea.setAlpha(alpha);
+        }
+    }
+
+    /**
      * Attach the controller to the view it relates to.
      */
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index 0982030..58807e4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -16,6 +16,7 @@
 
 package com.android.keyguard;
 
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_PIN_APPEAR;
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_PIN_DISAPPEAR;
 import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_HALF_OPENED;
 import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN;
@@ -184,6 +185,7 @@
         }
         mAppearAnimator.setDuration(ANIMATION_DURATION);
         mAppearAnimator.addUpdateListener(animation -> animate(animation.getAnimatedFraction()));
+        mAppearAnimator.addListener(getAnimationListener(CUJ_LOCKSCREEN_PIN_APPEAR));
         mAppearAnimator.start();
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 693268d..1cbcb9d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -264,8 +264,7 @@
          */
         @Override
         public void finish(boolean strongAuth, int targetUserId) {
-            if (mFeatureFlags.isEnabled(Flags.PREVENT_BYPASS_KEYGUARD)
-                    && !mKeyguardStateController.canDismissLockScreen() && !strongAuth) {
+            if (!mKeyguardStateController.canDismissLockScreen() && !strongAuth) {
                 Log.e(TAG,
                         "Tried to dismiss keyguard when lockscreen is not dismissible and user "
                                 + "was not authenticated with a primary security method "
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index d8e1eb0f..2313609 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -135,4 +135,31 @@
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         Trace.endSection();
     }
+
+    /**
+     * Clock content will be clipped when goes beyond bounds,
+     * so we setAlpha for all views except clock
+     */
+    public void setAlpha(float alpha, boolean excludeClock) {
+        if (!excludeClock) {
+            setAlpha(alpha);
+            return;
+        }
+        if (alpha == 1 || alpha == 0) {
+            setAlpha(alpha);
+        }
+        for (int i = 0; i < getChildCount(); i++) {
+            View child = getChildAt(i);
+            if (child == mStatusViewContainer) {
+                for (int j = 0; j < mStatusViewContainer.getChildCount(); j++) {
+                    View innerChild = mStatusViewContainer.getChildAt(j);
+                    if (innerChild != mClockView) {
+                        innerChild.setAlpha(alpha);
+                    }
+                }
+            } else {
+                child.setAlpha(alpha);
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 794eeda..af47466 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -180,7 +180,8 @@
      */
     public void setAlpha(float alpha) {
         if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) {
-            mView.setAlpha(alpha);
+            mView.setAlpha(alpha, true);
+            mKeyguardClockSwitchController.setAlpha(alpha);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
index 5499d2c..f04fdfff 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
@@ -23,6 +23,7 @@
 import android.view.DisplayInfo
 import android.view.Surface
 import android.view.View
+import androidx.annotation.VisibleForTesting
 import com.airbnb.lottie.LottieAnimationView
 import com.android.settingslib.widget.LottieColorUtils
 import com.android.systemui.R
@@ -133,13 +134,19 @@
         }
     }
 
-    private fun getIconContentDescription(@BiometricState newState: Int): CharSequence? {
+    @VisibleForTesting
+    fun getIconContentDescription(@BiometricState newState: Int): CharSequence? {
         val id = when (newState) {
             STATE_IDLE,
             STATE_AUTHENTICATING_ANIMATING_IN,
             STATE_AUTHENTICATING,
             STATE_PENDING_CONFIRMATION,
-            STATE_AUTHENTICATED -> R.string.security_settings_sfps_enroll_find_sensor_message
+            STATE_AUTHENTICATED ->
+                if (isSideFps) {
+                    R.string.security_settings_sfps_enroll_find_sensor_message
+                } else {
+                    R.string.fingerprint_dialog_touch_sensor
+                }
             STATE_ERROR,
             STATE_HELP -> R.string.biometric_dialog_try_again
             else -> null
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
index 92aff06..e600632 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
@@ -189,7 +189,7 @@
                     authorizedPanelsRepository.addAuthorizedPanels(
                             setOf(serviceInfo.componentName.packageName)
                     )
-                    val selected = SelectedItem.PanelItem(appName, componentName)
+                    val selected = SelectedItem.PanelItem(appName, serviceInfo.componentName)
                     controlsController.setPreferredSelection(selected)
                     animateExitAndFinish()
                     openControlsOrigin()
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index b446724..a4d4a9a 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -206,11 +206,6 @@
                     "wallpaper_picker_ui_for_aiwp"
             )
 
-    /** Whether to inflate the bouncer view on a background thread. */
-    // TODO(b/273341787): Tracking Bug
-    @JvmField
-    val PREVENT_BYPASS_KEYGUARD = releasedFlag(230, "prevent_bypass_keyguard")
-
     /** Whether to use a new data source for intents to run on keyguard dismissal. */
     @JvmField
     val REFACTOR_KEYGUARD_DISMISS_INTENT = unreleasedFlag(231, "refactor_keyguard_dismiss_intent")
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index b5ddc2e..552e5ea 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2941,9 +2941,12 @@
         if (mSurfaceBehindRemoteAnimationFinishedCallback != null) {
             try {
                 mSurfaceBehindRemoteAnimationFinishedCallback.onAnimationFinished();
+            } catch (Throwable t) {
+                // The surface may no longer be available. Just capture the exception
+                Log.w(TAG, "Surface behind remote animation callback failed, and it's probably ok: "
+                        + t.getMessage());
+            } finally {
                 mSurfaceBehindRemoteAnimationFinishedCallback = null;
-            } catch (RemoteException e) {
-                e.printStackTrace();
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaVibrations.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaVibrations.kt
index 568db2f..e7803c5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaVibrations.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaVibrations.kt
@@ -31,7 +31,9 @@
         VibrationEffect.startComposition()
             .apply {
                 val vibrationDelayMs =
-                    (ShakeAnimationDuration.inWholeMilliseconds / ShakeAnimationCycles * 2).toInt()
+                    (ShakeAnimationDuration.inWholeMilliseconds / (ShakeAnimationCycles * 2))
+                    .toInt()
+
                 val vibrationCount = ShakeAnimationCycles.toInt() * 2
                 repeat(vibrationCount) {
                     addPrimitive(
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index f50a7a8..d949cf56f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -37,11 +37,13 @@
 import androidx.core.widget.CompoundButtonCompat;
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.media.LocalMediaManager.MediaDeviceState;
 import com.android.settingslib.media.MediaDevice;
 import com.android.systemui.R;
 
 import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * Adapter for media output dialog.
@@ -52,6 +54,7 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final float DEVICE_DISCONNECTED_ALPHA = 0.5f;
     private static final float DEVICE_CONNECTED_ALPHA = 1f;
+    protected List<MediaItem> mMediaItemList = new CopyOnWriteArrayList<>();
 
     public MediaOutputAdapter(MediaOutputController controller) {
         super(controller);
@@ -59,6 +62,13 @@
     }
 
     @Override
+    public void updateItems() {
+        mMediaItemList.clear();
+        mMediaItemList.addAll(mController.getMediaItemList());
+        notifyDataSetChanged();
+    }
+
+    @Override
     public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
             int viewType) {
         super.onCreateViewHolder(viewGroup, viewType);
@@ -79,14 +89,14 @@
     @Override
     public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
         if (mController.isAdvancedLayoutSupported()) {
-            if (position >= mController.getMediaItemList().size()) {
+            if (position >= mMediaItemList.size()) {
                 if (DEBUG) {
                     Log.d(TAG, "Incorrect position: " + position + " list size: "
-                            + mController.getMediaItemList().size());
+                            + mMediaItemList.size());
                 }
                 return;
             }
-            MediaItem currentMediaItem = mController.getMediaItemList().get(position);
+            MediaItem currentMediaItem = mMediaItemList.get(position);
             switch (currentMediaItem.getMediaItemType()) {
                 case MediaItem.MediaItemType.TYPE_GROUP_DIVIDER:
                     ((MediaGroupDividerViewHolder) viewHolder).onBind(currentMediaItem.getTitle());
@@ -119,11 +129,11 @@
     @Override
     public long getItemId(int position) {
         if (mController.isAdvancedLayoutSupported()) {
-            if (position >= mController.getMediaItemList().size()) {
+            if (position >= mMediaItemList.size()) {
                 Log.d(TAG, "Incorrect position for item id: " + position);
                 return position;
             }
-            MediaItem currentMediaItem = mController.getMediaItemList().get(position);
+            MediaItem currentMediaItem = mMediaItemList.get(position);
             return currentMediaItem.getMediaDevice().isPresent()
                     ? currentMediaItem.getMediaDevice().get().getId().hashCode()
                     : position;
@@ -143,12 +153,12 @@
     @Override
     public int getItemViewType(int position) {
         if (mController.isAdvancedLayoutSupported()
-                && position >= mController.getMediaItemList().size()) {
+                && position >= mMediaItemList.size()) {
             Log.d(TAG, "Incorrect position for item type: " + position);
             return MediaItem.MediaItemType.TYPE_GROUP_DIVIDER;
         }
         return mController.isAdvancedLayoutSupported()
-                ? mController.getMediaItemList().get(position).getMediaItemType()
+                ? mMediaItemList.get(position).getMediaItemType()
                 : super.getItemViewType(position);
     }
 
@@ -156,7 +166,7 @@
     public int getItemCount() {
         // Add extra one for "pair new"
         return mController.isAdvancedLayoutSupported()
-                ? mController.getMediaItemList().size()
+                ? mMediaItemList.size()
                 : mController.getMediaDevices().size() + 1;
     }
 
@@ -482,6 +492,14 @@
         }
 
         private void onItemClick(View view, MediaDevice device) {
+            if (mController.isCurrentOutputDeviceHasSessionOngoing()) {
+                showCustomEndSessionDialog(device);
+            } else {
+                transferOutput(device);
+            }
+        }
+
+        private void transferOutput(MediaDevice device) {
             if (mController.isAnyDeviceTransferring()) {
                 return;
             }
@@ -496,6 +514,14 @@
             notifyDataSetChanged();
         }
 
+        @VisibleForTesting
+        void showCustomEndSessionDialog(MediaDevice device) {
+            MediaSessionReleaseDialog mediaSessionReleaseDialog = new MediaSessionReleaseDialog(
+                    mContext, () -> transferOutput(device), mController.getColorButtonBackground(),
+                    mController.getColorItemContent());
+            mediaSessionReleaseDialog.show();
+        }
+
         private void cancelMuteAwaitConnection() {
             mController.cancelMuteAwaitConnection();
             notifyDataSetChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 73ab5272..151dbb2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -81,6 +81,11 @@
         mIsInitVolumeFirstTime = true;
     }
 
+    /**
+     * Refresh current dataset
+     */
+    public abstract void updateItems();
+
     @Override
     public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
             int viewType) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 08e47a0..770e4df 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -382,7 +382,7 @@
                     && currentActivePosition < mAdapter.getItemCount()) {
                 mAdapter.notifyItemChanged(currentActivePosition);
             } else {
-                mAdapter.notifyDataSetChanged();
+                mAdapter.updateItems();
             }
         } else {
             mMediaOutputController.setRefreshing(false);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 8e014c6..822644b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -783,6 +783,12 @@
                 currentConnectedMediaDevice);
     }
 
+    boolean isCurrentOutputDeviceHasSessionOngoing() {
+        MediaDevice currentConnectedMediaDevice = getCurrentConnectedMediaDevice();
+        return currentConnectedMediaDevice != null
+                && (currentConnectedMediaDevice.isHostForOngoingSession());
+    }
+
     public boolean isAdvancedLayoutSupported() {
         return mFeatureFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSessionReleaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSessionReleaseDialog.java
new file mode 100644
index 0000000..2680a2f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSessionReleaseDialog.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.dialog;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.ColorFilter;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+
+/**
+ * Confirmation dialog for releasing media session
+ */
+
+public class MediaSessionReleaseDialog extends SystemUIDialog {
+
+    private View mDialogView;
+
+    private final Context mContext;
+    private final View.OnClickListener mPositiveButtonListener;
+    private final ColorFilter mButtonColorFilter;
+    private final int mIconColor;
+
+    public MediaSessionReleaseDialog(Context context, Runnable runnable, int buttonColor,
+            int iconColor) {
+        super(context, R.style.Theme_SystemUI_Dialog_Media);
+        mContext = getContext();
+        mPositiveButtonListener = (v) -> {
+            runnable.run();
+            dismiss();
+        };
+        mButtonColorFilter = new PorterDuffColorFilter(
+                buttonColor,
+                PorterDuff.Mode.SRC_IN);
+        mIconColor = iconColor;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mDialogView = LayoutInflater.from(mContext).inflate(R.layout.media_session_end_dialog,
+                null);
+        final Window window = getWindow();
+        window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL);
+        window.setContentView(mDialogView);
+
+        final WindowManager.LayoutParams lp = window.getAttributes();
+        lp.gravity = Gravity.CENTER;
+        lp.width = (int) (mContext.getResources().getDisplayMetrics().widthPixels * 0.90);
+
+        ImageView headerIcon = mDialogView.requireViewById(R.id.end_icon);
+        headerIcon.setImageDrawable(mContext.getDrawable(R.drawable.media_output_status_failed));
+        headerIcon.setImageTintList(
+                ColorStateList.valueOf(mIconColor));
+
+        Button stopButton = mDialogView.requireViewById(R.id.stop_button);
+        stopButton.setOnClickListener(mPositiveButtonListener);
+        stopButton.getBackground().setColorFilter(mButtonColorFilter);
+
+        Button cancelButton = mDialogView.requireViewById(R.id.cancel_button);
+        cancelButton.setOnClickListener((v) -> dismiss());
+        cancelButton.getBackground().setColorFilter(mButtonColorFilter);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index 2312c70..4bc7ec8 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -343,22 +343,24 @@
         } else {
             String editorPackage = getString(R.string.config_screenshotEditor);
             Intent intent = new Intent(Intent.ACTION_EDIT);
-            if (!TextUtils.isEmpty(editorPackage)) {
-                intent.setComponent(ComponentName.unflattenFromString(editorPackage));
-            }
             intent.setDataAndType(uri, "image/png");
             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                     | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+            Bundle options = null;
 
-            mTransitionView.setImageBitmap(mOutputBitmap);
-            mTransitionView.setVisibility(View.VISIBLE);
-            mTransitionView.setTransitionName(
-                    ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
-            // TODO: listen for transition completing instead of finishing onStop
-            mTransitionStarted = true;
-            startActivity(intent,
-                    ActivityOptions.makeSceneTransitionAnimation(this, mTransitionView,
-                            ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME).toBundle());
+            // Skip shared element transition for implicit edit intents
+            if (!TextUtils.isEmpty(editorPackage)) {
+                intent.setComponent(ComponentName.unflattenFromString(editorPackage));
+                mTransitionView.setImageBitmap(mOutputBitmap);
+                mTransitionView.setVisibility(View.VISIBLE);
+                mTransitionView.setTransitionName(
+                        ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
+                options = ActivityOptions.makeSceneTransitionAnimation(this, mTransitionView,
+                        ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME).toBundle();
+                // TODO: listen for transition completing instead of finishing onStop
+                mTransitionStarted = true;
+            }
+            startActivity(intent, options);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/OverlayActionChip.java b/packages/SystemUI/src/com/android/systemui/screenshot/OverlayActionChip.java
index 860bfe37..13678b0 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/OverlayActionChip.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/OverlayActionChip.java
@@ -121,13 +121,15 @@
         LinearLayout.LayoutParams textParams =
                 (LinearLayout.LayoutParams) mTextView.getLayoutParams();
         if (hasText) {
-            int paddingHorizontal = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.overlay_action_chip_padding_horizontal);
+            int paddingStart = mContext.getResources().getDimensionPixelSize(
+                    R.dimen.overlay_action_chip_padding_start);
             int spacing = mContext.getResources().getDimensionPixelSize(
                     R.dimen.overlay_action_chip_spacing);
-            iconParams.setMarginStart(paddingHorizontal);
+            int paddingEnd = mContext.getResources().getDimensionPixelSize(
+                    R.dimen.overlay_action_chip_padding_end);
+            iconParams.setMarginStart(paddingStart);
             iconParams.setMarginEnd(spacing);
-            textParams.setMarginEnd(paddingHorizontal);
+            textParams.setMarginEnd(paddingEnd);
         } else {
             int paddingHorizontal = mContext.getResources().getDimensionPixelSize(
                     R.dimen.overlay_action_chip_icon_only_padding_horizontal);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 560ea8a..313410a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -604,6 +604,7 @@
         }
         updateAodIconsVisibility(animate, false /* force */);
         updateAodNotificationIcons();
+        updateAodIconColors();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index bd5815aa..7bbb03b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -304,10 +304,11 @@
             ActivityManager.getService().resumeAppSwitches();
         } catch (RemoteException e) {
         }
-        // If we are launching a work activity and require to launch
-        // separate work challenge, we defer the activity action and cancel
-        // notification until work challenge is unlocked.
-        if (isActivityIntent) {
+        // If the notification should be cancelled on click and we are launching a work activity in
+        // a locked profile with separate challenge, we defer the activity action and cancelling of
+        // the notification until work challenge is unlocked. If the notification shouldn't be
+        // cancelled, the work challenge will be shown by ActivityManager if necessary anyway.
+        if (isActivityIntent && shouldAutoCancel(entry.getSbn())) {
             final int userId = intent.getCreatorUserHandle().getIdentifier();
             if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
                     && mKeyguardManager.isDeviceLocked(userId)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
index eec91a0..e1ffae0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
@@ -259,7 +259,7 @@
      */
     override val isDefaultConnectionFailed: StateFlow<Boolean> =
         combine(
-                mobileConnectionsRepo.mobileIsDefault,
+                mobileIsDefault,
                 mobileConnectionsRepo.defaultConnectionIsValidated,
                 forcingCellularValidation,
             ) { mobileIsDefault, defaultConnectionIsValidated, forcingCellularValidation ->
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
index d74906a..eed7950 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
@@ -154,10 +154,6 @@
                 pendingScrimReadyCallback = onReady
             }
         } else if (isFolded && !isFoldHandled && alwaysOnEnabled && isDozing) {
-            // Screen turning on for the first time after folding and we are already dozing
-            // We should play the folding to AOD animation
-            isFoldHandled = true
-
             setAnimationState(playing = true)
             getShadeFoldAnimator().prepareFoldToAodAnimation()
 
@@ -173,6 +169,13 @@
             // No animation, call ready callback immediately
             onReady.run()
         }
+
+        if (isFolded) {
+            // Any time the screen turns on, this state needs to be reset if the device has been
+            // folded. Reaching this line implies AOD has been shown in one way or another,
+            // if enabled
+            isFoldHandled = true
+        }
     }
 
     /** Called when keyguard scrim opaque changed */
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index fb73845..d8e2a38 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -134,6 +134,7 @@
 
     private KeyguardClockSwitchController mController;
     private View mSliceView;
+    private LinearLayout mStatusArea;
     private FakeExecutor mExecutor;
 
     @Before
@@ -195,8 +196,8 @@
 
         mSliceView = new View(getContext());
         when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView);
-        when(mView.findViewById(R.id.keyguard_status_area)).thenReturn(
-                new LinearLayout(getContext()));
+        mStatusArea = new LinearLayout(getContext());
+        when(mView.findViewById(R.id.keyguard_status_area)).thenReturn(mStatusArea);
     }
 
     @Test
@@ -401,6 +402,15 @@
         assertNull(mController.getClock());
     }
 
+    @Test
+    public void testSetAlpha_setClockAlphaForCLockFace() {
+        mController.onViewAttached();
+        mController.setAlpha(0.5f);
+        verify(mLargeClockView).setAlpha(0.5f);
+        verify(mSmallClockView).setAlpha(0.5f);
+        assertEquals(0.5f, mStatusArea.getAlpha(), 0.0f);
+    }
+
     private void verifyAttachment(VerificationMode times) {
         verify(mClockRegistry, times).registerClockChangeListener(
                 any(ClockRegistry.ClockChangeListener.class));
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index 8a05a37..65ddb53 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -64,7 +64,6 @@
 import com.android.systemui.classifier.FalsingA11yDelegate;
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.plugins.ActivityStarter;
@@ -398,26 +397,6 @@
     }
 
     @Test
-    public void showNextSecurityScreenOrFinish_DeviceNotSecure_prevent_bypass_on() {
-        when(mFeatureFlags.isEnabled(Flags.PREVENT_BYPASS_KEYGUARD)).thenReturn(true);
-        // GIVEN the current security method is SimPin
-        when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
-        when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(TARGET_USER_ID)).thenReturn(false);
-        mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.SimPin);
-
-        // WHEN a request is made from the SimPin screens to show the next security method
-        when(mKeyguardSecurityModel.getSecurityMode(TARGET_USER_ID)).thenReturn(SecurityMode.None);
-        mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
-                /* authenticated= */true,
-                TARGET_USER_ID,
-                /* bypassSecondaryLockScreen= */true,
-                SecurityMode.SimPin);
-
-        // THEN the next security method of None will dismiss keyguard.
-        verify(mViewMediatorCallback).keyguardDone(anyBoolean(), anyInt());
-    }
-
-    @Test
     public void showNextSecurityScreenOrFinish_ignoresCallWhenSecurityMethodHasChanged() {
         //GIVEN current security mode has been set to PIN
         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.PIN);
@@ -608,7 +587,6 @@
 
     @Test
     public void testSecurityCallbackFinish_cannotDismissLockScreenAndNotStrongAuth() {
-        when(mFeatureFlags.isEnabled(Flags.PREVENT_BYPASS_KEYGUARD)).thenReturn(true);
         when(mKeyguardStateController.canDismissLockScreen()).thenReturn(false);
         mKeyguardSecurityContainerController.finish(false, 0);
         verify(mViewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt());
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
index 508aea5..a8c281c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
@@ -24,6 +24,8 @@
         get() = keyguardStatusView.findViewById(R.id.status_view_media_container)
     private val statusViewContainer: ViewGroup
         get() = keyguardStatusView.findViewById(R.id.status_view_container)
+    private val clockView: ViewGroup
+        get() = keyguardStatusView.findViewById(R.id.keyguard_clock_container)
     private val childrenExcludingMedia
         get() = statusViewContainer.children.filter { it != mediaView }
 
@@ -56,4 +58,12 @@
             assertThat(it.translationY).isEqualTo(translationY)
         }
     }
+
+    @Test
+    fun setAlphaExcludeClock() {
+        keyguardStatusView.setAlpha(0.5f, /* excludeClock= */true)
+        assertThat(statusViewContainer.alpha).isNotEqualTo(0.5f)
+        assertThat(mediaView.alpha).isEqualTo(0.5f)
+        assertThat(clockView.alpha).isNotEqualTo(0.5f)
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconControllerTest.kt
new file mode 100644
index 0000000..cac618b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconControllerTest.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics
+
+import android.content.Context
+import android.hardware.biometrics.SensorProperties
+import android.hardware.fingerprint.FingerprintManager
+import android.hardware.fingerprint.FingerprintSensorProperties
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
+import android.view.ViewGroup.LayoutParams
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.airbnb.lottie.LottieAnimationView
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when` as whenEver
+import org.mockito.junit.MockitoJUnit
+
+private const val SENSOR_ID = 1
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AuthBiometricFingerprintIconControllerTest : SysuiTestCase() {
+
+    @JvmField @Rule var mockitoRule = MockitoJUnit.rule()
+
+    @Mock private lateinit var iconView: LottieAnimationView
+    @Mock private lateinit var iconViewOverlay: LottieAnimationView
+    @Mock private lateinit var layoutParam: LayoutParams
+    @Mock private lateinit var fingerprintManager: FingerprintManager
+
+    private lateinit var controller: AuthBiometricFingerprintIconController
+
+    @Before
+    fun setUp() {
+        context.addMockSystemService(Context.FINGERPRINT_SERVICE, fingerprintManager)
+        whenEver(iconView.layoutParams).thenReturn(layoutParam)
+        whenEver(iconViewOverlay.layoutParams).thenReturn(layoutParam)
+    }
+
+    @Test
+    fun testIconContentDescription_SfpsDevice() {
+        setupFingerprintSensorProperties(FingerprintSensorProperties.TYPE_POWER_BUTTON)
+        controller = AuthBiometricFingerprintIconController(context, iconView, iconViewOverlay)
+
+        assertThat(controller.getIconContentDescription(AuthBiometricView.STATE_AUTHENTICATING))
+            .isEqualTo(
+                context.resources.getString(
+                    R.string.security_settings_sfps_enroll_find_sensor_message
+                )
+            )
+    }
+
+    @Test
+    fun testIconContentDescription_NonSfpsDevice() {
+        setupFingerprintSensorProperties(FingerprintSensorProperties.TYPE_UDFPS_OPTICAL)
+        controller = AuthBiometricFingerprintIconController(context, iconView, iconViewOverlay)
+
+        assertThat(controller.getIconContentDescription(AuthBiometricView.STATE_AUTHENTICATING))
+            .isEqualTo(context.resources.getString(R.string.fingerprint_dialog_touch_sensor))
+    }
+
+    private fun setupFingerprintSensorProperties(sensorType: Int) {
+        whenEver(fingerprintManager.sensorPropertiesInternal)
+            .thenReturn(
+                listOf(
+                    FingerprintSensorPropertiesInternal(
+                        SENSOR_ID,
+                        SensorProperties.STRENGTH_STRONG,
+                        5 /* maxEnrollmentsPerUser */,
+                        listOf() /* componentInfo */,
+                        sensorType,
+                        true /* halControlsIllumination */,
+                        true /* resetLockoutRequiresHardwareAuthToken */,
+                        listOf() /* sensorLocations */
+                    )
+                )
+            )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt
index 8dfd223..b2e37cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.controls.ControlsServiceInfo
 import com.android.systemui.controls.controller.ControlsController
 import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.ui.SelectedItem
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.settings.UserTracker
@@ -190,6 +191,9 @@
         val setCaptor: ArgumentCaptor<Set<String>> = argumentCaptor()
         verify(authorizedPanelsRepository).addAuthorizedPanels(capture(setCaptor))
         assertThat(setCaptor.value).containsExactly(info.componentName.packageName)
+        val selectedComponentCaptor: ArgumentCaptor<SelectedItem> = argumentCaptor()
+        verify(controlsController).setPreferredSelection(capture(selectedComponentCaptor))
+        assertThat(selectedComponentCaptor.value.componentName).isEqualTo(info.componentName)
 
         assertThat(activityRule.activity.triedToFinish).isTrue()
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 7f7952f..faca8a91d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -26,6 +26,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -34,6 +35,7 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Icon;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.SeekBar;
@@ -60,6 +62,7 @@
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
[email protected](setAsMainLooper = true)
 public class MediaOutputAdapterTest extends SysuiTestCase {
 
     private static final String TEST_DEVICE_NAME_1 = "test_device_name_1";
@@ -116,6 +119,7 @@
         mMediaItems.add(new MediaItem(mMediaDevice2));
 
         mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
+        mMediaOutputAdapter.updateItems();
         mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
                 .onCreateViewHolder(new LinearLayout(mContext), 0);
         mSpyMediaOutputSeekbar = spy(mViewHolder.mSeekBar);
@@ -202,9 +206,11 @@
     public void advanced_onBindViewHolder_bindPairNew_verifyView() {
         when(mMediaOutputController.isAdvancedLayoutSupported()).thenReturn(true);
         mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
+        mMediaOutputAdapter.updateItems();
         mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
                 .onCreateViewHolder(new LinearLayout(mContext), 0);
         mMediaItems.add(new MediaItem());
+        mMediaOutputAdapter.updateItems();
         mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2);
 
         assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -223,6 +229,7 @@
                         Collectors.toList()));
         when(mMediaOutputController.getSessionName()).thenReturn(TEST_SESSION_NAME);
         mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
+        mMediaOutputAdapter.updateItems();
         mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
                 .onCreateViewHolder(new LinearLayout(mContext), 0);
         mMediaOutputAdapter.getItemCount();
@@ -243,6 +250,7 @@
                         Collectors.toList()));
         when(mMediaOutputController.getSessionName()).thenReturn(null);
         mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
+        mMediaOutputAdapter.updateItems();
         mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
                 .onCreateViewHolder(new LinearLayout(mContext), 0);
         mMediaOutputAdapter.getItemCount();
@@ -602,9 +610,11 @@
     public void advanced_onItemClick_clickPairNew_verifyLaunchBluetoothPairing() {
         when(mMediaOutputController.isAdvancedLayoutSupported()).thenReturn(true);
         mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
+        mMediaOutputAdapter.updateItems();
         mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
                 .onCreateViewHolder(new LinearLayout(mContext), 0);
         mMediaItems.add(new MediaItem());
+        mMediaOutputAdapter.updateItems();
         mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2);
         mViewHolder.mContainerLayout.performClick();
 
@@ -613,6 +623,7 @@
 
     @Test
     public void onItemClick_clickDevice_verifyConnectDevice() {
+        when(mMediaOutputController.isCurrentOutputDeviceHasSessionOngoing()).thenReturn(false);
         assertThat(mMediaDevice2.getState()).isEqualTo(
                 LocalMediaManager.MediaDeviceState.STATE_DISCONNECTED);
         mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
@@ -623,6 +634,21 @@
     }
 
     @Test
+    public void onItemClick_clickDeviceWithSessionOngoing_verifyShowsDialog() {
+        when(mMediaOutputController.isCurrentOutputDeviceHasSessionOngoing()).thenReturn(true);
+        assertThat(mMediaDevice2.getState()).isEqualTo(
+                LocalMediaManager.MediaDeviceState.STATE_DISCONNECTED);
+        MediaOutputAdapter.MediaDeviceViewHolder spyMediaDeviceViewHolder = spy(mViewHolder);
+
+        mMediaOutputAdapter.onBindViewHolder(spyMediaDeviceViewHolder, 0);
+        mMediaOutputAdapter.onBindViewHolder(spyMediaDeviceViewHolder, 1);
+        spyMediaDeviceViewHolder.mContainerLayout.performClick();
+
+        verify(mMediaOutputController, never()).connectDevice(mMediaDevice2);
+        verify(spyMediaDeviceViewHolder).showCustomEndSessionDialog(mMediaDevice2);
+    }
+
+    @Test
     public void onItemClick_clicksWithMutingExpectedDeviceExist_cancelsMuteAwaitConnection() {
         when(mMediaOutputController.isAnyDeviceTransferring()).thenReturn(false);
         when(mMediaOutputController.hasMutingExpectedDevice()).thenReturn(true);
@@ -700,6 +726,7 @@
                 mMediaItems.stream().map((item) -> item.getMediaDevice().get()).collect(
                         Collectors.toList()));
         mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
+        mMediaOutputAdapter.updateItems();
         mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
                 .onCreateViewHolder(new LinearLayout(mContext), 0);
         List<MediaDevice> selectableDevices = new ArrayList<>();
@@ -734,4 +761,18 @@
 
         verify(mMediaOutputController).setCurrentColorScheme(wallpaperColors, true);
     }
+
+    @Test
+    public void updateItems_controllerItemsUpdated_notUpdatesInAdapterUntilUpdateItems() {
+        when(mMediaOutputController.isAdvancedLayoutSupported()).thenReturn(true);
+        mMediaOutputAdapter.updateItems();
+        List<MediaItem> updatedList = new ArrayList<>();
+        updatedList.add(new MediaItem());
+        when(mMediaOutputController.getMediaItemList()).thenReturn(updatedList);
+        assertThat(mMediaOutputAdapter.getItemCount()).isEqualTo(mMediaItems.size());
+
+        mMediaOutputAdapter.updateItems();
+
+        assertThat(mMediaOutputAdapter.getItemCount()).isEqualTo(updatedList.size());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index f206409..480d59c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -239,7 +239,7 @@
         when(mMediaOutputBaseAdapter.isDragging()).thenReturn(false);
         mMediaOutputBaseDialogImpl.refresh();
 
-        verify(mMediaOutputBaseAdapter).notifyDataSetChanged();
+        verify(mMediaOutputBaseAdapter).updateItems();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
index 6e1ab58..1c219da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
@@ -361,6 +361,21 @@
             job.cancel()
         }
 
+    @Test
+    fun failedConnection_carrierMergedDefault_notValidated_failed() =
+        testScope.runTest {
+            var latest: Boolean? = null
+            val job = underTest.isDefaultConnectionFailed.onEach { latest = it }.launchIn(this)
+
+            connectionsRepository.hasCarrierMergedConnection.value = true
+            connectionsRepository.defaultConnectionIsValidated.value = false
+            yield()
+
+            assertThat(latest).isTrue()
+
+            job.cancel()
+        }
+
     /** Regression test for b/275076959. */
     @Test
     fun failedConnection_dataSwitchInSameGroup_notFailed() =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
index 8fc0a1a..6298506 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
@@ -200,6 +200,31 @@
         }
 
     @Test
+    fun onFolded_onScreenTurningOnWithoutDozingThenWithDozing_doesNotLogLatency() =
+        runBlocking(IMMEDIATE) {
+            val job = underTest.listenForDozing(this)
+            keyguardRepository.setDozing(false)
+            setAodEnabled(enabled = true)
+
+            yield()
+
+            fold()
+            simulateScreenTurningOn()
+            reset(latencyTracker)
+
+            // Now enable dozing and trigger a second run through the aod animation code. It should
+            // not rerun the animation
+            keyguardRepository.setDozing(true)
+            yield()
+            simulateScreenTurningOn()
+
+            verify(latencyTracker, never()).onActionStart(any())
+            verify(latencyTracker, never()).onActionEnd(any())
+
+            job.cancel()
+        }
+
+    @Test
     fun onFolded_animationCancelled_doesNotLogLatency() =
         runBlocking(IMMEDIATE) {
             val job = underTest.listenForDozing(this)
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 7463061..a324b2f 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -2551,6 +2551,9 @@
     @Override
     public void attachAccessibilityOverlayToWindow(int accessibilityWindowId, SurfaceControl sc)
             throws RemoteException {
+        SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+        t.setTrustedOverlay(sc, true).apply();
+        t.close();
         synchronized (mLock) {
             RemoteAccessibilityConnection connection =
                     mA11yWindowManager.getConnectionLocked(
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index e894f1c..2d1290c 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -5329,9 +5329,8 @@
             mA11yOverlayLayers.remove(displayId);
             return;
         }
-        SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
-        transaction.reparent(sc, parent);
-        transaction.apply();
-        transaction.close();
+        SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+        t.reparent(sc, parent).setTrustedOverlay(sc, true).apply();
+        t.close();
     }
 }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index d290c361..fb94af6 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -1581,6 +1581,13 @@
         // TODO(b/266379948): Ideally wait for PCC request to finish for a while more
         // (say 100ms) before proceeding further on.
 
+        processResponseLockedForPcc(response, response.getClientState(), requestFlags);
+    }
+
+
+    @GuardedBy("mLock")
+    private void processResponseLockedForPcc(@NonNull FillResponse response,
+            @Nullable Bundle newClientState, int flags) {
         if (DBG) {
             Slog.d(TAG, "DBG: Initial response: " + response);
         }
@@ -1588,12 +1595,15 @@
             response = getEffectiveFillResponse(response);
             if (isEmptyResponse(response)) {
                 // Treat it as a null response.
-                processNullResponseLocked(requestId, requestFlags);
+                processNullResponseLocked(
+                        response != null ? response.getRequestId() : 0,
+                        flags);
+                return;
             }
             if (DBG) {
                 Slog.d(TAG, "DBG: Processed response: " + response);
             }
-            processResponseLocked(response, null, requestFlags);
+            processResponseLocked(response, newClientState, flags);
         }
     }
 
@@ -2490,7 +2500,10 @@
                     if (sDebug) Slog.d(TAG,  "Updating client state from auth dataset");
                     mClientState = newClientState;
                 }
-                final Dataset dataset = (Dataset) result;
+                Dataset dataset = (Dataset) result;
+                FillResponse temp = new FillResponse.Builder().addDataset(dataset).build();
+                temp = getEffectiveFillResponse(temp);
+                dataset = temp.getDatasets().get(0);
                 final Dataset oldDataset = authenticatedResponse.getDatasets().get(datasetIdx);
                 if (!isAuthResultDatasetEphemeral(oldDataset, data)) {
                     authenticatedResponse.getDatasets().set(datasetIdx, dataset);
@@ -4665,10 +4678,8 @@
         setViewStatesLocked(oldResponse, ViewState.STATE_INITIAL, true);
         // Move over the id
         newResponse.setRequestId(oldResponse.getRequestId());
-        // Replace the old response
-        mResponses.put(newResponse.getRequestId(), newResponse);
         // Now process the new response
-        processResponseLocked(newResponse, newClientState, 0);
+        processResponseLockedForPcc(newResponse, newClientState, 0);
     }
 
     @GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/SoundTriggerInternal.java b/services/core/java/com/android/server/SoundTriggerInternal.java
index f184574..f8830ea 100644
--- a/services/core/java/com/android/server/SoundTriggerInternal.java
+++ b/services/core/java/com/android/server/SoundTriggerInternal.java
@@ -47,7 +47,14 @@
     int STATUS_OK = SoundTrigger.STATUS_OK;
 
     // Attach to a specific underlying STModule
-    Session attach(@NonNull IBinder client, ModuleProperties underlyingModule);
+    /**
+     * Attach to a specific underlying STModule.
+     * @param client - Binder token representing the app client for death notifications
+     * @param underlyingModule - Properties of the underlying STModule to attach to
+     * @param isTrusted - {@code true} if callbacks will be appropriately AppOps attributed by
+     * a trusted component prior to delivery to the ultimate client.
+     */
+    Session attach(@NonNull IBinder client, ModuleProperties underlyingModule, boolean isTrusted);
 
     // Enumerate possible STModules to attach to
     List<ModuleProperties> listModuleProperties(Identity originatorIdentity);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a888a0b..8ce1829 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2497,13 +2497,10 @@
         final File systemDir = SystemServiceManager.ensureSystemDir();
 
         // TODO: Move creation of battery stats service outside of activity manager service.
-        mBatteryStatsService = new BatteryStatsService(systemContext, systemDir,
-                BackgroundThread.get().getHandler());
-        mBatteryStatsService.getActiveStatistics().readLocked();
-        mBatteryStatsService.scheduleWriteToDisk();
+        mBatteryStatsService = BatteryStatsService.create(systemContext, systemDir,
+                BackgroundThread.getHandler(), this);
         mOnBattery = DEBUG_POWER ? true
                 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
-        mBatteryStatsService.getActiveStatistics().setCallback(this);
         mOomAdjProfiler.batteryPowerChanged(mOnBattery);
 
         mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 6360e2a0..36da888 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -399,6 +399,20 @@
         mCpuWakeupStats = new CpuWakeupStats(context, R.xml.irq_device_map, mHandler);
     }
 
+    /**
+     * Creates an instance of BatteryStatsService and restores data from stored state.
+     */
+    public static BatteryStatsService create(Context context, File systemDir, Handler handler,
+            BatteryStatsImpl.BatteryCallback callback) {
+        BatteryStatsService service = new BatteryStatsService(context, systemDir, handler);
+        service.mStats.setCallback(callback);
+        synchronized (service.mStats) {
+            service.mStats.readLocked();
+        }
+        service.scheduleWriteToDisk();
+        return service;
+    }
+
     public void publish() {
         LocalServices.addService(BatteryStatsInternal.class, new LocalService());
         ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index d7b22a8..c393213 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2300,6 +2300,8 @@
 
             final Process.ProcessStartResult startResult;
             boolean regularZygote = false;
+            app.mProcessGroupCreated = false;
+            app.mSkipProcessGroupCreation = false;
             if (hostingRecord.usesWebviewZygote()) {
                 startResult = startWebView(entryPoint,
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
@@ -2328,18 +2330,28 @@
                         isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap,
                         allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
                         new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
+                // By now the process group should have been created by zygote.
+                app.mProcessGroupCreated = true;
             }
 
             if (!regularZygote) {
                 // webview and app zygote don't have the permission to create the nodes
-                final int res = Process.createProcessGroup(uid, startResult.pid);
-                if (res < 0) {
-                    if (res == -OsConstants.ESRCH) {
-                        Slog.e(ActivityManagerService.TAG, "Unable to create process group for "
-                            + app.processName + " (" + startResult.pid + ")");
-                    } else {
-                        throw new AssertionError("Unable to create process group for "
-                            + app.processName + " (" + startResult.pid + ")");
+                synchronized (app) {
+                    if (!app.mSkipProcessGroupCreation) {
+                        // If we're not told to skip the process group creation, go create it.
+                        final int res = Process.createProcessGroup(uid, startResult.pid);
+                        if (res < 0) {
+                            if (res == -OsConstants.ESRCH) {
+                                Slog.e(ActivityManagerService.TAG,
+                                        "Unable to create process group for "
+                                        + app.processName + " (" + startResult.pid + ")");
+                            } else {
+                                throw new AssertionError("Unable to create process group for "
+                                    + app.processName + " (" + startResult.pid + ")");
+                            }
+                        } else {
+                            app.mProcessGroupCreated = true;
+                        }
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 0417b8c..4ec813e 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -424,6 +424,16 @@
      */
     Runnable mSuccessorStartRunnable;
 
+    /**
+     * Whether or not the process group of this process has been created.
+     */
+    volatile boolean mProcessGroupCreated;
+
+    /**
+     * Whether or not we should skip the process group creation.
+     */
+    volatile boolean mSkipProcessGroupCreation;
+
     void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
             long startUptime, long startElapsedTime) {
         this.mStartUid = startUid;
@@ -1192,8 +1202,26 @@
                 EventLog.writeEvent(EventLogTags.AM_KILL,
                         userId, mPid, processName, mState.getSetAdj(), reason);
                 Process.killProcessQuiet(mPid);
-                if (!asyncKPG) Process.sendSignalToProcessGroup(uid, mPid, OsConstants.SIGKILL);
-                ProcessList.killProcessGroup(uid, mPid);
+                final boolean killProcessGroup;
+                if (mHostingRecord != null
+                        && (mHostingRecord.usesWebviewZygote() || mHostingRecord.usesAppZygote())) {
+                    synchronized (ProcessRecord.this) {
+                        killProcessGroup = mProcessGroupCreated;
+                        if (!killProcessGroup) {
+                            // The process group hasn't been created, request to skip it.
+                            mSkipProcessGroupCreation = true;
+                        }
+                    }
+                } else {
+                    killProcessGroup = true;
+                }
+                if (killProcessGroup) {
+                    if (asyncKPG) {
+                        ProcessList.killProcessGroup(uid, mPid);
+                    } else {
+                        Process.sendSignalToProcessGroup(uid, mPid, OsConstants.SIGKILL);
+                    }
+                }
             } else {
                 mPendingStart = false;
             }
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index a110169..1f3795a 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -44,6 +44,7 @@
 import static android.app.AppOpsManager.OP_RECORD_AUDIO;
 import static android.app.AppOpsManager.OP_RECORD_AUDIO_HOTWORD;
 import static android.app.AppOpsManager.OP_RECORD_AUDIO_SANDBOXED;
+import static android.app.AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;
 import static android.app.AppOpsManager.OP_VIBRATE;
 import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_FAILED;
 import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_STARTED;
@@ -1769,6 +1770,11 @@
     @Override
     public void setUidMode(int code, int uid, int mode) {
         setUidMode(code, uid, mode, null);
+        if (code == OP_RUN_ANY_IN_BACKGROUND) {
+            // TODO (b/280869337): Remove this once we have the required data.
+            Slog.wtfStack(TAG, "setUidMode called for RUN_ANY_IN_BACKGROUND by uid: "
+                    + UserHandle.formatUid(Binder.getCallingUid()));
+        }
     }
 
     private void setUidMode(int code, int uid, int mode,
@@ -1944,6 +1950,17 @@
     @Override
     public void setMode(int code, int uid, @NonNull String packageName, int mode) {
         setMode(code, uid, packageName, mode, null);
+        final int callingUid = Binder.getCallingUid();
+        if (code == OP_RUN_ANY_IN_BACKGROUND && mode != MODE_ALLOWED) {
+            // TODO (b/280869337): Remove this once we have the required data.
+            final String callingPackage = ArrayUtils.firstOrNull(getPackagesForUid(callingUid));
+            Slog.wtfStack(TAG,
+                    "RUN_ANY_IN_BACKGROUND for package " + packageName + " changed to mode: "
+                            + modeToName(mode) + " via setMode. Calling package: " + callingPackage
+                            + ", calling uid: " + UserHandle.formatUid(callingUid)
+                            + ", calling pid: " + Binder.getCallingPid()
+                            + ", system pid: " + Process.myPid());
+        }
     }
 
     void setMode(int code, int uid, @NonNull String packageName, int mode,
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 773df37..1d8bef1 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -1031,7 +1031,8 @@
         synchronized (rolesMap) {
             Pair<Integer, Integer> key = new Pair<>(useCase, role);
             if (!rolesMap.containsKey(key)) {
-                return AudioSystem.SUCCESS;
+                // trying to remove a role for a device that wasn't set
+                return AudioSystem.BAD_VALUE;
             }
             List<AudioDeviceAttributes> roleDevices = rolesMap.get(key);
             List<AudioDeviceAttributes> appliedDevices = new ArrayList<>();
diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java
index aece17e7..4aa256d 100644
--- a/services/core/java/com/android/server/audio/SoundDoseHelper.java
+++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java
@@ -78,6 +78,23 @@
     /*package*/ static final String ACTION_CHECK_MUSIC_ACTIVE =
             "com.android.server.audio.action.CHECK_MUSIC_ACTIVE";
 
+    /**
+     * Property to force the index based safe volume warnings. Note that usually when the
+     * CSD warnings are active the safe volume warnings are deactivated. In combination with
+     * {@link SoundDoseHelper#SYSTEM_PROPERTY_SAFEMEDIA_CSD_FORCE} both approaches can be active
+     * at the same time.
+     */
+    private static final String SYSTEM_PROPERTY_SAFEMEDIA_FORCE = "audio.safemedia.force";
+    /** Property for bypassing the index based safe volume approach. */
+    private static final String SYSTEM_PROPERTY_SAFEMEDIA_BYPASS = "audio.safemedia.bypass";
+    /**
+     * Property to force the CSD warnings. Note that usually when the CSD warnings are active the
+     * safe volume warnings are deactivated. In combination with
+     * {@link SoundDoseHelper#SYSTEM_PROPERTY_SAFEMEDIA_FORCE} both approaches can be active
+     * at the same time.
+     */
+    private static final String SYSTEM_PROPERTY_SAFEMEDIA_CSD_FORCE = "audio.safemedia.csd.force";
+
     // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
     // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
     // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
@@ -830,56 +847,64 @@
     }
 
     private void onConfigureSafeMedia(boolean force, String caller) {
+        updateCsdEnabled(caller);
+
         synchronized (mSafeMediaVolumeStateLock) {
             int mcc = mContext.getResources().getConfiguration().mcc;
             if ((mMcc != mcc) || ((mMcc == 0) && force)) {
                 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
                         com.android.internal.R.integer.config_safe_media_volume_index) * 10;
-
                 initSafeMediaVolumeIndex();
 
-                boolean safeMediaVolumeEnabled =
-                        SystemProperties.getBoolean("audio.safemedia.force", false)
-                                || mContext.getResources().getBoolean(
-                                com.android.internal.R.bool.config_safe_media_volume_enabled);
-                boolean safeMediaVolumeBypass =
-                        SystemProperties.getBoolean("audio.safemedia.bypass", false);
+                updateSafeMediaVolume_l(caller);
 
-                // The persisted state is either "disabled" or "active": this is the state applied
-                // next time we boot and cannot be "inactive"
-                int persistedState;
-                if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
-                    persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
-                    // The state can already be "inactive" here if the user has forced it before
-                    // the 30 seconds timeout for forced configuration. In this case we don't reset
-                    // it to "active".
-                    if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
-                        if (mMusicActiveMs == 0) {
-                            mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
-                            enforceSafeMediaVolume(caller);
-                        } else {
-                            // We have existing playback time recorded, already confirmed.
-                            mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
-                            mLastMusicActiveTimeMs = 0;
-                        }
-                    }
-                } else {
-                    persistedState = SAFE_MEDIA_VOLUME_DISABLED;
-                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
-                }
                 mMcc = mcc;
-                mAudioHandler.sendMessageAtTime(
-                        mAudioHandler.obtainMessage(MSG_PERSIST_SAFE_VOLUME_STATE,
-                                persistedState, /*arg2=*/0,
-                                /*obj=*/null), /*delay=*/0);
             }
-
-            updateCsdEnabled(caller);
         }
     }
 
+    @GuardedBy("mSafeMediaVolumeStateLock")
+    private void updateSafeMediaVolume_l(String caller) {
+        boolean safeMediaVolumeEnabled =
+                SystemProperties.getBoolean(SYSTEM_PROPERTY_SAFEMEDIA_FORCE, false)
+                        || (mContext.getResources().getBoolean(
+                        com.android.internal.R.bool.config_safe_media_volume_enabled)
+                        && !mEnableCsd.get());
+        boolean safeMediaVolumeBypass =
+                SystemProperties.getBoolean(SYSTEM_PROPERTY_SAFEMEDIA_BYPASS, false);
+
+        // The persisted state is either "disabled" or "active": this is the state applied
+        // next time we boot and cannot be "inactive"
+        int persistedState;
+        if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
+            persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
+            // The state can already be "inactive" here if the user has forced it before
+            // the 30 seconds timeout for forced configuration. In this case we don't reset
+            // it to "active".
+            if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
+                if (mMusicActiveMs == 0) {
+                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
+                    enforceSafeMediaVolume(caller);
+                } else {
+                    // We have existing playback time recorded, already confirmed.
+                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
+                    mLastMusicActiveTimeMs = 0;
+                }
+            }
+        } else {
+            persistedState = SAFE_MEDIA_VOLUME_DISABLED;
+            mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
+        }
+
+        mAudioHandler.sendMessageAtTime(
+                mAudioHandler.obtainMessage(MSG_PERSIST_SAFE_VOLUME_STATE,
+                        persistedState, /*arg2=*/0,
+                        /*obj=*/null), /*delay=*/0);
+    }
+
     private void updateCsdEnabled(String caller) {
-        boolean newEnableCsd = SystemProperties.getBoolean("audio.safemedia.force", false);
+        boolean newEnableCsd = SystemProperties.getBoolean(SYSTEM_PROPERTY_SAFEMEDIA_CSD_FORCE,
+                false);
         if (!newEnableCsd) {
             final String featureFlagEnableCsdValue = DeviceConfig.getProperty(
                     DeviceConfig.NAMESPACE_MEDIA,
@@ -895,6 +920,10 @@
         if (mEnableCsd.compareAndSet(!newEnableCsd, newEnableCsd)) {
             Log.i(TAG, caller + ": enable CSD " + newEnableCsd);
             initCsd();
+
+            synchronized (mSafeMediaVolumeStateLock) {
+                updateSafeMediaVolume_l(caller);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index da822fa..3e31bd1 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -892,9 +892,8 @@
      * @return true/false if contact sharing is enabled/disabled
      */
     protected boolean isContactSharingAllowedForCloneProfile() {
-        // TODO(b/253449368): This method should also check for the config controlling
-        // all app-cloning features.
-        return mAppCloningDeviceConfigHelper.getEnableAppCloningBuildingBlocks();
+        return mContext.getResources().getBoolean(R.bool.config_enableAppCloningBuildingBlocks)
+                && mAppCloningDeviceConfigHelper.getEnableAppCloningBuildingBlocks();
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 9b1a80be..0bd6dff 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -1330,7 +1330,11 @@
         @Override
         public PendingIntent getActivityLaunchIntent(String callingPackage, ComponentName component,
                 UserHandle user) {
-            ensureShortcutPermission(callingPackage);
+            if (mContext.checkPermission(android.Manifest.permission.START_TASKS_FROM_RECENTS,
+                    injectBinderCallingPid(), injectBinderCallingUid())
+                            != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Permission START_TASKS_FROM_RECENTS required");
+            }
             if (!canAccessProfile(user.getIdentifier(), "Cannot start activity")) {
                 throw new ActivityNotFoundException("Activity could not be found");
             }
diff --git a/services/core/java/com/android/server/pm/NoFilteringResolver.java b/services/core/java/com/android/server/pm/NoFilteringResolver.java
index 3923890..ccd5b0e 100644
--- a/services/core/java/com/android/server/pm/NoFilteringResolver.java
+++ b/services/core/java/com/android/server/pm/NoFilteringResolver.java
@@ -23,6 +23,7 @@
 import android.content.pm.ResolveInfo;
 import android.os.Binder;
 
+import com.android.internal.R;
 import com.android.internal.config.appcloning.AppCloningDeviceConfigHelper;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.resolution.ComponentResolverApi;
@@ -61,7 +62,8 @@
             long flags) {
         final long token = Binder.clearCallingIdentity();
         try {
-            return appCloningDeviceConfigHelper.getEnableAppCloningBuildingBlocks()
+            return  context.getResources().getBoolean(R.bool.config_enableAppCloningBuildingBlocks)
+                    && appCloningDeviceConfigHelper.getEnableAppCloningBuildingBlocks()
                     && (resolveForStart || (((flags & PackageManager.MATCH_CLONE_PROFILE) != 0)
                     && hasPermission(context, Manifest.permission.QUERY_CLONED_APPS)));
         } finally {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 1c89ec4..3c5ad2a 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -1573,7 +1573,7 @@
         @Override
         public void reportUserMayRequestUnlock(int userId) throws RemoteException {
             enforceReportPermission();
-            mHandler.obtainMessage(MSG_USER_MAY_REQUEST_UNLOCK, userId).sendToTarget();
+            mHandler.obtainMessage(MSG_USER_MAY_REQUEST_UNLOCK, userId, /*arg2=*/ 0).sendToTarget();
         }
 
         @Override
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 88c9042..1f5c1cf 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -2629,6 +2629,10 @@
                         getSessionLocked(sessionState).notifyAdBufferReady(buffer);
                     } catch (RemoteException | SessionNotFoundException e) {
                         Slog.e(TAG, "error in notifyAdBuffer", e);
+                    } finally {
+                        if (buffer != null) {
+                            buffer.getSharedMemory().close();
+                        }
                     }
                 }
             } finally {
@@ -3891,10 +3895,13 @@
                     return;
                 }
                 try {
-                    mSessionState.client.onAdBufferConsumed(
-                            buffer, mSessionState.seq);
+                    mSessionState.client.onAdBufferConsumed(buffer, mSessionState.seq);
                 } catch (RemoteException e) {
                     Slog.e(TAG, "error in onAdBufferConsumed", e);
+                } finally {
+                    if (buffer != null) {
+                        buffer.getSharedMemory().close();
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
index 80cb085..e6273d3 100644
--- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
@@ -2007,6 +2007,10 @@
                         getSessionLocked(sessionState).notifyAdBufferConsumed(buffer);
                     } catch (RemoteException | SessionNotFoundException e) {
                         Slogf.e(TAG, "error in notifyAdBufferConsumed", e);
+                    } finally {
+                        if (buffer != null) {
+                            buffer.getSharedMemory().close();
+                        }
                     }
                 }
             } finally {
@@ -3063,6 +3067,10 @@
                     mSessionState.mClient.onAdBufferReady(buffer, mSessionState.mSeq);
                 } catch (RemoteException e) {
                     Slogf.e(TAG, "error in onAdBuffer", e);
+                } finally {
+                    if (buffer != null) {
+                        buffer.getSharedMemory().close();
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index c40d72c..6b90181 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -1159,9 +1159,10 @@
             }
             return;
         }
+        transition.collect(topFocusedRootTask);
+        executeMultiWindowFullscreenRequest(fullscreenRequest, topFocusedRootTask);
         r.mTransitionController.requestStartTransition(transition, topFocusedRootTask,
                 null /* remoteTransition */, null /* displayChange */);
-        executeMultiWindowFullscreenRequest(fullscreenRequest, topFocusedRootTask);
         transition.setReady(topFocusedRootTask, true);
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 0b572df..f35343c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3555,7 +3555,10 @@
                 mRootWindowContainer.forAllDisplays(displayContent -> {
                     mKeyguardController.keyguardGoingAway(displayContent.getDisplayId(), flags);
                 });
-                getWallpaperManagerInternal().onKeyguardGoingAway();
+                WallpaperManagerInternal wallpaperManagerInternal = getWallpaperManagerInternal();
+                if (wallpaperManagerInternal != null) {
+                    wallpaperManagerInternal.onKeyguardGoingAway();
+                }
             }
         } finally {
             Binder.restoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index be52e5a..76fd6932 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -184,7 +184,6 @@
 
     private final boolean mCarDockEnablesAccelerometer;
     private final boolean mDeskDockEnablesAccelerometer;
-    private final boolean mDeskDockRespectsNoSensorAndLockedWithoutAccelerometer;
     private final AccessibilityManager mAccessibilityManager;
     private final ImmersiveModeConfirmation mImmersiveModeConfirmation;
     private final ScreenshotHelper mScreenshotHelper;
@@ -394,8 +393,6 @@
         final Resources r = mContext.getResources();
         mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer);
         mDeskDockEnablesAccelerometer = r.getBoolean(R.bool.config_deskDockEnablesAccelerometer);
-        mDeskDockRespectsNoSensorAndLockedWithoutAccelerometer =
-                r.getBoolean(R.bool.config_deskRespectsNoSensorAndLockedWithoutAccelerometer);
         mCanSystemBarsBeShownByUser = !r.getBoolean(
                 R.bool.config_remoteInsetsControllerControlsSystemBars) || r.getBoolean(
                 R.bool.config_remoteInsetsControllerSystemBarsCanBeShownByUserAction);
@@ -707,10 +704,6 @@
         return mDeskDockEnablesAccelerometer;
     }
 
-    boolean isDeskDockRespectsNoSensorAndLockedWithoutAccelerometer() {
-        return mDeskDockRespectsNoSensorAndLockedWithoutAccelerometer;
-    }
-
     public void setPersistentVrModeEnabled(boolean persistentVrModeEnabled) {
         mPersistentVrModeEnabled = persistentVrModeEnabled;
     }
@@ -2514,8 +2507,6 @@
         pw.print("mCarDockEnablesAccelerometer="); pw.print(mCarDockEnablesAccelerometer);
         pw.print(" mDeskDockEnablesAccelerometer=");
         pw.println(mDeskDockEnablesAccelerometer);
-        pw.print(" mDeskDockRespectsNoSensorAndLockedWithoutAccelerometer=");
-        pw.println(mDeskDockRespectsNoSensorAndLockedWithoutAccelerometer);
         pw.print(prefix); pw.print("mDockMode="); pw.print(Intent.dockStateToString(mDockMode));
         pw.print(" mLidState="); pw.println(WindowManagerFuncs.lidStateToString(mLidState));
         pw.print(prefix); pw.print("mAwake="); pw.print(mAwake);
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index a3d233d..87de0f6 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -1239,10 +1239,6 @@
                 mDisplayPolicy.isCarDockEnablesAccelerometer();
         final boolean deskDockEnablesAccelerometer =
                 mDisplayPolicy.isDeskDockEnablesAccelerometer();
-        final boolean deskDockRespectsNoSensorAndLockedWithoutAccelerometer =
-                mDisplayPolicy.isDeskDockRespectsNoSensorAndLockedWithoutAccelerometer()
-                        && (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED
-                                || orientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
 
         @Surface.Rotation
         final int preferredRotation;
@@ -1263,10 +1259,10 @@
                 || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
                 || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
                 && (deskDockEnablesAccelerometer || mDeskDockRotation >= 0)
-                && !deskDockRespectsNoSensorAndLockedWithoutAccelerometer) {
+                && !(orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED
+                        || orientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR)) {
             // Ignore sensor when in desk dock unless explicitly enabled.
-            // This case can override the behavior of NOSENSOR, and can also
-            // enable 180 degree rotation while docked.
+            // This case can enable 180 degree rotation while docked.
             preferredRotation = deskDockEnablesAccelerometer ? sensorRotation : mDeskDockRotation;
         } else if (hdmiPlugged && mDemoHdmiRotationLock) {
             // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 50bf38b..bfd0d96 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -314,7 +314,6 @@
 
         mLogger.mCreateWallTimeMs = System.currentTimeMillis();
         mLogger.mCreateTimeNs = SystemClock.elapsedRealtimeNanos();
-        controller.mTransitionTracer.logState(this);
     }
 
     @Nullable
@@ -532,7 +531,6 @@
 
         mLogger.mSyncId = mSyncId;
         mLogger.mCollectTimeNs = SystemClock.elapsedRealtimeNanos();
-        mController.mTransitionTracer.logState(this);
     }
 
     /**
@@ -555,7 +553,6 @@
         applyReady();
 
         mLogger.mStartTimeNs = SystemClock.elapsedRealtimeNanos();
-        mController.mTransitionTracer.logState(this);
 
         mController.updateAnimatingState(mTmpTransaction);
         // merge into the next-time the global transaction is applied. This is too-early to set
@@ -1232,7 +1229,6 @@
         validateVisibility();
 
         mState = STATE_FINISHED;
-        mController.mTransitionTracer.logState(this);
         // Rotation change may be deferred while there is a display change transition, so check
         // again in case there is a new pending change.
         if (hasParticipatedDisplay && !mController.useShellTransitionsRotation()) {
@@ -1261,6 +1257,7 @@
         }
         ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Aborting Transition: %d", mSyncId);
         mState = STATE_ABORT;
+        mLogger.mAbortTimeNs = SystemClock.elapsedRealtimeNanos();
         mController.mTransitionTracer.logAbortedTransition(this);
         // Syncengine abort will call through to onTransactionReady()
         mSyncEngine.abort(mSyncId);
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index c9316bf..b697ab1 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -941,7 +941,6 @@
         }
         mPlayingTransitions.add(transition);
         updateRunningRemoteAnimation(transition, true /* isPlaying */);
-        mTransitionTracer.logState(transition);
         // Sync engine should become idle after this, so the idle listener will check the queue.
     }
 
@@ -1122,7 +1121,6 @@
                 mLatestOnTopTasksReported.clear();
             }
         }
-        mTransitionTracer.logState(transition);
         // This is called during Transition.abort whose codepath will eventually check the queue
         // via sync-engine idle.
     }
@@ -1416,12 +1414,11 @@
         long mReadyTimeNs;
         long mSendTimeNs;
         long mFinishTimeNs;
+        long mAbortTimeNs;
         TransitionRequestInfo mRequest;
         WindowContainerTransaction mStartWCT;
         int mSyncId;
         TransitionInfo mInfo;
-        ProtoOutputStream mProtoOutputStream = new ProtoOutputStream();
-        long mProtoToken;
 
         private String buildOnSendLog() {
             StringBuilder sb = new StringBuilder("Sent Transition #").append(mSyncId)
diff --git a/services/core/java/com/android/server/wm/TransitionTracer.java b/services/core/java/com/android/server/wm/TransitionTracer.java
index 6aac81b..afc1492 100644
--- a/services/core/java/com/android/server/wm/TransitionTracer.java
+++ b/services/core/java/com/android/server/wm/TransitionTracer.java
@@ -50,10 +50,11 @@
     private static final int ALWAYS_ON_TRACING_CAPACITY = 15 * 1024; // 15 KB
     private static final int ACTIVE_TRACING_BUFFER_CAPACITY = 5000 * 1024; // 5 MB
     static final String WINSCOPE_EXT = ".winscope";
-    private static final String TRACE_FILE = "/data/misc/wmtrace/transition_trace" + WINSCOPE_EXT;
+    private static final String TRACE_FILE =
+            "/data/misc/wmtrace/wm_transition_trace" + WINSCOPE_EXT;
     private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
 
-    private final TransitionTraceBuffer mTraceBuffer = new TransitionTraceBuffer();
+    private final TraceBuffer mTraceBuffer = new TraceBuffer(ALWAYS_ON_TRACING_CAPACITY);
 
     private final Object mEnabledLock = new Object();
     private volatile boolean mActiveTracingEnabled = false;
@@ -72,18 +73,22 @@
      */
     public void logSentTransition(Transition transition, ArrayList<ChangeInfo> targets,
             TransitionInfo info) {
-        // Dump the info to proto that will not be available when the transition finishes or
-        // is canceled
-        final ProtoOutputStream outputStream = transition.mLogger.mProtoOutputStream;
-        transition.mLogger.mProtoToken = outputStream
-                .start(com.android.server.wm.shell.TransitionTraceProto.FINISHED_TRANSITIONS);
+        final ProtoOutputStream outputStream = new ProtoOutputStream();
+        final long protoToken = outputStream
+                .start(com.android.server.wm.shell.TransitionTraceProto.TRANSITIONS);
+        outputStream.write(com.android.server.wm.shell.Transition.ID, transition.getSyncId());
+        outputStream.write(com.android.server.wm.shell.Transition.CREATE_TIME_NS,
+                transition.mLogger.mCreateTimeNs);
+        outputStream.write(com.android.server.wm.shell.Transition.SEND_TIME_NS,
+                transition.mLogger.mSendTimeNs);
         outputStream.write(com.android.server.wm.shell.Transition.START_TRANSACTION_ID,
                 transition.getStartTransaction().getId());
         outputStream.write(com.android.server.wm.shell.Transition.FINISH_TRANSACTION_ID,
                 transition.getFinishTransaction().getId());
         dumpTransitionTargetsToProto(outputStream, transition, targets);
+        outputStream.end(protoToken);
 
-        logTransitionInfo(transition, info);
+        mTraceBuffer.add(outputStream);
     }
 
     /**
@@ -93,17 +98,15 @@
      * @param transition The transition that has finished.
      */
     public void logFinishedTransition(Transition transition) {
-        if (transition.mLogger.mProtoToken == 0) {
-            // Transition finished but never sent, so open token never added
-            final ProtoOutputStream outputStream = transition.mLogger.mProtoOutputStream;
-            transition.mLogger.mProtoToken = outputStream
-                    .start(com.android.server.wm.shell.TransitionTraceProto.FINISHED_TRANSITIONS);
-        }
+        final ProtoOutputStream outputStream = new ProtoOutputStream();
+        final long protoToken = outputStream
+                .start(com.android.server.wm.shell.TransitionTraceProto.TRANSITIONS);
+        outputStream.write(com.android.server.wm.shell.Transition.ID, transition.getSyncId());
+        outputStream.write(com.android.server.wm.shell.Transition.FINISH_TIME_NS,
+                transition.mLogger.mFinishTimeNs);
+        outputStream.end(protoToken);
 
-        // Dump the rest of the transition's info that wasn't dumped during logSentTransition
-        dumpFinishedTransitionToProto(transition.mLogger.mProtoOutputStream, transition);
-        transition.mLogger.mProtoOutputStream.end(transition.mLogger.mProtoToken);
-        mTraceBuffer.pushTransitionProto(transition.mLogger.mProtoOutputStream);
+        mTraceBuffer.add(outputStream);
     }
 
     /**
@@ -113,38 +116,15 @@
      * @param transition The transition that has been aborted
      */
     public void logAbortedTransition(Transition transition) {
-        // We don't care about aborted transitions unless actively tracing
-        if (!mActiveTracingEnabled) {
-            return;
-        }
-        logFinishedTransition(transition);
-    }
-
-    /**
-     * Records the current state of a transition in the transition trace (if it is running).
-     * @param transition the transition that we want to record the state of.
-     */
-    public void logState(com.android.server.wm.Transition transition) {
-        if (!mActiveTracingEnabled) {
-            return;
-        }
         final ProtoOutputStream outputStream = new ProtoOutputStream();
-        dumpTransitionStateToProto(outputStream, transition);
-        mTraceBuffer.pushTransitionState(outputStream);
-    }
+        final long protoToken = outputStream
+                .start(com.android.server.wm.shell.TransitionTraceProto.TRANSITIONS);
+        outputStream.write(com.android.server.wm.shell.Transition.ID, transition.getSyncId());
+        outputStream.write(com.android.server.wm.shell.Transition.ABORT_TIME_NS,
+                transition.mLogger.mAbortTimeNs);
+        outputStream.end(protoToken);
 
-    /**
-     * Records the transition info that is being sent over to Shell.
-     * @param transition The transition the info is associated with.
-     * @param info The transition info we want to log.
-     */
-    private void logTransitionInfo(Transition transition, TransitionInfo info) {
-        if (!mActiveTracingEnabled) {
-            return;
-        }
-        final ProtoOutputStream outputStream = new ProtoOutputStream();
-        dumpTransitionInfoToProto(outputStream, transition, info);
-        mTraceBuffer.pushTransitionInfo(outputStream);
+        mTraceBuffer.add(outputStream);
     }
 
     private void dumpTransitionTargetsToProto(ProtoOutputStream outputStream,
@@ -189,139 +169,6 @@
         Trace.endSection();
     }
 
-    private void dumpFinishedTransitionToProto(
-            ProtoOutputStream outputStream,
-            Transition transition
-    ) {
-        Trace.beginSection("TransitionTracer#dumpFinishedTransitionToProto");
-
-        outputStream.write(com.android.server.wm.shell.Transition.CREATE_TIME_NS,
-                transition.mLogger.mCreateTimeNs);
-        outputStream.write(com.android.server.wm.shell.Transition.SEND_TIME_NS,
-                transition.mLogger.mSendTimeNs);
-        outputStream.write(com.android.server.wm.shell.Transition.FINISH_TIME_NS,
-                transition.mLogger.mFinishTimeNs);
-
-        Trace.endSection();
-    }
-
-    private void dumpTransitionStateToProto(ProtoOutputStream outputStream, Transition transition) {
-        Trace.beginSection("TransitionTracer#dumpTransitionStateToProto");
-
-        final long stateToken = outputStream
-                .start(com.android.server.wm.shell.TransitionTraceProto.TRANSITION_STATES);
-
-        outputStream.write(com.android.server.wm.shell.TransitionState.TIME_NS,
-                SystemClock.elapsedRealtimeNanos());
-        outputStream.write(com.android.server.wm.shell.TransitionState.TRANSITION_ID,
-                transition.getSyncId());
-        outputStream.write(com.android.server.wm.shell.TransitionState.TRANSITION_TYPE,
-                transition.mType);
-        outputStream.write(com.android.server.wm.shell.TransitionState.STATE,
-                transition.getState());
-        outputStream.write(com.android.server.wm.shell.TransitionState.FLAGS,
-                transition.getFlags());
-
-        for (int i = 0; i < transition.mChanges.size(); ++i) {
-            final WindowContainer window = transition.mChanges.keyAt(i);
-            final ChangeInfo changeInfo = transition.mChanges.valueAt(i);
-            dumpChangeInfoToProto(outputStream, window, changeInfo);
-        }
-
-        for (int i = 0; i < transition.mParticipants.size(); ++i) {
-            final WindowContainer window = transition.mParticipants.valueAt(i);
-            window.writeIdentifierToProto(outputStream,
-                    com.android.server.wm.shell.TransitionState.PARTICIPANTS);
-        }
-
-        outputStream.end(stateToken);
-        Trace.endSection();
-    }
-
-    private void dumpChangeInfoToProto(ProtoOutputStream outputStream, WindowContainer window,
-            ChangeInfo changeInfo) {
-        Trace.beginSection("TransitionTraceBuffer#writeChange");
-        final long changeEntryToken =
-                outputStream.start(com.android.server.wm.shell.TransitionState.CHANGE);
-
-        final int transitMode = changeInfo.getTransitMode(window);
-        final boolean hasChanged = changeInfo.hasChanged();
-        final int changeFlags = changeInfo.getChangeFlags(window);
-        final int windowingMode = changeInfo.mWindowingMode;
-
-        outputStream.write(com.android.server.wm.shell.ChangeInfo.TRANSIT_MODE, transitMode);
-        outputStream.write(com.android.server.wm.shell.ChangeInfo.HAS_CHANGED, hasChanged);
-        outputStream.write(com.android.server.wm.shell.ChangeInfo.CHANGE_FLAGS, changeFlags);
-        outputStream.write(com.android.server.wm.shell.ChangeInfo.WINDOWING_MODE, windowingMode);
-        window.writeIdentifierToProto(
-                outputStream, com.android.server.wm.shell.ChangeInfo.WINDOW_IDENTIFIER);
-
-        outputStream.end(changeEntryToken);
-        Trace.endSection();
-    }
-
-    private void dumpTransitionInfoToProto(ProtoOutputStream outputStream,
-            Transition transition, TransitionInfo info) {
-        Trace.beginSection("TransitionTracer#dumpTransitionInfoToProto");
-        final long transitionInfoToken = outputStream
-                .start(com.android.server.wm.shell.TransitionTraceProto.TRANSITION_INFO);
-
-        outputStream.write(com.android.server.wm.shell.TransitionInfo.TRANSITION_ID,
-                transition.getSyncId());
-        for (int i = 0; i < info.getChanges().size(); ++i) {
-            TransitionInfo.Change change = info.getChanges().get(i);
-            dumpTransitionInfoChangeToProto(outputStream, change);
-        }
-
-        outputStream.end(transitionInfoToken);
-        Trace.endSection();
-    }
-
-    private void dumpTransitionInfoChangeToProto(
-            ProtoOutputStream outputStream,
-            TransitionInfo.Change change
-    ) {
-        Trace.beginSection("TransitionTracer#dumpTransitionInfoChangeToProto");
-        final long changeEntryToken = outputStream
-                .start(com.android.server.wm.shell.TransitionInfo.CHANGE);
-
-        outputStream.write(com.android.server.wm.shell.TransitionInfoChange.LAYER_ID,
-                change.getLeash().getLayerId());
-        outputStream.write(com.android.server.wm.shell.TransitionInfoChange.MODE, change.getMode());
-
-        outputStream.end(changeEntryToken);
-        Trace.endSection();
-    }
-
-    private class TransitionTraceBuffer {
-        private final TraceBuffer mTransitionBuffer = new TraceBuffer(ALWAYS_ON_TRACING_CAPACITY);
-        private final TraceBuffer mStateBuffer = new TraceBuffer(ACTIVE_TRACING_BUFFER_CAPACITY);
-        private final TraceBuffer mTransitionInfoBuffer =
-                new TraceBuffer(ACTIVE_TRACING_BUFFER_CAPACITY);
-
-        private void pushTransitionProto(ProtoOutputStream outputStream) {
-            mTransitionBuffer.add(outputStream);
-        }
-
-        private void pushTransitionState(ProtoOutputStream outputStream) {
-            mStateBuffer.add(outputStream);
-        }
-
-        private void pushTransitionInfo(ProtoOutputStream outputStream) {
-            mTransitionInfoBuffer.add(outputStream);
-        }
-
-        public void writeToFile(File file, ProtoOutputStream proto) throws IOException {
-            mTransitionBuffer.writeTraceToFile(file, proto);
-        }
-
-        public void reset() {
-            mTransitionBuffer.resetBuffer();
-            mStateBuffer.resetBuffer();
-            mTransitionInfoBuffer.resetBuffer();
-        }
-    }
-
     /**
      * Starts collecting transitions for the trace.
      * If called while a trace is already running, this will reset the trace.
@@ -335,8 +182,8 @@
         LogAndPrintln.i(pw, "Starting shell transition trace.");
         synchronized (mEnabledLock) {
             mActiveTracingEnabled = true;
-            mTraceBuffer.mTransitionBuffer.setCapacity(ACTIVE_TRACING_BUFFER_CAPACITY);
-            mTraceBuffer.reset();
+            mTraceBuffer.resetBuffer();
+            mTraceBuffer.setCapacity(ACTIVE_TRACING_BUFFER_CAPACITY);
         }
         Trace.endSection();
     }
@@ -364,8 +211,8 @@
         synchronized (mEnabledLock) {
             mActiveTracingEnabled = false;
             writeTraceToFileLocked(pw, outputFile);
-            mTraceBuffer.reset();
-            mTraceBuffer.mTransitionBuffer.setCapacity(ALWAYS_ON_TRACING_CAPACITY);
+            mTraceBuffer.resetBuffer();
+            mTraceBuffer.setCapacity(ALWAYS_ON_TRACING_CAPACITY);
         }
         Trace.endSection();
     }
@@ -404,7 +251,7 @@
             int pid = android.os.Process.myPid();
             LogAndPrintln.i(pw, "Writing file to " + file.getAbsolutePath()
                     + " from process " + pid);
-            mTraceBuffer.writeToFile(file, proto);
+            mTraceBuffer.writeTraceToFile(file, proto);
         } catch (IOException e) {
             LogAndPrintln.e(pw, "Unable to write buffer to file", e);
         }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 3ccf183..829a33d 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -3592,11 +3592,11 @@
                 && !mTransitionController.useShellTransitionsRotation()) {
             if (deltaRotation != Surface.ROTATION_0) {
                 updateSurfaceRotation(t, deltaRotation, null /* positionLeash */);
-                t.setFixedTransformHint(mSurfaceControl,
+                getPendingTransaction().setFixedTransformHint(mSurfaceControl,
                         getWindowConfiguration().getDisplayRotation());
             } else if (deltaRotation != mLastDeltaRotation) {
                 t.setMatrix(mSurfaceControl, 1, 0, 0, 1);
-                t.unsetFixedTransformHint(mSurfaceControl);
+                getPendingTransaction().unsetFixedTransformHint(mSurfaceControl);
             }
         }
         mLastDeltaRotation = deltaRotation;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 4c5efef..31afcbf 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -596,7 +596,8 @@
                 .build();
         t.setPosition(leash, mLastSurfacePosition.x, mLastSurfacePosition.y);
         t.reparent(getSurfaceControl(), leash);
-        t.setFixedTransformHint(leash, getWindowConfiguration().getDisplayRotation());
+        getPendingTransaction().setFixedTransformHint(leash,
+                getWindowConfiguration().getDisplayRotation());
         mFixedRotationTransformLeash = leash;
         updateSurfaceRotation(t, rotation, mFixedRotationTransformLeash);
         return mFixedRotationTransformLeash;
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index 8728c3c..86dbe11 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -482,7 +482,7 @@
                             callback,
                             request,
                             constructCallingAppInfo(callingPackage, userId, request.getOrigin()),
-                            getEnabledProviders(),
+                            getEnabledProvidersForUser(userId),
                             CancellationSignal.fromTransport(cancelTransport),
                             timestampBegan);
             addSessionLocked(userId, session);
@@ -537,7 +537,7 @@
                             getCredentialCallback,
                             request,
                             constructCallingAppInfo(callingPackage, userId, request.getOrigin()),
-                            getEnabledProviders(),
+                            getEnabledProvidersForUser(userId),
                             CancellationSignal.fromTransport(cancelTransport),
                             timestampBegan,
                             prepareGetCredentialCallback);
@@ -655,7 +655,7 @@
                             request,
                             callback,
                             constructCallingAppInfo(callingPackage, userId, request.getOrigin()),
-                            getEnabledProviders(),
+                            getEnabledProvidersForUser(userId),
                             getPrimaryProvidersForUserId(getContext(), userId),
                             CancellationSignal.fromTransport(cancelTransport),
                             timestampBegan);
@@ -726,10 +726,13 @@
                             "setEnabledProviders",
                             null);
 
+            Set<String> enableProvider = new HashSet<>(providers);
+            enableProvider.addAll(primaryProviders);
+
             boolean writeEnabledStatus =
                     Settings.Secure.putStringForUser(getContext().getContentResolver(),
                             Settings.Secure.CREDENTIAL_SERVICE,
-                            String.join(":", providers),
+                            String.join(":", enableProvider),
                             userId);
 
             boolean writePrimaryStatus =
@@ -804,7 +807,7 @@
             verifyGetProvidersPermission();
 
             return CredentialProviderInfoFactory.getCredentialProviderServices(
-                    mContext, userId, providerFilter, getEnabledProviders(),
+                    mContext, userId, providerFilter, getEnabledProvidersForUser(userId),
                     getPrimaryProvidersForUserId(mContext, userId));
         }
 
@@ -815,7 +818,7 @@
 
             final int userId = UserHandle.getCallingUserId();
             return CredentialProviderInfoFactory.getCredentialProviderServicesForTesting(
-                    mContext, userId, providerFilter, getEnabledProviders(),
+                    mContext, userId, providerFilter, getEnabledProvidersForUser(userId),
                     getPrimaryProvidersForUserId(mContext, userId));
         }
 
@@ -832,24 +835,26 @@
             }
         }
 
-        @SuppressWarnings("GuardedBy") // ErrorProne requires service.mLock which is the same
-        // this.mLock
-        private Set<ComponentName> getEnabledProviders() {
+        private Set<ComponentName> getEnabledProvidersForUser(int userId) {
+            final int resolvedUserId = ActivityManager.handleIncomingUser(
+                Binder.getCallingPid(), Binder.getCallingUid(),
+                userId, false, false,
+                "getEnabledProvidersForUser", null);
+
             Set<ComponentName> enabledProviders = new HashSet<>();
-            synchronized (mLock) {
-                runForUser(
-                        (service) -> {
-                            try {
-                                enabledProviders.add(
-                                        service.getCredentialProviderInfo()
-                                                .getServiceInfo().getComponentName());
-                            } catch (NullPointerException e) {
-                                // Safe check
-                                Slog.e(TAG, "Skipping provider as either the providerInfo"
-                                        + " or serviceInfo is null - weird");
-                            }
-                        });
+            String directValue = Settings.Secure.getStringForUser(
+                mContext.getContentResolver(), Settings.Secure.CREDENTIAL_SERVICE, resolvedUserId);
+
+            if (!TextUtils.isEmpty(directValue)) {
+                String[] components = directValue.split(":");
+                for (String componentString : components) {
+                    ComponentName component = ComponentName.unflattenFromString(componentString);
+                    if (component != null) {
+                        enabledProviders.add(component);
+                    }
+                }
             }
+
             return enabledProviders;
         }
 
@@ -879,7 +884,7 @@
                             callback,
                             request,
                             constructCallingAppInfo(callingPackage, userId, null),
-                            getEnabledProviders(),
+                            getEnabledProvidersForUser(userId),
                             CancellationSignal.fromTransport(cancelTransport),
                             timestampBegan);
             addSessionLocked(userId, session);
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index 1503410..e9fa883 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
+import android.credentials.CredentialOption;
 import android.credentials.CredentialProviderInfo;
 import android.credentials.GetCredentialException;
 import android.credentials.GetCredentialRequest;
@@ -52,11 +53,22 @@
             CancellationSignal cancellationSignal,
             long startedTimestamp) {
         super(context, sessionCallback, lock, userId, callingUid, request, callback,
-                RequestInfo.TYPE_GET, callingAppInfo, enabledProviders, cancellationSignal,
-                startedTimestamp);
+                getRequestInfoFromRequest(request), callingAppInfo, enabledProviders,
+                cancellationSignal, startedTimestamp);
         mRequestSessionMetric.collectGetFlowInitialMetricInfo(request);
     }
 
+    private static String getRequestInfoFromRequest(GetCredentialRequest request) {
+        for (CredentialOption option : request.getCredentialOptions()) {
+            if (option.getCredentialRetrievalData().getStringArrayList(
+                    CredentialOption
+                            .SUPPORTED_ELEMENT_KEYS) != null) {
+                return RequestInfo.TYPE_GET_VIA_REGISTRY;
+            }
+        }
+        return RequestInfo.TYPE_GET;
+    }
+
     /**
      * Creates a new provider session, and adds it list of providers that are contributing to
      * this session.
diff --git a/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java b/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
index f5e3b86..83e7e93 100644
--- a/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
+++ b/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
@@ -59,7 +59,7 @@
 
     private static final String TAG = "RemoteCredentialService";
     /** Timeout for a single request. */
-    private static final long TIMEOUT_REQUEST_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS;
+    private static final long TIMEOUT_REQUEST_MILLIS = 3 * DateUtils.SECOND_IN_MILLIS;
     /** Timeout to unbind after the task queue is empty. */
     private static final long TIMEOUT_IDLE_SERVICE_CONNECTION_MILLIS =
             5 * DateUtils.SECOND_IN_MILLIS;
diff --git a/services/credentials/java/com/android/server/credentials/metrics/ApiName.java b/services/credentials/java/com/android/server/credentials/metrics/ApiName.java
index 1930a48..fd49796 100644
--- a/services/credentials/java/com/android/server/credentials/metrics/ApiName.java
+++ b/services/credentials/java/com/android/server/credentials/metrics/ApiName.java
@@ -18,11 +18,13 @@
 
 import static android.credentials.ui.RequestInfo.TYPE_CREATE;
 import static android.credentials.ui.RequestInfo.TYPE_GET;
+import static android.credentials.ui.RequestInfo.TYPE_GET_VIA_REGISTRY;
 import static android.credentials.ui.RequestInfo.TYPE_UNDEFINED;
 
 import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
 import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_CREATE_CREDENTIAL;
 import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_GET_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_GET_CREDENTIAL_VIA_REGISTRY;
 import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE;
 import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_UNKNOWN;
 
@@ -35,6 +37,8 @@
 public enum ApiName {
     UNKNOWN(CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_UNKNOWN),
     GET_CREDENTIAL(CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_GET_CREDENTIAL),
+    GET_CREDENTIAL_VIA_REGISTRY(
+CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_GET_CREDENTIAL_VIA_REGISTRY),
     CREATE_CREDENTIAL(
             CREDENTIAL_MANAGER_INITIAL_PHASE_REPORTED__API_NAME__API_NAME_CREATE_CREDENTIAL),
     CLEAR_CREDENTIAL(
@@ -52,6 +56,8 @@
                     CREATE_CREDENTIAL.mInnerMetricCode),
             new AbstractMap.SimpleEntry<>(TYPE_GET,
                     GET_CREDENTIAL.mInnerMetricCode),
+            new AbstractMap.SimpleEntry<>(TYPE_GET_VIA_REGISTRY,
+                    GET_CREDENTIAL_VIA_REGISTRY.mInnerMetricCode),
             new AbstractMap.SimpleEntry<>(TYPE_UNDEFINED,
                     CLEAR_CREDENTIAL.mInnerMetricCode)
     );
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index debfedc..bb3b438 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -23200,6 +23200,8 @@
                 MANAGE_DEVICE_POLICY_ACROSS_USERS);
         CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_DEFAULT_SMS,
                 MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_INPUT_METHODS,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
         CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_MICROPHONE,
                 MANAGE_DEVICE_POLICY_ACROSS_USERS);
         CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_MOBILE_NETWORK,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
index 8030bb7..bac39e0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
@@ -265,7 +265,7 @@
                     //  never used, but might need some refactoring to not always assume a non-null
                     //  mechanism.
                     TRUE_MORE_RESTRICTIVE,
-                    POLICY_FLAG_LOCAL_ONLY_POLICY,
+                    POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_INHERITABLE,
                     PolicyEnforcerCallbacks::setApplicationHidden,
                     new BooleanPolicySerializer());
 
@@ -290,7 +290,7 @@
                     new AccountTypePolicyKey(
                             DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY),
                     TRUE_MORE_RESTRICTIVE,
-                    POLICY_FLAG_LOCAL_ONLY_POLICY,
+                    POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_INHERITABLE,
                     // Nothing is enforced, we just need to store it
                     (Boolean value, Context context, Integer userId, PolicyKey policyKey) -> true,
                     new BooleanPolicySerializer());
@@ -311,7 +311,7 @@
     static PolicyDefinition<Set<String>> PERMITTED_INPUT_METHODS = new PolicyDefinition<>(
             new NoArgsPolicyKey(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY),
             new MostRecent<>(),
-            POLICY_FLAG_LOCAL_ONLY_POLICY,
+            POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_INHERITABLE,
             (Set<String> value, Context context, Integer userId, PolicyKey policyKey) -> true,
             new StringSetPolicySerializer());
 
@@ -319,14 +319,14 @@
     static PolicyDefinition<Boolean> SCREEN_CAPTURE_DISABLED = new PolicyDefinition<>(
             new NoArgsPolicyKey(DevicePolicyIdentifiers.SCREEN_CAPTURE_DISABLED_POLICY),
             TRUE_MORE_RESTRICTIVE,
-            /* flags= */ 0,
+            POLICY_FLAG_INHERITABLE,
             PolicyEnforcerCallbacks::setScreenCaptureDisabled,
             new BooleanPolicySerializer());
 
     static PolicyDefinition<Boolean> PERSONAL_APPS_SUSPENDED = new PolicyDefinition<>(
             new NoArgsPolicyKey(DevicePolicyIdentifiers.PERSONAL_APPS_SUSPENDED_POLICY),
             new MostRecent<>(),
-            POLICY_FLAG_LOCAL_ONLY_POLICY,
+            POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_INHERITABLE,
             PolicyEnforcerCallbacks::setPersonalAppsSuspended,
             new BooleanPolicySerializer());
 
@@ -547,7 +547,7 @@
             String restriction, int flags) {
         String identifier = DevicePolicyIdentifiers.getIdentifierForUserRestriction(restriction);
         UserRestrictionPolicyKey key = new UserRestrictionPolicyKey(identifier, restriction);
-        flags |= POLICY_FLAG_USER_RESTRICTION_POLICY;
+        flags |= (POLICY_FLAG_USER_RESTRICTION_POLICY | POLICY_FLAG_INHERITABLE);
         PolicyDefinition<Boolean> definition = new PolicyDefinition<>(
                 key,
                 TRUE_MORE_RESTRICTIVE,
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
index 906cc83..9e37164 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
@@ -93,6 +93,9 @@
     private static final int PLATFORM_VERSION = 20;
     private static final int NEWER_VERSION = 30;
 
+    private static final int DISALLOW_PRERELEASE = -1;
+    private static final int DISALLOW_RELEASED = -1;
+
     @Rule public final Expect expect = Expect.create();
 
     private void verifyComputeMinSdkVersion(int minSdkVersion, String minSdkCodename,
@@ -149,8 +152,10 @@
         // Don't allow newer pre-release minSdkVersion on pre-release platform.
         // APP: Pre-release API 30
         // DEV: Pre-release API 20
-        verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, -1);
-        verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false, -1);
+        verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false,
+                DISALLOW_PRERELEASE);
+        verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false,
+                DISALLOW_PRERELEASE);
     }
 
     @Test
@@ -173,21 +178,27 @@
         // Don't allow older pre-release minSdkVersion on released platform.
         // APP: Pre-release API 10
         // DEV: Released API 20
-        verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, -1);
-        verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true, -1);
+        verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true,
+                DISALLOW_RELEASED);
+        verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true,
+                DISALLOW_RELEASED);
 
         // Don't allow same pre-release minSdkVersion on released platform.
         // APP: Pre-release API 20
         // DEV: Released API 20
-        verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, -1);
-        verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, -1);
+        verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true,
+                DISALLOW_RELEASED);
+        verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true,
+                DISALLOW_RELEASED);
 
 
         // Don't allow newer pre-release minSdkVersion on released platform.
         // APP: Pre-release API 30
         // DEV: Released API 20
-        verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1);
-        verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true, -1);
+        verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true,
+                DISALLOW_RELEASED);
+        verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true,
+                DISALLOW_RELEASED);
     }
 
     private void verifyComputeTargetSdkVersion(int targetSdkVersion, String targetSdkCodename,
@@ -254,10 +265,10 @@
         // Don't allow newer pre-release targetSdkVersion on pre-release platform.
         // APP: Pre-release API 30
         // DEV: Pre-release API 20
-        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, false, -1);
+        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, false,
+                DISALLOW_PRERELEASE);
         verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false,
-                false, -1
-        );
+                false, DISALLOW_PRERELEASE);
 
         // Do allow newer pre-release targetSdkVersion on pre-release platform when
         // allowUnknownCodenames is true.
@@ -290,35 +301,35 @@
         // Don't allow older pre-release targetSdkVersion on released platform.
         // APP: Pre-release API 10
         // DEV: Released API 20
-        verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, false, -1);
+        verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, false,
+                DISALLOW_RELEASED);
         verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true,
-                false, -1
-        );
+                false, DISALLOW_RELEASED);
 
         // Don't allow same pre-release targetSdkVersion on released platform.
         // APP: Pre-release API 20
         // DEV: Released API 20
-        verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, false, -1);
+        verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, false,
+                DISALLOW_RELEASED);
         verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, false,
-                -1
-        );
+                DISALLOW_RELEASED);
 
         // Don't allow same pre-release targetSdkVersion on released platform when
         // allowUnknownCodenames is true.
         // APP: Pre-release API 20
         // DEV: Released API 20
         verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, true,
-                -1);
+                DISALLOW_RELEASED);
         verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, true,
-                -1);
+                DISALLOW_RELEASED);
 
         // Don't allow newer pre-release targetSdkVersion on released platform.
         // APP: Pre-release API 30
         // DEV: Released API 20
-        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, false, -1);
+        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, false,
+                DISALLOW_RELEASED);
         verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true,
-                false, -1
-        );
+                false, DISALLOW_RELEASED);
         // Do allow newer pre-release targetSdkVersion on released platform when
         // allowUnknownCodenames is true.
         // APP: Pre-release API 30
diff --git a/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java b/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java
index 3d963ed..56bd192 100644
--- a/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java
+++ b/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java
@@ -164,7 +164,7 @@
     public void testAttachDetach() throws Exception {
         // Normal attachment / detachment.
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
         assertNotNull(module);
         module.detach();
     }
@@ -172,7 +172,7 @@
     @Test
     public void testLoadUnloadModel() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         final int hwHandle = 7;
         int handle = loadGenericModel(module, hwHandle).first;
@@ -183,7 +183,7 @@
     @Test
     public void testLoadPreemptModel() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         final int hwHandle = 7;
         Pair<Integer, SoundTriggerHwCallback> loadResult = loadGenericModel(module, hwHandle);
@@ -202,7 +202,7 @@
     @Test
     public void testLoadUnloadPhraseModel() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         final int hwHandle = 73;
         int handle = loadPhraseModel(module, hwHandle).first;
@@ -213,7 +213,7 @@
     @Test
     public void testStartStopRecognition() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         // Load the model.
         final int hwHandle = 7;
@@ -233,7 +233,7 @@
     @Test
     public void testStartRecognitionBusy() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         // Load the model.
         final int hwHandle = 7;
@@ -257,7 +257,7 @@
     @Test
     public void testStartStopPhraseRecognition() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         // Load the model.
         final int hwHandle = 67;
@@ -277,7 +277,7 @@
     @Test
     public void testRecognition() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         // Load the model.
         final int hwHandle = 7;
@@ -322,7 +322,7 @@
     @Test
     public void testPhraseRecognition() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         // Load the model.
         final int hwHandle = 7;
@@ -352,7 +352,7 @@
     @Test
     public void testForceRecognition() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         // Load the model.
         final int hwHandle = 17;
@@ -389,7 +389,7 @@
     @Test
     public void testForceRecognitionNotSupported() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         // Load the model.
         final int hwHandle = 17;
@@ -420,7 +420,7 @@
     @Test
     public void testForcePhraseRecognition() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         // Load the model.
         final int hwHandle = 17;
@@ -457,7 +457,7 @@
     @Test
     public void testForcePhraseRecognitionNotSupported() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         // Load the model.
         final int hwHandle = 17;
@@ -489,7 +489,7 @@
     public void testAbortRecognition() throws Exception {
         // Make sure the HAL doesn't support concurrent capture.
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         // Load the model.
         final int hwHandle = 11;
@@ -521,7 +521,7 @@
     public void testAbortPhraseRecognition() throws Exception {
         // Make sure the HAL doesn't support concurrent capture.
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
 
         // Load the model.
         final int hwHandle = 11;
@@ -552,7 +552,7 @@
     @Test
     public void testParameterSupported() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
         final int hwHandle = 12;
         int modelHandle = loadGenericModel(module, hwHandle).first;
 
@@ -574,7 +574,7 @@
     @Test
     public void testParameterNotSupported() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
         final int hwHandle = 13;
         int modelHandle = loadGenericModel(module, hwHandle).first;
 
@@ -592,7 +592,7 @@
     @Test
     public void testGetParameter() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
         final int hwHandle = 14;
         int modelHandle = loadGenericModel(module, hwHandle).first;
 
@@ -609,7 +609,7 @@
     @Test
     public void testSetParameter() throws Exception {
         ISoundTriggerCallback callback = createCallbackMock();
-        ISoundTriggerModule module = mService.attach(0, callback);
+        ISoundTriggerModule module = mService.attach(0, callback, false);
         final int hwHandle = 17;
         int modelHandle = loadGenericModel(module, hwHandle).first;
 
diff --git a/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLoggingLatencyTest.java b/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLoggingLatencyTest.java
index cc357d7..385c28a 100644
--- a/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLoggingLatencyTest.java
+++ b/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLoggingLatencyTest.java
@@ -20,6 +20,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.verify;
 
@@ -101,8 +102,9 @@
             throws RemoteException {
         ArgumentCaptor<ISoundTriggerCallback> soundTriggerCallbackCaptor = ArgumentCaptor.forClass(
                 ISoundTriggerCallback.class);
-        mSoundTriggerMiddlewareLogging.attach(0, mISoundTriggerCallback);
-        verify(mDelegateMiddleware).attach(anyInt(), soundTriggerCallbackCaptor.capture());
+        mSoundTriggerMiddlewareLogging.attach(0, mISoundTriggerCallback, false);
+        verify(mDelegateMiddleware).attach(anyInt(), soundTriggerCallbackCaptor.capture(),
+                anyBoolean());
 
         triggerPhraseRecognitionEvent(soundTriggerCallbackCaptor.getValue(),
                 RecognitionStatus.SUCCESS, 100 /* keyphraseId */);
@@ -116,8 +118,9 @@
     public void testOnPhraseRecognitionRestartsActiveSession() throws RemoteException {
         ArgumentCaptor<ISoundTriggerCallback> soundTriggerCallbackCaptor = ArgumentCaptor.forClass(
                 ISoundTriggerCallback.class);
-        mSoundTriggerMiddlewareLogging.attach(0, mISoundTriggerCallback);
-        verify(mDelegateMiddleware).attach(anyInt(), soundTriggerCallbackCaptor.capture());
+        mSoundTriggerMiddlewareLogging.attach(0, mISoundTriggerCallback, false);
+        verify(mDelegateMiddleware).attach(anyInt(), soundTriggerCallbackCaptor.capture(),
+                anyBoolean());
 
         triggerPhraseRecognitionEvent(soundTriggerCallbackCaptor.getValue(),
                 RecognitionStatus.SUCCESS, 100 /* keyphraseId */);
@@ -137,8 +140,9 @@
             throws RemoteException {
         ArgumentCaptor<ISoundTriggerCallback> soundTriggerCallbackCaptor = ArgumentCaptor.forClass(
                 ISoundTriggerCallback.class);
-        mSoundTriggerMiddlewareLogging.attach(0, mISoundTriggerCallback);
-        verify(mDelegateMiddleware).attach(anyInt(), soundTriggerCallbackCaptor.capture());
+        mSoundTriggerMiddlewareLogging.attach(0, mISoundTriggerCallback, false);
+        verify(mDelegateMiddleware).attach(anyInt(), soundTriggerCallbackCaptor.capture(),
+                anyBoolean());
 
         triggerPhraseRecognitionEvent(soundTriggerCallbackCaptor.getValue(),
                 RecognitionStatus.ABORTED, 100 /* keyphraseId */);
@@ -154,8 +158,9 @@
             throws RemoteException {
         ArgumentCaptor<ISoundTriggerCallback> soundTriggerCallbackCaptor = ArgumentCaptor.forClass(
                 ISoundTriggerCallback.class);
-        mSoundTriggerMiddlewareLogging.attach(0, mISoundTriggerCallback);
-        verify(mDelegateMiddleware).attach(anyInt(), soundTriggerCallbackCaptor.capture());
+        mSoundTriggerMiddlewareLogging.attach(0, mISoundTriggerCallback, false);
+        verify(mDelegateMiddleware).attach(anyInt(), soundTriggerCallbackCaptor.capture(),
+                anyBoolean());
 
         triggerPhraseRecognitionEvent(soundTriggerCallbackCaptor.getValue(),
                 RecognitionStatus.SUCCESS);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 8e80485..04e1d9c0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -940,8 +940,6 @@
     @Test
     public void testIgnoresDeskDockRotation_whenNoSensorAndLockedRespected() throws Exception {
         mBuilder.setDeskDockRotation(Surface.ROTATION_270).build();
-        when(mMockDisplayPolicy.isDeskDockRespectsNoSensorAndLockedWithoutAccelerometer())
-                .thenReturn(true);
         configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
 
         when(mMockDisplayPolicy.getDockMode()).thenReturn(Intent.EXTRA_DOCK_STATE_DESK);
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 67320009..a675248 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -303,6 +303,10 @@
 
     private SoundTriggerHelper newSoundTriggerHelper(
             ModuleProperties moduleProperties, EventLogger eventLogger) {
+        return newSoundTriggerHelper(moduleProperties, eventLogger, false);
+    }
+    private SoundTriggerHelper newSoundTriggerHelper(
+            ModuleProperties moduleProperties, EventLogger eventLogger, boolean isTrusted) {
 
         Identity middlemanIdentity = new Identity();
         middlemanIdentity.packageName = ActivityThread.currentOpPackageName();
@@ -325,7 +329,7 @@
                 eventLogger,
                 (SoundTrigger.StatusListener statusListener) -> new SoundTriggerModule(
                         mMiddlewareService, moduleId, statusListener,
-                        Looper.getMainLooper(), middlemanIdentity, originatorIdentity),
+                        Looper.getMainLooper(), middlemanIdentity, originatorIdentity, isTrusted),
                 moduleId,
                 () -> listUnderlyingModuleProperties(originatorIdentity)
                 );
@@ -1724,7 +1728,8 @@
         }
 
         @Override
-        public Session attach(@NonNull IBinder client, ModuleProperties underlyingModule) {
+        public Session attach(@NonNull IBinder client, ModuleProperties underlyingModule,
+                boolean isTrusted) {
             var identity = IdentityContext.getNonNull();
             int sessionId = mSessionIdCounter.getAndIncrement();
             mServiceEventLogger.enqueue(new ServiceEvent(
@@ -1733,7 +1738,7 @@
                     "LocalSoundTriggerEventLogger for package: " +
                     identity.packageName + "#" + sessionId);
 
-            return new SessionImpl(newSoundTriggerHelper(underlyingModule, eventLogger),
+            return new SessionImpl(newSoundTriggerHelper(underlyingModule, eventLogger, isTrusted),
                     client, eventLogger, identity);
         }
 
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/ISoundTriggerMiddlewareInternal.java b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/ISoundTriggerMiddlewareInternal.java
index 60f89da..ca35b51 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/ISoundTriggerMiddlewareInternal.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/ISoundTriggerMiddlewareInternal.java
@@ -38,7 +38,10 @@
      *
      * listModules() must be called prior to calling this method and the provided handle must be
      * one of the handles from the returned list.
+     * @param isTrusted - {@code true} if this service should not note AppOps for recognitions,
+     * and should delegate these checks to the **trusted** client.
      */
     public ISoundTriggerModule attach(int handle,
-            ISoundTriggerCallback callback);
+            ISoundTriggerCallback callback,
+            boolean isTrusted);
 }
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImpl.java b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImpl.java
index c8c0f3d..3b800de 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImpl.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImpl.java
@@ -116,7 +116,8 @@
 
     @Override
     public @NonNull
-    ISoundTriggerModule attach(int handle, @NonNull ISoundTriggerCallback callback) {
+    ISoundTriggerModule attach(int handle, @NonNull ISoundTriggerCallback callback,
+            boolean isTrusted) {
         return mModules[handle].attach(callback);
     }
 }
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
index ecd65ae..e3366f8 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
@@ -149,22 +149,22 @@
 
     @Override
     public @NonNull
-    ISoundTriggerModule attach(int handle, ISoundTriggerCallback callback) {
+    ISoundTriggerModule attach(int handle, ISoundTriggerCallback callback, boolean isTrusted) {
         try {
             var originatorIdentity = IdentityContext.getNonNull();
             String packageIdentification = originatorIdentity.packageName
-                    + mSessionCount.getAndIncrement();
+                    + mSessionCount.getAndIncrement() + (isTrusted ? "trusted" : "");
             ModuleLogging result = new ModuleLogging();
             var eventLogger = new EventLogger(SESSION_MAX_EVENT_SIZE,
                 "Session logger for: " + packageIdentification);
 
             var callbackWrapper = new CallbackLogging(callback, eventLogger, originatorIdentity);
 
-            result.attach(mDelegate.attach(handle, callbackWrapper), eventLogger);
+            result.attach(mDelegate.attach(handle, callbackWrapper, isTrusted), eventLogger);
 
             mServiceEventLogger.enqueue(ServiceEvent.createForReturn(
                         ServiceEvent.Type.ATTACH,
-                        packageIdentification, result, handle, callback)
+                        packageIdentification, result, handle, callback, isTrusted)
                     .printLog(ALOGI, TAG));
 
             mSessionEventLoggers.add(eventLogger);
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
index 6b724de..2e641a2 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
@@ -85,11 +85,11 @@
     @Override
     public @NonNull
     ISoundTriggerModule attach(int handle,
-            @NonNull ISoundTriggerCallback callback) {
+            @NonNull ISoundTriggerCallback callback, boolean isTrusted) {
         Identity identity = getIdentity();
         enforcePermissionsForPreflight(identity);
-        ModuleWrapper wrapper = new ModuleWrapper(identity, callback);
-        return wrapper.attach(mDelegate.attach(handle, wrapper.getCallbackWrapper()));
+        ModuleWrapper wrapper = new ModuleWrapper(identity, callback, isTrusted);
+        return wrapper.attach(mDelegate.attach(handle, wrapper.getCallbackWrapper(), isTrusted));
     }
 
     // Override toString() in order to have the delegate's ID in it.
@@ -204,11 +204,14 @@
         private ISoundTriggerModule mDelegate;
         private final @NonNull Identity mOriginatorIdentity;
         private final @NonNull CallbackWrapper mCallbackWrapper;
+        private final boolean mIsTrusted;
 
         ModuleWrapper(@NonNull Identity originatorIdentity,
-                @NonNull ISoundTriggerCallback callback) {
+                @NonNull ISoundTriggerCallback callback,
+                boolean isTrusted) {
             mOriginatorIdentity = originatorIdentity;
             mCallbackWrapper = new CallbackWrapper(callback);
+            mIsTrusted = isTrusted;
         }
 
         ModuleWrapper attach(@NonNull ISoundTriggerModule delegate) {
@@ -347,7 +350,11 @@
             }
 
             private void enforcePermissions(String reason) {
-                enforcePermissionsForDataDelivery(mOriginatorIdentity, reason);
+                if (mIsTrusted) {
+                    enforcePermissionsForPreflight(mOriginatorIdentity);
+                } else {
+                    enforcePermissionsForDataDelivery(mOriginatorIdentity, reason);
+                }
             }
         }
     }
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
index 1558acf..9de2438 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
@@ -105,17 +105,17 @@
     public ISoundTriggerModule attachAsOriginator(int handle, Identity identity,
             ISoundTriggerCallback callback) {
         try (SafeCloseable ignored = establishIdentityDirect(Objects.requireNonNull(identity))) {
-            return new ModuleService(mDelegate.attach(handle, callback));
+            return new ModuleService(mDelegate.attach(handle, callback, /* isTrusted= */ false));
         }
     }
 
     @Override
     public ISoundTriggerModule attachAsMiddleman(int handle, Identity middlemanIdentity,
-            Identity originatorIdentity, ISoundTriggerCallback callback) {
+            Identity originatorIdentity, ISoundTriggerCallback callback, boolean isTrusted) {
         try (SafeCloseable ignored = establishIdentityIndirect(
                 Objects.requireNonNull(middlemanIdentity),
                 Objects.requireNonNull(originatorIdentity))) {
-            return new ModuleService(mDelegate.attach(handle, callback));
+            return new ModuleService(mDelegate.attach(handle, callback, isTrusted));
         }
     }
 
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
index 2924c12..31fab89 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
@@ -191,7 +191,7 @@
 
     @Override
     public @NonNull ISoundTriggerModule attach(int handle,
-            @NonNull ISoundTriggerCallback callback) {
+            @NonNull ISoundTriggerCallback callback, boolean isTrusted) {
         // Input validation.
         Objects.requireNonNull(callback);
         Objects.requireNonNull(callback.asBinder());
@@ -209,7 +209,7 @@
             // From here on, every exception isn't client's fault.
             try {
                 Session session = new Session(handle, callback);
-                session.attach(mDelegate.attach(handle, session.getCallbackWrapper()));
+                session.attach(mDelegate.attach(handle, session.getCallbackWrapper(), isTrusted));
                 return session;
             } catch (Exception e) {
                 throw handleException(e);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 27f3fb3..423a81a 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -381,51 +381,21 @@
                 @NonNull Identity originatorIdentity, IBinder client,
                 ModuleProperties moduleProperties) {
             Objects.requireNonNull(originatorIdentity);
-            boolean forHotwordDetectionService;
+            boolean forHotwordDetectionService = false;
             synchronized (VoiceInteractionManagerServiceStub.this) {
                 enforceIsCurrentVoiceInteractionService();
                 forHotwordDetectionService =
                         mImpl != null && mImpl.mHotwordDetectionConnection != null;
             }
-            IVoiceInteractionSoundTriggerSession session;
-            if (forHotwordDetectionService) {
-                // Use our own identity and handle the permission checks ourselves. This allows
-                // properly checking/noting against the voice interactor or hotword detection
-                // service as needed.
-                if (HotwordDetectionConnection.DEBUG) {
-                    Slog.d(TAG, "Creating a SoundTriggerSession for a HotwordDetectionService");
-                }
-                originatorIdentity.uid = Binder.getCallingUid();
-                originatorIdentity.pid = Binder.getCallingPid();
-                session = new SoundTriggerSessionPermissionsDecorator(
-                        createSoundTriggerSessionForSelfIdentity(client, moduleProperties),
-                        mContext,
-                        originatorIdentity);
-            } else {
-                if (HotwordDetectionConnection.DEBUG) {
-                    Slog.d(TAG, "Creating a SoundTriggerSession");
-                }
-                try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect(
-                        originatorIdentity)) {
-                    session = new SoundTriggerSession(mSoundTriggerInternal.attach(client,
-                                moduleProperties));
-                }
+            if (HotwordDetectionConnection.DEBUG) {
+                Slog.d(TAG, "Creating a SoundTriggerSession, for HDS: "
+                        + forHotwordDetectionService);
             }
-            return new SoundTriggerSessionBinderProxy(session);
-        }
-
-        private IVoiceInteractionSoundTriggerSession createSoundTriggerSessionForSelfIdentity(
-                IBinder client, ModuleProperties moduleProperties) {
-            Identity identity = new Identity();
-            identity.uid = Process.myUid();
-            identity.pid = Process.myPid();
-            identity.packageName = ActivityThread.currentOpPackageName();
-            return Binder.withCleanCallingIdentity(() -> {
-                try (SafeCloseable ignored = IdentityContext.create(identity)) {
-                    return new SoundTriggerSession(
-                            mSoundTriggerInternal.attach(client, moduleProperties));
-                }
-            });
+            try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect(
+                    originatorIdentity)) {
+                return new SoundTriggerSession(mSoundTriggerInternal.attach(client,
+                            moduleProperties, forHotwordDetectionService));
+            }
         }
 
         @Override
@@ -1700,11 +1670,7 @@
             return null;
         }
 
-        /**
-         * Implementation of SoundTriggerSession. Does not implement {@link #asBinder()} as it's
-         * intended to be wrapped by an {@link IVoiceInteractionSoundTriggerSession.Stub} object.
-         */
-        private class SoundTriggerSession implements IVoiceInteractionSoundTriggerSession {
+        private class SoundTriggerSession extends IVoiceInteractionSoundTriggerSession.Stub {
             final SoundTriggerInternal.Session mSession;
             private IHotwordRecognitionStatusCallback mSessionExternalCallback;
             private IRecognitionStatusCallback mSessionInternalCallback;
@@ -1851,12 +1817,6 @@
             }
 
             @Override
-            public IBinder asBinder() {
-                throw new UnsupportedOperationException(
-                        "This object isn't intended to be used as a Binder.");
-            }
-
-            @Override
             public void detach() {
                 mSession.detach();
             }
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index b003f59..331caa1 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -43,8 +43,8 @@
     /** Disconnected because of a local user-initiated action, such as hanging up. */
     public static final int LOCAL = TelecomProtoEnums.LOCAL; // = 2
     /**
-     * Disconnected because of a remote user-initiated action, such as the other party hanging up
-     * up.
+     * Disconnected because the remote party hung up an ongoing call, or because an outgoing call
+     * was not answered by the remote party.
      */
     public static final int REMOTE = TelecomProtoEnums.REMOTE; // = 3
     /** Disconnected because it has been canceled. */
diff --git a/tests/SilkFX/res/layout/gainmap_metadata.xml b/tests/SilkFX/res/layout/gainmap_metadata.xml
index 0dabaca..4cc3e0c 100644
--- a/tests/SilkFX/res/layout/gainmap_metadata.xml
+++ b/tests/SilkFX/res/layout/gainmap_metadata.xml
@@ -21,8 +21,8 @@
     android:layout_height="wrap_content">
 
     <LinearLayout
-        android:layout_width="350dp"
-        android:layout_height="300dp"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:layout_centerHorizontal="true"
         android:padding="8dp"
         android:orientation="vertical"
diff --git a/tests/TrustTests/src/android/trust/test/UserUnlockRequestTest.kt b/tests/TrustTests/src/android/trust/test/UserUnlockRequestTest.kt
index 6a8752a..501b9d3 100644
--- a/tests/TrustTests/src/android/trust/test/UserUnlockRequestTest.kt
+++ b/tests/TrustTests/src/android/trust/test/UserUnlockRequestTest.kt
@@ -79,6 +79,16 @@
             .isEqualTo(oldCount + 1)
     }
 
+    @Test
+    fun reportUserMayRequestUnlock_differentUserId_doesNotPropagateToAgent() {
+        val oldCount = trustAgentRule.agent.onUserMayRequestUnlockCallCount
+        trustManager.reportUserMayRequestUnlock(userId + 1)
+        await()
+
+        assertThat(trustAgentRule.agent.onUserMayRequestUnlockCallCount)
+            .isEqualTo(oldCount)
+    }
+
     companion object {
         private const val TAG = "UserUnlockRequestTest"
         private fun await() = Thread.sleep(250)
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index 2ce2167..1b1e93bd 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -209,6 +209,11 @@
     AddOptionalFlag("--compile-sdk-version-name",
         "Version name to inject into the AndroidManifest.xml if none is present.",
         &options_.manifest_fixer_options.compile_sdk_version_codename);
+    AddOptionalSwitch(
+        "--no-compile-sdk-metadata",
+        "Suppresses output of compile SDK-related attributes in AndroidManifest.xml,\n"
+        "including android:compileSdkVersion and platformBuildVersion.",
+        &options_.manifest_fixer_options.no_compile_sdk_metadata);
     AddOptionalFlagList("--fingerprint-prefix", "Fingerprint prefix to add to install constraints.",
                         &options_.manifest_fixer_options.fingerprint_prefixes);
     AddOptionalSwitch("--shared-lib", "Generates a shared Android runtime library.",
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 53f0abe..c4f6e70 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -719,7 +719,7 @@
     root->InsertChild(0, std::move(uses_sdk));
   }
 
-  if (options_.compile_sdk_version) {
+  if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version) {
     xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersion");
 
     // Make sure we un-compile the value if it was set to something else.
@@ -731,10 +731,9 @@
     // Make sure we un-compile the value if it was set to something else.
     attr->compiled_value = {};
     attr->value = options_.compile_sdk_version.value();
-
   }
 
-  if (options_.compile_sdk_version_codename) {
+  if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version_codename) {
     xml::Attribute* attr =
         root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
 
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index 175ab6f..42938a4 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -67,11 +67,12 @@
   std::optional<std::string> revision_code_default;
 
   // The version of the framework being compiled against to set for 'android:compileSdkVersion' in
-  // the <manifest> tag.
+  // the <manifest> tag. Not used if no_compile_sdk_metadata is set.
   std::optional<std::string> compile_sdk_version;
 
   // The version codename of the framework being compiled against to set for
-  // 'android:compileSdkVersionCodename' in the <manifest> tag.
+  // 'android:compileSdkVersionCodename' in the <manifest> tag. Not used if no_compile_sdk_metadata
+  // is set.
   std::optional<std::string> compile_sdk_version_codename;
 
   // The fingerprint prefixes to be added to the <install-constraints> tag.
@@ -87,6 +88,9 @@
 
   // Whether to replace the manifest version with the the command line version
   bool replace_version = false;
+
+  // Whether to suppress `android:compileSdkVersion*` and `platformBuildVersion*` attributes.
+  bool no_compile_sdk_metadata = false;
 };
 
 // Verifies that the manifest is correctly formed and inserts defaults where specified with
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 1b8f05b..6151a8e 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -892,6 +892,35 @@
   EXPECT_THAT(attr->value, StrEq("P"));
 }
 
+TEST_F(ManifestFixerTest, DoNotInsertCompileSdkVersions) {
+  std::string input = R"(<manifest package="com.pkg" />)";
+  ManifestFixerOptions options;
+  options.no_compile_sdk_metadata = true;
+  options.compile_sdk_version = {"28"};
+  options.compile_sdk_version_codename = {"P"};
+
+  std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
+  ASSERT_THAT(manifest, NotNull());
+
+  // There should be a declaration of kSchemaAndroid, even when the input
+  // didn't have one.
+  EXPECT_EQ(manifest->root->namespace_decls.size(), 1);
+  EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android");
+  EXPECT_EQ(manifest->root->namespace_decls[0].uri, xml::kSchemaAndroid);
+
+  xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
+  ASSERT_THAT(attr, IsNull());
+
+  attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
+  ASSERT_THAT(attr, IsNull());
+
+  attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
+  ASSERT_THAT(attr, IsNull());
+
+  attr = manifest->root->FindAttribute("", "platformBuildVersionName");
+  ASSERT_THAT(attr, IsNull());
+}
+
 TEST_F(ManifestFixerTest, OverrideCompileSdkVersions) {
   std::string input = R"(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"