diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 6d74a840525bad68ca81c4a21cac346685cef21f..1c9785f34b79f70a506eb7c162029f1b514433f0 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -51,6 +51,7 @@ aconfig_srcjars = [
     ":aconfig_midi_flags_java_lib{.generated_srcjars}",
     ":android.service.autofill.flags-aconfig-java{.generated_srcjars}",
     ":com.android.net.flags-aconfig-java{.generated_srcjars}",
+    ":device_policy_aconfig_flags_lib{.generated_srcjars}",
 ]
 
 filegroup {
@@ -523,3 +524,23 @@ java_aconfig_library {
     aconfig_declarations: "com.android.net.flags-aconfig",
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
+
+// DevicePolicy
+aconfig_declarations {
+    name: "device_policy_aconfig_flags",
+    package: "android.app.admin.flags",
+    srcs: [
+        "core/java/android/app/admin/flags/flags.aconfig",
+    ],
+}
+
+java_aconfig_library {
+    name: "device_policy_aconfig_flags_lib",
+    aconfig_declarations: "device_policy_aconfig_flags",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
+cc_aconfig_library {
+    name: "device_policy_aconfig_flags_c_lib",
+    aconfig_declarations: "device_policy_aconfig_flags",
+}
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index b5d3ed7c8a7e66d4f22892b073572827069b1755..2af3c34bf2c45bf5ed28a65d5c6e35f2f7caab31 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -6,7 +6,7 @@ package android {
     field public static final String CONTROL_AUTOMOTIVE_GNSS = "android.permission.CONTROL_AUTOMOTIVE_GNSS";
     field public static final String GET_INTENT_SENDER_INTENT = "android.permission.GET_INTENT_SENDER_INTENT";
     field public static final String MAKE_UID_VISIBLE = "android.permission.MAKE_UID_VISIBLE";
-    field public static final String USE_COMPANION_TRANSPORTS = "android.permission.USE_COMPANION_TRANSPORTS";
+    field @FlaggedApi("android.companion.flags.companion_transport_apis") public static final String USE_COMPANION_TRANSPORTS = "android.permission.USE_COMPANION_TRANSPORTS";
   }
 
 }
@@ -85,21 +85,21 @@ package android.app.admin {
 package android.companion {
 
   public final class CompanionDeviceManager {
-    method @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void addOnMessageReceivedListener(@NonNull java.util.concurrent.Executor, int, @NonNull android.companion.CompanionDeviceManager.OnMessageReceivedListener);
-    method @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void addOnTransportsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.CompanionDeviceManager.OnTransportsChangedListener);
-    method @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void removeOnMessageReceivedListener(int, @NonNull android.companion.CompanionDeviceManager.OnMessageReceivedListener);
-    method @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void removeOnTransportsChangedListener(@NonNull android.companion.CompanionDeviceManager.OnTransportsChangedListener);
-    method @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void sendMessage(int, @NonNull byte[], @NonNull int[]);
-    field public static final int MESSAGE_REQUEST_CONTEXT_SYNC = 1667729539; // 0x63678883
-    field public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 1669491075; // 0x63826983
-    field public static final int MESSAGE_REQUEST_REMOTE_AUTHENTICATION = 1669494629; // 0x63827765
+    method @FlaggedApi("android.companion.companion_transport_apis") @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void addOnMessageReceivedListener(@NonNull java.util.concurrent.Executor, int, @NonNull android.companion.CompanionDeviceManager.OnMessageReceivedListener);
+    method @FlaggedApi("android.companion.companion_transport_apis") @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void addOnTransportsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.CompanionDeviceManager.OnTransportsChangedListener);
+    method @FlaggedApi("android.companion.companion_transport_apis") @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void removeOnMessageReceivedListener(int, @NonNull android.companion.CompanionDeviceManager.OnMessageReceivedListener);
+    method @FlaggedApi("android.companion.companion_transport_apis") @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void removeOnTransportsChangedListener(@NonNull android.companion.CompanionDeviceManager.OnTransportsChangedListener);
+    method @FlaggedApi("android.companion.companion_transport_apis") @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void sendMessage(int, @NonNull byte[], @NonNull int[]);
+    field @FlaggedApi("android.companion.companion_transport_apis") public static final int MESSAGE_REQUEST_CONTEXT_SYNC = 1667729539; // 0x63678883
+    field @FlaggedApi("android.companion.companion_transport_apis") public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 1669491075; // 0x63826983
+    field @FlaggedApi("android.companion.companion_transport_apis") public static final int MESSAGE_REQUEST_REMOTE_AUTHENTICATION = 1669494629; // 0x63827765
   }
 
-  public static interface CompanionDeviceManager.OnMessageReceivedListener {
+  @FlaggedApi("android.companion.companion_transport_apis") public static interface CompanionDeviceManager.OnMessageReceivedListener {
     method public void onMessageReceived(int, @NonNull byte[]);
   }
 
-  public static interface CompanionDeviceManager.OnTransportsChangedListener {
+  @FlaggedApi("android.companion.companion_transport_apis") public static interface CompanionDeviceManager.OnTransportsChangedListener {
     method public void onTransportsChanged(@NonNull java.util.List<android.companion.AssociationInfo>);
   }
 
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 384b9573528eb2db0b27bdcb763dcaed101c6145..306bdeb84e4d17e0306d6584b9398dca1943352d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -541,7 +541,7 @@ package android.app.admin {
     field public static final String PERMITTED_INPUT_METHODS_POLICY = "permittedInputMethods";
     field public static final String PERSONAL_APPS_SUSPENDED_POLICY = "personalAppsSuspended";
     field public static final String SCREEN_CAPTURE_DISABLED_POLICY = "screenCaptureDisabled";
-    field public static final String USB_DATA_SIGNALING_POLICY = "usbDataSignaling";
+    field @FlaggedApi("android.app.admin.flags.policy_engine_migration_v2_enabled") public static final String USB_DATA_SIGNALING_POLICY = "usbDataSignaling";
   }
 
   public class DevicePolicyManager {
@@ -857,7 +857,7 @@ package android.companion {
 
   public final class CompanionDeviceManager {
     method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public void enableSecureTransport(boolean);
-    field public static final int MESSAGE_REQUEST_PING = 1669362552; // 0x63807378
+    field @FlaggedApi("android.companion.companion_transport_apis") public static final int MESSAGE_REQUEST_PING = 1669362552; // 0x63807378
   }
 
   public abstract class CompanionDeviceService extends android.app.Service {
diff --git a/core/java/android/app/admin/DevicePolicyIdentifiers.java b/core/java/android/app/admin/DevicePolicyIdentifiers.java
index ad0af72c72b4445d4f10a5535869b9f6aa289ac6..84b1ca5c6a61f7f5e878becc1fd86525b39b41fd 100644
--- a/core/java/android/app/admin/DevicePolicyIdentifiers.java
+++ b/core/java/android/app/admin/DevicePolicyIdentifiers.java
@@ -16,10 +16,13 @@
 
 package android.app.admin;
 
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
+import android.app.admin.flags.Flags;
 import android.os.UserManager;
 
+
 import java.util.Objects;
 
 /**
@@ -164,6 +167,7 @@ public final class DevicePolicyIdentifiers {
      *
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_POLICY_ENGINE_MIGRATION_V2_ENABLED)
     @TestApi
     public static final String USB_DATA_SIGNALING_POLICY = "usbDataSignaling";
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/flags/FlagUtils.java b/core/java/android/app/admin/flags/FlagUtils.java
similarity index 68%
rename from services/devicepolicy/java/com/android/server/devicepolicy/flags/FlagUtils.java
rename to core/java/android/app/admin/flags/FlagUtils.java
index 7e17ef111cf0fcfe55ecc8bc228c3172a48d1291..7c3c3d5260b44b1e01b98a6351b37d639362eb26 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/flags/FlagUtils.java
+++ b/core/java/android/app/admin/flags/FlagUtils.java
@@ -14,15 +14,20 @@
  * limitations under the License.
  */
 
-package com.android.server.devicepolicy.flags;
+package android.app.admin.flags;
 
-import static com.android.server.devicepolicy.flags.Flags.devicePolicySizeTrackingEnabled;
-import static com.android.server.devicepolicy.flags.Flags.policyEngineMigrationV2Enabled;
+import static android.app.admin.flags.Flags.devicePolicySizeTrackingEnabled;
+import static android.app.admin.flags.Flags.policyEngineMigrationV2Enabled;
+import static android.app.admin.flags.Flags.onboardingBugreportV2Enabled;
 
 import android.os.Binder;
 
+/**
+ *
+ * @hide
+ */
 public final class FlagUtils {
-    private FlagUtils(){}
+    private FlagUtils() {}
 
     public static boolean isPolicyEngineMigrationV2Enabled() {
         return Binder.withCleanCallingIdentity(() -> {
@@ -35,4 +40,10 @@ public final class FlagUtils {
             return devicePolicySizeTrackingEnabled();
         });
     }
+
+    public static boolean isOnboardingBugreportV2Enabled() {
+        return Binder.withCleanCallingIdentity(() -> {
+            return onboardingBugreportV2Enabled();
+        });
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
similarity index 58%
rename from services/devicepolicy/java/com/android/server/devicepolicy/flags/flags.aconfig
rename to core/java/android/app/admin/flags/flags.aconfig
index 0dde496e728582b0fbd6609ad6cbde473764176b..c145c0255b0aa89bdb7bdcc1e1816d6e2752bde0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -1,4 +1,4 @@
-package: "com.android.server.devicepolicy.flags"
+package: "android.app.admin.flags"
 
 flag {
   name: "policy_engine_migration_v2_enabled"
@@ -6,9 +6,17 @@ flag {
   description: "V2 of the policy engine migrations for Android V"
   bug: "289520697"
 }
+
 flag {
   name: "device_policy_size_tracking_enabled"
   namespace: "enterprise"
   description: "Add feature to track the total policy size and have a max threshold."
   bug: "281543351"
+}
+
+flag {
+  name: "onboarding_bugreport_v2_enabled"
+  namespace: "enterprise"
+  description: "Add feature to track required changes for enabled V2 of auto-capturing of onboarding bug reports."
+  bug: "302517677"
 }
\ No newline at end of file
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index a84845a15a79217b2404d5a174f043d28d10bba6..dbc67fc5a3a3683777e6b1bee5b11ad781025010 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -23,6 +23,7 @@ import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH;
 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
 
 import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -216,12 +217,14 @@ public final class CompanionDeviceManager {
      *
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
     @TestApi public static final int MESSAGE_REQUEST_PING = 0x63807378; // ?PIN
     /**
      * Message header assigned to the remote authentication handshakes.
      *
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
     @SystemApi(client = MODULE_LIBRARIES)
     public static final int MESSAGE_REQUEST_REMOTE_AUTHENTICATION = 0x63827765; // ?RMA
     /**
@@ -229,6 +232,7 @@ public final class CompanionDeviceManager {
      *
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
     @SystemApi(client = MODULE_LIBRARIES)
     public static final int MESSAGE_REQUEST_CONTEXT_SYNC = 0x63678883; // ?CXS
     /**
@@ -236,6 +240,7 @@ public final class CompanionDeviceManager {
      *
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
     @SystemApi(client = MODULE_LIBRARIES)
     public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES
 
@@ -873,6 +878,7 @@ public final class CompanionDeviceManager {
      *
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
     @SystemApi(client = MODULE_LIBRARIES)
     public interface OnTransportsChangedListener {
         /**
@@ -892,6 +898,7 @@ public final class CompanionDeviceManager {
      *
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
     @SystemApi(client = MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS)
     public void addOnTransportsChangedListener(
@@ -913,6 +920,7 @@ public final class CompanionDeviceManager {
      *
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
     @SystemApi(client = MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS)
     public void removeOnTransportsChangedListener(
@@ -934,6 +942,7 @@ public final class CompanionDeviceManager {
      *
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
     @SystemApi(client = MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS)
     public void sendMessage(int messageType, @NonNull byte[] data, @NonNull int[] associationIds) {
@@ -951,6 +960,7 @@ public final class CompanionDeviceManager {
      *
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
     @SystemApi(client = MODULE_LIBRARIES)
     public interface OnMessageReceivedListener {
         /**
@@ -964,6 +974,7 @@ public final class CompanionDeviceManager {
      *
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
     @SystemApi(client = MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS)
     public void addOnMessageReceivedListener(
@@ -983,6 +994,7 @@ public final class CompanionDeviceManager {
      *
      * @hide
      */
+    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
     @SystemApi(client = MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS)
     public void removeOnMessageReceivedListener(int messageType,
diff --git a/core/java/android/companion/flags.aconfig b/core/java/android/companion/flags.aconfig
index b9e5609171c3eddd4ac6b50cea69f16e58d3cdbd..1b4234b5205ccb5484394f1563e558a844a55b96 100644
--- a/core/java/android/companion/flags.aconfig
+++ b/core/java/android/companion/flags.aconfig
@@ -5,4 +5,11 @@ flag {
     namespace: "companion"
     description: "Controls if the new Builder is exposed to test apis."
     bug: "296251481"
+}
+
+flag {
+    name: "companion_transport_apis"
+    namespace: "companion"
+    description: "Grants access to the companion transport apis."
+    bug: "288297505"
 }
\ No newline at end of file
diff --git a/core/java/android/companion/virtual/sensor/VirtualSensor.java b/core/java/android/companion/virtual/sensor/VirtualSensor.java
index eaa17925b14bd5a0a145da1e97a745c06b3109ef..14c799763a96f792af62360699f8761eb0c68c25 100644
--- a/core/java/android/companion/virtual/sensor/VirtualSensor.java
+++ b/core/java/android/companion/virtual/sensor/VirtualSensor.java
@@ -115,6 +115,11 @@ public final class VirtualSensor implements Parcelable {
         parcel.writeStrongBinder(mToken);
     }
 
+    @Override
+    public String toString() {
+        return "VirtualSensor{ mType=" + mType + ", mName='" + mName + "' }";
+    }
+
     /**
      * Send a sensor event to the system.
      */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b765562ab587b7e1006a90b0489f058b438e69da..bb9cc0bef6717b74a2388c415ee54533b76e0f4c 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -64,6 +64,7 @@ import android.os.Process;
 import android.os.ResultReceiver;
 import android.os.ShellCommand;
 import android.os.StrictMode;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.provider.ContactsContract.QuickContact;
@@ -2796,6 +2797,8 @@ public class Intent implements Parcelable, Cloneable {
      * started and is no longer considered stopped.
      * <ul>
      * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package.
+     * <li> {@link #EXTRA_TIME} containing the {@link SystemClock#elapsedRealtime()
+     *          elapsed realtime} of when the package was unstopped.
      * </ul>
      *
      * <p class="note">This is a protected intent that can only be sent by the system.
@@ -2869,9 +2872,15 @@ public class Intent implements Parcelable, Cloneable {
      *
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
+     * <p>
+     * Starting in {@link Build.VERSION_CODES#VANILLA_ICE_CREAM Android V}, an extra timestamp
+     * {@link #EXTRA_TIME} is included with this broadcast to indicate the exact time the package
+     * was restarted, in {@link SystemClock#elapsedRealtime() elapsed realtime}.
+     * </p>
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED";
+
     /**
      * Broadcast Action: The user has cleared the data of a package.  This should
      * be preceded by {@link #ACTION_PACKAGE_RESTARTED}, after which all of
@@ -6578,8 +6587,8 @@ public class Intent implements Parcelable, Cloneable {
             = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
 
     /**
-     * Optional extra specifying a time in milliseconds since the Epoch. The value must be
-     * non-negative.
+     * Optional extra specifying a time in milliseconds. The timebase depends on the Intent
+     * including this extra. The value must be non-negative.
      * <p>
      * Type: long
      * </p>
diff --git a/core/java/android/service/rotationresolver/OWNERS b/core/java/android/service/rotationresolver/OWNERS
index 5b57fc7fa52853dcd275dc3e67804c888917e87c..dce874dcd982c2a2a56e085928cd8db5926a887e 100644
--- a/core/java/android/service/rotationresolver/OWNERS
+++ b/core/java/android/service/rotationresolver/OWNERS
@@ -1,9 +1,7 @@
 # Bug component: 814982
 
 asalo@google.com
-augale@google.com
 eejiang@google.com
 payamp@google.com
 siddikap@google.com
-svetoslavganov@google.com
 tgadh@google.com
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 506945501609ab54a2324183724954569a47c1fd..17c7fcc3a7bb8cf28d4686f9d6e348c47004c771 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -2656,6 +2656,7 @@ public final class Display {
             if (displayId == getDisplayId()) {
                 float newRatio = getHdrSdrRatio();
                 if (newRatio != mLastReportedRatio) {
+                    mLastReportedRatio = newRatio;
                     mListener.accept(Display.this);
                 }
             }
diff --git a/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig b/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig
index 5c86feb3c22c463573822b61a69f6129a3f73f32..f6ee061fdd89891e852a7f9277a07ea7b8ced77e 100644
--- a/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig
+++ b/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig
@@ -13,3 +13,10 @@ flag {
     description: "If true, content protection groups config will be parsed."
     bug: "302187922"
 }
+
+flag {
+    name: "setting_ui_enabled"
+    namespace: "content_protection"
+    description: "If true, content protection setting ui is displayed in Settings > Privacy & Security > More security & privacy."
+    bug: "305792348"
+}
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index 73778900399ca16ba9a0071b2da3985fe1079764..7cfd35b075473ff17995b5829d4e42e65647e1e6 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -18,7 +18,7 @@ flag {
   name: "dimmer_refactor"
   namespace: "windowing_frontend"
   description: "Refactor dim to fix flickers"
-  bug: "281632483,295291019"
+  bug: "295291019"
   is_fixed_read_only: true
 }
 
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 4e7bfe50cd30905e83197f4bef729014d7b539ff..71bbccb3d989aede572d4b87b83c503592e6e57f 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -259,7 +259,7 @@ public class PlatLogoActivity extends Activity {
             }
             return true;
         }
-        return false;
+        return super.onKeyDown(keyCode,event);
     }
 
     @Override
@@ -268,7 +268,7 @@ public class PlatLogoActivity extends Activity {
             stopWarp();
             return true;
         }
-        return false;
+        return super.onKeyUp(keyCode,event);
     }
 
     private void startWarp() {
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 6e836e077e4446e1f3c84a8276cb66dd1692e870..7e9cef720a136ee74b85b92c4fc50acc9c7754dc 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -40,6 +40,7 @@ import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_IN
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_SEARCH_RESULT;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNFOLD_ANIM;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNLOCK_ENTRANCE_ANIMATION;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA;
@@ -273,7 +274,9 @@ public class InteractionJankMonitor {
 
     public static final int CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER = 82;
 
-    private static final int LAST_CUJ = CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
+    public static final int CUJ_LAUNCHER_UNFOLD_ANIM = 83;
+
+    private static final int LAST_CUJ = CUJ_LAUNCHER_UNFOLD_ANIM;
     private static final int NO_STATSD_LOGGING = -1;
 
     // Used to convert CujType to InteractionType enum value for statsd logging.
@@ -366,6 +369,7 @@ public class InteractionJankMonitor {
         CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_SHOW_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_SHOW_ANIMATION;
         CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_HIDE_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_HIDE_ANIMATION;
         CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_UNFOLD_ANIM] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNFOLD_ANIM;
     }
 
     private static class InstanceHolder {
@@ -468,6 +472,7 @@ public class InteractionJankMonitor {
             CUJ_IME_INSETS_SHOW_ANIMATION,
             CUJ_IME_INSETS_HIDE_ANIMATION,
             CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER,
+            CUJ_LAUNCHER_UNFOLD_ANIM,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface CujType {
@@ -1101,6 +1106,8 @@ public class InteractionJankMonitor {
                 return "IME_INSETS_HIDE_ANIMATION";
             case CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER:
                 return "SPLIT_SCREEN_DOUBLE_TAP_DIVIDER";
+            case CUJ_LAUNCHER_UNFOLD_ANIM:
+                return "LAUNCHER_UNFOLD_ANIM";
         }
         return "UNKNOWN";
     }
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 406505517bcc5f9782d5f0aa13ab8b9bf185ddfd..82367834f93d5813ab7a3b63a6c6aecdb969ef9b 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -108,4 +108,5 @@ interface ILockSettings {
     boolean removeWeakEscrowToken(long handle, int userId);
     boolean isWeakEscrowTokenActive(long handle, int userId);
     boolean isWeakEscrowTokenValid(long handle, in byte[] token, int userId);
+    void unlockUserKeyIfUnsecured(int userId);
 }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index d5b8f62aaf2b85ecc42bcffd740b4b4bde6cf2eb..a3e27062fa7b9de88f39d551539b89d1e785e37f 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1933,8 +1933,23 @@ public class LockPatternUtils {
         }
     }
 
+    /**
+     * Unlocks the credential-encrypted storage for the given user if the user is not secured, i.e.
+     * doesn't have an LSKF.
+     * <p>
+     * Whether the storage has been unlocked can be determined by
+     * {@link StorageManager#isUserKeyUnlocked()}.
+     *
+     * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+     *
+     * @param userId the ID of the user whose storage to unlock
+     */
     public void unlockUserKeyIfUnsecured(@UserIdInt int userId) {
-        getLockSettingsInternal().unlockUserKeyIfUnsecured(userId);
+        try {
+            getLockSettings().unlockUserKeyIfUnsecured(userId);
+        } catch (RemoteException re) {
+            re.rethrowFromSystemServer();
+        }
     }
 
     public void createNewUser(@UserIdInt int userId, int userSerialNumber) {
diff --git a/core/java/com/android/internal/widget/LockSettingsInternal.java b/core/java/com/android/internal/widget/LockSettingsInternal.java
index 6063c90d6ab9e080098e91fdb470157e689dd65a..8114e1fd3bb0401e58a44aab2b22b2d12ff6affd 100644
--- a/core/java/com/android/internal/widget/LockSettingsInternal.java
+++ b/core/java/com/android/internal/widget/LockSettingsInternal.java
@@ -59,17 +59,6 @@ public abstract class LockSettingsInternal {
      */
     public abstract void onThirdPartyAppsStarted();
 
-    /**
-     * Unlocks the credential-encrypted storage for the given user if the user is not secured, i.e.
-     * doesn't have an LSKF.
-     * <p>
-     * This doesn't throw an exception on failure; whether the storage has been unlocked can be
-     * determined by {@link StorageManager#isUserKeyUnlocked()}.
-     *
-     * @param userId the ID of the user whose storage to unlock
-     */
-    public abstract void unlockUserKeyIfUnsecured(@UserIdInt int userId);
-
     /**
      * Creates the locksettings state for a new user.
      * <p>
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b73a7651c567774ab2d3da542ce90d02760048e8..6daa5b934284a42c7de15ecec98f0fb036305a40 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -5668,7 +5668,8 @@
                 android:description="@string/permdesc_deliverCompanionMessages"
                 android:protectionLevel="normal" />
 
-    <!-- @hide @SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)
+    <!-- @hide @FlaggedApi("android.companion.flags.companion_transport_apis")
+         @SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)
          Allows an application to send and receive messages via CDM transports.
     -->
     <permission android:name="android.permission.USE_COMPANION_TRANSPORTS"
diff --git a/core/tests/coretests/src/android/view/OWNERS b/core/tests/coretests/src/android/view/OWNERS
index 2ca99943a8a0b8913cf01b5a36fca1402252a8db..23668a4b2afb83e872271fa23de82a1480317b34 100644
--- a/core/tests/coretests/src/android/view/OWNERS
+++ b/core/tests/coretests/src/android/view/OWNERS
@@ -20,4 +20,7 @@ per-file *ContentRecord*  = file:/services/core/java/com/android/server/wm/OWNER
 per-file *ScrollCapture*.java = file:/packages/SystemUI/src/com/android/systemui/screenshot/OWNERS
 
 # Stylus
-per-file stylus/* = file:/core/java/android/text/OWNERS
\ No newline at end of file
+per-file stylus/* = file:/core/java/android/text/OWNERS
+
+# View
+file:/core/java/android/view/OWNERS
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index c72a42cce2bd88f4a2cbb16fb9df30dcd0c717a5..187964947b946e5e11f12650f07a546532d803ce 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -151,6 +151,7 @@ android_library {
     static_libs: [
         "androidx.appcompat_appcompat",
         "androidx.core_core-animation",
+        "androidx.core_core-ktx",
         "androidx.arch.core_core-runtime",
         "androidx-constraintlayout_constraintlayout",
         "androidx.dynamicanimation_dynamicanimation",
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/EntryHighlight.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/EntryHighlight.kt
index 90c44b549df9fe4cb7ea1c6c558b2216f00ff102..330755c0b4195e0ed3a6c71929b1b330b1a27bba 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/EntryHighlight.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/EntryHighlight.kt
@@ -30,11 +30,11 @@ import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
 import com.android.settingslib.spa.framework.common.LocalEntryDataProvider
-import com.android.settingslib.spa.framework.theme.SettingsTheme
 
 @Composable
-internal fun EntryHighlight(UiLayoutFn: @Composable () -> Unit) {
+internal fun EntryHighlight(content: @Composable () -> Unit) {
     val entryData = LocalEntryDataProvider.current
     val entryIsHighlighted = rememberSaveable { entryData.isHighlighted }
     var localHighlighted by rememberSaveable { mutableStateOf(false) }
@@ -45,15 +45,16 @@ internal fun EntryHighlight(UiLayoutFn: @Composable () -> Unit) {
     val backgroundColor by animateColorAsState(
         targetValue = when {
             localHighlighted -> MaterialTheme.colorScheme.surfaceVariant
-            else -> SettingsTheme.colorScheme.background
+            else -> Color.Transparent
         },
         animationSpec = repeatable(
             iterations = 3,
             animation = tween(durationMillis = 500),
             repeatMode = RepeatMode.Restart
-        )
+        ),
+        label = "BackgroundColorAnimation",
     )
     Box(modifier = Modifier.background(color = backgroundColor)) {
-        UiLayoutFn()
+        content()
     }
 }
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 9ac1e9f58dbca396aa65d4b21b723b8c6dfd560c..572f6ff2745e3fc96fa8be5de7a364ec7b28b4b2 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -531,19 +531,25 @@
     </string>
 
     <!-- A path similar to frameworks/base/core/res/res/values/config.xml
-      config_mainBuiltInDisplayCutout that describes a path larger than the exact path of a display
-      cutout. If present as well as config_enableDisplayCutoutProtection is set to true, then
-      SystemUI will draw this "protection path" instead of the display cutout path that is normally
-      used for anti-aliasing.
+      config_mainBuiltInDisplayCutout that describes a path larger than the exact path of a outer
+      display cutout. If present as well as config_enableDisplayCutoutProtection is set to true,
+      then SystemUI will draw this "protection path" instead of the display cutout path that is
+      normally used for anti-aliasing.
 
       This path will only be drawn when the front-facing camera turns on, otherwise the main
       DisplayCutout path will be rendered
        -->
     <string translatable="false" name="config_frontBuiltInDisplayCutoutProtection"></string>
 
-    <!--  ID for the camera that needs extra protection -->
+    <!--  ID for the camera of outer display that needs extra protection -->
     <string translatable="false" name="config_protectedCameraId"></string>
 
+    <!-- Similar to config_frontBuiltInDisplayCutoutProtection but for inner display. -->
+    <string translatable="false" name="config_innerBuiltInDisplayCutoutProtection"></string>
+
+    <!-- ID for the camera of inner display that needs extra protection -->
+    <string translatable="false" name="config_protectedInnerCameraId"></string>
+
     <!-- Comma-separated list of packages to exclude from camera protection e.g.
     "com.android.systemui,com.android.xyz" -->
     <string translatable="false" name="config_cameraProtectionExcludedPackages"></string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
index 1e896142f7188c5ed85fb3ff59d8b76ba9093178..400f6529eed6f47b12bbbe14d48550da231a7bd9 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
@@ -702,13 +702,18 @@ public class RotationButtonController {
 
         @Override
         public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) {
-            // Only hide the icon if the top task changes its requestedOrientation
-            // Launcher can alter its requestedOrientation while it's not on top, don't hide on this
-            Optional.ofNullable(ActivityManagerWrapper.getInstance())
-                    .map(ActivityManagerWrapper::getRunningTask)
-                    .ifPresent(a -> {
-                        if (a.id == taskId) setRotateSuggestionButtonState(false /* visible */);
-                    });
+            mBgExecutor.execute(() -> {
+                // Only hide the icon if the top task changes its requestedOrientation Launcher can
+                // alter its requestedOrientation while it's not on top, don't hide on this
+                Optional.ofNullable(ActivityManagerWrapper.getInstance())
+                        .map(ActivityManagerWrapper::getRunningTask)
+                        .ifPresent(a -> {
+                            if (a.id == taskId) {
+                                mMainThreadHandler.post(() ->
+                                        setRotateSuggestionButtonState(false /* visible */));
+                            }
+                        });
+            });
         }
     }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
index eb20669360880355539e80cd59e9e262404a9eb2..c505bd5029858ce709bb42d22552e24279ffcc67 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
@@ -61,6 +61,8 @@ public final class InteractionJankMonitorWrapper {
             InteractionJankMonitor.CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS;
     public static final int CUJ_OPEN_SEARCH_RESULT =
             InteractionJankMonitor.CUJ_LAUNCHER_OPEN_SEARCH_RESULT;
+    public static final int CUJ_LAUNCHER_UNFOLD_ANIM =
+            InteractionJankMonitor.CUJ_LAUNCHER_UNFOLD_ANIM;
 
     @IntDef({
             CUJ_APP_LAUNCH_FROM_RECENTS,
@@ -77,6 +79,7 @@ public final class InteractionJankMonitorWrapper {
             CUJ_CLOSE_ALL_APPS_SWIPE,
             CUJ_CLOSE_ALL_APPS_TO_HOME,
             CUJ_OPEN_SEARCH_RESULT,
+            CUJ_LAUNCHER_UNFOLD_ANIM,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface CujType {
diff --git a/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt b/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt
index 2d2ebe99d651100b9865165d029bad2338385652..d33d279023daa35ad3594678dff2e8a9f11cbde9 100644
--- a/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt
@@ -17,6 +17,7 @@
 package com.android.systemui
 
 import android.content.Context
+import android.content.res.Resources
 import android.graphics.Path
 import android.graphics.Rect
 import android.graphics.RectF
@@ -33,37 +34,32 @@ import kotlin.math.roundToInt
  */
 class CameraAvailabilityListener(
     private val cameraManager: CameraManager,
-    private val cutoutProtectionPath: Path,
-    private val targetCameraId: String,
+    private val cameraProtectionInfoList: List<CameraProtectionInfo>,
     excludedPackages: String,
     private val executor: Executor
 ) {
-    private var cutoutBounds = Rect()
     private val excludedPackageIds: Set<String>
     private val listeners = mutableListOf<CameraTransitionCallback>()
     private val availabilityCallback: CameraManager.AvailabilityCallback =
             object : CameraManager.AvailabilityCallback() {
                 override fun onCameraClosed(cameraId: String) {
-                    if (targetCameraId == cameraId) {
-                        notifyCameraInactive()
+                    cameraProtectionInfoList.forEach {
+                        if (cameraId == it.cameraId) {
+                            notifyCameraInactive()
+                        }
                     }
                 }
 
                 override fun onCameraOpened(cameraId: String, packageId: String) {
-                    if (targetCameraId == cameraId && !isExcluded(packageId)) {
-                        notifyCameraActive()
+                    cameraProtectionInfoList.forEach {
+                        if (cameraId == it.cameraId && !isExcluded(packageId)) {
+                            notifyCameraActive(it)
+                        }
                     }
                 }
     }
 
     init {
-        val computed = RectF()
-        cutoutProtectionPath.computeBounds(computed, false /* unused */)
-        cutoutBounds.set(
-                computed.left.roundToInt(),
-                computed.top.roundToInt(),
-                computed.right.roundToInt(),
-                computed.bottom.roundToInt())
         excludedPackageIds = excludedPackages.split(",").toSet()
     }
 
@@ -100,8 +96,10 @@ class CameraAvailabilityListener(
         cameraManager.unregisterAvailabilityCallback(availabilityCallback)
     }
 
-    private fun notifyCameraActive() {
-        listeners.forEach { it.onApplyCameraProtection(cutoutProtectionPath, cutoutBounds) }
+    private fun notifyCameraActive(info: CameraProtectionInfo) {
+        listeners.forEach {
+            it.onApplyCameraProtection(info.cutoutProtectionPath, info.cutoutBounds)
+        }
     }
 
     private fun notifyCameraInactive() {
@@ -121,12 +119,11 @@ class CameraAvailabilityListener(
             val manager = context
                     .getSystemService(Context.CAMERA_SERVICE) as CameraManager
             val res = context.resources
-            val pathString = res.getString(R.string.config_frontBuiltInDisplayCutoutProtection)
-            val cameraId = res.getString(R.string.config_protectedCameraId)
+            val cameraProtectionInfoList = loadCameraProtectionInfoList(res)
             val excluded = res.getString(R.string.config_cameraProtectionExcludedPackages)
 
             return CameraAvailabilityListener(
-                    manager, pathFromString(pathString), cameraId, excluded, executor)
+                    manager, cameraProtectionInfoList, excluded, executor)
         }
 
         private fun pathFromString(pathString: String): Path {
@@ -140,5 +137,53 @@ class CameraAvailabilityListener(
 
             return p
         }
+
+        private fun loadCameraProtectionInfoList(res: Resources): List<CameraProtectionInfo> {
+            val list = mutableListOf<CameraProtectionInfo>()
+            val front = loadCameraProtectionInfo(
+                    res,
+                    R.string.config_protectedCameraId,
+                    R.string.config_frontBuiltInDisplayCutoutProtection
+            )
+            if (front != null) {
+                list.add(front)
+            }
+            val inner = loadCameraProtectionInfo(
+                    res,
+                    R.string.config_protectedInnerCameraId,
+                    R.string.config_innerBuiltInDisplayCutoutProtection
+            )
+            if (inner != null) {
+                list.add(inner)
+            }
+            return list
+        }
+
+        private fun loadCameraProtectionInfo(
+                res: Resources,
+                cameraIdRes: Int,
+                pathRes: Int
+        ): CameraProtectionInfo? {
+            val cameraId = res.getString(cameraIdRes)
+            if (cameraId == null || cameraId.isEmpty()) {
+                return null
+            }
+            val protectionPath = pathFromString(res.getString(pathRes))
+            val computed = RectF()
+            protectionPath.computeBounds(computed)
+            val protectionBounds = Rect(
+                    computed.left.roundToInt(),
+                    computed.top.roundToInt(),
+                    computed.right.roundToInt(),
+                    computed.bottom.roundToInt()
+            )
+            return CameraProtectionInfo(cameraId, protectionPath, protectionBounds)
+        }
     }
+
+    data class CameraProtectionInfo (
+            val cameraId: String,
+            val cutoutProtectionPath: Path,
+            val cutoutBounds: Rect
+    )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
index 84cd3ef622ba8a180559560ab43ba1ebf00c9e0f..3eef6aa37122ab343d1cee1a7e261c236805d4a1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
@@ -25,6 +25,7 @@ import android.util.Log
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import java.util.UUID
@@ -48,8 +49,8 @@ import kotlinx.coroutines.flow.filter
  * [TransitionInteractor]. These interactors will call [startTransition] and [updateTransition] on
  * this repository.
  *
- * To print all transitions to logcat to help with debugging, run this command:
- * adb shell settings put global systemui/buffer/KeyguardLog VERBOSE
+ * To print all transitions to logcat to help with debugging, run this command: adb shell settings
+ * put global systemui/buffer/KeyguardLog VERBOSE
  *
  * This will print all keyguard transitions to logcat with the KeyguardTransitionAuditLogger tag.
  */
@@ -73,11 +74,8 @@ interface KeyguardTransitionRepository {
     /**
      * Begin a transition from one state to another. Transitions are interruptible, and will issue a
      * [TransitionStep] with state = [TransitionState.CANCELED] before beginning the next one.
-     *
-     * When canceled, there are two options: to continue from the current position of the prior
-     * transition, or to reset the position. When [resetIfCanceled] == true, it will do the latter.
      */
-    fun startTransition(info: TransitionInfo, resetIfCanceled: Boolean = false): UUID?
+    fun startTransition(info: TransitionInfo): UUID?
 
     /**
      * Allows manual control of a transition. When calling [startTransition], the consumer must pass
@@ -138,10 +136,7 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
         )
     }
 
-    override fun startTransition(
-        info: TransitionInfo,
-        resetIfCanceled: Boolean,
-    ): UUID? {
+    override fun startTransition(info: TransitionInfo): UUID? {
         if (lastStep.from == info.from && lastStep.to == info.to) {
             Log.i(TAG, "Duplicate call to start the transition, rejecting: $info")
             return null
@@ -149,10 +144,10 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
         val startingValue =
             if (lastStep.transitionState != TransitionState.FINISHED) {
                 Log.i(TAG, "Transition still active: $lastStep, canceling")
-                if (resetIfCanceled) {
-                    0f
-                } else {
-                    lastStep.value
+                when (info.modeOnCanceled) {
+                    TransitionModeOnCanceled.LAST_VALUE -> lastStep.value
+                    TransitionModeOnCanceled.RESET -> 0f
+                    TransitionModeOnCanceled.REVERSE -> 1f - lastStep.value
                 }
             } else {
                 0f
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
index 6e0aa4c7682d6c91ef1b40cb6b1c33400bfae8b6..a331a668e1351d8018e8167c73b362bfc41bb1bb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
@@ -24,6 +24,7 @@ import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositor
 import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.Companion.isWakeAndUnlock
 import com.android.systemui.keyguard.shared.model.DozeStateModel
 import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
 import com.android.systemui.util.kotlin.Utils.Companion.toTriple
 import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
@@ -65,8 +66,21 @@ constructor(
                 )
                 .collect { (_, lastStartedStep, occluded) ->
                     if (lastStartedStep.to == KeyguardState.AOD) {
-                        startTransitionTo(
+                        val toState =
                             if (occluded) KeyguardState.OCCLUDED else KeyguardState.LOCKSCREEN
+                        val modeOnCanceled =
+                            if (
+                                toState == KeyguardState.LOCKSCREEN &&
+                                    lastStartedStep.from == KeyguardState.LOCKSCREEN
+                            ) {
+                                TransitionModeOnCanceled.REVERSE
+                            } else {
+                                TransitionModeOnCanceled.LAST_VALUE
+                            }
+
+                        startTransitionTo(
+                            toState = toState,
+                            modeOnCanceled = modeOnCanceled,
                         )
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
index c67153a5963da2d60e54d9cbf9bf0f97f0215c61..eace0c70cb5ba8189c868d4c5d196f9291617430 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
@@ -22,6 +22,7 @@ import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.util.kotlin.Utils.Companion.toTriple
 import com.android.systemui.util.kotlin.sample
@@ -114,8 +115,9 @@ constructor(
                 .collect { (isAsleep, lastStartedStep, isAodAvailable) ->
                     if (lastStartedStep.to == KeyguardState.GONE && isAsleep) {
                         startTransitionTo(
-                            if (isAodAvailable) KeyguardState.AOD else KeyguardState.DOZING,
-                            resetIfCancelled = true,
+                            toState =
+                                if (isAodAvailable) KeyguardState.AOD else KeyguardState.DOZING,
+                            modeOnCanceled = TransitionModeOnCanceled.RESET,
                         )
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index c39a4c9c41729ed3b4d87fc099c152759844f1e5..d44a9d86a731762f665b03bc49bdf25a190b6874 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -27,6 +27,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardSurfaceBehindModel
 import com.android.systemui.keyguard.shared.model.StatusBarState.KEYGUARD
 import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.shade.data.repository.ShadeRepository
@@ -340,8 +341,20 @@ constructor(
                 )
                 .collect { (isAsleep, lastStartedStep, isAodAvailable) ->
                     if (lastStartedStep.to == KeyguardState.LOCKSCREEN && isAsleep) {
-                        startTransitionTo(
+                        val toState =
                             if (isAodAvailable) KeyguardState.AOD else KeyguardState.DOZING
+                        val modeOnCanceled =
+                            if (
+                                toState == KeyguardState.AOD &&
+                                    lastStartedStep.from == KeyguardState.AOD
+                            ) {
+                                TransitionModeOnCanceled.REVERSE
+                            } else {
+                                TransitionModeOnCanceled.LAST_VALUE
+                            }
+                        startTransitionTo(
+                            toState = toState,
+                            modeOnCanceled = modeOnCanceled,
                         )
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
index f1649fb2851e8476d345f59f7e8108317a32b580..24b666185ce2172ad418c70f71932038de11b4e4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
@@ -25,6 +25,7 @@ import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardSurfaceBehindModel
+import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.kotlin.Utils.Companion.toQuad
@@ -236,7 +237,7 @@ constructor(
                                 getDefaultAnimatorForTransitionsToState(KeyguardState.GONE).apply {
                                     this.duration = duration.inWholeMilliseconds
                                 },
-                            resetIfCancelled = true
+                            modeOnCanceled = TransitionModeOnCanceled.RESET,
                         )
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
index 54c6d5f6d09f4eeb16b5770a033d2611b3848c11..76018080848f764e2ee05a7613f3c3919ed948ae 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
@@ -21,6 +21,7 @@ import android.util.Log
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
 import com.android.systemui.util.kotlin.sample
 import java.util.UUID
 import kotlinx.coroutines.CoroutineScope
@@ -49,7 +50,7 @@ sealed class TransitionInteractor(
     fun startTransitionTo(
         toState: KeyguardState,
         animator: ValueAnimator? = getDefaultAnimatorForTransitionsToState(toState),
-        resetIfCancelled: Boolean = false,
+        modeOnCanceled: TransitionModeOnCanceled = TransitionModeOnCanceled.LAST_VALUE
     ): UUID? {
         if (
             fromState != transitionInteractor.startedKeyguardState.value &&
@@ -73,8 +74,8 @@ sealed class TransitionInteractor(
                 fromState,
                 toState,
                 animator,
-            ),
-            resetIfCancelled
+                modeOnCanceled,
+            )
         )
     }
 
@@ -91,8 +92,8 @@ sealed class TransitionInteractor(
                     // so use the last finishedKeyguardState to determine the overriding FROM state
                     if (finishedKeyguardState == fromState) {
                         startTransitionTo(
-                            KeyguardState.OCCLUDED,
-                            resetIfCancelled = true,
+                            toState = KeyguardState.OCCLUDED,
+                            modeOnCanceled = TransitionModeOnCanceled.RESET,
                         )
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionInfo.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionInfo.kt
index bfccf3fe076cbc48b5a619e1cd0fdb515267bc8b..7a37365a9cbea2d6e79d7bb84cc603397aece095 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionInfo.kt
@@ -22,7 +22,13 @@ data class TransitionInfo(
     val ownerName: String,
     val from: KeyguardState,
     val to: KeyguardState,
-    val animator: ValueAnimator?, // 'null' animator signal manual control
+    /** [null] animator signals manual control, otherwise transition run by the animator */
+    val animator: ValueAnimator?,
+    /**
+     * If the transition resets in the cancellation of another transition, use this mode to
+     * determine how to continue.
+     */
+    val modeOnCanceled: TransitionModeOnCanceled = TransitionModeOnCanceled.LAST_VALUE,
 ) {
     override fun toString(): String =
         "TransitionInfo(ownerName=$ownerName, from=$from, to=$to, " +
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/QSTilesDefaultLog.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionModeOnCanceled.kt
similarity index 54%
rename from packages/SystemUI/src/com/android/systemui/log/dagger/QSTilesDefaultLog.kt
rename to packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionModeOnCanceled.kt
index 6575cdd69c93888d10858e73fe3c0eb45b9eced3..56f90bdb4f718c7d7c688c7af3dc4cd56a8431dc 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/QSTilesDefaultLog.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TransitionModeOnCanceled.kt
@@ -11,18 +11,16 @@
  * 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.
+ * limitations under the License
  */
-package com.android.systemui.log.dagger
+package com.android.systemui.keyguard.shared.model
 
-import javax.inject.Qualifier
-
-/**
- * A default [com.android.systemui.log.LogBuffer] for QS tiles messages. It's used exclusively in
- * [com.android.systemui.qs.tiles.base.logging.QSTileLogger]. If you need to increase it for you
- * tile, add one to the map provided by the [QSTilesLogBuffers]
- */
-@Qualifier
-@MustBeDocumented
-@Retention(AnnotationRetention.RUNTIME)
-annotation class QSTilesDefaultLog
+/** When canceled, provide different ways to start the next transition. */
+enum class TransitionModeOnCanceled {
+    /** Proceed from the last value. If canceled at .7, start from .7 and end at 1 */
+    LAST_VALUE,
+    /** Start over from 0. If canceled at .7, start from 0 and end at 1 */
+    RESET,
+    /** Reverse the transition. If canceled at .7, start from 1-.7 (0.3) and end at 1 */
+    REVERSE
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 67531ad9926a4f3b887885be6c665732f920cdc2..fd6b3f1e0f45ba06b7f0bd5fdd879c7a03e82191 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -190,17 +190,6 @@ public class LogModule {
         }
     }
 
-    /**
-     * Provides a logging buffer for all logs related to Quick Settings tiles. This LogBuffer is
-     * unique for each tile.
-     * go/qs-tile-refactor
-     */
-    @Provides
-    @QSTilesDefaultLog
-    public static LogBuffer provideQuickSettingsTilesLogBuffer(LogBufferFactory factory) {
-        return factory.create("QSTileLog", 25 /* maxSize */, false /* systrace */);
-    }
-
     @Provides
     @QSTilesLogBuffers
     public static Map<TileSpec, LogBuffer> provideQuickSettingsTilesLogBufferCache() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
index a48e56a9f158eec982749c58e8fa3bb20ea142dd..7cb5b3bc092494f212098d74913baa39b414996d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
@@ -731,6 +731,7 @@ constructor(
                     removePlayer(existingSmartspaceMediaKey, dismissMediaData = false)
                 removedPlayer?.run {
                     debugLogger.logPotentialMemoryLeak(existingSmartspaceMediaKey)
+                    onDestroy()
                 }
             }
 
@@ -1302,6 +1303,7 @@ internal object MediaPlayerData {
         val removedPlayer = removeMediaPlayer(key)
         if (removedPlayer != null && removedPlayer != player) {
             debugLogger?.logPotentialMemoryLeak(key)
+            removedPlayer.onDestroy()
         }
         val sortKey =
             MediaSortKey(
@@ -1329,6 +1331,7 @@ internal object MediaPlayerData {
         val removedPlayer = removeMediaPlayer(key)
         if (!update && removedPlayer != null && removedPlayer != player) {
             debugLogger?.logPotentialMemoryLeak(key)
+            removedPlayer.onDestroy()
         }
         val sortKey =
             MediaSortKey(
@@ -1357,7 +1360,10 @@ internal object MediaPlayerData {
             // MediaPlayer should not be visible
             // no need to set isDismissed flag.
             val removedPlayer = removeMediaPlayer(newKey)
-            removedPlayer?.run { debugLogger?.logPotentialMemoryLeak(newKey) }
+            removedPlayer?.run {
+                debugLogger?.logPotentialMemoryLeak(newKey)
+                onDestroy()
+            }
             mediaData.put(newKey, it)
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLogger.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLogger.kt
index a53f0f11c38047741c10af8767c608c59a257376..ce8b79cd9e38882adc0a494a5e1e66cd66313cf1 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLogger.kt
@@ -24,6 +24,7 @@ import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGE
 import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_SYSTEM_UI_SCREEN_RECORDER as METRICS_CREATION_SOURCE_SYSTEM_UI_SCREEN_RECORDER
 import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN as METRICS_CREATION_SOURCE_UNKNOWN
 import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED
+import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED as METRICS_STATE_PERMISSION_REQUEST_DISPLAYED
 import com.android.systemui.dagger.SysUISingleton
 import javax.inject.Inject
 
@@ -47,6 +48,10 @@ constructor(private val service: IMediaProjectionManager) {
         )
     }
 
+    fun notifyPermissionRequestDisplayed() {
+        notifyToServer(METRICS_STATE_PERMISSION_REQUEST_DISPLAYED, SessionCreationSource.UNKNOWN)
+    }
+
     /**
      * Request to log that the permission request moved to the given state.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
index fa418fc8b98b47db4c37d3351d2d5a16f8b60678..2d830d3115625152d1cf832c2f17172e7ba3bd92 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java
@@ -249,6 +249,10 @@ public class MediaProjectionPermissionActivity extends Activity
 
         setUpDialog(mDialog);
         mDialog.show();
+
+        if (savedInstanceState == null) {
+            mMediaProjectionMetricsLogger.notifyPermissionRequestDisplayed();
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
index 959afd86ee8d9966bf4fd65f40c7aff1695b6ec2..e27a59c6fb21e8300f6815a2a1ad866e5361eaa9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
@@ -30,12 +30,12 @@ import androidx.annotation.Nullable;
 
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.res.R;
 import com.android.systemui.animation.DialogCuj;
 import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.qs.QSTile;
@@ -45,6 +45,7 @@ import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 import com.android.systemui.screenrecord.RecordingController;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -69,6 +70,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState>
     private final DialogLaunchAnimator mDialogLaunchAnimator;
     private final FeatureFlags mFlags;
     private final PanelInteractor mPanelInteractor;
+    private final MediaProjectionMetricsLogger mMediaProjectionMetricsLogger;
 
     private long mMillisUntilFinished = 0;
 
@@ -88,7 +90,8 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState>
             KeyguardDismissUtil keyguardDismissUtil,
             KeyguardStateController keyguardStateController,
             DialogLaunchAnimator dialogLaunchAnimator,
-            PanelInteractor panelInteractor
+            PanelInteractor panelInteractor,
+            MediaProjectionMetricsLogger mediaProjectionMetricsLogger
     ) {
         super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
                 statusBarStateController, activityStarter, qsLogger);
@@ -99,6 +102,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState>
         mKeyguardStateController = keyguardStateController;
         mDialogLaunchAnimator = dialogLaunchAnimator;
         mPanelInteractor = panelInteractor;
+        mMediaProjectionMetricsLogger = mediaProjectionMetricsLogger;
     }
 
     @Override
@@ -190,6 +194,9 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState>
             } else {
                 dialog.show();
             }
+
+            mMediaProjectionMetricsLogger.notifyPermissionRequestDisplayed();
+
             return false;
         };
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/logging/QSTileLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/logging/QSTileLogger.kt
index 70a683b81f75ab8bfa20311f3ea495e885ff508b..f8de36563dd245a59e3f352f97ae194fa5e0edc0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/logging/QSTileLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/logging/QSTileLogger.kt
@@ -19,8 +19,8 @@ package com.android.systemui.qs.tiles.base.logging
 import androidx.annotation.GuardedBy
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogBufferFactory
 import com.android.systemui.log.core.LogLevel
-import com.android.systemui.log.dagger.QSTilesDefaultLog
 import com.android.systemui.log.dagger.QSTilesLogBuffers
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.qs.pipeline.shared.TileSpec
@@ -29,14 +29,13 @@ import com.android.systemui.qs.tiles.viewmodel.QSTileState
 import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
 import com.android.systemui.statusbar.StatusBarState
 import javax.inject.Inject
-import javax.inject.Provider
 
 @SysUISingleton
 class QSTileLogger
 @Inject
 constructor(
     @QSTilesLogBuffers logBuffers: Map<TileSpec, LogBuffer>,
-    @QSTilesDefaultLog private val defaultLogBufferProvider: Provider<LogBuffer>,
+    private val factory: LogBufferFactory,
     private val mStatusBarStateController: StatusBarStateController,
 ) {
     @GuardedBy("logBufferCache") private val logBufferCache = logBuffers.toMutableMap()
@@ -154,7 +153,13 @@ constructor(
 
     private fun TileSpec.getLogBuffer(): LogBuffer =
         synchronized(logBufferCache) {
-            logBufferCache.getOrPut(this) { defaultLogBufferProvider.get() }
+            logBufferCache.getOrPut(this) {
+                factory.create(
+                    "QSTileLog_${this.getLogTag()}",
+                    BUFFER_MAX_SIZE /* maxSize */,
+                    false /* systrace */
+                )
+            }
         }
 
     private fun StateUpdateTrigger.toLogString(): String =
@@ -185,5 +190,6 @@ constructor(
     private companion object {
         const val TAG_FORMAT_PREFIX = "QSLog"
         const val DATA_MAX_LENGTH = 50
+        const val BUFFER_MAX_SIZE = 25
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
index cf1fbe3685e3785c8f117b11e5c5dc8fd9ae6d1c..d6f1ed9c33343fdf331a6f1ebb029ab8a2a92caf 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
@@ -68,6 +68,10 @@ interface UserTracker : UserContentResolverProvider, UserContextProvider {
      */
     @WeaklyReferencedCallback
     interface Callback {
+        /**
+         * Notifies that the current user will be changed.
+         */
+        fun onBeforeUserSwitching(newUser: Int) {}
 
         /**
          * Same as {@link onUserChanging(Int, Context, Runnable)} but the callback will be
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 99127ea928bfcd4f20f19fafa3e78e85e573cff9..9f416bbf2c59d28b685934e980bd6f758739c4cb 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -227,6 +227,13 @@ open class UserTrackerImpl internal constructor(
     protected open fun handleBeforeUserSwitching(newUserId: Int) {
         Assert.isNotMainThread()
         setUserIdInternal(newUserId)
+
+        val list = synchronized(callbacks) {
+            callbacks.toList()
+        }
+        list.forEach {
+            it.callback.get()?.onBeforeUserSwitching(newUserId)
+        }
     }
 
     @WorkerThread
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
index 9dca013f8aa4cbac05c86eed60195be44f8aefdd..aea3030967d281ef23fa9c5fd680a46e548836e0 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
@@ -109,6 +109,7 @@ public class ImageWallpaper extends WallpaperService {
         private WallpaperManager mWallpaperManager;
         private final WallpaperLocalColorExtractor mWallpaperLocalColorExtractor;
         private SurfaceHolder mSurfaceHolder;
+        private boolean mDrawn = false;
         @VisibleForTesting
         static final int MIN_SURFACE_WIDTH = 128;
         @VisibleForTesting
@@ -239,6 +240,7 @@ public class ImageWallpaper extends WallpaperService {
 
         private void drawFrameSynchronized() {
             synchronized (mLock) {
+                if (mDrawn) return;
                 drawFrameInternal();
             }
         }
@@ -276,6 +278,7 @@ public class ImageWallpaper extends WallpaperService {
                 Rect dest = mSurfaceHolder.getSurfaceFrame();
                 try {
                     canvas.drawBitmap(bitmap, null, dest, null);
+                    mDrawn = true;
                 } finally {
                     surface.unlockCanvasAndPost(canvas);
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 897c4da0fae2069c3003ee889c62c83a1242d681..1e801aeb5a29f80bf0b8c19d73519b60e4771b40 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -33,6 +33,7 @@ import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.inputmethodservice.InputMethodService;
 import android.os.IBinder;
+import android.util.Log;
 import android.view.Display;
 import android.view.KeyEvent;
 
@@ -66,6 +67,7 @@ import com.android.wm.shell.splitscreen.SplitScreen;
 import com.android.wm.shell.sysui.ShellInterface;
 
 import java.io.PrintWriter;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.Executor;
@@ -371,6 +373,13 @@ public final class WMShell implements
 
     @Override
     public void dump(PrintWriter pw, String[] args) {
+        Log.d(TAG, "Dumping with args: " + String.join(", ", args));
+
+        // Strip out the SysUI "dependency" arg before sending to WMShell
+        if (args[0].equals("dependency")) {
+            args = Arrays.copyOfRange(args, 1, args.length);
+        }
+
         // Handle commands if provided
         if (mShell.handleCommand(args, pw)) {
             return;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/CameraAvailabilityListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/CameraAvailabilityListenerTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b1421b21b3771f72676f7ea46963128fc1daf2b8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/CameraAvailabilityListenerTest.kt
@@ -0,0 +1,162 @@
+package com.android.systemui
+
+import android.graphics.Path
+import android.graphics.Rect
+import android.graphics.RectF
+import android.hardware.camera2.CameraManager
+import android.testing.AndroidTestingRunner
+import android.util.PathParser
+import androidx.test.filters.SmallTest
+import com.android.systemui.res.R
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.withArgCaptor
+import java.util.concurrent.Executor
+import kotlin.math.roundToInt
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class CameraAvailabilityListenerTest : SysuiTestCase() {
+    companion object {
+        const val EXCLUDED_PKG = "test.excluded.package"
+        const val CAMERA_ID_FRONT = "0"
+        const val CAMERA_ID_INNER = "1"
+        const val PROTECTION_PATH_STRING_FRONT = "M 50,50 a 20,20 0 1 0 40,0 a 20,20 0 1 0 -40,0 Z"
+        const val PROTECTION_PATH_STRING_INNER = "M 40,40 a 10,10 0 1 0 20,0 a 10,10 0 1 0 -20,0 Z"
+        val PATH_RECT_FRONT = rectFromPath(pathFromString(PROTECTION_PATH_STRING_FRONT))
+        val PATH_RECT_INNER = rectFromPath(pathFromString(PROTECTION_PATH_STRING_INNER))
+
+        private fun pathFromString(pathString: String): Path {
+            val spec = pathString.trim()
+            val p: Path
+            try {
+                p = PathParser.createPathFromPathData(spec)
+            } catch (e: Throwable) {
+                throw IllegalArgumentException("Invalid protection path", e)
+            }
+
+            return p
+        }
+
+        private fun rectFromPath(path: Path): Rect {
+            val computed = RectF()
+            path.computeBounds(computed)
+            return Rect(
+                computed.left.roundToInt(),
+                computed.top.roundToInt(),
+                computed.right.roundToInt(),
+                computed.bottom.roundToInt()
+            )
+        }
+    }
+
+    @Mock private lateinit var cameraManager: CameraManager
+    @Mock
+    private lateinit var cameraTransitionCb: CameraAvailabilityListener.CameraTransitionCallback
+    private lateinit var cameraAvailabilityListener: CameraAvailabilityListener
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        context
+            .getOrCreateTestableResources()
+            .addOverride(R.string.config_cameraProtectionExcludedPackages, EXCLUDED_PKG)
+        context
+            .getOrCreateTestableResources()
+            .addOverride(R.string.config_protectedCameraId, CAMERA_ID_FRONT)
+        context
+            .getOrCreateTestableResources()
+            .addOverride(
+                R.string.config_frontBuiltInDisplayCutoutProtection,
+                PROTECTION_PATH_STRING_FRONT
+            )
+        context
+            .getOrCreateTestableResources()
+            .addOverride(R.string.config_protectedInnerCameraId, CAMERA_ID_INNER)
+        context
+            .getOrCreateTestableResources()
+            .addOverride(
+                R.string.config_innerBuiltInDisplayCutoutProtection,
+                PROTECTION_PATH_STRING_INNER
+            )
+
+        context.addMockSystemService(CameraManager::class.java, cameraManager)
+
+        cameraAvailabilityListener =
+            CameraAvailabilityListener.Factory.build(context, context.mainExecutor)
+    }
+
+    @Test
+    fun testFrontCamera() {
+        var path: Path? = null
+        var rect: Rect? = null
+        val callback =
+            object : CameraAvailabilityListener.CameraTransitionCallback {
+                override fun onApplyCameraProtection(protectionPath: Path, bounds: Rect) {
+                    path = protectionPath
+                    rect = bounds
+                }
+
+                override fun onHideCameraProtection() {}
+            }
+
+        cameraAvailabilityListener.addTransitionCallback(callback)
+        cameraAvailabilityListener.startListening()
+
+        val callbackCaptor = withArgCaptor {
+            verify(cameraManager).registerAvailabilityCallback(any(Executor::class.java), capture())
+        }
+
+        callbackCaptor.onCameraOpened(CAMERA_ID_FRONT, "")
+        assertNotNull(path)
+        assertEquals(PATH_RECT_FRONT, rect)
+    }
+
+    @Test
+    fun testInnerCamera() {
+        var path: Path? = null
+        var rect: Rect? = null
+        val callback =
+            object : CameraAvailabilityListener.CameraTransitionCallback {
+                override fun onApplyCameraProtection(protectionPath: Path, bounds: Rect) {
+                    path = protectionPath
+                    rect = bounds
+                }
+
+                override fun onHideCameraProtection() {}
+            }
+
+        cameraAvailabilityListener.addTransitionCallback(callback)
+        cameraAvailabilityListener.startListening()
+
+        val callbackCaptor = withArgCaptor {
+            verify(cameraManager).registerAvailabilityCallback(any(Executor::class.java), capture())
+        }
+
+        callbackCaptor.onCameraOpened(CAMERA_ID_INNER, "")
+        assertNotNull(path)
+        assertEquals(PATH_RECT_INNER, rect)
+    }
+
+    @Test
+    fun testExcludedPackage() {
+        cameraAvailabilityListener.addTransitionCallback(cameraTransitionCb)
+        cameraAvailabilityListener.startListening()
+
+        val callbackCaptor = withArgCaptor {
+            verify(cameraManager).registerAvailabilityCallback(any(Executor::class.java), capture())
+        }
+        callbackCaptor.onCameraOpened(CAMERA_ID_FRONT, EXCLUDED_PKG)
+
+        verify(cameraTransitionCb, never())
+            .onApplyCameraProtection(any(Path::class.java), any(Rect::class.java))
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
index 5afc4059357c8b3dc6bde1eccf0e5ed5a4f0a800..ad80a06e3fcd6e0e4903be0fd7d48ae5384389a5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
@@ -29,6 +29,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.keyguard.util.KeyguardTransitionRunner
@@ -86,7 +87,7 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
         }
 
     @Test
-    fun startingSecondTransitionWillCancelTheFirstTransition() =
+    fun startingSecondTransitionWillCancelTheFirstTransitionAndUseLastValue() =
         TestScope().runTest {
             val steps = mutableListOf<TransitionStep>()
             val job = underTest.transition(AOD, LOCKSCREEN).onEach { steps.add(it) }.launchIn(this)
@@ -100,12 +101,19 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
             val job2 = underTest.transition(LOCKSCREEN, AOD).onEach { steps.add(it) }.launchIn(this)
             runner.startTransition(
                 this,
-                TransitionInfo(OWNER_NAME, LOCKSCREEN, AOD, getAnimator()),
+                TransitionInfo(
+                    OWNER_NAME,
+                    LOCKSCREEN,
+                    AOD,
+                    getAnimator(),
+                    TransitionModeOnCanceled.LAST_VALUE
+                ),
             )
 
             val firstTransitionSteps = listWithStep(step = BigDecimal(.1), stop = BigDecimal(.1))
             assertSteps(steps.subList(0, 4), firstTransitionSteps, AOD, LOCKSCREEN)
 
+            // Second transition starts from .1 (LAST_VALUE)
             val secondTransitionSteps = listWithStep(step = BigDecimal(.1), start = BigDecimal(.1))
             assertSteps(steps.subList(4, steps.size), secondTransitionSteps, LOCKSCREEN, AOD)
 
@@ -113,6 +121,76 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
             job2.cancel()
         }
 
+    @Test
+    fun startingSecondTransitionWillCancelTheFirstTransitionAndUseReset() =
+        TestScope().runTest {
+            val steps = mutableListOf<TransitionStep>()
+            val job = underTest.transition(AOD, LOCKSCREEN).onEach { steps.add(it) }.launchIn(this)
+            runner.startTransition(
+                this,
+                TransitionInfo(OWNER_NAME, AOD, LOCKSCREEN, getAnimator()),
+                maxFrames = 3,
+            )
+
+            // Now start 2nd transition, which will interrupt the first
+            val job2 = underTest.transition(LOCKSCREEN, AOD).onEach { steps.add(it) }.launchIn(this)
+            runner.startTransition(
+                this,
+                TransitionInfo(
+                    OWNER_NAME,
+                    LOCKSCREEN,
+                    AOD,
+                    getAnimator(),
+                    TransitionModeOnCanceled.RESET
+                ),
+            )
+
+            val firstTransitionSteps = listWithStep(step = BigDecimal(.1), stop = BigDecimal(.1))
+            assertSteps(steps.subList(0, 4), firstTransitionSteps, AOD, LOCKSCREEN)
+
+            // Second transition starts from 0 (RESET)
+            val secondTransitionSteps = listWithStep(start = BigDecimal(0), step = BigDecimal(.1))
+            assertSteps(steps.subList(4, steps.size), secondTransitionSteps, LOCKSCREEN, AOD)
+
+            job.cancel()
+            job2.cancel()
+        }
+
+    @Test
+    fun startingSecondTransitionWillCancelTheFirstTransitionAndUseReverse() =
+        TestScope().runTest {
+            val steps = mutableListOf<TransitionStep>()
+            val job = underTest.transition(AOD, LOCKSCREEN).onEach { steps.add(it) }.launchIn(this)
+            runner.startTransition(
+                this,
+                TransitionInfo(OWNER_NAME, AOD, LOCKSCREEN, getAnimator()),
+                maxFrames = 3,
+            )
+
+            // Now start 2nd transition, which will interrupt the first
+            val job2 = underTest.transition(LOCKSCREEN, AOD).onEach { steps.add(it) }.launchIn(this)
+            runner.startTransition(
+                this,
+                TransitionInfo(
+                    OWNER_NAME,
+                    LOCKSCREEN,
+                    AOD,
+                    getAnimator(),
+                    TransitionModeOnCanceled.REVERSE
+                ),
+            )
+
+            val firstTransitionSteps = listWithStep(step = BigDecimal(.1), stop = BigDecimal(.1))
+            assertSteps(steps.subList(0, 4), firstTransitionSteps, AOD, LOCKSCREEN)
+
+            // Second transition starts from .9 (REVERSE)
+            val secondTransitionSteps = listWithStep(start = BigDecimal(0.9), step = BigDecimal(.1))
+            assertSteps(steps.subList(4, steps.size), secondTransitionSteps, LOCKSCREEN, AOD)
+
+            job.cancel()
+            job2.cancel()
+        }
+
     @Test
     fun nullAnimatorEnablesManualControlWithUpdateTransition() =
         TestScope().runTest {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index f3930a37c4867f72db9dde540af7690928f84642..275ac804b321f528cdcaf420528f274be2f55056 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -57,7 +57,6 @@ import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
-import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
 import org.mockito.Mockito.clearInvocations
@@ -244,7 +243,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to PRIMARY_BOUNCER should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -271,7 +270,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
@@ -298,7 +297,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
@@ -328,7 +327,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DREAMING should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -359,7 +358,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DREAMING_LOCKSCREEN_HOSTED should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -386,7 +385,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -413,7 +412,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -446,7 +445,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to Lockscreen should occur
             assertThat(info.ownerName).isEqualTo("FromDreamingLockscreenHostedTransitionInteractor")
@@ -474,7 +473,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to Gone should occur
             assertThat(info.ownerName).isEqualTo("FromDreamingLockscreenHostedTransitionInteractor")
@@ -504,7 +503,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to PRIMARY_BOUNCER should occur
             assertThat(info.ownerName).isEqualTo("FromDreamingLockscreenHostedTransitionInteractor")
@@ -537,7 +536,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromDreamingLockscreenHostedTransitionInteractor")
@@ -569,7 +568,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to OCCLUDED should occur
             assertThat(info.ownerName).isEqualTo("FromDreamingLockscreenHostedTransitionInteractor")
@@ -593,7 +592,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
@@ -625,7 +624,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
             advanceUntilIdle()
 
             // THEN the transition is ignored
-            verify(transitionRepository, never()).startTransition(any(), anyBoolean())
+            verify(transitionRepository, never()).startTransition(any())
 
             coroutineContext.cancelChildren()
         }
@@ -642,7 +641,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
@@ -669,7 +668,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -696,7 +695,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to AOD should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -719,7 +718,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to AOD should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -749,7 +748,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DREAMING should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -780,7 +779,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DREAMING_LOCKSCREEN_HOSTED should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -806,7 +805,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to PRIMARY_BOUNCER should occur
             assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -838,7 +837,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to AOD should occur
             assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -871,7 +870,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -901,7 +900,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to LOCKSCREEN should occur
             assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -929,7 +928,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to AOD should occur
             assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -957,7 +956,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -981,7 +980,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to LOCKSCREEN should occur
             assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -1011,7 +1010,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition back to DREAMING_LOCKSCREEN_HOSTED should occur
             assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -1042,7 +1041,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to GONE should occur
             assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
@@ -1071,7 +1070,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to LOCKSCREEN should occur
             assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
@@ -1096,7 +1095,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to AlternateBouncer should occur
             assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
@@ -1121,7 +1120,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to AlternateBouncer should occur
             assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
@@ -1147,7 +1146,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to OCCLUDED should occur
             assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -1172,7 +1171,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to OCCLUDED should occur
             assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
@@ -1199,7 +1198,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to OCCLUDED should occur
             assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
@@ -1223,7 +1222,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to OCCLUDED should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -1253,7 +1252,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             // THEN a transition to OCCLUDED should occur
             assertThat(info.ownerName).isEqualTo("FromAodTransitionInteractor")
@@ -1287,7 +1286,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
             // THEN a transition from LOCKSCREEN => OCCLUDED should occur
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
             assertThat(info.from).isEqualTo(KeyguardState.LOCKSCREEN)
@@ -1318,7 +1317,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
             // THEN a transition from LOCKSCREEN => PRIMARY_BOUNCER should occur
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
             assertThat(info.from).isEqualTo(KeyguardState.LOCKSCREEN)
@@ -1339,7 +1338,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
             // THEN a transition from PRIMARY_BOUNCER => LOCKSCREEN should occur
             val info2 =
                 withArgCaptor<TransitionInfo> {
-                    verify(transitionRepository).startTransition(capture(), anyBoolean())
+                    verify(transitionRepository).startTransition(capture())
                 }
             assertThat(info2.from).isEqualTo(KeyguardState.PRIMARY_BOUNCER)
             assertThat(info2.to).isEqualTo(KeyguardState.LOCKSCREEN)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/util/KeyguardTransitionRunner.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/util/KeyguardTransitionRunner.kt
index 54fc4938e1b0034909b26efb64b1a65533967747..1abb441439fe0c0d6a697d65e37ea53ab51d9870 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/util/KeyguardTransitionRunner.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/util/KeyguardTransitionRunner.kt
@@ -42,7 +42,7 @@ class KeyguardTransitionRunner(
     private var frameCount = 1L
     private var frames = MutableStateFlow(Pair<Long, FrameCallback?>(0L, null))
     private var job: Job? = null
-    private var isTerminated = false
+    @Volatile private var isTerminated = false
 
     /**
      * For transitions being directed by an animator. Will control the number of frames being
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
index 5b3d45bb6625ec4ddf030161c1d7451c55464d1c..ac03073be17badea38dfe202929324b73ed80a20 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -22,11 +22,13 @@ import static junit.framework.Assert.assertTrue;
 
 import static org.junit.Assert.assertFalse;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.Dialog;
 import android.os.Handler;
 import android.service.quicksettings.Tile;
 import android.testing.AndroidTestingRunner;
@@ -35,11 +37,11 @@ import android.testing.TestableLooper;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -48,6 +50,7 @@ import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 import com.android.systemui.screenrecord.RecordingController;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -89,6 +92,10 @@ public class ScreenRecordTileTest extends SysuiTestCase {
     private PanelInteractor mPanelInteractor;
     @Mock
     private QsEventLogger mUiEventLogger;
+    @Mock
+    private MediaProjectionMetricsLogger mMediaProjectionMetricsLogger;
+    @Mock
+    private Dialog mPermissionDialogPrompt;
 
     private TestableLooper mTestableLooper;
     private ScreenRecordTile mTile;
@@ -116,7 +123,8 @@ public class ScreenRecordTileTest extends SysuiTestCase {
                 mKeyguardDismissUtil,
                 mKeyguardStateController,
                 mDialogLaunchAnimator,
-                mPanelInteractor
+                mPanelInteractor,
+                mMediaProjectionMetricsLogger
         );
 
         mTile.initialize();
@@ -280,4 +288,27 @@ public class ScreenRecordTileTest extends SysuiTestCase {
         assertEquals(state.icon, QSTileImpl.ResourceIcon.get(R.drawable.qs_screen_record_icon_off));
     }
 
+    @Test
+    public void showingDialogPrompt_logsMediaProjectionPermissionRequested() {
+        when(mController.isStarting()).thenReturn(false);
+        when(mController.isRecording()).thenReturn(false);
+        when(mController.createScreenRecordDialog(any(), any(), any(), any(), any()))
+                .thenReturn(mPermissionDialogPrompt);
+
+        mTile.handleClick(null /* view */);
+        mTestableLooper.processAllMessages();
+
+        verify(mController).createScreenRecordDialog(any(), eq(mFeatureFlags),
+                eq(mDialogLaunchAnimator), eq(mActivityStarter), any());
+        var onDismissAction = ArgumentCaptor.forClass(ActivityStarter.OnDismissAction.class);
+        verify(mKeyguardDismissUtil).executeWhenUnlocked(
+                onDismissAction.capture(), anyBoolean(), anyBoolean());
+        assertNotNull(onDismissAction.getValue());
+
+        onDismissAction.getValue().onDismiss();
+
+        verify(mPermissionDialogPrompt).show();
+        verify(mMediaProjectionMetricsLogger).notifyPermissionRequestDisplayed();
+    }
+
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt
index f1fcee318141ffbf3dd609cac66dc2488919f2c7..9907278402b0b06da95c886e37c26db18c7f3d84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt
@@ -23,11 +23,14 @@ import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.dump.LogcatEchoTrackerAlways
 import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogBufferFactory
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.qs.pipeline.shared.TileSpec
 import com.android.systemui.qs.tiles.base.interactor.StateUpdateTrigger
 import com.android.systemui.qs.tiles.viewmodel.QSTileState
 import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import java.io.PrintWriter
 import java.io.StringWriter
@@ -42,6 +45,7 @@ import org.mockito.MockitoAnnotations
 class QSTileLoggerTest : SysuiTestCase() {
 
     @Mock private lateinit var statusBarController: StatusBarStateController
+    @Mock private lateinit var logBufferFactory: LogBufferFactory
 
     private val chattyLogBuffer = LogBuffer("TestChatty", 5, LogcatEchoTrackerAlways())
     private val logBuffer = LogBuffer("Test", 1, LogcatEchoTrackerAlways())
@@ -51,10 +55,11 @@ class QSTileLoggerTest : SysuiTestCase() {
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
+        whenever(logBufferFactory.create(any(), any(), any())).thenReturn(logBuffer)
         underTest =
             QSTileLogger(
                 mapOf(TileSpec.create("chatty_tile") to chattyLogBuffer),
-                { logBuffer },
+                logBufferFactory,
                 statusBarController
             )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
index e160548fed78095bcb364a499665aea09e950319..71e2bc1339a66ae2a905c6742c5b57765a10d217 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
@@ -42,7 +42,7 @@ class FakeKeyguardTransitionRepository @Inject constructor() : KeyguardTransitio
         _transitions.emit(step)
     }
 
-    override fun startTransition(info: TransitionInfo, resetIfCanceled: Boolean): UUID? {
+    override fun startTransition(info: TransitionInfo): UUID? {
         return if (info.animator == null) UUID.randomUUID() else null
     }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
index 4307ff980be41b8a8cf8e7af9c83c0edee7f43c7..7494ccf32a2cd693e5ef5ec2a1c5b8b5d1acaa4b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
@@ -69,10 +69,16 @@ class FakeUserTracker(
         _userId = _userInfo.id
         _userHandle = UserHandle.of(_userId)
 
+        onBeforeUserSwitching()
         onUserChanging()
         onUserChanged()
     }
 
+    fun onBeforeUserSwitching(userId: Int = _userId) {
+        val copy = callbacks.toList()
+        copy.forEach { it.onBeforeUserSwitching(userId) }
+    }
+
     fun onUserChanging(userId: Int = _userId) {
         val copy = callbacks.toList()
         copy.forEach { it.onUserChanging(userId, userContext) {} }
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 2d231b3cf42eaba30ba6342f68375103bf4481b6..aa788ebb6ba7833995b39acadc1abb1b326b5587 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -118,6 +118,7 @@ public class SettingsToPropertiesMapper {
     // The list is sorted.
     @VisibleForTesting
     static final String[] sDeviceConfigAconfigScopes = new String[] {
+        "accessibility",
         "android_core_networking",
         "angle",
         "arc_next",
diff --git a/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java b/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java
index 39f0b13f716aa4a32f6e4455ddfae9211acf7e17..200d88a78dd787db89c7c0596d76b9f7536f24a8 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java
@@ -24,7 +24,6 @@ import android.os.PowerManager;
 import android.view.SurfaceControlHdrLayerInfoListener;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.display.BrightnessUtils;
 import com.android.server.display.config.HdrBrightnessData;
 
 import java.io.PrintWriter;
@@ -176,21 +175,14 @@ public class HdrClamper {
         } else if (mDesiredMaxBrightness != expectedMaxBrightness) {
             mDesiredMaxBrightness = expectedMaxBrightness;
             long debounceTime;
-            long transitionDuration;
             if (mDesiredMaxBrightness > mMaxBrightness) {
                 debounceTime = mHdrBrightnessData.mBrightnessIncreaseDebounceMillis;
-                transitionDuration = mHdrBrightnessData.mBrightnessIncreaseDurationMillis;
+                mDesiredTransitionRate = mHdrBrightnessData.mScreenBrightnessRampIncrease;
             } else {
                 debounceTime = mHdrBrightnessData.mBrightnessDecreaseDebounceMillis;
-                transitionDuration = mHdrBrightnessData.mBrightnessDecreaseDurationMillis;
+                mDesiredTransitionRate = mHdrBrightnessData.mScreenBrightnessRampDecrease;
             }
 
-            float maxHlg = BrightnessUtils.convertLinearToGamma(mMaxBrightness);
-            float desiredMaxHlg = BrightnessUtils.convertLinearToGamma(mDesiredMaxBrightness);
-
-            mDesiredTransitionRate = Math.abs(
-                    (maxHlg - desiredMaxHlg) * 1000f / transitionDuration);
-
             mHandler.removeCallbacks(mDebouncer);
             mHandler.postDelayed(mDebouncer, debounceTime);
         }
diff --git a/services/core/java/com/android/server/display/config/HdrBrightnessData.java b/services/core/java/com/android/server/display/config/HdrBrightnessData.java
index 48d671d356f7a559fb6cbfa659b8f70d048ad9ca..837fbf7ca17c0894d4773e7eb0e125ee1fc6da3b 100644
--- a/services/core/java/com/android/server/display/config/HdrBrightnessData.java
+++ b/services/core/java/com/android/server/display/config/HdrBrightnessData.java
@@ -40,9 +40,9 @@ public class HdrBrightnessData {
     public final long mBrightnessIncreaseDebounceMillis;
 
     /**
-     * Brightness increase animation duration
+     * Brightness increase animation speed
      */
-    public final long mBrightnessIncreaseDurationMillis;
+    public final float mScreenBrightnessRampIncrease;
 
     /**
      * Debounce time for brightness decrease
@@ -50,19 +50,19 @@ public class HdrBrightnessData {
     public final long mBrightnessDecreaseDebounceMillis;
 
     /**
-     * Brightness decrease animation duration
+     * Brightness decrease animation speed
      */
-    public final long mBrightnessDecreaseDurationMillis;
+    public final float mScreenBrightnessRampDecrease;
 
     @VisibleForTesting
     public HdrBrightnessData(Map<Float, Float> maxBrightnessLimits,
-            long brightnessIncreaseDebounceMillis, long brightnessIncreaseDurationMillis,
-            long brightnessDecreaseDebounceMillis, long brightnessDecreaseDurationMillis) {
+            long brightnessIncreaseDebounceMillis, float screenBrightnessRampIncrease,
+            long brightnessDecreaseDebounceMillis, float screenBrightnessRampDecrease) {
         mMaxBrightnessLimits = maxBrightnessLimits;
         mBrightnessIncreaseDebounceMillis = brightnessIncreaseDebounceMillis;
-        mBrightnessIncreaseDurationMillis = brightnessIncreaseDurationMillis;
+        mScreenBrightnessRampIncrease = screenBrightnessRampIncrease;
         mBrightnessDecreaseDebounceMillis = brightnessDecreaseDebounceMillis;
-        mBrightnessDecreaseDurationMillis = brightnessDecreaseDurationMillis;
+        mScreenBrightnessRampDecrease = screenBrightnessRampDecrease;
     }
 
     @Override
@@ -70,9 +70,9 @@ public class HdrBrightnessData {
         return "HdrBrightnessData {"
                 + "mMaxBrightnessLimits: " + mMaxBrightnessLimits
                 + ", mBrightnessIncreaseDebounceMillis: " + mBrightnessIncreaseDebounceMillis
-                + ", mBrightnessIncreaseDurationMillis: " + mBrightnessIncreaseDurationMillis
+                + ", mScreenBrightnessRampIncrease: " + mScreenBrightnessRampIncrease
                 + ", mBrightnessDecreaseDebounceMillis: " + mBrightnessDecreaseDebounceMillis
-                + ", mBrightnessDecreaseDurationMillis: " + mBrightnessDecreaseDurationMillis
+                + ", mScreenBrightnessRampDecrease: " + mScreenBrightnessRampDecrease
                 + "} ";
     }
 
@@ -94,8 +94,8 @@ public class HdrBrightnessData {
 
         return new HdrBrightnessData(brightnessLimits,
                 hdrConfig.getBrightnessIncreaseDebounceMillis().longValue(),
-                hdrConfig.getBrightnessIncreaseDurationMillis().longValue(),
+                hdrConfig.getScreenBrightnessRampIncrease().floatValue(),
                 hdrConfig.getBrightnessDecreaseDebounceMillis().longValue(),
-                hdrConfig.getBrightnessDecreaseDurationMillis().longValue());
+                hdrConfig.getScreenBrightnessRampDecrease().floatValue());
     }
 }
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index f168f435b5d7d77c7bc82f0a35aae01abe89bb24..f35b045471a66dfb8736aa42a8622256d08bfd3c 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -240,6 +240,10 @@ public class LockSettingsService extends ILockSettings.Stub {
     private static final String LSKF_LAST_CHANGED_TIME_KEY = "sp-handle-ts";
     private static final String USER_SERIAL_NUMBER_KEY = "serial-number";
 
+    private static final String MIGRATED_FRP2 = "migrated_frp2";
+    private static final String MIGRATED_KEYSTORE_NS = "migrated_keystore_namespace";
+    private static final String MIGRATED_SP_CE_ONLY = "migrated_all_users_to_sp_and_bound_ce";
+
     // Duration that LockSettingsService will store the gatekeeper password for. This allows
     // multiple biometric enrollments without prompting the user to enter their password via
     // ConfirmLockPassword/ConfirmLockPattern multiple times. This needs to be at least the duration
@@ -909,14 +913,14 @@ public class LockSettingsService extends ILockSettings.Stub {
     }
 
     private void migrateOldData() {
-        if (getString("migrated_keystore_namespace", null, 0) == null) {
+        if (getString(MIGRATED_KEYSTORE_NS, null, 0) == null) {
             boolean success = true;
             synchronized (mSpManager) {
                 success &= mSpManager.migrateKeyNamespace();
             }
             success &= migrateProfileLockKeys();
             if (success) {
-                setString("migrated_keystore_namespace", "true", 0);
+                setString(MIGRATED_KEYSTORE_NS, "true", 0);
                 Slog.i(TAG, "Migrated keys to LSS namespace");
             } else {
                 Slog.w(TAG, "Failed to migrate keys to LSS namespace");
@@ -936,9 +940,9 @@ public class LockSettingsService extends ILockSettings.Stub {
         // "migrated_frp" to "migrated_frp2" to cause migrateFrpCredential() to run again on devices
         // where it had run before.
         if (LockPatternUtils.frpCredentialEnabled(mContext)
-                && !getBoolean("migrated_frp2", false, 0)) {
+                && !getBoolean(MIGRATED_FRP2, false, 0)) {
             migrateFrpCredential();
-            setBoolean("migrated_frp2", true, 0);
+            setBoolean(MIGRATED_FRP2, true, 0);
         }
     }
 
@@ -1028,14 +1032,14 @@ public class LockSettingsService extends ILockSettings.Stub {
             // If this gets interrupted (e.g. by the device powering off), there shouldn't be a
             // problem since this will run again on the next boot, and setUserKeyProtection() is
             // okay with the key being already protected by the given secret.
-            if (getString("migrated_all_users_to_sp_and_bound_ce", null, 0) == null) {
+            if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null) {
                 for (UserInfo user : mUserManager.getAliveUsers()) {
                     removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber);
                     synchronized (mSpManager) {
                         migrateUserToSpWithBoundCeKeyLocked(user.id);
                     }
                 }
-                setString("migrated_all_users_to_sp_and_bound_ce", "true", 0);
+                setString(MIGRATED_SP_CE_ONLY, "true", 0);
             }
 
             mThirdPartyAppsStarted = true;
@@ -1062,7 +1066,7 @@ public class LockSettingsService extends ILockSettings.Stub {
                 Slogf.wtf(TAG, "Failed to unwrap synthetic password for unsecured user %d", userId);
                 return;
             }
-            setUserKeyProtection(userId, result.syntheticPassword.deriveFileBasedEncryptionKey());
+            setUserKeyProtection(userId, result.syntheticPassword);
         }
     }
 
@@ -1347,8 +1351,8 @@ public class LockSettingsService extends ILockSettings.Stub {
         AndroidKeyStoreMaintenance.onUserPasswordChanged(userHandle, password);
     }
 
-    private void unlockKeystore(byte[] password, int userHandle) {
-        Authorization.onLockScreenEvent(false, userHandle, password, null);
+    private void unlockKeystore(int userId, SyntheticPassword sp) {
+        Authorization.onLockScreenEvent(false, userId, sp.deriveKeyStorePassword(), null);
     }
 
     @VisibleForTesting /** Note: this method is overridden in unit tests */
@@ -2001,7 +2005,8 @@ public class LockSettingsService extends ILockSettings.Stub {
         mStorage.writeChildProfileLock(profileUserId, ArrayUtils.concat(iv, ciphertext));
     }
 
-    private void setUserKeyProtection(@UserIdInt int userId, byte[] secret) {
+    private void setUserKeyProtection(@UserIdInt int userId, SyntheticPassword sp) {
+        final byte[] secret = sp.deriveFileBasedEncryptionKey();
         final long callingId = Binder.clearCallingIdentity();
         try {
             mStorageManager.setUserKeyProtection(userId, secret);
@@ -2045,7 +2050,9 @@ public class LockSettingsService extends ILockSettings.Stub {
         }
     }
 
-    private void unlockUserKeyIfUnsecured(@UserIdInt int userId) {
+    @Override
+    public void unlockUserKeyIfUnsecured(@UserIdInt int userId) {
+        checkPasswordReadPermission();
         synchronized (mSpManager) {
             if (isUserKeyUnlocked(userId)) {
                 Slogf.d(TAG, "CE storage for user %d is already unlocked", userId);
@@ -2768,7 +2775,7 @@ public class LockSettingsService extends ILockSettings.Stub {
             final long protectorId = mSpManager.createLskfBasedProtector(getGateKeeperService(),
                     LockscreenCredential.createNone(), sp, userId);
             setCurrentLskfBasedProtectorId(protectorId, userId);
-            setUserKeyProtection(userId, sp.deriveFileBasedEncryptionKey());
+            setUserKeyProtection(userId, sp);
             onSyntheticPasswordCreated(userId, sp);
             Slogf.i(TAG, "Successfully initialized synthetic password for user %d", userId);
             return sp;
@@ -2827,7 +2834,7 @@ public class LockSettingsService extends ILockSettings.Stub {
             }
         }
 
-        unlockKeystore(sp.deriveKeyStorePassword(), userId);
+        unlockKeystore(userId, sp);
 
         unlockUserKey(userId, sp);
 
@@ -2894,7 +2901,7 @@ public class LockSettingsService extends ILockSettings.Stub {
             mSpManager.clearSidForUser(userId);
             gateKeeperClearSecureUserId(userId);
             unlockUserKey(userId, sp);
-            unlockKeystore(sp.deriveKeyStorePassword(), userId);
+            unlockKeystore(userId, sp);
             setKeystorePassword(null, userId);
             removeBiometricsForUser(userId);
         }
@@ -3453,11 +3460,6 @@ public class LockSettingsService extends ILockSettings.Stub {
             LockSettingsService.this.onThirdPartyAppsStarted();
         }
 
-        @Override
-        public void unlockUserKeyIfUnsecured(@UserIdInt int userId) {
-            LockSettingsService.this.unlockUserKeyIfUnsecured(userId);
-        }
-
         @Override
         public void createNewUser(@UserIdInt int userId, int userSerialNumber) {
             LockSettingsService.this.createNewUser(userId, userSerialNumber);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
index df95c69e7271cefce1b4f8ab0cfb822b2ba105f6..4bac872dbaa9674e85ad31da2518b0d2a8d06f2b 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
@@ -174,7 +174,7 @@ class LockSettingsShellCommand extends ShellCommand {
             pw.println("    Sets the lock screen as PIN, using the given PIN to unlock.");
             pw.println("");
             pw.println("  set-password [--old <CREDENTIAL>] [--user USER_ID] <PASSWORD>");
-            pw.println("    Sets the lock screen as password, using the given PASSOWRD to unlock.");
+            pw.println("    Sets the lock screen as password, using the given PASSWORD to unlock.");
             pw.println("");
             pw.println("  clear [--old <CREDENTIAL>] [--user USER_ID]");
             pw.println("    Clears the lock credentials.");
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 0e8f90795ef930a82cea2be5cee199a4f2b7b1d3..2c595116afed5a90b421b67d62e99a8d8140b557 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -268,7 +268,14 @@ public class MediaSessionService extends SystemService implements Monitor {
             }
             if (record.isSystemPriority()) {
                 if (DEBUG_KEY_EVENT) {
-                    Log.d(TAG, "Global priority session is updated, active=" + record.isActive());
+                    Log.d(
+                            TAG,
+                            "Global priority session updated - user id="
+                                    + record.getUserId()
+                                    + " package="
+                                    + record.getPackageName()
+                                    + " active="
+                                    + record.isActive());
                 }
                 user.pushAddressedPlayerChangedLocked();
             } else {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 839b6998bd8b60708223125c41589befad7090e8..61b6b24ba97e04f40412db504ce8e10a2c945190 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4566,6 +4566,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                 final Bundle extras = new Bundle();
                 extras.putInt(Intent.EXTRA_UID, pmi.getPackageUid(packageName, 0, userId));
                 extras.putInt(Intent.EXTRA_USER_HANDLE, userId);
+                extras.putLong(Intent.EXTRA_TIME, SystemClock.elapsedRealtime());
                 mHandler.post(() -> {
                     mBroadcastHelper.sendPackageBroadcast(Intent.ACTION_PACKAGE_UNSTOPPED,
                             packageName, extras,
@@ -6969,6 +6970,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
             final Bundle extras = new Bundle();
             extras.putInt(Intent.EXTRA_UID, uid);
             extras.putInt(Intent.EXTRA_USER_HANDLE, userId);
+            extras.putLong(Intent.EXTRA_TIME, SystemClock.elapsedRealtime());
             mHandler.post(() -> {
                 mBroadcastHelper.sendPackageBroadcast(Intent.ACTION_PACKAGE_RESTARTED,
                         packageName, extras,
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 3ca933a66656d90f6bac58d3e0cff7800037e871..42f4cfb8b4dfa084f4e65ce072a27e68250b27b2 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -238,34 +238,16 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
     }
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    public PackageSetting(String name, String realName, @NonNull File path,
-            String legacyNativeLibraryPath, String primaryCpuAbi,
-            String secondaryCpuAbi, String cpuAbiOverride,
-            long longVersionCode, int pkgFlags, int pkgPrivateFlags,
-            int sharedUserAppId,
-            String[] usesSdkLibraries, long[] usesSdkLibrariesVersionsMajor,
-            String[] usesStaticLibraries, long[] usesStaticLibrariesVersions,
-            Map<String, Set<String>> mimeGroups,
-            @NonNull UUID domainSetId) {
+    public PackageSetting(@NonNull String name, @Nullable String realName, @NonNull File path,
+                          int pkgFlags, int pkgPrivateFlags, @NonNull UUID domainSetId) {
         super(pkgFlags, pkgPrivateFlags);
         this.mName = name;
         this.mRealName = realName;
-        this.usesSdkLibraries = usesSdkLibraries;
-        this.usesSdkLibrariesVersionsMajor = usesSdkLibrariesVersionsMajor;
-        this.usesStaticLibraries = usesStaticLibraries;
-        this.usesStaticLibrariesVersions = usesStaticLibrariesVersions;
         this.mPath = path;
         this.mPathString = path.toString();
-        this.legacyNativeLibraryPath = legacyNativeLibraryPath;
-        this.mPrimaryCpuAbi = primaryCpuAbi;
-        this.mSecondaryCpuAbi = secondaryCpuAbi;
-        this.mCpuAbiOverride = cpuAbiOverride;
-        this.versionCode = longVersionCode;
         this.signatures = new PackageSignatures();
         this.installSource = InstallSource.EMPTY;
-        this.mSharedUserAppId = sharedUserAppId;
-        mDomainSetId = domainSetId;
-        copyMimeGroups(mimeGroups);
+        this.mDomainSetId = domainSetId;
         mSnapshot = makeCache();
     }
 
@@ -536,9 +518,10 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
         return this;
     }
 
-    public void setSharedUserAppId(int sharedUserAppId) {
+    public PackageSetting setSharedUserAppId(int sharedUserAppId) {
         mSharedUserAppId = sharedUserAppId;
         onChanged();
+        return this;
     }
 
     public PackageSetting setIsPersistent(boolean isPersistent) {
@@ -576,7 +559,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
                 + " " + mName + "/" + mAppId + "}";
     }
 
-    protected void copyMimeGroups(@Nullable Map<String, Set<String>> newMimeGroups) {
+    private void copyMimeGroups(@Nullable Map<String, Set<String>> newMimeGroups) {
         if (newMimeGroups == null) {
             mimeGroups = null;
             return;
@@ -1250,7 +1233,8 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
     /**
      * @see #mPath
      */
-    PackageSetting setPath(@NonNull File path) {
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public PackageSetting setPath(@NonNull File path) {
         this.mPath = path;
         this.mPathString = path.toString();
         onChanged();
@@ -1451,9 +1435,11 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
         return this;
     }
 
-    public PackageSetting setMimeGroups(@NonNull Map<String, Set<String>> mimeGroups) {
-        this.mimeGroups = mimeGroups;
-        onChanged();
+    public PackageSetting setMimeGroups(@Nullable Map<String, Set<String>> mimeGroups) {
+        if (mimeGroups != null) {
+            copyMimeGroups(mimeGroups);
+            onChanged();
+        }
         return this;
     }
 
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index e726d91c30a0e0090dc9946ab30f6a20f6f4f3e6..a39178ec4baa84a41664d5450c461e3adc6c8001 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -931,16 +931,24 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
             sharedUserSetting.mDisabledPackages.remove(p);
         }
         p.getPkgState().setUpdatedSystemApp(false);
-        PackageSetting ret = addPackageLPw(name, p.getRealName(), p.getPath(),
-                p.getLegacyNativeLibraryPath(), p.getPrimaryCpuAbiLegacy(),
-                p.getSecondaryCpuAbiLegacy(), p.getCpuAbiOverride(),
-                p.getAppId(), p.getVersionCode(), p.getFlags(), p.getPrivateFlags(),
-                p.getUsesSdkLibraries(), p.getUsesSdkLibrariesVersionsMajor(),
-                p.getUsesStaticLibraries(), p.getUsesStaticLibrariesVersions(), p.getMimeGroups(),
-                mDomainVerificationManager.generateNewId());
+        PackageSetting ret = addPackageLPw(name, p.getRealName(), p.getPath(), p.getAppId(),
+                p.getFlags(), p.getPrivateFlags(), mDomainVerificationManager.generateNewId());
         if (ret != null) {
+            ret.setLegacyNativeLibraryPath(p.getLegacyNativeLibraryPath());
+            ret.setPrimaryCpuAbi(p.getPrimaryCpuAbiLegacy());
+            ret.setSecondaryCpuAbi(p.getSecondaryCpuAbiLegacy());
+            ret.setCpuAbiOverride(p.getCpuAbiOverride());
+            ret.setLongVersionCode(p.getVersionCode());
+            ret.setUsesSdkLibraries(p.getUsesSdkLibraries());
+            ret.setUsesSdkLibrariesVersionsMajor(p.getUsesSdkLibrariesVersionsMajor());
+            ret.setUsesStaticLibraries(p.getUsesStaticLibraries());
+            ret.setUsesStaticLibrariesVersions(p.getUsesStaticLibrariesVersions());
+            ret.setMimeGroups(p.getMimeGroups());
             ret.setAppMetadataFilePath(p.getAppMetadataFilePath());
             ret.getPkgState().setUpdatedSystemApp(false);
+            ret.setIsPersistent(p.isPersistent());
+            ret.setTargetSdkVersion(p.getTargetSdkVersion());
+            ret.setRestrictUpdateHash(p.getRestrictUpdateHash());
         }
         mDisabledSysPackages.remove(name);
         return ret;
@@ -961,13 +969,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
         }
     }
 
-    PackageSetting addPackageLPw(String name, String realName, File codePath,
-            String legacyNativeLibraryPathString, String primaryCpuAbiString,
-            String secondaryCpuAbiString, String cpuAbiOverrideString, int uid, long vc,
-            int pkgFlags, int pkgPrivateFlags, String[] usesSdkLibraries,
-            long[] usesSdkLibrariesVersions, String[] usesStaticLibraries,
-            long[] usesStaticLibrariesVersions, Map<String, Set<String>> mimeGroups,
-            @NonNull UUID domainSetId) {
+    PackageSetting addPackageLPw(String name, String realName, File codePath, int uid, int pkgFlags,
+                                 int pkgPrivateFlags, @NonNull UUID domainSetId) {
         PackageSetting p = mPackages.get(name);
         if (p != null) {
             if (p.getAppId() == uid) {
@@ -977,11 +980,8 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
                     "Adding duplicate package, keeping first: " + name);
             return null;
         }
-        p = new PackageSetting(name, realName, codePath, legacyNativeLibraryPathString,
-                primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, vc, pkgFlags,
-                pkgPrivateFlags, 0 /*userId*/, usesSdkLibraries, usesSdkLibrariesVersions,
-                usesStaticLibraries, usesStaticLibrariesVersions, mimeGroups, domainSetId);
-        p.setAppId(uid);
+        p = new PackageSetting(name, realName, codePath, pkgFlags, pkgPrivateFlags, domainSetId)
+                .setAppId(uid);
         if (mAppIds.registerExistingAppId(uid, p, name)) {
             mPackages.put(name, p);
             return p;
@@ -1092,16 +1092,21 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
             int installUserId = installUser != null ? installUser.getIdentifier()
                     : UserHandle.USER_SYSTEM;
 
-            pkgSetting = new PackageSetting(pkgName, realPkgName, codePath,
-                    legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
-                    null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
-                    0 /*sharedUserAppId*/, usesSdkLibraries, usesSdkLibrariesVersions,
-                    usesStaticLibraries, usesStaticLibrariesVersions,
-                    createMimeGroups(mimeGroupNames), domainSetId)
+            pkgSetting = new PackageSetting(pkgName, realPkgName, codePath, pkgFlags,
+                    pkgPrivateFlags, domainSetId)
+                    .setUsesSdkLibraries(usesSdkLibraries)
+                    .setUsesSdkLibrariesVersionsMajor(usesSdkLibrariesVersions)
+                    .setUsesStaticLibraries(usesStaticLibraries)
+                    .setUsesStaticLibrariesVersions(usesStaticLibrariesVersions)
+                    .setLegacyNativeLibraryPath(legacyNativeLibraryPath)
+                    .setPrimaryCpuAbi(primaryCpuAbi)
+                    .setSecondaryCpuAbi(secondaryCpuAbi)
+                    .setLongVersionCode(versionCode)
+                    .setMimeGroups(createMimeGroups(mimeGroupNames))
                     .setIsPersistent(isPersistent)
                     .setTargetSdkVersion(targetSdkVersion)
-                    .setRestrictUpdateHash(restrictUpdatedHash);
-            pkgSetting.setLastModifiedTime(codePath.lastModified());
+                    .setRestrictUpdateHash(restrictUpdatedHash)
+                    .setLastModifiedTime(codePath.lastModified());
             if (sharedUser != null) {
                 pkgSetting.setSharedUserAppId(sharedUser.mAppId);
             }
@@ -3066,6 +3071,12 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
         serializer.attributeLongHex(null, "ft", pkg.getLastModifiedTime());
         serializer.attributeLongHex(null, "ut", pkg.getLastUpdateTime());
         serializer.attributeLong(null, "version", pkg.getVersionCode());
+        serializer.attributeBoolean(null, "isPersistent", pkg.isPersistent());
+        serializer.attributeInt(null, "targetSdkVersion", pkg.getTargetSdkVersion());
+        if (pkg.getRestrictUpdateHash() != null) {
+            serializer.attributeBytesBase64(null, "restrictUpdateHash",
+                    pkg.getRestrictUpdateHash());
+        }
         if (pkg.getLegacyNativeLibraryPath() != null) {
             serializer.attribute(null, "nativeLibraryPath", pkg.getLegacyNativeLibraryPath());
         }
@@ -3129,6 +3140,12 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
         serializer.attributeLongHex(null, "ft", pkg.getLastModifiedTime());
         serializer.attributeLongHex(null, "ut", pkg.getLastUpdateTime());
         serializer.attributeLong(null, "version", pkg.getVersionCode());
+        serializer.attributeBoolean(null, "isPersistent", pkg.isPersistent());
+        serializer.attributeInt(null, "targetSdkVersion", pkg.getTargetSdkVersion());
+        if (pkg.getRestrictUpdateHash() != null) {
+            serializer.attributeBytesBase64(null, "restrictUpdateHash",
+                    pkg.getRestrictUpdateHash());
+        }
         if (!pkg.hasSharedUser()) {
             serializer.attributeInt(null, "userId", pkg.getAppId());
         } else {
@@ -3861,6 +3878,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
         }
 
         long versionCode = parser.getAttributeLong(null, "version", 0);
+        boolean isPersistent = parser.getAttributeBoolean(null, "isPersistent", false);
+        int targetSdkVersion = parser.getAttributeInt(null, "targetSdkVersion", 0);
+        byte[] restrictUpdateHash = parser.getAttributeBytesBase64(null, "restrictUpdateHash",
+                null);
 
         int pkgFlags = 0;
         int pkgPrivateFlags = 0;
@@ -3873,10 +3894,16 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
         // debug invalid entries. The actual logic for migrating to a new ID is done in other
         // methods that use DomainVerificationManagerInternal#generateNewId
         UUID domainSetId = DomainVerificationManagerInternal.DISABLED_ID;
-        PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr),
-                legacyNativeLibraryPathStr, primaryCpuAbiStr, secondaryCpuAbiStr, cpuAbiOverrideStr,
-                versionCode, pkgFlags, pkgPrivateFlags, 0 /*sharedUserAppId*/, null, null, null,
-                null, null, domainSetId);
+        PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr), pkgFlags,
+                pkgPrivateFlags, domainSetId)
+                .setLegacyNativeLibraryPath(legacyNativeLibraryPathStr)
+                .setPrimaryCpuAbi(primaryCpuAbiStr)
+                .setSecondaryCpuAbi(secondaryCpuAbiStr)
+                .setCpuAbiOverride(cpuAbiOverrideStr)
+                .setLongVersionCode(versionCode)
+                .setIsPersistent(isPersistent)
+                .setTargetSdkVersion(targetSdkVersion)
+                .setRestrictUpdateHash(restrictUpdateHash);
         long timeStamp = parser.getAttributeLongHex(null, "ft", 0);
         if (timeStamp == 0) {
             timeStamp = parser.getAttributeLong(null, "ts", 0);
@@ -3970,6 +3997,9 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
         long loadingCompletedTime = 0;
         UUID domainSetId;
         String appMetadataFilePath = null;
+        boolean isPersistent = false;
+        int targetSdkVersion = 0;
+        byte[] restrictUpdateHash = null;
         try {
             name = parser.getAttributeValue(null, ATTR_NAME);
             realName = parser.getAttributeValue(null, "realName");
@@ -3993,6 +4023,9 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
             }
 
             versionCode = parser.getAttributeLong(null, "version", 0);
+            isPersistent = parser.getAttributeBoolean(null, "isPersistent", false);
+            targetSdkVersion = parser.getAttributeInt(null, "targetSdkVersion", 0);
+            restrictUpdateHash = parser.getAttributeBytesBase64(null, "restrictUpdateHash", null);
             installerPackageName = parser.getAttributeValue(null, "installer");
             installerPackageUid = parser.getAttributeInt(null, "installerUid", INVALID_UID);
             updateOwnerPackageName = parser.getAttributeValue(null, "updateOwner");
@@ -4088,11 +4121,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
                                 + parser.getPositionDescription());
             } else if (appId > 0) {
                 packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
-                        legacyNativeLibraryPathStr, primaryCpuAbiString, secondaryCpuAbiString,
-                        cpuAbiOverrideString, appId, versionCode, pkgFlags, pkgPrivateFlags,
-                        null /* usesSdkLibraries */, null /* usesSdkLibraryVersions */,
-                        null /* usesStaticLibraries */, null /* usesStaticLibraryVersions */,
-                        null /* mimeGroups */, domainSetId);
+                        appId, pkgFlags, pkgPrivateFlags, domainSetId);
                 if (PackageManagerService.DEBUG_SETTINGS)
                     Log.i(PackageManagerService.TAG, "Reading package " + name + ": appId="
                             + appId + " pkg=" + packageSetting);
@@ -4101,22 +4130,26 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
                             + appId + " while parsing settings at "
                             + parser.getPositionDescription());
                 } else {
+                    packageSetting.setLegacyNativeLibraryPath(legacyNativeLibraryPathStr);
+                    packageSetting.setPrimaryCpuAbi(primaryCpuAbiString);
+                    packageSetting.setSecondaryCpuAbi(secondaryCpuAbiString);
+                    packageSetting.setCpuAbiOverride(cpuAbiOverrideString);
+                    packageSetting.setLongVersionCode(versionCode);
                     packageSetting.setLastModifiedTime(timeStamp);
                     packageSetting.setLastUpdateTime(lastUpdateTime);
                 }
             } else if (sharedUserAppId != 0) {
                 if (sharedUserAppId > 0) {
                     packageSetting = new PackageSetting(name.intern(), realName,
-                            new File(codePathStr), legacyNativeLibraryPathStr,
-                            primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
-                            versionCode, pkgFlags, pkgPrivateFlags, sharedUserAppId,
-                            null /* usesSdkLibraries */,
-                            null /* usesSdkLibrariesVersions */,
-                            null /* usesStaticLibraries */,
-                            null /* usesStaticLibraryVersions */,
-                            null /* mimeGroups */, domainSetId);
-                    packageSetting.setLastModifiedTime(timeStamp);
-                    packageSetting.setLastUpdateTime(lastUpdateTime);
+                            new File(codePathStr), pkgFlags, pkgPrivateFlags, domainSetId)
+                            .setLegacyNativeLibraryPath(legacyNativeLibraryPathStr)
+                            .setPrimaryCpuAbi(primaryCpuAbiString)
+                            .setSecondaryCpuAbi(secondaryCpuAbiString)
+                            .setCpuAbiOverride(cpuAbiOverrideString)
+                            .setLongVersionCode(versionCode)
+                            .setSharedUserAppId(sharedUserAppId)
+                            .setLastModifiedTime(timeStamp)
+                            .setLastUpdateTime(lastUpdateTime);
                     mPendingPackages.add(packageSetting);
                     if (PackageManagerService.DEBUG_SETTINGS)
                         Log.i(PackageManagerService.TAG, "Reading package " + name
@@ -4155,7 +4188,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
                     .setForceQueryableOverride(installedForceQueryable)
                     .setLoadingProgress(loadingProgress)
                     .setLoadingCompletedTime(loadingCompletedTime)
-                    .setAppMetadataFilePath(appMetadataFilePath);
+                    .setAppMetadataFilePath(appMetadataFilePath)
+                    .setIsPersistent(isPersistent)
+                    .setTargetSdkVersion(targetSdkVersion)
+                    .setRestrictUpdateHash(restrictUpdateHash);
             // Handle legacy string here for single-user mode
             final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
             if (enabledStr != null) {
@@ -4916,9 +4952,11 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
         }
         pw.print(prefix); pw.print("  versionCode="); pw.print(ps.getVersionCode());
         if (pkg != null) {
-            pw.print(" minSdk="); pw.print(pkg.getMinSdkVersion());
-            pw.print(" targetSdk="); pw.println(pkg.getTargetSdkVersion());
-
+            pw.print(" minSdk=");
+            pw.print(pkg.getMinSdkVersion());
+        }
+        pw.print(" targetSdk="); pw.println(ps.getTargetSdkVersion());
+        if (pkg != null) {
             SparseIntArray minExtensionVersions = pkg.getMinExtensionVersions();
 
             pw.print(prefix); pw.print("  minExtensionVersions=[");
diff --git a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
index 99878679431c932aecdaea22ef3b96c58025d237..585e2e48fb854e677c01f09443e608c38d1d3021 100644
--- a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
+++ b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import static android.content.pm.Flags.sdkLibIndependence;
 import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
 import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_LIBRARY_BAD_CERTIFICATE_DIGEST;
 
@@ -951,10 +952,12 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable
             }
         }
         if (!pkg.getUsesSdkLibraries().isEmpty()) {
+            // Allow installation even if sdk-library dependency doesn't exist
+            boolean required = !sdkLibIndependence();
             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesSdkLibraries(),
                     pkg.getUsesSdkLibrariesVersionsMajor(), pkg.getUsesSdkLibrariesCertDigests(),
-                    pkg.getPackageName(), "sdk", true, pkg.getTargetSdkVersion(), usesLibraryInfos,
-                    availablePackages, newLibraries);
+                    pkg.getPackageName(), "sdk", required, pkg.getTargetSdkVersion(),
+                    usesLibraryInfos, availablePackages, newLibraries);
         }
         return usesLibraryInfos;
     }
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index d6e35e8b1fd3653697d93ef3db8ed2cdb8c411bd..a33e3532153b64129ae3931e92f2c46f0f3ff846 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -347,8 +347,15 @@ public final class PermissionPolicyService extends SystemService {
                 UserHandle user = UserHandle.getUserHandleForUid(uid);
                 PermissionControllerManager manager = mPermControllerManagers.get(user);
                 if (manager == null) {
-                    manager = new PermissionControllerManager(
-                            getUserContext(getContext(), user), PermissionThread.getHandler());
+                    try {
+                        manager = new PermissionControllerManager(
+                                getUserContext(getContext(), user), PermissionThread.getHandler());
+                    } catch (IllegalArgumentException exception) {
+                        // There's a possible race condition when a user is being removed
+                        Log.e(LOG_TAG, "Could not create PermissionControllerManager for user"
+                                        + user, exception);
+                        return;
+                    }
                     mPermControllerManagers.put(user, manager);
                 }
                 manager.updateUserSensitiveForApp(uid);
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index 1d5cac54d12bf65b18afd92a29345012091ed9dd..7f55836598b5feec677f78740189ff85e59e75cf 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -833,18 +833,24 @@ final class VibrationSettings {
         private final SparseArray<Integer> mProcStatesCache = new SparseArray<>();
 
         public boolean isUidForeground(int uid) {
-            return mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)
-                    <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+            synchronized (this) {
+                return mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)
+                        <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+            }
         }
 
         @Override
         public void onUidGone(int uid, boolean disabled) {
-            mProcStatesCache.delete(uid);
+            synchronized (this) {
+                mProcStatesCache.delete(uid);
+            }
         }
 
         @Override
         public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
-            mProcStatesCache.put(uid, procState);
+            synchronized (this) {
+                mProcStatesCache.put(uid, procState);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index a01113b26a1e019aecbc86194c88edfa8963fc49..9fa5ed2cfde97a45bc2716c810739b94d03df752 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4030,6 +4030,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
         if (mAppStopped) {
             abortAndClearOptionsAnimation();
         }
+        if (mDisplayContent != null) {
+            mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
+        }
     }
 
     boolean isFinishing() {
@@ -5388,12 +5391,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
         mLastDeferHidingClient = deferHidingClient;
 
         if (!visible) {
-            // If this activity is about to finish/stopped and now becomes invisible, remove it
-            // from the unknownApp list in case the activity does not want to draw anything, which
-            // keep the user waiting for the next transition to start.
-            if (finishing || isState(STOPPED)) {
-                displayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
-            }
             // Because starting window was transferred, this activity may be a trampoline which has
             // been occluded by next activity. If it has added windows, set client visibility
             // immediately to avoid the client getting RELAYOUT_RES_FIRST_TIME from relayout and
@@ -5837,6 +5834,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                 break;
             case STOPPED:
                 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
+                if (mDisplayContent != null) {
+                    mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
+                }
                 break;
             case DESTROYED:
                 if (app != null && (mVisible || mVisibleRequested)) {
@@ -6517,7 +6517,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
         }
         // Reset the last saved PiP snap fraction on app stop.
         mDisplayContent.mPinnedTaskController.onActivityHidden(mActivityComponent);
-        mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
         if (isClientVisible()) {
             // Though this is usually unlikely to happen, still make sure the client is invisible.
             setClientVisible(false);
diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
index 444470952c5dcbdf7ab98fe6db3fba7aa16b8820..c79a8b6b13a167bad426e6aa88399acd5359cda3 100644
--- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java
+++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
@@ -378,8 +378,23 @@ class BLASTSyncEngine {
                 if (!wc.isSyncFinished(this)) {
                     allFinished = false;
                     Slog.i(TAG, "Unfinished container: " + wc);
+                    wc.forAllActivities(a -> {
+                        if (a.isVisibleRequested()) {
+                            if (a.isRelaunching()) {
+                                Slog.i(TAG, "  " + a + " is relaunching");
+                            }
+                            a.forAllWindows(w -> {
+                                Slog.i(TAG, "  " + w + " " + w.mWinAnimator.drawStateToString());
+                            }, true /* traverseTopToBottom */);
+                        } else if (a.mDisplayContent != null && !a.mDisplayContent
+                                .mUnknownAppVisibilityController.allResolved()) {
+                            Slog.i(TAG, "  UnknownAppVisibility: " + a.mDisplayContent
+                                    .mUnknownAppVisibilityController.getDebugMessage());
+                        }
+                    });
                 }
             }
+
             for (int i = mDependencies.size() - 1; i >= 0; --i) {
                 allFinished = false;
                 Slog.i(TAG, "Unfinished dependency: " + mDependencies.get(i).mSyncId);
diff --git a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
index 41c1e793dd90181b494690d4fca86ba1d9e4200d..c0713966d8de80d6d9b2a369e8cc7cc216a576a8 100644
--- a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
+++ b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
@@ -70,6 +70,9 @@ class UnknownAppVisibilityController {
     }
 
     boolean isVisibilityUnknown(ActivityRecord r) {
+        if (mUnknownApps.isEmpty()) {
+            return false;
+        }
         return mUnknownApps.containsKey(r);
     }
 
@@ -90,6 +93,9 @@ class UnknownAppVisibilityController {
     }
 
     void appRemovedOrHidden(@NonNull ActivityRecord activity) {
+        if (mUnknownApps.isEmpty()) {
+            return;
+        }
         if (DEBUG_UNKNOWN_APP_VISIBILITY) {
             Slog.d(TAG, "App removed or hidden activity=" + activity);
         }
@@ -117,8 +123,11 @@ class UnknownAppVisibilityController {
      * Notifies that {@param activity} has finished resuming.
      */
     void notifyAppResumedFinished(@NonNull ActivityRecord activity) {
-        if (mUnknownApps.containsKey(activity)
-                && mUnknownApps.get(activity) == UNKNOWN_STATE_WAITING_RESUME) {
+        if (mUnknownApps.isEmpty()) {
+            return;
+        }
+        final Integer state = mUnknownApps.get(activity);
+        if (state != null && state == UNKNOWN_STATE_WAITING_RESUME) {
             if (DEBUG_UNKNOWN_APP_VISIBILITY) {
                 Slog.d(TAG, "App resume finished activity=" + activity);
             }
@@ -130,13 +139,16 @@ class UnknownAppVisibilityController {
      * Notifies that {@param activity} has relaid out.
      */
     void notifyRelayouted(@NonNull ActivityRecord activity) {
-        if (!mUnknownApps.containsKey(activity)) {
+        if (mUnknownApps.isEmpty()) {
+            return;
+        }
+        final Integer state = mUnknownApps.get(activity);
+        if (state == null) {
             return;
         }
         if (DEBUG_UNKNOWN_APP_VISIBILITY) {
             Slog.d(TAG, "App relayouted appWindow=" + activity);
         }
-        int state = mUnknownApps.get(activity);
         if (state == UNKNOWN_STATE_WAITING_RELAYOUT || activity.mStartingWindow != null) {
             mUnknownApps.put(activity, UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE);
             mDisplayContent.notifyKeyguardFlagsChanged();
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index debd891400b6d540f7d4ef5426a0005665d4ad39..215934f4dc09f828078c4e5956607cadc1e02b88 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -272,12 +272,12 @@
         <xs:element name="brightnessDecreaseDebounceMillis" type="xs:nonNegativeInteger">
             <xs:annotation name="final"/>
         </xs:element>
-        <!-- Animation time for brightness increase in millis -->
-        <xs:element  name="brightnessIncreaseDurationMillis" type="xs:nonNegativeInteger">
+        <!-- Animation speed for brightness increase. In framework brightness units per second. -->
+        <xs:element  name="screenBrightnessRampIncrease" type="nonNegativeDecimal">
             <xs:annotation name="final"/>
         </xs:element>
-        <!-- Animation time for brightness decrease in millis -->
-        <xs:element name="brightnessDecreaseDurationMillis" type="xs:nonNegativeInteger">
+        <!-- Animation speed for brightness decrease. In framework brightness units per second. -->
+        <xs:element name="screenBrightnessRampDecrease" type="nonNegativeDecimal">
             <xs:annotation name="final"/>
         </xs:element>
     </xs:complexType>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 2d27f0c7966082bb94e29736396fbd728e0889a8..f7e004375071aee24d80c3bd7b1d8d45d62bcc63 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -179,15 +179,15 @@ package com.android.server.display.config {
   public class HdrBrightnessConfig {
     ctor public HdrBrightnessConfig();
     method public final java.math.BigInteger getBrightnessDecreaseDebounceMillis();
-    method public final java.math.BigInteger getBrightnessDecreaseDurationMillis();
     method public final java.math.BigInteger getBrightnessIncreaseDebounceMillis();
-    method public final java.math.BigInteger getBrightnessIncreaseDurationMillis();
     method @NonNull public final com.android.server.display.config.NonNegativeFloatToFloatMap getBrightnessMap();
+    method public final java.math.BigDecimal getScreenBrightnessRampDecrease();
+    method public final java.math.BigDecimal getScreenBrightnessRampIncrease();
     method public final void setBrightnessDecreaseDebounceMillis(java.math.BigInteger);
-    method public final void setBrightnessDecreaseDurationMillis(java.math.BigInteger);
     method public final void setBrightnessIncreaseDebounceMillis(java.math.BigInteger);
-    method public final void setBrightnessIncreaseDurationMillis(java.math.BigInteger);
     method public final void setBrightnessMap(@NonNull com.android.server.display.config.NonNegativeFloatToFloatMap);
+    method public final void setScreenBrightnessRampDecrease(java.math.BigDecimal);
+    method public final void setScreenBrightnessRampIncrease(java.math.BigDecimal);
   }
 
   public class HighBrightnessMode {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index 25e8475fcf4243d7f1f68136ac7ea43308bbf8aa..922f69c1e816fea77cc93c1eb76cccd8179d3027 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -40,6 +40,7 @@ import android.app.admin.PolicyUpdateReceiver;
 import android.app.admin.PolicyValue;
 import android.app.admin.TargetUser;
 import android.app.admin.UserRestrictionPolicyKey;
+import android.app.admin.flags.FlagUtils;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -65,7 +66,6 @@ import android.util.Xml;
 import com.android.internal.util.XmlUtils;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
-import com.android.server.devicepolicy.flags.FlagUtils;
 import com.android.server.utils.Slogf;
 
 import libcore.io.IoUtils;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 5a620a3b87f53649b35054a6a13f715bfef5694c..8509155861f5c3fee2414ff8bea0d8d116e8a54d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -330,6 +330,7 @@ import android.app.admin.SystemUpdatePolicy;
 import android.app.admin.UnsafeStateException;
 import android.app.admin.UserRestrictionPolicyKey;
 import android.app.admin.WifiSsidPolicy;
+import android.app.admin.flags.FlagUtils;
 import android.app.backup.IBackupManager;
 import android.app.compat.CompatChanges;
 import android.app.role.OnRoleHoldersChangedListener;
@@ -490,7 +491,6 @@ import com.android.server.SystemServerInitThreadPool;
 import com.android.server.SystemService;
 import com.android.server.SystemServiceManager;
 import com.android.server.devicepolicy.ActiveAdmin.TrustAgentInfo;
-import com.android.server.devicepolicy.flags.FlagUtils;
 import com.android.server.inputmethod.InputMethodManagerInternal;
 import com.android.server.net.NetworkPolicyManagerInternal;
 import com.android.server.pdb.PersistentDataBlockManagerInternal;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/flags/Android.bp b/services/devicepolicy/java/com/android/server/devicepolicy/flags/Android.bp
deleted file mode 100644
index 1a45782ccd39a56075d38d1838cbfe65b58f4460..0000000000000000000000000000000000000000
--- a/services/devicepolicy/java/com/android/server/devicepolicy/flags/Android.bp
+++ /dev/null
@@ -1,16 +0,0 @@
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-aconfig_declarations {
-    name: "device_policy_aconfig_flags",
-    package: "com.android.server.devicepolicy.flags",
-    srcs: [
-        "flags.aconfig",
-    ],
-}
-
-java_aconfig_library {
-    name: "device_policy_aconfig_flags_lib",
-    aconfig_declarations: "device_policy_aconfig_flags",
-}
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
index f3ac7d55c5db7c726dae1616243470ab047b7791..12cd0f6e1a7c28b83c32d5b0ff2421c1306c2e31 100644
--- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -143,8 +143,8 @@ class PackageManagerComponentLabelIconOverrideTest {
             val result: Result,
             val componentName: ComponentName? = ComponentName(pkgName, COMPONENT_CLASS_NAME)
         ) {
-            constructor(pkgName: String, appType: AppType, exception: Class<out Exception>)
-                    : this(pkgName, appType, Result.Exception(exception))
+            constructor(pkgName: String, appType: AppType, exception: Class<out Exception>) :
+                    this(pkgName, appType, Result.Exception(exception))
 
             val expectedLabel = when (result) {
                 Result.Changed, Result.ChangedWithoutNotify, Result.NotChanged -> TEST_LABEL
@@ -299,11 +299,9 @@ class PackageManagerComponentLabelIconOverrideTest {
                     .hideAsFinal()
 
     private fun makePkgSetting(pkgName: String, pkg: AndroidPackageInternal) =
-        PackageSetting(
-            pkgName, null, File("/test"),
-            null, null, null, null, 0, 0, 0, 0, null, null, null, null, null,
-            UUID.fromString("3f9d52b7-d7b4-406a-a1da-d9f19984c72c")
-        ).apply {
+        PackageSetting(pkgName, null, File("/test"), 0, 0,
+                UUID.fromString("3f9d52b7-d7b4-406a-a1da-d9f19984c72c"))
+        .apply {
             if (params.isSystem) {
                 this.flags = this.flags or ApplicationInfo.FLAG_SYSTEM
             }
@@ -373,7 +371,7 @@ class PackageManagerComponentLabelIconOverrideTest {
             whenever(this.isCallerRecents(anyInt())) { false }
         }
         val mockAppsFilter: AppsFilterImpl = mockThrowOnUnmocked {
-            whenever(this.shouldFilterApplication(any<PackageDataSnapshot>(), anyInt(), 
+            whenever(this.shouldFilterApplication(any<PackageDataSnapshot>(), anyInt(),
                     any<PackageSetting>(), any<PackageSetting>(), anyInt())) { false }
             whenever(this.snapshot()) { this@mockThrowOnUnmocked }
             whenever(registerObserver(any())).thenCallRealMethod()
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
index cbedcaf97358379793f6214f4e398859db32ed2c..aaad669d5b8daafa1ff754579e68ea640a386096 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -967,20 +967,12 @@ public class PackageManagerSettingsTests {
                 PACKAGE_NAME,
                 REAL_PACKAGE_NAME,
                 INITIAL_CODE_PATH /*codePath*/,
-                null /*legacyNativeLibraryPathString*/,
-                "x86_64" /*primaryCpuAbiString*/,
-                "x86" /*secondaryCpuAbiString*/,
-                null /*cpuAbiOverrideString*/,
-                INITIAL_VERSION_CODE,
                 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_HAS_CODE,
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN,
-                0,
-                null /*usesSdkLibraries*/,
-                null /*usesSdkLibrariesVersions*/,
-                null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/,
-                null /*mimeGroups*/,
-                UUID.randomUUID());
+                UUID.randomUUID())
+                .setPrimaryCpuAbi("x86_64")
+                .setSecondaryCpuAbi("x86")
+                .setLongVersionCode(INITIAL_VERSION_CODE);
         origPkgSetting01.setPkg(mockAndroidPackage(origPkgSetting01));
         final PackageSetting testPkgSetting01 = new PackageSetting(origPkgSetting01);
         verifySettingCopy(origPkgSetting01, testPkgSetting01);
@@ -989,23 +981,15 @@ public class PackageManagerSettingsTests {
     @Test
     public void testPackageStateCopy02() {
         final PackageSetting origPkgSetting01 = new PackageSetting(
-                PACKAGE_NAME /*pkgName*/,
-                REAL_PACKAGE_NAME /*realPkgName*/,
+                PACKAGE_NAME,
+                REAL_PACKAGE_NAME,
                 INITIAL_CODE_PATH /*codePath*/,
-                null /*legacyNativeLibraryPathString*/,
-                "x86_64" /*primaryCpuAbiString*/,
-                "x86" /*secondaryCpuAbiString*/,
-                null /*cpuAbiOverrideString*/,
-                INITIAL_VERSION_CODE,
                 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_HAS_CODE,
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN,
-                0,
-                null /*usesSdkLibraries*/,
-                null /*usesSdkLibrariesVersions*/,
-                null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/,
-                null /*mimeGroups*/,
-                UUID.randomUUID());
+                UUID.randomUUID())
+                .setPrimaryCpuAbi("x86_64")
+                .setSecondaryCpuAbi("x86")
+                .setLongVersionCode(INITIAL_VERSION_CODE);
         origPkgSetting01.setUserState(0, 100, 100, 1, true, false, false, false, 0, null, false,
                 false, "lastDisabledCaller", new ArraySet<>(new String[]{"enabledComponent1"}),
                 new ArraySet<>(new String[]{"disabledComponent1"}), 0, 0, "harmfulAppWarning",
@@ -1028,20 +1012,10 @@ public class PackageManagerSettingsTests {
                 PACKAGE_NAME /*pkgName*/,
                 REAL_PACKAGE_NAME /*realPkgName*/,
                 UPDATED_CODE_PATH /*codePath*/,
-                null /*legacyNativeLibraryPathString*/,
-                null /*primaryCpuAbiString*/,
-                null /*secondaryCpuAbiString*/,
-                null /*cpuAbiOverrideString*/,
-                UPDATED_VERSION_CODE,
                 0 /*pkgFlags*/,
                 0 /*pkgPrivateFlags*/,
-                0,
-                null /*usesSdkLibraries*/,
-                null /*usesSdkLibrariesVersions*/,
-                null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/,
-                null /*mimeGroups*/,
-                UUID.randomUUID());
+                UUID.randomUUID())
+                .setLongVersionCode(UPDATED_VERSION_CODE);
         testPkgSetting01.copyPackageSetting(origPkgSetting01, true);
         verifySettingCopy(origPkgSetting01, testPkgSetting01);
         verifyUserStatesCopy(origPkgSetting01.readUserState(0),
@@ -1717,20 +1691,13 @@ public class PackageManagerSettingsTests {
                 PACKAGE_NAME,
                 REAL_PACKAGE_NAME,
                 INITIAL_CODE_PATH /*codePath*/,
-                null /*legacyNativeLibraryPathString*/,
-                "x86_64" /*primaryCpuAbiString*/,
-                "x86" /*secondaryCpuAbiString*/,
-                null /*cpuAbiOverrideString*/,
-                INITIAL_VERSION_CODE,
                 pkgFlags,
                 0 /*privateFlags*/,
-                sharedUserId,
-                null /*usesSdkLibraries*/,
-                null /*usesSdkLibrariesVersions*/,
-                null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/,
-                null /*mimeGroups*/,
-                UUID.randomUUID());
+                UUID.randomUUID())
+                .setPrimaryCpuAbi("x86_64")
+                .setSecondaryCpuAbi("x86")
+                .setLongVersionCode(INITIAL_VERSION_CODE)
+                .setSharedUserAppId(sharedUserId);
     }
 
     private PackageSetting createPackageSetting(String packageName) {
@@ -1738,20 +1705,12 @@ public class PackageManagerSettingsTests {
                 packageName,
                 packageName,
                 INITIAL_CODE_PATH /*codePath*/,
-                null /*legacyNativeLibraryPathString*/,
-                "x86_64" /*primaryCpuAbiString*/,
-                "x86" /*secondaryCpuAbiString*/,
-                null /*cpuAbiOverrideString*/,
-                INITIAL_VERSION_CODE,
                 0,
                 0 /*privateFlags*/,
-                0,
-                null /*usesSdkLibraries*/,
-                null /*usesSdkLibrariesVersions*/,
-                null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/,
-                null /*mimeGroups*/,
-                UUID.randomUUID());
+                UUID.randomUUID())
+                .setPrimaryCpuAbi("x86_64")
+                .setSecondaryCpuAbi("x86")
+                .setLongVersionCode(INITIAL_VERSION_CODE);
     }
 
     static @NonNull List<UserInfo> createFakeUsers() {
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
index c37d21ae1cc05de3114a19f15cc1bca15482f261..179a9d5f748ea31ef06f9003fe0dbf879c0906a7 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -570,9 +570,9 @@ public final class DisplayDeviceConfigTest {
         assertNotNull(data);
         assertEquals(2, data.mMaxBrightnessLimits.size());
         assertEquals(13000, data.mBrightnessDecreaseDebounceMillis);
-        assertEquals(10000, data.mBrightnessDecreaseDurationMillis);
+        assertEquals(0.1f, data.mScreenBrightnessRampDecrease, SMALL_DELTA);
         assertEquals(1000, data.mBrightnessIncreaseDebounceMillis);
-        assertEquals(11000, data.mBrightnessIncreaseDurationMillis);
+        assertEquals(0.11f, data.mScreenBrightnessRampIncrease, SMALL_DELTA);
 
         assertEquals(0.3f, data.mMaxBrightnessLimits.get(500f), SMALL_DELTA);
         assertEquals(0.6f, data.mMaxBrightnessLimits.get(1200f), SMALL_DELTA);
@@ -841,9 +841,9 @@ public final class DisplayDeviceConfigTest {
               + "        </point>\n"
               + "    </brightnessMap>\n"
               + "    <brightnessIncreaseDebounceMillis>1000</brightnessIncreaseDebounceMillis>\n"
-              + "    <brightnessIncreaseDurationMillis>11000</brightnessIncreaseDurationMillis>\n"
+              + "    <screenBrightnessRampIncrease>0.11</screenBrightnessRampIncrease>\n"
               + "    <brightnessDecreaseDebounceMillis>13000</brightnessDecreaseDebounceMillis>\n"
-              + "    <brightnessDecreaseDurationMillis>10000</brightnessDecreaseDurationMillis>\n"
+              + "    <screenBrightnessRampDecrease>0.1</screenBrightnessRampDecrease>\n"
               + "</hdrBrightnessConfig>";
     }
 
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java
index ee187baf524e4b3be3d19fc08bfb715aa275162a..8d8274c61b208e8eca4d01fe8ec74ae5c0a63a7b 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java
@@ -56,9 +56,9 @@ public class HdrClamperTest {
     private static final HdrBrightnessData TEST_HDR_DATA = new HdrBrightnessData(
             Map.of(500f, 0.6f),
             /* brightnessIncreaseDebounceMillis= */ 1000,
-            /* brightnessIncreaseDurationMillis= */ 2000,
+            /* screenBrightnessRampIncrease= */ 0.02f,
             /* brightnessDecreaseDebounceMillis= */ 3000,
-            /* brightnessDecreaseDurationMillis= */4000
+            /* screenBrightnessRampDecrease= */0.04f
     );
 
     private static final int WIDTH = 600;
@@ -152,8 +152,7 @@ public class HdrClamperTest {
         mClock.fastForward(3000);
         mTestHandler.timeAdvance();
         assertEquals(0.6f, mHdrClamper.getMaxBrightness(), FLOAT_TOLERANCE);
-        // 0.6 to HLG = 0.905727, rate = (1-0.905727) / 4
-        assertEquals(0.023568f, mHdrClamper.getTransitionRate(), FLOAT_TOLERANCE);
+        assertEquals(0.04, mHdrClamper.getTransitionRate(), FLOAT_TOLERANCE);
     }
 
     @Test
@@ -181,8 +180,7 @@ public class HdrClamperTest {
         mClock.fastForward(1000);
         mTestHandler.timeAdvance();
         assertEquals(PowerManager.BRIGHTNESS_MAX, mHdrClamper.getMaxBrightness(), FLOAT_TOLERANCE);
-        // 0.6 to HLG = 0.905727, rate = (1-0.905727) / 2
-        assertEquals(0.047137f, mHdrClamper.getTransitionRate(), FLOAT_TOLERANCE);
+        assertEquals(0.02f, mHdrClamper.getTransitionRate(), FLOAT_TOLERANCE);
     }
 
     @Test
@@ -209,8 +207,7 @@ public class HdrClamperTest {
         mClock.fastForward(3000);
         mTestHandler.timeAdvance();
         assertEquals(0.6f, mHdrClamper.getMaxBrightness(), FLOAT_TOLERANCE);
-        // 0.6 to HLG = 0.905727, rate = (1-0.905727) / 4
-        assertEquals(0.023568f, mHdrClamper.getTransitionRate(), FLOAT_TOLERANCE);
+        assertEquals(0.04f, mHdrClamper.getTransitionRate(), FLOAT_TOLERANCE);
     }
 
     // MsgInfo.sendTime is calculated first by adding SystemClock.uptimeMillis()
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index 2f6859c14742ad7090496e757348279609e94d47..be33b1b6f34fc272572fd4e7ded53972aeb2f2b1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -165,8 +165,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
             null
         }
         whenever(mocks.settings.addPackageLPw(nullable(), nullable(), nullable(), nullable(),
-                nullable(), nullable(), nullable(), nullable(), nullable(), nullable(), nullable(),
-                nullable(), nullable(), nullable(), nullable(), nullable(), nullable())) {
+                nullable(), nullable(), nullable())) {
             val name: String = getArgument(0)
             val pendingAdd = mPendingPackageAdds.firstOrNull { it.first == name }
                     ?: return@whenever null
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 37a6d22f038beb14051660f3cd3b39209838349d..eca19c8e8c4d6724c6518fa7922953d684c0c2ae 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -255,7 +255,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
     public void testUnlockUserKeyIfUnsecuredPassesPrimaryUserAuthSecret() throws RemoteException {
         initSpAndSetCredential(PRIMARY_USER_ID, newPassword(null));
         reset(mAuthSecretService);
-        mLocalService.unlockUserKeyIfUnsecured(PRIMARY_USER_ID);
+        mService.unlockUserKeyIfUnsecured(PRIMARY_USER_ID);
         verify(mAuthSecretService).setPrimaryUserCredential(any(byte[].class));
     }
 
@@ -267,7 +267,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
         mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);
 
         reset(mAuthSecretService);
-        mLocalService.unlockUserKeyIfUnsecured(PRIMARY_USER_ID);
+        mService.unlockUserKeyIfUnsecured(PRIMARY_USER_ID);
         verify(mAuthSecretService).setPrimaryUserCredential(any(byte[].class));
     }
 
@@ -285,39 +285,39 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
     @Test
     public void testHeadlessSystemUserDoesNotPassAuthSecret() throws RemoteException {
         setupHeadlessTest();
-        mLocalService.unlockUserKeyIfUnsecured(PRIMARY_USER_ID);
+        mService.unlockUserKeyIfUnsecured(PRIMARY_USER_ID);
         verify(mAuthSecretService, never()).setPrimaryUserCredential(any(byte[].class));
     }
 
     @Test
     public void testHeadlessSecondaryUserPassesAuthSecret() throws RemoteException {
         setupHeadlessTest();
-        mLocalService.unlockUserKeyIfUnsecured(SECONDARY_USER_ID);
+        mService.unlockUserKeyIfUnsecured(SECONDARY_USER_ID);
         verify(mAuthSecretService).setPrimaryUserCredential(any(byte[].class));
     }
 
     @Test
     public void testHeadlessTertiaryUserPassesSameAuthSecret() throws RemoteException {
         setupHeadlessTest();
-        mLocalService.unlockUserKeyIfUnsecured(SECONDARY_USER_ID);
+        mService.unlockUserKeyIfUnsecured(SECONDARY_USER_ID);
         var captor = ArgumentCaptor.forClass(byte[].class);
         verify(mAuthSecretService).setPrimaryUserCredential(captor.capture());
         var value = captor.getValue();
         reset(mAuthSecretService);
-        mLocalService.unlockUserKeyIfUnsecured(TERTIARY_USER_ID);
+        mService.unlockUserKeyIfUnsecured(TERTIARY_USER_ID);
         verify(mAuthSecretService).setPrimaryUserCredential(eq(value));
     }
 
     @Test
     public void testHeadlessTertiaryUserPassesSameAuthSecretAfterReset() throws RemoteException {
         setupHeadlessTest();
-        mLocalService.unlockUserKeyIfUnsecured(SECONDARY_USER_ID);
+        mService.unlockUserKeyIfUnsecured(SECONDARY_USER_ID);
         var captor = ArgumentCaptor.forClass(byte[].class);
         verify(mAuthSecretService).setPrimaryUserCredential(captor.capture());
         var value = captor.getValue();
         mService.clearAuthSecret();
         reset(mAuthSecretService);
-        mLocalService.unlockUserKeyIfUnsecured(TERTIARY_USER_ID);
+        mService.unlockUserKeyIfUnsecured(TERTIARY_USER_ID);
         verify(mAuthSecretService).setPrimaryUserCredential(eq(value));
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
index 42be3d36620af52896899507fe556f442350ae32..5d6f36c005b4e35f5e256134a4a2fe869b73b022 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
@@ -19,7 +19,6 @@ package com.android.server.pm;
 import android.content.pm.SigningDetails;
 import android.util.SparseArray;
 
-import com.android.server.pm.parsing.pkg.ParsedPackage;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageUserStateImpl;
 
@@ -159,17 +158,19 @@ public class PackageSettingBuilder {
 
     public PackageSetting build() {
         final PackageSetting packageSetting = new PackageSetting(mName, mRealName,
-                new File(mCodePath), mLegacyNativeLibraryPathString, mPrimaryCpuAbiString,
-                mSecondaryCpuAbiString, mCpuAbiOverrideString, mPVersionCode, mPkgFlags,
-                mPrivateFlags, mSharedUserId, null /* usesSdkLibraries */,
-                null /* usesSdkLibrariesVersions */, null /* usesStaticLibraries */,
-                null  /* usesStaticLibrariesVersions */, mMimeGroups, mDomainSetId);
-        packageSetting.setSignatures(mSigningDetails != null
-                ? new PackageSignatures(mSigningDetails)
-                : new PackageSignatures());
-        packageSetting.setPkg((ParsedPackage) mPkg);
-        packageSetting.setAppId(mAppId);
-        packageSetting.setVolumeUuid(this.mVolumeUuid);
+                new File(mCodePath), mPkgFlags, mPrivateFlags, mDomainSetId)
+                .setLegacyNativeLibraryPath(mLegacyNativeLibraryPathString)
+                .setPrimaryCpuAbi(mPrimaryCpuAbiString)
+                .setSecondaryCpuAbi(mSecondaryCpuAbiString)
+                .setCpuAbiOverride(mCpuAbiOverrideString)
+                .setLongVersionCode(mPVersionCode)
+                .setSharedUserAppId(mSharedUserId)
+                .setMimeGroups(mMimeGroups)
+                .setSignatures(mSigningDetails != null
+                        ? new PackageSignatures(mSigningDetails) : new PackageSignatures())
+                .setPkg(mPkg)
+                .setAppId(mAppId)
+                .setVolumeUuid(this.mVolumeUuid);
         if (mInstallSource != null) {
             packageSetting.setInstallSource(mInstallSource);
         }
diff --git a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 75a8dd822914b6c3266ce713f8ae4bbca3e55fb1..085eddd2e73d808459a108441919d98fe7e8ef8d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import android.platform.test.annotations.Presubmit;
@@ -94,10 +95,14 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
     public void testRemoveFinishingInvisibleActivityFromUnknown() {
         final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
         mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
-        activity.finishing = true;
-        activity.setVisibleRequested(true);
-        activity.setVisibility(false);
+        assertFalse(mDisplayContent.mUnknownAppVisibilityController.allResolved());
+        activity.makeFinishingLocked();
         assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
+
+        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
+        assertTrue(mDisplayContent.mUnknownAppVisibilityController.isVisibilityUnknown(activity));
+        activity.setState(ActivityRecord.State.STOPPED, "test");
+        assertFalse(mDisplayContent.mUnknownAppVisibilityController.isVisibilityUnknown(activity));
     }
 
     @Test