Merge "Add flag to show all permission dialogs on virtual devices" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 73b35b2..bb60e02 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -37075,6 +37075,7 @@
 
   @FlaggedApi("android.provider.new_default_account_api_enabled") public static final class ContactsContract.RawContacts.DefaultAccount {
     method @FlaggedApi("android.provider.new_default_account_api_enabled") @NonNull public static android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState getDefaultAccountForNewContacts(@NonNull android.content.ContentResolver);
+    field public static final String ACTION_MOVE_CONTACTS_TO_DEFAULT_ACCOUNT = "android.provider.action.MOVE_CONTACTS_TO_DEFAULT_ACCOUNT";
   }
 
   @FlaggedApi("android.provider.new_default_account_api_enabled") public static final class ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index f04df2f..41732fe 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -6054,7 +6054,7 @@
     method @NonNull public android.hardware.location.ContextHubInfo getAttachedHub();
     method @IntRange(from=0, to=65535) public int getId();
     method @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public int sendMessageToNanoApp(@NonNull android.hardware.location.NanoAppMessage);
-    method @FlaggedApi("android.chre.flags.reliable_message") @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public android.hardware.location.ContextHubTransaction<java.lang.Void> sendReliableMessageToNanoApp(@NonNull android.hardware.location.NanoAppMessage);
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public android.hardware.location.ContextHubTransaction<java.lang.Void> sendReliableMessageToNanoApp(@NonNull android.hardware.location.NanoAppMessage);
   }
 
   public class ContextHubClientCallback {
@@ -6090,7 +6090,7 @@
     method public String getToolchain();
     method public int getToolchainVersion();
     method public String getVendor();
-    method @FlaggedApi("android.chre.flags.reliable_message") public boolean supportsReliableMessages();
+    method public boolean supportsReliableMessages();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.hardware.location.ContextHubInfo> CREATOR;
   }
@@ -6174,7 +6174,7 @@
     field public static final int RESULT_FAILED_BAD_PARAMS = 2; // 0x2
     field public static final int RESULT_FAILED_BUSY = 4; // 0x4
     field public static final int RESULT_FAILED_HAL_UNAVAILABLE = 8; // 0x8
-    field @FlaggedApi("android.chre.flags.reliable_message") public static final int RESULT_FAILED_NOT_SUPPORTED = 9; // 0x9
+    field public static final int RESULT_FAILED_NOT_SUPPORTED = 9; // 0x9
     field public static final int RESULT_FAILED_SERVICE_INTERNAL_FAILURE = 7; // 0x7
     field public static final int RESULT_FAILED_TIMEOUT = 6; // 0x6
     field public static final int RESULT_FAILED_UNINITIALIZED = 3; // 0x3
@@ -6184,7 +6184,7 @@
     field public static final int TYPE_ENABLE_NANOAPP = 2; // 0x2
     field public static final int TYPE_LOAD_NANOAPP = 0; // 0x0
     field public static final int TYPE_QUERY_NANOAPPS = 4; // 0x4
-    field @FlaggedApi("android.chre.flags.reliable_message") public static final int TYPE_RELIABLE_MESSAGE = 5; // 0x5
+    field public static final int TYPE_RELIABLE_MESSAGE = 5; // 0x5
     field public static final int TYPE_UNLOAD_NANOAPP = 1; // 0x1
   }
 
@@ -6367,15 +6367,15 @@
 
   public final class NanoAppMessage implements android.os.Parcelable {
     method public static android.hardware.location.NanoAppMessage createMessageFromNanoApp(long, int, byte[], boolean);
-    method @FlaggedApi("android.chre.flags.reliable_message") @NonNull public static android.hardware.location.NanoAppMessage createMessageFromNanoApp(long, int, @NonNull byte[], boolean, boolean, int);
+    method @NonNull public static android.hardware.location.NanoAppMessage createMessageFromNanoApp(long, int, @NonNull byte[], boolean, boolean, int);
     method public static android.hardware.location.NanoAppMessage createMessageToNanoApp(long, int, byte[]);
     method public int describeContents();
     method public byte[] getMessageBody();
-    method @FlaggedApi("android.chre.flags.reliable_message") public int getMessageSequenceNumber();
+    method public int getMessageSequenceNumber();
     method public int getMessageType();
     method public long getNanoAppId();
     method public boolean isBroadcastMessage();
-    method @FlaggedApi("android.chre.flags.reliable_message") public boolean isReliable();
+    method public boolean isReliable();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.hardware.location.NanoAppMessage> CREATOR;
   }
diff --git a/core/java/android/hardware/LutProperties.java b/core/java/android/hardware/LutProperties.java
index 57f8a4e..c9c6d6d 100644
--- a/core/java/android/hardware/LutProperties.java
+++ b/core/java/android/hardware/LutProperties.java
@@ -30,7 +30,7 @@
  */
 public final class LutProperties {
     private final @Dimension int mDimension;
-    private final long mSize;
+    private final int mSize;
     private final @SamplingKey int[] mSamplingKeys;
 
     @Retention(RetentionPolicy.SOURCE)
@@ -68,7 +68,7 @@
     /**
      * @return the size of the Lut.
      */
-    public long getSize() {
+    public int getSize() {
         return mSize;
     }
 
@@ -83,7 +83,7 @@
     }
 
     /* use in the native code */
-    private LutProperties(@Dimension int dimension, long size, @SamplingKey int[] samplingKeys) {
+    private LutProperties(@Dimension int dimension, int size, @SamplingKey int[] samplingKeys) {
         if (dimension != ONE_DIMENSION || dimension != THREE_DIMENSION) {
             throw new IllegalArgumentException("The dimension is either 1 or 3!");
         }
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 953086d..538e2fb 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -194,23 +194,20 @@
     /**
      * Sends a reliable message to a nanoapp.
      *
-     * This method is similar to {@link ContextHubClient#sendMessageToNanoApp} with the
+     * <p>This method is similar to {@link ContextHubClient#sendMessageToNanoApp} with the
      * difference that it expects the message to be acknowledged by CHRE.
      *
-     * The transaction succeeds after we received an ACK from CHRE without error.
-     * In all other cases the transaction will fail.
+     * <p>The transaction succeeds after we received an ACK from CHRE without error. In all other
+     * cases the transaction will fail.
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
     @NonNull
-    @FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE)
     public ContextHubTransaction<Void> sendReliableMessageToNanoApp(
             @NonNull NanoAppMessage message) {
         ContextHubTransaction<Void> transaction =
                 new ContextHubTransaction<>(ContextHubTransaction.TYPE_RELIABLE_MESSAGE);
 
-        if (!Flags.reliableMessageImplementation() ||
-            !mAttachedHub.supportsReliableMessages() ||
-            message.isBroadcastMessage()) {
+        if (!mAttachedHub.supportsReliableMessages() || message.isBroadcastMessage()) {
             transaction.setResponse(new ContextHubTransaction.Response<Void>(
                     ContextHubTransaction.RESULT_FAILED_NOT_SUPPORTED, null));
             return transaction;
diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java
index d934970..858ec23 100644
--- a/core/java/android/hardware/location/ContextHubInfo.java
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -99,8 +99,7 @@
         mSleepPowerDrawMw = 0;
         mPeakPowerDrawMw = 0;
         mMaxPacketLengthBytes = contextHub.maxSupportedMessageLengthBytes;
-        mSupportsReliableMessages = Flags.reliableMessageImplementation()
-                && contextHub.supportsReliableMessages;
+        mSupportsReliableMessages = contextHub.supportsReliableMessages;
         mChrePlatformId = contextHub.chrePlatformId;
         mChreApiMajorVersion = contextHub.chreApiMajorVersion;
         mChreApiMinorVersion = contextHub.chreApiMinorVersion;
@@ -124,7 +123,6 @@
      *
      * @return whether reliable messages are supported.
      */
-    @FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE)
     public boolean supportsReliableMessages() {
         return mSupportsReliableMessages;
     }
@@ -364,22 +362,22 @@
         boolean isEqual = false;
         if (object instanceof ContextHubInfo) {
             ContextHubInfo other = (ContextHubInfo) object;
-            isEqual = (other.getId() == mId)
-                    && other.getName().equals(mName)
-                    && other.getVendor().equals(mVendor)
-                    && other.getToolchain().equals(mToolchain)
-                    && (other.getToolchainVersion() == mToolchainVersion)
-                    && (other.getStaticSwVersion() == getStaticSwVersion())
-                    && (other.getChrePlatformId() == mChrePlatformId)
-                    && (other.getPeakMips() == mPeakMips)
-                    && (other.getStoppedPowerDrawMw() == mStoppedPowerDrawMw)
-                    && (other.getSleepPowerDrawMw() == mSleepPowerDrawMw)
-                    && (other.getPeakPowerDrawMw() == mPeakPowerDrawMw)
-                    && (other.getMaxPacketLengthBytes() == mMaxPacketLengthBytes)
-                    && (!Flags.reliableMessage()
-                            || (other.supportsReliableMessages() == mSupportsReliableMessages))
-                    && Arrays.equals(other.getSupportedSensors(), mSupportedSensors)
-                    && Arrays.equals(other.getMemoryRegions(), mMemoryRegions);
+            isEqual =
+                    (other.getId() == mId)
+                            && other.getName().equals(mName)
+                            && other.getVendor().equals(mVendor)
+                            && other.getToolchain().equals(mToolchain)
+                            && (other.getToolchainVersion() == mToolchainVersion)
+                            && (other.getStaticSwVersion() == getStaticSwVersion())
+                            && (other.getChrePlatformId() == mChrePlatformId)
+                            && (other.getPeakMips() == mPeakMips)
+                            && (other.getStoppedPowerDrawMw() == mStoppedPowerDrawMw)
+                            && (other.getSleepPowerDrawMw() == mSleepPowerDrawMw)
+                            && (other.getPeakPowerDrawMw() == mPeakPowerDrawMw)
+                            && (other.getMaxPacketLengthBytes() == mMaxPacketLengthBytes)
+                            && (other.supportsReliableMessages() == mSupportsReliableMessages)
+                            && Arrays.equals(other.getSupportedSensors(), mSupportedSensors)
+                            && Arrays.equals(other.getMemoryRegions(), mMemoryRegions);
         }
 
         return isEqual;
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 218b023..6284e70 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -750,9 +750,7 @@
                 executor.execute(
                         () -> {
                             callback.onMessageFromNanoApp(client, message);
-                            if (Flags.reliableMessage()
-                                        && Flags.reliableMessageImplementation()
-                                        && message.isReliable()) {
+                            if (message.isReliable()) {
                                 client.reliableMessageCallbackFinished(
                                         message.getMessageSequenceNumber(), ErrorCode.OK);
                             } else {
diff --git a/core/java/android/hardware/location/ContextHubTransaction.java b/core/java/android/hardware/location/ContextHubTransaction.java
index 4060f4c..bd87b5c 100644
--- a/core/java/android/hardware/location/ContextHubTransaction.java
+++ b/core/java/android/hardware/location/ContextHubTransaction.java
@@ -69,7 +69,6 @@
     public static final int TYPE_ENABLE_NANOAPP = 2;
     public static final int TYPE_DISABLE_NANOAPP = 3;
     public static final int TYPE_QUERY_NANOAPPS = 4;
-    @FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE)
     public static final int TYPE_RELIABLE_MESSAGE = 5;
 
     /**
@@ -123,10 +122,8 @@
      * Failure mode when the Context Hub HAL was not available.
      */
     public static final int RESULT_FAILED_HAL_UNAVAILABLE = 8;
-    /**
-     * Failure mode when the operation is not supported.
-     */
-    @FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE)
+
+    /** Failure mode when the operation is not supported. */
     public static final int RESULT_FAILED_NOT_SUPPORTED = 9;
 
     /**
@@ -232,11 +229,8 @@
                 return upperCase ? "Disable" : "disable";
             case ContextHubTransaction.TYPE_QUERY_NANOAPPS:
                 return upperCase ? "Query" : "query";
-            case ContextHubTransaction.TYPE_RELIABLE_MESSAGE: {
-                if (Flags.reliableMessage()) {
-                    return upperCase ? "Reliable Message" : "reliable message";
-                }
-            }
+            case ContextHubTransaction.TYPE_RELIABLE_MESSAGE:
+                return upperCase ? "Reliable Message" : "reliable message";
             default:
                 return upperCase ? "Unknown" : "unknown";
         }
diff --git a/core/java/android/hardware/location/NanoAppMessage.java b/core/java/android/hardware/location/NanoAppMessage.java
index ec0adda..32b9283 100644
--- a/core/java/android/hardware/location/NanoAppMessage.java
+++ b/core/java/android/hardware/location/NanoAppMessage.java
@@ -97,7 +97,7 @@
     /**
      * Creates a NanoAppMessage object sent from a nanoapp.
      *
-     * This factory method is intended only to be used by the Context Hub Service when delivering
+     * <p>This factory method is intended only to be used by the Context Hub Service when delivering
      * messages from a nanoapp to clients.
      *
      * @param sourceNanoAppId the ID of the nanoapp that the message was sent from
@@ -106,12 +106,14 @@
      * @param broadcasted {@code true} if the message was broadcasted, {@code false} otherwise
      * @param isReliable if the NanoAppMessage is reliable
      * @param messageSequenceNumber the message sequence number of the NanoAppMessage
-     *
      * @return the NanoAppMessage object
      */
-    @FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE)
-    public static @NonNull NanoAppMessage createMessageFromNanoApp(long sourceNanoAppId,
-            int messageType, @NonNull byte[] messageBody, boolean broadcasted, boolean isReliable,
+    public static @NonNull NanoAppMessage createMessageFromNanoApp(
+            long sourceNanoAppId,
+            int messageType,
+            @NonNull byte[] messageBody,
+            boolean broadcasted,
+            boolean isReliable,
             int messageSequenceNumber) {
         return new NanoAppMessage(sourceNanoAppId, messageType, messageBody, broadcasted,
                 isReliable, messageSequenceNumber);
@@ -147,18 +149,18 @@
 
     /**
      * Returns if the message is reliable. The default value is {@code false}
+     *
      * @return {@code true} if the message is reliable, {@code false} otherwise
      */
-    @FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE)
     public boolean isReliable() {
         return mIsReliable;
     }
 
     /**
      * Returns the message sequence number. The default value is 0
+     *
      * @return the message sequence number of the message
      */
-    @FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE)
     public int getMessageSequenceNumber() {
         return mMessageSequenceNumber;
     }
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 5ecf361..8afc177 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3071,6 +3071,14 @@
                     "queryDefaultAccountForNewContacts";
 
             /**
+             * Action used to launch the UI to move contacts to the default account.
+             */
+            @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+            public static final String ACTION_MOVE_CONTACTS_TO_DEFAULT_ACCOUNT =
+                    "android.provider.action.MOVE_CONTACTS_TO_DEFAULT_ACCOUNT";
+
+
+            /**
              * Represents the state of the default account, and the actual {@link Account} if it's
              * a cloud account.
              * If the default account is set to {@link #DEFAULT_ACCOUNT_STATE_LOCAL} or
diff --git a/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java b/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java
index e2237f6..0e0098e 100644
--- a/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java
+++ b/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java
@@ -57,7 +57,7 @@
     }
 
     public static void logPostGcMemorySnapshot() {
-        if (!com.android.libcore.Flags.nativeMetrics()) {
+        if (!com.android.libcore.readonly.Flags.nativeMetrics()) {
             return;
         }
         int pid = Process.myPid();
diff --git a/core/jni/android_hardware_OverlayProperties.cpp b/core/jni/android_hardware_OverlayProperties.cpp
index 63de195..bb4084e 100644
--- a/core/jni/android_hardware_OverlayProperties.cpp
+++ b/core/jni/android_hardware_OverlayProperties.cpp
@@ -213,6 +213,6 @@
     clazz = FindClassOrDie(env, "android/hardware/LutProperties");
     gLutPropertiesClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
     gLutPropertiesClassInfo.ctor =
-            GetMethodIDOrDie(env, gLutPropertiesClassInfo.clazz, "<init>", "(IJ[I)V");
+            GetMethodIDOrDie(env, gLutPropertiesClassInfo.clazz, "<init>", "(II[I)V");
     return err;
 }
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9c92e5c..b55e5f0 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -7054,6 +7054,9 @@
          RSS is being collected instead. -->
     <item name="config_am_pssToRssThresholdModifier" format="float" type="dimen">1.5</item>
 
+    <!-- The size of the UI tier if cached app oom_adj_score tiers are enabled. -->
+    <integer name="config_am_tieredCachedAdjUiTierSize">10</integer>
+
     <!-- Whether unlocking and waking a device are sequenced -->
     <bool name="config_orderUnlockAndWake">false</bool>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 712b994..ecc3afe 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5499,6 +5499,9 @@
   <java-symbol type="bool" name="config_am_disablePssProfiling" />
   <java-symbol type="dimen" name="config_am_pssToRssThresholdModifier" />
 
+  <!-- For OomAdjuster cached app tiers configurability -->
+  <java-symbol type="integer" name="config_am_tieredCachedAdjUiTierSize" />
+
   <java-symbol type="raw" name="default_ringtone_vibration_effect" />
 
   <!-- For activity embedding divider -->
diff --git a/core/tests/coretests/AppThatUsesAppOps/OWNERS b/core/tests/coretests/AppThatUsesAppOps/OWNERS
new file mode 100644
index 0000000..d774570
--- /dev/null
+++ b/core/tests/coretests/AppThatUsesAppOps/OWNERS
@@ -0,0 +1 @@
+file:/core/java/android/permission/OWNERS
diff --git a/core/tests/coretests/OWNERS b/core/tests/coretests/OWNERS
index 6aefb63..eea694e 100644
--- a/core/tests/coretests/OWNERS
+++ b/core/tests/coretests/OWNERS
@@ -4,4 +4,5 @@
 per-file ParcelTest.java = file:platform/frameworks/native:/libs/binder/OWNERS
 per-file SurfaceControlRegistryTests.java = file:/services/core/java/com/android/server/wm/OWNERS
 per-file VintfObjectTest.java = file:platform/system/libvintf:/OWNERS
-per-file AppOpsLoggingTest.kt,AppOpsLoggingTest.cpp,IAppOps*.aidl,AppThatUsesAppOps/* = file:/core/java/android/permission/OWNERS
+per-file AppOpsLoggingTest.kt,AppOpsLoggingTest.cpp,IAppOps*.aidl = file:/core/java/android/permission/OWNERS
+per-file WallpaperDescriptionTest,WallpaperInstanceTest = file:/core/java/android/service/wallpaper/OWNERS
diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
index cf0a975..714d5e0 100644
--- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig
+++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
@@ -168,3 +168,13 @@
     description: "Enables flexibile split feature for split screen"
     bug: "349828130"
 }
+
+flag {
+    name: "enable_task_view_controller_cleanup"
+    namespace: "multitasking"
+    description: "Fix memory leak with task view controllers"
+    bug: "369995920"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index b700a54..7f54786 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -17,7 +17,6 @@
 package com.android.wm.shell.dagger;
 
 import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS;
-import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS;
 import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_TASK_LIMIT;
 
 import android.annotation.Nullable;
@@ -848,8 +847,7 @@
             InteractionJankMonitor interactionJankMonitor,
             @ShellMainThread Handler handler
     ) {
-        if (!DesktopModeStatus.canEnterDesktopMode(context)
-                || !ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS.isTrue()) {
+        if (!DesktopModeStatus.canEnterDesktopMode(context)) {
             return Optional.empty();
         }
         return Optional.of(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
index dba46d0..54a07f2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
@@ -23,6 +23,7 @@
 import android.os.IBinder
 import android.view.SurfaceControl
 import android.view.WindowManager
+import android.window.DesktopModeFlags
 import android.window.TransitionInfo
 import android.window.TransitionRequestInfo
 import android.window.WindowContainerTransaction
@@ -59,6 +60,9 @@
 
     /** Starts close transition and handles or delegates desktop task close animation. */
     override fun startRemoveTransition(wct: WindowContainerTransaction?): IBinder {
+        if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS.isTrue) {
+            return freeformTaskTransitionHandler.startRemoveTransition(wct)
+        }
         requireNotNull(wct)
         return transitions.startTransition(WindowManager.TRANSIT_CLOSE, wct, /* handler= */ this)
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
index 5036837..be0663c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
@@ -24,6 +24,9 @@
 import android.os.Binder
 import android.os.Handler
 import android.os.IBinder
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import android.view.SurfaceControl
@@ -33,6 +36,7 @@
 import androidx.test.filters.SmallTest
 import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE
 import com.android.internal.jank.InteractionJankMonitor
+import com.android.window.flags.Flags
 import com.android.wm.shell.ShellTestCase
 import com.android.wm.shell.TestRunningTaskInfoBuilder
 import com.android.wm.shell.freeform.FreeformTaskTransitionHandler
@@ -41,6 +45,7 @@
 import org.junit.Assert.assertNull
 import org.junit.Assert.assertTrue
 import org.junit.Before
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
@@ -60,6 +65,8 @@
 @RunWith(AndroidTestingRunner::class)
 class DesktopMixedTransitionHandlerTest : ShellTestCase() {
 
+    @JvmField @Rule val setFlagsRule = SetFlagsRule()
+
     @Mock lateinit var transitions: Transitions
     @Mock lateinit var desktopRepository: DesktopRepository
     @Mock lateinit var freeformTaskTransitionHandler: FreeformTaskTransitionHandler
@@ -106,6 +113,19 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS)
+    fun startRemoveTransition_callsFreeformTaskTransitionHandler() {
+        val wct = WindowContainerTransaction()
+        whenever(freeformTaskTransitionHandler.startRemoveTransition(wct))
+            .thenReturn(mock())
+
+        mixedHandler.startRemoveTransition(wct)
+
+        verify(freeformTaskTransitionHandler).startRemoveTransition(wct)
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS)
     fun startRemoveTransition_startsCloseTransition() {
         val wct = WindowContainerTransaction()
         whenever(transitions.startTransition(WindowManager.TRANSIT_CLOSE, wct, mixedHandler))
diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java
index 905d6f6..520ba89 100644
--- a/nfc/java/android/nfc/NfcOemExtension.java
+++ b/nfc/java/android/nfc/NfcOemExtension.java
@@ -923,12 +923,15 @@
     }
 
     private @CardEmulation.ProtocolAndTechnologyRoute int routeStringToInt(String route) {
-        return switch (route) {
-            case "DH" -> PROTOCOL_AND_TECHNOLOGY_ROUTE_DH;
-            case "eSE" -> PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE;
-            case "SIM" -> PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC;
-            default -> throw new IllegalStateException("Unexpected value: " + route);
-        };
+        if (route.equals("DH")) {
+            return PROTOCOL_AND_TECHNOLOGY_ROUTE_DH;
+        } else if (route.startsWith("eSE")) {
+            return PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE;
+        } else if (route.startsWith("SIM")) {
+            return PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC;
+        } else {
+            throw new IllegalStateException("Unexpected value: " + route);
+        }
     }
 
     private class ReceiverWrapper<T> implements Consumer<T> {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index c9a4d58..5042403 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -127,22 +127,23 @@
 /** A scope that can be used to query the target state of an element or scene. */
 interface ElementStateScope {
     /**
-     * Return the *target* size of [this] element in the given [scene], i.e. the size of the element
-     * when idle, or `null` if the element is not composed and measured in that scene (yet).
+     * Return the *target* size of [this] element in the given [content], i.e. the size of the
+     * element when idle, or `null` if the element is not composed and measured in that content
+     * (yet).
      */
-    fun ElementKey.targetSize(scene: SceneKey): IntSize?
+    fun ElementKey.targetSize(content: ContentKey): IntSize?
 
     /**
-     * Return the *target* offset of [this] element in the given [scene], i.e. the size of the
-     * element when idle, or `null` if the element is not composed and placed in that scene (yet).
+     * Return the *target* offset of [this] element in the given [content], i.e. the size of the
+     * element when idle, or `null` if the element is not composed and placed in that content (yet).
      */
-    fun ElementKey.targetOffset(scene: SceneKey): Offset?
+    fun ElementKey.targetOffset(content: ContentKey): Offset?
 
     /**
-     * Return the *target* size of [this] scene, i.e. the size of the scene when idle, or `null` if
-     * the scene was never composed.
+     * Return the *target* size of [this] content, i.e. the size of the content when idle, or `null`
+     * if the content was not composed (yet).
      */
-    fun SceneKey.targetSize(): IntSize?
+    fun ContentKey.targetSize(): IntSize?
 }
 
 @Stable
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
index 65c4043..d58d3f24 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
@@ -172,7 +172,12 @@
         return scenes[key] ?: error("Scene $key is not configured")
     }
 
-    internal fun sceneOrNull(key: SceneKey): Scene? = scenes[key]
+    internal fun contentOrNull(key: ContentKey): Content? {
+        return when (key) {
+            is SceneKey -> scenes[key]
+            is OverlayKey -> overlays[key]
+        }
+    }
 
     internal fun overlay(key: OverlayKey): Overlay {
         return overlays[key] ?: error("Overlay $key is not configured")
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt
index b7fa0d4..690c809 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt
@@ -21,20 +21,20 @@
 
 internal class ElementStateScopeImpl(private val layoutImpl: SceneTransitionLayoutImpl) :
     ElementStateScope {
-    override fun ElementKey.targetSize(scene: SceneKey): IntSize? {
-        return layoutImpl.elements[this]?.stateByContent?.get(scene)?.targetSize.takeIf {
+    override fun ElementKey.targetSize(content: ContentKey): IntSize? {
+        return layoutImpl.elements[this]?.stateByContent?.get(content)?.targetSize.takeIf {
             it != Element.SizeUnspecified
         }
     }
 
-    override fun ElementKey.targetOffset(scene: SceneKey): Offset? {
-        return layoutImpl.elements[this]?.stateByContent?.get(scene)?.targetOffset.takeIf {
+    override fun ElementKey.targetOffset(content: ContentKey): Offset? {
+        return layoutImpl.elements[this]?.stateByContent?.get(content)?.targetOffset.takeIf {
             it != Offset.Unspecified
         }
     }
 
-    override fun SceneKey.targetSize(): IntSize? {
-        return layoutImpl.sceneOrNull(this)?.targetSize.takeIf { it != IntSize.Zero }
+    override fun ContentKey.targetSize(): IntSize? {
+        return layoutImpl.contentOrNull(this)?.targetSize.takeIf { it != IntSize.Zero }
     }
 }
 
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AssetLoader.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AssetLoader.kt
index 031fbab..2a2d333 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AssetLoader.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AssetLoader.kt
@@ -17,34 +17,24 @@
 package com.android.systemui.shared.clocks
 
 import android.content.Context
-import android.content.res.ColorStateList
 import android.content.res.Resources
-import android.graphics.Color
 import android.graphics.Typeface
 import android.graphics.drawable.Drawable
 import android.util.TypedValue
-import com.android.internal.graphics.ColorUtils
-import com.android.internal.graphics.cam.Cam
-import com.android.internal.graphics.cam.CamUtils
 import com.android.internal.policy.SystemBarUtils
 import com.android.systemui.log.core.Logger
 import com.android.systemui.log.core.MessageBuffer
-import com.android.systemui.monet.ColorScheme
 import com.android.systemui.monet.Style as MonetStyle
-import com.android.systemui.monet.TonalPalette
 import java.io.IOException
-import kotlin.math.abs
 
 class AssetLoader
 private constructor(
     private val pluginCtx: Context,
     private val sysuiCtx: Context,
     private val baseDir: String,
-    var colorScheme: ColorScheme?,
     var seedColor: Int?,
     var overrideChroma: Float?,
     val typefaceCache: TypefaceCache,
-    val getThemeSeedColor: (Context) -> Int,
     messageBuffer: MessageBuffer,
 ) {
     val logger = Logger(messageBuffer, TAG)
@@ -59,12 +49,10 @@
         sysuiCtx: Context,
         baseDir: String,
         messageBuffer: MessageBuffer,
-        getThemeSeedColor: ((Context) -> Int)? = null,
     ) : this(
         pluginCtx,
         sysuiCtx,
         baseDir,
-        colorScheme = null,
         seedColor = null,
         overrideChroma = null,
         typefaceCache =
@@ -72,7 +60,6 @@
                 // TODO(b/364680873): Move constant to config_clockFontFamily when shipping
                 return@TypefaceCache Typeface.create("google-sans-flex-clock", Typeface.NORMAL)
             },
-        getThemeSeedColor = getThemeSeedColor ?: Companion::getThemeSeedColor,
         messageBuffer = messageBuffer,
     )
 
@@ -92,107 +79,6 @@
         return res.getString(id)
     }
 
-    fun tryReadColor(resStr: String): Int? = tryRead(resStr, ::readColor)
-
-    fun readColor(resStr: String): Int {
-        if (resStr.startsWith("#")) {
-            return Color.parseColor(resStr)
-        }
-
-        val schemeColor = tryParseColorFromScheme(resStr)
-        if (schemeColor != null) {
-            logColor("ColorScheme: $resStr", schemeColor)
-            return checkChroma(schemeColor)
-        }
-
-        val result = resolveColorResourceId(resStr)
-        if (result == null) {
-            throw IOException("Failed to parse color: $resStr")
-        }
-
-        val (res, colorId, targetTone) = result
-        val color = res.getColor(colorId)
-        if (targetTone == null || TonalPalette.SHADE_KEYS.contains(targetTone.toInt())) {
-            logColor("Resources: $resStr", color)
-            return checkChroma(color)
-        } else {
-            val interpolatedColor =
-                ColorStateList.valueOf(color)
-                    .withLStar((1000f - targetTone) / 10f)
-                    .getDefaultColor()
-            logColor("Resources (interpolated tone): $resStr", interpolatedColor)
-            return checkChroma(interpolatedColor)
-        }
-    }
-
-    private fun checkChroma(color: Int): Int {
-        return overrideChroma?.let {
-            val cam = Cam.fromInt(color)
-            val tone = CamUtils.lstarFromInt(color)
-            val result = ColorUtils.CAMToColor(cam.hue, it, tone)
-            logColor("Chroma override", result)
-            result
-        } ?: color
-    }
-
-    private fun tryParseColorFromScheme(resStr: String): Int? {
-        val colorScheme = this.colorScheme
-        if (colorScheme == null) {
-            logger.w("No color scheme available")
-            return null
-        }
-
-        val (packageName, category, name) = parseResourceId(resStr)
-        if (packageName != "android" || category != "color") {
-            logger.w("Failed to parse package from $resStr")
-            return null
-        }
-
-        var parts = name.split('_')
-        if (parts.size != 3) {
-            logger.w("Failed to find palette and shade from $name")
-            return null
-        }
-        val (_, paletteKey, shadeKeyStr) = parts
-
-        val palette =
-            when (paletteKey) {
-                "accent1" -> colorScheme.accent1
-                "accent2" -> colorScheme.accent2
-                "accent3" -> colorScheme.accent3
-                "neutral1" -> colorScheme.neutral1
-                "neutral2" -> colorScheme.neutral2
-                else -> return null
-            }
-
-        if (shadeKeyStr.contains("+") || shadeKeyStr.contains("-")) {
-            val signIndex = shadeKeyStr.indexOfLast { it == '-' || it == '+' }
-            // Use the tone of the seed color if it was set explicitly.
-            var baseTone =
-                if (seedColor != null) colorScheme.seedTone.toFloat()
-                else shadeKeyStr.substring(0, signIndex).toFloatOrNull()
-            val diff = shadeKeyStr.substring(signIndex).toFloatOrNull()
-
-            if (baseTone == null) {
-                logger.w("Failed to parse base tone from $shadeKeyStr")
-                return null
-            }
-
-            if (diff == null) {
-                logger.w("Failed to parse relative tone from $shadeKeyStr")
-                return null
-            }
-            return palette.getAtTone(baseTone + diff)
-        } else {
-            val shadeKey = shadeKeyStr.toIntOrNull()
-            if (shadeKey == null) {
-                logger.w("Failed to parse tone from $shadeKeyStr")
-                return null
-            }
-            return palette.allShadesMapped.get(shadeKey) ?: palette.getAtTone(shadeKey.toFloat())
-        }
-    }
-
     fun readFontAsset(resStr: String): Typeface = typefaceCache.getTypeface(resStr)
 
     fun tryReadTextAsset(path: String?): String? = tryRead(path, ::readTextAsset)
@@ -250,52 +136,6 @@
         }
     }
 
-    fun resolveColorResourceId(resStr: String): Triple<Resources, Int, Float?>? {
-        var (packageName, category, name) = parseResourceId(resStr)
-
-        // Convert relative tonal specifiers to standard
-        val relIndex = name.indexOfLast { it == '_' }
-        val isToneRelative = name.contains("-") || name.contains("+")
-        val targetTone =
-            if (packageName != "android") {
-                null
-            } else if (isToneRelative) {
-                val signIndex = name.indexOfLast { it == '-' || it == '+' }
-                val baseTone = name.substring(relIndex + 1, signIndex).toFloatOrNull()
-                var diff = name.substring(signIndex).toFloatOrNull()
-                if (baseTone == null || diff == null) {
-                    logger.w("Failed to parse relative tone from $name")
-                    return null
-                }
-                baseTone + diff
-            } else {
-                val absTone = name.substring(relIndex + 1).toFloatOrNull()
-                if (absTone == null) {
-                    logger.w("Failed to parse absolute tone from $name")
-                    return null
-                }
-                absTone
-            }
-
-        if (
-            targetTone != null &&
-                (isToneRelative || !TonalPalette.SHADE_KEYS.contains(targetTone.toInt()))
-        ) {
-            val closeTone = TonalPalette.SHADE_KEYS.minBy { abs(it - targetTone) }
-            val prevName = name
-            name = name.substring(0, relIndex + 1) + closeTone
-            logger.i("Converted $prevName to $name")
-        }
-
-        val result = resolveResourceId(packageName, category, name)
-        if (result == null) {
-            return null
-        }
-
-        val (res, resId) = result
-        return Triple(res, resId, targetTone)
-    }
-
     fun resolveResourceId(resStr: String): Pair<Resources, Int>? {
         val (packageName, category, name) = parseResourceId(resStr)
         return resolveResourceId(packageName, category, name)
@@ -331,8 +171,7 @@
         try {
             if (path.startsWith("@")) {
                 val pair = resolveResourceId(path)
-                val colorPair = resolveColorResourceId(path)
-                return pair != null || colorPair != null
+                return pair != null
             } else {
                 val stream = pluginCtx.resources.assets.open("$baseDir$path")
                 if (stream == null) {
@@ -352,37 +191,14 @@
             pluginCtx,
             sysuiCtx,
             baseDir,
-            colorScheme,
             seedColor,
             overrideChroma,
             typefaceCache,
-            getThemeSeedColor,
             messageBuffer ?: logger.buffer,
         )
 
     fun setSeedColor(seedColor: Int?, style: MonetStyle?) {
         this.seedColor = seedColor
-        refreshColorPalette(style)
-    }
-
-    fun refreshColorPalette(style: MonetStyle?) {
-        val seedColor =
-            this.seedColor ?: getThemeSeedColor(sysuiCtx).also { logColor("Theme Seed Color", it) }
-        this.colorScheme =
-            ColorScheme(
-                seedColor,
-                false, // darkTheme is not used for palette generation
-                style ?: MonetStyle.CLOCK,
-            )
-
-        // Enforce low chroma on output colors if low chroma theme is selected
-        this.overrideChroma = run {
-            val cam = colorScheme?.seed?.let { Cam.fromInt(it) }
-            if (cam != null && cam.chroma < LOW_CHROMA_LIMIT) {
-                return@run cam.chroma * LOW_CHROMA_SCALE
-            }
-            return@run null
-        }
     }
 
     fun getClockPaddingStart(): Int {
@@ -430,22 +246,7 @@
         throw Exception("Cannot find id of $name from $TAG")
     }
 
-    private fun logColor(name: String, color: Int) {
-        if (DEBUG_COLOR) {
-            val cam = Cam.fromInt(color)
-            val tone = CamUtils.lstarFromInt(color)
-            logger.i("$name -> (hue: ${cam.hue}, chroma: ${cam.chroma}, tone: $tone)")
-        }
-    }
-
     companion object {
-        private val DEBUG_COLOR = true
-        private val LOW_CHROMA_LIMIT = 15
-        private val LOW_CHROMA_SCALE = 1.5f
         private val TAG = AssetLoader::class.simpleName!!
-
-        private fun getThemeSeedColor(ctx: Context): Int {
-            return ctx.resources.getColor(android.R.color.system_palette_key_color_primary_light)
-        }
     }
 }
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt
index eedddb2..a883977 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.plugins.clocks.ClockFaceConfig
 import com.android.systemui.plugins.clocks.ClockFaceEvents
 import com.android.systemui.plugins.clocks.ClockReactiveSetting
+import com.android.systemui.plugins.clocks.ThemeConfig
 import com.android.systemui.plugins.clocks.WeatherData
 import com.android.systemui.plugins.clocks.ZenData
 import com.android.systemui.shared.clocks.view.FlexClockView
@@ -46,7 +47,6 @@
 
     val layerControllers = mutableListOf<SimpleClockLayerController>()
     val dozeState = DefaultClockController.AnimationState(1F)
-    var isRegionDark = true
 
     override val view = FlexClockView(ctx, assets, messageBuffer)
 
@@ -103,10 +103,6 @@
                 view.onZenDataChanged(data)
             }
 
-            override fun onColorPaletteChanged(resources: Resources) {}
-
-            override fun onSeedColorChanged(seedColor: Int?) {}
-
             override fun onReactiveAxesChanged(axes: List<ClockReactiveSetting>) {}
 
             override var isReactiveTouchInteractionEnabled
@@ -116,10 +112,6 @@
                 }
         }
 
-    override fun updateColors() {
-        view.updateColors(assets, isRegionDark)
-    }
-
     override val animations =
         object : ClockAnimations {
             override fun enter() {
@@ -158,9 +150,15 @@
                 refreshTime()
             }
 
-            override fun onRegionDarknessChanged(isRegionDark: Boolean) {
-                this@ComposedDigitalLayerController.isRegionDark = isRegionDark
-                updateColors()
+            override fun onThemeChanged(theme: ThemeConfig) {
+                val color =
+                    when {
+                        theme.seedColor != null -> theme.seedColor!!
+                        theme.isDarkTheme -> resources.getColor(android.R.color.system_accent1_100)
+                        else -> resources.getColor(android.R.color.system_accent2_600)
+                    }
+
+                view.updateColor(color)
             }
 
             override fun onFontSettingChanged(fontSizePx: Float) {
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 5ed11ad..c5b7518 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -37,6 +37,7 @@
 import com.android.systemui.plugins.clocks.ClockReactiveSetting
 import com.android.systemui.plugins.clocks.ClockSettings
 import com.android.systemui.plugins.clocks.DefaultClockFaceLayout
+import com.android.systemui.plugins.clocks.ThemeConfig
 import com.android.systemui.plugins.clocks.WeatherData
 import com.android.systemui.plugins.clocks.ZenData
 import java.io.PrintWriter
@@ -100,28 +101,33 @@
         events.onLocaleChanged(Locale.getDefault())
     }
 
-    override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
+    override fun initialize(isDarkTheme: Boolean, dozeFraction: Float, foldFraction: Float) {
         largeClock.recomputePadding(null)
+
         largeClock.animations = LargeClockAnimations(largeClock.view, dozeFraction, foldFraction)
         smallClock.animations = DefaultClockAnimations(smallClock.view, dozeFraction, foldFraction)
-        events.onColorPaletteChanged(resources)
+
+        val theme = ThemeConfig(isDarkTheme, settings?.seedColor)
+        largeClock.events.onThemeChanged(theme)
+        smallClock.events.onThemeChanged(theme)
+
         events.onTimeZoneChanged(TimeZone.getDefault())
+
         smallClock.events.onTimeTick()
         largeClock.events.onTimeTick()
     }
 
     open inner class DefaultClockFaceController(
         override val view: AnimatableClockView,
-        var seedColor: Int?,
+        seedColor: Int?,
         messageBuffer: MessageBuffer?,
     ) : ClockFaceController {
-
         // MAGENTA is a placeholder, and will be assigned correctly in initialize
-        private var currentColor = Color.MAGENTA
-        private var isRegionDark = false
+        private var currentColor = seedColor ?: Color.MAGENTA
         protected var targetRegion: Rect? = null
 
         override val config = ClockFaceConfig()
+        override var theme = ThemeConfig(true, seedColor)
         override val layout =
             DefaultClockFaceLayout(view).apply {
                 views[0].id =
@@ -132,9 +138,6 @@
             internal set
 
         init {
-            if (seedColor != null) {
-                currentColor = seedColor!!
-            }
             view.setColors(DOZE_COLOR, currentColor)
             messageBuffer?.let { view.messageBuffer = it }
         }
@@ -143,9 +146,26 @@
             object : ClockFaceEvents {
                 override fun onTimeTick() = view.refreshTime()
 
-                override fun onRegionDarknessChanged(isRegionDark: Boolean) {
-                    this@DefaultClockFaceController.isRegionDark = isRegionDark
-                    updateColor()
+                override fun onThemeChanged(theme: ThemeConfig) {
+                    this@DefaultClockFaceController.theme = theme
+
+                    val color =
+                        when {
+                            theme.seedColor != null -> theme.seedColor!!
+                            theme.isDarkTheme ->
+                                resources.getColor(android.R.color.system_accent1_100)
+                            else -> resources.getColor(android.R.color.system_accent2_600)
+                        }
+
+                    if (currentColor == color) {
+                        return
+                    }
+
+                    currentColor = color
+                    view.setColors(DOZE_COLOR, color)
+                    if (!animations.dozeState.isActive) {
+                        view.animateColorChange()
+                    }
                 }
 
                 override fun onTargetRegionChanged(targetRegion: Rect?) {
@@ -165,27 +185,6 @@
             }
 
         open fun recomputePadding(targetRegion: Rect?) {}
-
-        fun updateColor() {
-            val color =
-                if (seedColor != null) {
-                    seedColor!!
-                } else if (isRegionDark) {
-                    resources.getColor(android.R.color.system_accent1_100)
-                } else {
-                    resources.getColor(android.R.color.system_accent2_600)
-                }
-
-            if (currentColor == color) {
-                return
-            }
-
-            currentColor = color
-            view.setColors(DOZE_COLOR, color)
-            if (!animations.dozeState.isActive) {
-                view.animateColorChange()
-            }
-        }
     }
 
     inner class LargeClockFaceController(
@@ -248,19 +247,6 @@
         override fun onTimeZoneChanged(timeZone: TimeZone) =
             clocks.forEach { it.onTimeZoneChanged(timeZone) }
 
-        override fun onColorPaletteChanged(resources: Resources) {
-            largeClock.updateColor()
-            smallClock.updateColor()
-        }
-
-        override fun onSeedColorChanged(seedColor: Int?) {
-            largeClock.seedColor = seedColor
-            smallClock.seedColor = seedColor
-
-            largeClock.updateColor()
-            smallClock.updateColor()
-        }
-
         override fun onLocaleChanged(locale: Locale) {
             val nf = NumberFormat.getInstance(locale)
             if (nf.format(FORMAT_NUMBER.toLong()) == burmeseNumerals) {
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
index 2a85823..8e838f3 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
@@ -58,6 +58,7 @@
             val buffer =
                 messageBuffers?.infraMessageBuffer ?: LogcatOnlyMessageBuffer(LogLevel.INFO)
             val assets = AssetLoader(ctx, ctx, "clocks/", buffer)
+            assets.setSeedColor(settings.seedColor, null)
             FlexClockController(ctx, resources, assets, FLEX_DESIGN, messageBuffers)
         } else {
             DefaultClockController(
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt
index b8ebd0f..a75022a 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockController.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.plugins.clocks.ClockEvents
 import com.android.systemui.plugins.clocks.ClockMessageBuffers
 import com.android.systemui.plugins.clocks.ClockReactiveSetting
+import com.android.systemui.plugins.clocks.ThemeConfig
 import com.android.systemui.plugins.clocks.WeatherData
 import com.android.systemui.plugins.clocks.ZenData
 import com.android.systemui.shared.clocks.view.FlexClockView
@@ -97,24 +98,6 @@
                 largeClock.events.onLocaleChanged(locale)
             }
 
-            override fun onColorPaletteChanged(resources: Resources) {
-                assets.refreshColorPalette(design.colorPalette)
-                smallClock.assets.refreshColorPalette(design.colorPalette)
-                largeClock.assets.refreshColorPalette(design.colorPalette)
-
-                smallClock.events.onColorPaletteChanged(resources)
-                largeClock.events.onColorPaletteChanged(resources)
-            }
-
-            override fun onSeedColorChanged(seedColor: Int?) {
-                assets.setSeedColor(seedColor, design.colorPalette)
-                smallClock.assets.setSeedColor(seedColor, design.colorPalette)
-                largeClock.assets.setSeedColor(seedColor, design.colorPalette)
-
-                smallClock.events.onSeedColorChanged(seedColor)
-                largeClock.events.onSeedColorChanged(seedColor)
-            }
-
             override fun onWeatherDataChanged(data: WeatherData) {
                 smallClock.events.onWeatherDataChanged(data)
                 largeClock.events.onWeatherDataChanged(data)
@@ -136,14 +119,21 @@
             }
         }
 
-    override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
-        events.onColorPaletteChanged(resources)
-        smallClock.animations.doze(dozeFraction)
-        largeClock.animations.doze(dozeFraction)
-        smallClock.animations.fold(foldFraction)
-        largeClock.animations.fold(foldFraction)
-        smallClock.events.onTimeTick()
-        largeClock.events.onTimeTick()
+    override fun initialize(isDarkTheme: Boolean, dozeFraction: Float, foldFraction: Float) {
+        val theme = ThemeConfig(isDarkTheme, assets.seedColor)
+        smallClock.run {
+            events.onThemeChanged(theme)
+            animations.doze(dozeFraction)
+            animations.fold(foldFraction)
+            events.onTimeTick()
+        }
+
+        largeClock.run {
+            events.onThemeChanged(theme)
+            animations.doze(dozeFraction)
+            animations.fold(foldFraction)
+            events.onTimeTick()
+        }
     }
 
     override fun dump(pw: PrintWriter) {}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
index 9067fb0..8ffc00d 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.plugins.clocks.ClockFaceLayout
 import com.android.systemui.plugins.clocks.ClockReactiveSetting
 import com.android.systemui.plugins.clocks.DefaultClockFaceLayout
+import com.android.systemui.plugins.clocks.ThemeConfig
 import com.android.systemui.plugins.clocks.WeatherData
 import com.android.systemui.plugins.clocks.ZenData
 import com.android.systemui.shared.clocks.view.FlexClockView
@@ -59,6 +60,8 @@
             hasCustomPositionUpdatedAnimation = false // TODO(b/364673982)
         )
 
+    override var theme = ThemeConfig(true, assets.seedColor)
+
     private val keyguardLargeClockTopMargin =
         resources.getDimensionPixelSize(R.dimen.keyguard_large_clock_top_margin)
     val layerController: SimpleClockLayerController
@@ -135,18 +138,8 @@
             layerController.faceEvents.onFontSettingChanged(fontSizePx)
         }
 
-        override fun onColorPaletteChanged(resources: Resources) {
-            layerController.events.onColorPaletteChanged(resources)
-            layerController.updateColors()
-        }
-
-        override fun onSeedColorChanged(seedColor: Int?) {
-            layerController.events.onSeedColorChanged(seedColor)
-            layerController.updateColors()
-        }
-
-        override fun onRegionDarknessChanged(isRegionDark: Boolean) {
-            layerController.faceEvents.onRegionDarknessChanged(isRegionDark)
+        override fun onThemeChanged(theme: ThemeConfig) {
+            layerController.faceEvents.onThemeChanged(theme)
         }
 
         override fun onReactiveAxesChanged(axes: List<ClockReactiveSetting>) {}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleClockLayerController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleClockLayerController.kt
index 5d1a2db..af00cc2 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleClockLayerController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleClockLayerController.kt
@@ -31,8 +31,4 @@
     val config: ClockFaceConfig
 
     @VisibleForTesting var fakeTimeMills: Long?
-
-    // Called immediately after either onColorPaletteChanged or onSeedColorChanged is called.
-    // Provided for convience to not duplicate color update logic after state updated.
-    fun updateColors() {}
 }
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt
index ce1eae4..7b1960e 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt
@@ -32,6 +32,7 @@
 import com.android.systemui.plugins.clocks.ClockFaceConfig
 import com.android.systemui.plugins.clocks.ClockFaceEvents
 import com.android.systemui.plugins.clocks.ClockReactiveSetting
+import com.android.systemui.plugins.clocks.ThemeConfig
 import com.android.systemui.plugins.clocks.WeatherData
 import com.android.systemui.plugins.clocks.ZenData
 import com.android.systemui.shared.clocks.view.SimpleDigitalClockView
@@ -63,7 +64,6 @@
 
     override val config = ClockFaceConfig()
     var dozeState: DefaultClockController.AnimationState? = null
-    var isRegionDark: Boolean = true
 
     init {
         view.layoutParams =
@@ -240,10 +240,6 @@
                 refreshTime()
             }
 
-            override fun onColorPaletteChanged(resources: Resources) {}
-
-            override fun onSeedColorChanged(seedColor: Int?) {}
-
             override fun onWeatherDataChanged(data: WeatherData) {}
 
             override fun onAlarmDataChanged(data: AlarmData) {}
@@ -253,11 +249,6 @@
             override fun onReactiveAxesChanged(axes: List<ClockReactiveSetting>) {}
         }
 
-    override fun updateColors() {
-        view.updateColors(assets, isRegionDark)
-        refreshTime()
-    }
-
     override val animations =
         object : ClockAnimations {
             override fun enter() {
@@ -309,21 +300,20 @@
                 applyMargin()
             }
 
-            override fun onRegionDarknessChanged(isRegionDark: Boolean) {
-                this@SimpleDigitalHandLayerController.isRegionDark = isRegionDark
-                updateColors()
+            override fun onThemeChanged(theme: ThemeConfig) {
+                val color =
+                    when {
+                        theme.seedColor != null -> theme.seedColor!!
+                        theme.isDarkTheme -> resources.getColor(android.R.color.system_accent1_100)
+                        else -> resources.getColor(android.R.color.system_accent2_600)
+                    }
+
+                view.updateColor(color)
+                refreshTime()
             }
 
             override fun onTargetRegionChanged(targetRegion: Rect?) {}
 
             override fun onSecondaryDisplayChanged(onSecondaryDisplay: Boolean) {}
         }
-
-    companion object {
-        private val DEFAULT_LIGHT_COLOR = "@android:color/system_accent1_100+0"
-        private val DEFAULT_DARK_COLOR = "@android:color/system_accent2_600+0"
-
-        fun getDefaultColor(assets: AssetLoader, isRegionDark: Boolean) =
-            assets.readColor(if (isRegionDark) DEFAULT_LIGHT_COLOR else DEFAULT_DARK_COLOR)
-    }
 }
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/DigitalClockFaceView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/DigitalClockFaceView.kt
index 81efcb9..ce4d71c 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/DigitalClockFaceView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/DigitalClockFaceView.kt
@@ -27,7 +27,6 @@
 import com.android.systemui.plugins.clocks.AlarmData
 import com.android.systemui.plugins.clocks.WeatherData
 import com.android.systemui.plugins.clocks.ZenData
-import com.android.systemui.shared.clocks.AssetLoader
 import com.android.systemui.shared.clocks.LogUtil
 import java.util.Locale
 
@@ -122,8 +121,8 @@
 
     open fun onPositionUpdated(fromLeft: Int, direction: Int, fraction: Float) {}
 
-    fun updateColors(assets: AssetLoader, isRegionDark: Boolean) {
-        digitalClockTextViewMap.forEach { _, view -> view.updateColors(assets, isRegionDark) }
+    fun updateColor(color: Int) {
+        digitalClockTextViewMap.forEach { _, view -> view.updateColor(color) }
         invalidate()
     }
 
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
index 74617b1..baed3ae 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
@@ -50,7 +50,6 @@
 import com.android.systemui.shared.clocks.RenderType
 import com.android.systemui.shared.clocks.TextStyle
 import java.lang.Thread
-import kotlin.math.ceil
 import kotlin.math.max
 import kotlin.math.min
 
@@ -94,11 +93,6 @@
     private var aodDozingInterpolator: Interpolator? = null
 
     @VisibleForTesting lateinit var textAnimator: TextAnimator
-    @VisibleForTesting var outlineAnimator: TextAnimator? = null
-    // used for hollow style for AOD version
-    // because stroke style for some fonts have some unwanted inner strokes
-    // we want to draw this layer on top to oclude them
-    @VisibleForTesting var innerAnimator: TextAnimator? = null
 
     lateinit var typefaceCache: TypefaceVariantCache
         private set
@@ -108,8 +102,6 @@
         if (this::textAnimator.isInitialized) {
             textAnimator.typefaceCache = value
         }
-        outlineAnimator?.typefaceCache = value
-        innerAnimator?.typefaceCache = value
     }
 
     @VisibleForTesting
@@ -136,32 +128,14 @@
         set(value) = super.setText(value)
 
     var textBorderWidth = 0F
-    var aodBorderWidth = 0F
     var baselineFromMeasure = 0
+    var lockscreenColor = Color.WHITE
 
-    var textFillColor: Int? = null
-    var textOutlineColor = TEXT_OUTLINE_DEFAULT_COLOR
-    var aodFillColor = AOD_DEFAULT_COLOR
-    var aodOutlineColor = AOD_OUTLINE_DEFAULT_COLOR
-
-    override fun updateColors(assets: AssetLoader, isRegionDark: Boolean) {
-        val fillColor = if (isRegionDark) textStyle.fillColorLight else textStyle.fillColorDark
-        textFillColor =
-            fillColor?.let { assets.readColor(it) }
-                ?: assets.seedColor
-                ?: getDefaultColor(assets, isRegionDark)
-        // for NumberOverlapView to read correct color
-        lockScreenPaint.color = textFillColor as Int
-        textStyle.outlineColor?.let { textOutlineColor = assets.readColor(it) }
-            ?: run { textOutlineColor = TEXT_OUTLINE_DEFAULT_COLOR }
-        (aodStyle.fillColorLight ?: aodStyle.fillColorDark)?.let {
-            aodFillColor = assets.readColor(it)
-        } ?: run { aodFillColor = AOD_DEFAULT_COLOR }
-        aodStyle.outlineColor?.let { aodOutlineColor = assets.readColor(it) }
-            ?: run { aodOutlineColor = AOD_OUTLINE_DEFAULT_COLOR }
+    override fun updateColor(color: Int) {
+        lockscreenColor = color
+        lockScreenPaint.color = lockscreenColor
         if (dozeFraction < 1f) {
-            textAnimator.setTextStyle(color = textFillColor, animate = false)
-            outlineAnimator?.setTextStyle(color = textOutlineColor, animate = false)
+            textAnimator.setTextStyle(color = lockscreenColor, animate = false)
         }
         invalidate()
     }
@@ -183,13 +157,9 @@
         if (layout != null) {
             if (!this::textAnimator.isInitialized) {
                 textAnimator = textAnimatorFactory(layout, ::invalidate)
-                outlineAnimator = textAnimatorFactory(layout) {}
-                innerAnimator = textAnimatorFactory(layout) {}
                 setInterpolatorPaint()
             } else {
                 textAnimator.updateLayout(layout)
-                outlineAnimator?.updateLayout(layout)
-                innerAnimator?.updateLayout(layout)
             }
             baselineFromMeasure = layout.getLineBaseline(0)
         } else {
@@ -248,10 +218,7 @@
             canvas.translate(0F, measuredHeight.toFloat())
             canvas.rotate(-90F)
         }
-        logger.d({ "onDraw(); ls: $str1; aod: $str2;" }) {
-            str1 = textAnimator.textInterpolator.shapedText
-            str2 = outlineAnimator?.textInterpolator?.shapedText
-        }
+        logger.d({ "onDraw(); ls: $str1" }) { str1 = textAnimator.textInterpolator.shapedText }
         val translation = getLocalTranslation()
         canvas.translate(translation.x.toFloat(), translation.y.toFloat())
         digitTranslateAnimator?.let {
@@ -266,7 +233,6 @@
                 (-translation.y + measuredHeight).toFloat(),
                 null,
             )
-            outlineAnimator?.draw(canvas)
             canvas.saveLayer(
                 -translation.x.toFloat(),
                 -translation.y.toFloat(),
@@ -274,11 +240,8 @@
                 (-translation.y + measuredHeight).toFloat(),
                 Paint().also { it.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT) },
             )
-            innerAnimator?.draw(canvas)
             canvas.restore()
             canvas.restore()
-        } else if (aodStyle.renderType != RenderType.CHANGE_WEIGHT) {
-            outlineAnimator?.draw(canvas)
         }
         textAnimator.draw(canvas)
 
@@ -309,30 +272,13 @@
         val fvar = if (isDozing) aodStyle.fontVariation else textStyle.fontVariation
         textAnimator.setTextStyle(
             animate = isAnimated && isAnimationEnabled,
-            color = if (isDozing) aodFillColor else textFillColor,
+            color = if (isDozing) AOD_COLOR else lockscreenColor,
             textSize = if (isDozing) aodFontSizePx else lockScreenPaint.textSize,
             fvar = fvar,
             duration = aodStyle.transitionDuration,
             interpolator = aodDozingInterpolator,
         )
         updateTextBoundsForTextAnimator()
-        outlineAnimator?.setTextStyle(
-            animate = isAnimated && isAnimationEnabled,
-            color = if (isDozing) aodOutlineColor else textOutlineColor,
-            textSize = if (isDozing) aodFontSizePx else lockScreenPaint.textSize,
-            fvar = fvar,
-            strokeWidth = if (isDozing) aodBorderWidth else textBorderWidth,
-            duration = aodStyle.transitionDuration,
-            interpolator = aodDozingInterpolator,
-        )
-        innerAnimator?.setTextStyle(
-            animate = isAnimated && isAnimationEnabled,
-            color = Color.WHITE,
-            textSize = if (isDozing) aodFontSizePx else lockScreenPaint.textSize,
-            fvar = fvar,
-            duration = aodStyle.transitionDuration,
-            interpolator = aodDozingInterpolator,
-        )
     }
 
     override fun animateCharge() {
@@ -345,8 +291,6 @@
         val endFvar = if (dozeFraction == 0F) textStyle.fontVariation else aodStyle.fontVariation
         val startAnimPhase2 = Runnable {
             textAnimator.setTextStyle(fvar = endFvar, animate = isAnimationEnabled)
-            outlineAnimator?.setTextStyle(fvar = endFvar, animate = isAnimationEnabled)
-            innerAnimator?.setTextStyle(fvar = endFvar, animate = isAnimationEnabled)
             updateTextBoundsForTextAnimator()
         }
         textAnimator.setTextStyle(
@@ -354,8 +298,6 @@
             animate = isAnimationEnabled,
             onAnimationEnd = startAnimPhase2,
         )
-        outlineAnimator?.setTextStyle(fvar = middleFvar, animate = isAnimationEnabled)
-        innerAnimator?.setTextStyle(fvar = middleFvar, animate = isAnimationEnabled)
         updateTextBoundsForTextAnimator()
     }
 
@@ -373,8 +315,6 @@
             requestLayout()
         } else {
             textAnimator.updateLayout(layout)
-            outlineAnimator?.updateLayout(layout)
-            innerAnimator?.updateLayout(layout)
         }
     }
 
@@ -500,8 +440,7 @@
             this.aodStyle = textStyle.copy()
         }
         this.aodStyle.transitionInterpolator?.let { aodDozingInterpolator = it.interpolator }
-        aodBorderWidth = parser.convert(this.aodStyle.borderWidth ?: DEFAULT_AOD_STROKE_WIDTH)
-        lockScreenPaint.strokeWidth = ceil(max(textBorderWidth, aodBorderWidth))
+        lockScreenPaint.strokeWidth = textBorderWidth
         measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)
         setInterpolatorPaint()
         recomputeMaxSingleDigitSizes()
@@ -524,27 +463,14 @@
             val lastUnconstrainedHeight = textBounds.height() + lockScreenPaint.strokeWidth * 2
             fontSizeAdjustFactor = lastUnconstrainedHeight / lastUnconstrainedTextSize
         }
-        textStyle.borderWidthScale?.let {
-            textBorderWidth = fontSizePx * it
-            if (dozeFraction < 1.0F) {
-                outlineAnimator?.setTextStyle(strokeWidth = textBorderWidth, animate = false)
-            }
-        }
-        aodStyle.borderWidthScale?.let {
-            aodBorderWidth = fontSizePx * it
-            if (dozeFraction > 0.0F) {
-                outlineAnimator?.setTextStyle(strokeWidth = aodBorderWidth, animate = false)
-            }
-        }
+        textStyle.borderWidthScale?.let { textBorderWidth = fontSizePx * it }
 
-        lockScreenPaint.strokeWidth = ceil(max(textBorderWidth, aodBorderWidth))
+        lockScreenPaint.strokeWidth = textBorderWidth
         recomputeMaxSingleDigitSizes()
 
         if (this::textAnimator.isInitialized) {
             textAnimator.setTextStyle(textSize = lockScreenPaint.textSize, animate = false)
         }
-        outlineAnimator?.setTextStyle(textSize = lockScreenPaint.textSize, animate = false)
-        innerAnimator?.setTextStyle(textSize = lockScreenPaint.textSize, animate = false)
     }
 
     private fun recomputeMaxSingleDigitSizes() {
@@ -570,42 +496,7 @@
             textAnimator.setTextStyle(
                 fvar = textStyle.fontVariation,
                 textSize = lockScreenPaint.textSize,
-                color = textFillColor,
-                animate = false,
-            )
-        }
-
-        if (outlineAnimator != null) {
-            outlineAnimator!!
-                .textInterpolator
-                .targetPaint
-                .set(
-                    TextPaint(lockScreenPaint).also {
-                        it.style =
-                            if (aodStyle.renderType == RenderType.HOLLOW_TEXT)
-                                Paint.Style.FILL_AND_STROKE
-                            else Paint.Style.STROKE
-                    }
-                )
-            outlineAnimator!!.textInterpolator.onTargetPaintModified()
-            outlineAnimator!!.setTextStyle(
-                fvar = aodStyle.fontVariation,
-                textSize = lockScreenPaint.textSize,
-                color = Color.TRANSPARENT,
-                animate = false,
-            )
-        }
-
-        if (innerAnimator != null) {
-            innerAnimator!!
-                .textInterpolator
-                .targetPaint
-                .set(TextPaint(lockScreenPaint).also { it.style = Paint.Style.FILL })
-            innerAnimator!!.textInterpolator.onTargetPaintModified()
-            innerAnimator!!.setTextStyle(
-                fvar = aodStyle.fontVariation,
-                textSize = lockScreenPaint.textSize,
-                color = Color.WHITE,
+                color = lockscreenColor,
                 animate = false,
             )
         }
@@ -641,14 +532,7 @@
     }
 
     companion object {
-        val DEFAULT_AOD_STROKE_WIDTH = "2dp"
-        val TEXT_OUTLINE_DEFAULT_COLOR = Color.TRANSPARENT
-        val AOD_DEFAULT_COLOR = Color.TRANSPARENT
-        val AOD_OUTLINE_DEFAULT_COLOR = Color.WHITE
-        private val DEFAULT_LIGHT_COLOR = "@android:color/system_accent1_100+0"
-        private val DEFAULT_DARK_COLOR = "@android:color/system_accent2_600+0"
-
-        fun getDefaultColor(assets: AssetLoader, isRegionDark: Boolean) =
-            assets.readColor(if (isRegionDark) DEFAULT_LIGHT_COLOR else DEFAULT_DARK_COLOR)
+        val AOD_STROKE_WIDTH = "2dp"
+        val AOD_COLOR = Color.WHITE
     }
 }
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockView.kt
index bbd2d3d..30b54d8 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockView.kt
@@ -32,7 +32,7 @@
 
     fun applyTextSize(targetFontSizePx: Float?, constrainedByHeight: Boolean = false)
 
-    fun updateColors(assets: AssetLoader, isRegionDark: Boolean)
+    fun updateColor(color: Int)
 
     fun refreshTime()
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/ShutdownUiTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/ShutdownUiTest.java
index 73509e2..acc17e7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/ShutdownUiTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/globalactions/ShutdownUiTest.java
@@ -19,20 +19,25 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNull;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.res.Resources;
 import android.nearby.NearbyManager;
 import android.net.platform.flags.Flags;
 import android.os.PowerManager;
 import android.platform.test.annotations.DisableFlags;
 import android.platform.test.annotations.EnableFlags;
+import android.testing.TestableLooper;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.BlurUtils;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -46,14 +51,13 @@
 
     ShutdownUi mShutdownUi;
     @Mock
-    BlurUtils mBlurUtils;
-    @Mock
     NearbyManager mNearbyManager;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mShutdownUi = new ShutdownUi(getContext(), mBlurUtils, mNearbyManager);
+        mContext = spy(mContext);
+        mShutdownUi = new ShutdownUi(mContext, mNearbyManager);
     }
 
     @Test
@@ -140,4 +144,24 @@
         assertEquals(actualLayout, expectedLayout);
     }
 
+    /**
+     * Main looper required here because showShutdown UI creates a dialog which instantiates a
+     * handler that needs to be on the main thread.
+     */
+    @TestableLooper.RunWithLooper(setAsMainLooper = true)
+    @Test
+    public void showShutdownUi_loadsShutdownTextColorAndAlpha() {
+        this.allowTestableLooperAsMainThread();
+
+        Resources mockResources = spy(mContext.getResources());
+        when(mContext.getResources()).thenReturn(mockResources);
+
+        mShutdownUi.showShutdownUi(false, "test");
+
+        verify(mockResources).getFloat(
+                eq(com.android.systemui.res.R.dimen.shutdown_scrim_behind_alpha));
+        verify(mockResources).getColor(
+                eq(com.android.systemui.res.R.color.global_actions_shutdown_ui_text),
+                any());
+    }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index bbe03f0..7e86ff3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.customization.R
 import com.android.systemui.plugins.clocks.ClockId
 import com.android.systemui.plugins.clocks.ClockSettings
+import com.android.systemui.plugins.clocks.ThemeConfig
 import com.android.systemui.shared.clocks.DefaultClockController.Companion.DOZE_COLOR
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
@@ -72,8 +73,7 @@
             .thenReturn(mockSmallClockView)
         whenever(layoutInflater.inflate(eq(R.layout.clock_default_large), any(), anyBoolean()))
             .thenReturn(mockLargeClockView)
-        whenever(resources.getString(R.string.clock_default_name))
-            .thenReturn("DEFAULT_CLOCK_NAME")
+        whenever(resources.getString(R.string.clock_default_name)).thenReturn("DEFAULT_CLOCK_NAME")
         whenever(resources.getString(R.string.clock_default_description))
             .thenReturn("DEFAULT_CLOCK_DESC")
         whenever(resources.getDrawable(R.drawable.clock_default_thumbnail, null))
@@ -108,7 +108,7 @@
         verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
         verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
 
-        clock.initialize(resources, 0f, 0f)
+        clock.initialize(true, 0f, 0f)
 
         val expectedColor = 0
         verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
@@ -167,21 +167,22 @@
     }
 
     @Test
-    fun defaultClock_events_onColorPaletteChanged() {
+    fun defaultClock_events_onThemeChanged_noSeed() {
         val expectedColor = 0
         val clock = provider.createClock(DEFAULT_CLOCK_ID)
 
         verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
         verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
 
-        clock.events.onColorPaletteChanged(resources)
+        clock.smallClock.events.onThemeChanged(ThemeConfig(true, null))
+        clock.largeClock.events.onThemeChanged(ThemeConfig(true, null))
 
         verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
         verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
     }
 
     @Test
-    fun defaultClock_events_onSeedColorChanged() {
+    fun defaultClock_events_onThemeChanged_newSeed() {
         val initSeedColor = 10
         val newSeedColor = 20
         val clock = provider.createClock(ClockSettings(DEFAULT_CLOCK_ID, initSeedColor))
@@ -189,7 +190,8 @@
         verify(mockSmallClockView).setColors(DOZE_COLOR, initSeedColor)
         verify(mockLargeClockView).setColors(DOZE_COLOR, initSeedColor)
 
-        clock.events.onSeedColorChanged(newSeedColor)
+        clock.smallClock.events.onThemeChanged(ThemeConfig(true, newSeedColor))
+        clock.largeClock.events.onThemeChanged(ThemeConfig(true, newSeedColor))
 
         verify(mockSmallClockView).setColors(DOZE_COLOR, newSeedColor)
         verify(mockLargeClockView).setColors(DOZE_COLOR, newSeedColor)
@@ -210,7 +212,7 @@
     fun test_aodClock_always_whiteColor() {
         val clock = provider.createClock(DEFAULT_CLOCK_ID)
         clock.smallClock.animations.doze(0.9f) // set AOD mode to active
-        clock.smallClock.events.onRegionDarknessChanged(true)
+        clock.smallClock.events.onThemeChanged(ThemeConfig(true, null))
         verify((clock.smallClock.view as AnimatableClockView), never()).animateAppearOnLockscreen()
     }
 }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
index 6d27b6f..f975c4f 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt
@@ -13,7 +13,6 @@
  */
 package com.android.systemui.plugins.clocks
 
-import android.content.res.Resources
 import android.graphics.Rect
 import android.graphics.drawable.Drawable
 import android.view.View
@@ -85,7 +84,7 @@
     val events: ClockEvents
 
     /** Initializes various rendering parameters. If never called, provides reasonable defaults. */
-    fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float)
+    fun initialize(isDarkTheme: Boolean, dozeFraction: Float, foldFraction: Float)
 
     /** Optional method for dumping debug information */
     fun dump(pw: PrintWriter)
@@ -108,6 +107,10 @@
     val config: ClockFaceConfig
 
     @get:SimpleProperty
+    /** Current theme information the clock is using */
+    val theme: ThemeConfig
+
+    @get:SimpleProperty
     /** Events specific to this clock face */
     val events: ClockFaceEvents
 
@@ -190,12 +193,6 @@
     /** Call whenever the locale changes */
     fun onLocaleChanged(locale: Locale)
 
-    /** Call whenever the color palette should update */
-    fun onColorPaletteChanged(resources: Resources)
-
-    /** Call if the seed color has changed and should be updated */
-    fun onSeedColorChanged(seedColor: Int?)
-
     /** Call whenever the weather data should update */
     fun onWeatherDataChanged(data: WeatherData)
 
@@ -269,11 +266,13 @@
     fun onTimeTick()
 
     /**
-     * Region Darkness specific to the clock face.
-     * - isRegionDark = dark theme -> clock should be light
-     * - !isRegionDark = light theme -> clock should be dark
+     * Call whenever the theme or seedColor is updated
+     *
+     * Theme can be specific to the clock face.
+     * - isDarkTheme -> clock should be light
+     * - !isDarkTheme -> clock should be dark
      */
-    fun onRegionDarknessChanged(isRegionDark: Boolean)
+    fun onThemeChanged(theme: ThemeConfig)
 
     /**
      * Call whenever font settings change. Pass in a target font size in pixels. The specific clock
@@ -294,6 +293,8 @@
     fun onSecondaryDisplayChanged(onSecondaryDisplay: Boolean)
 }
 
+data class ThemeConfig(val isDarkTheme: Boolean, val seedColor: Int?)
+
 /** Tick rates for clocks */
 enum class ClockTickRate(val value: Int) {
     PER_MINUTE(2), // Update the clock once per minute.
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index e5cf7cf..9ec038b 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -140,7 +140,7 @@
         val clockStr = clock.toString()
         loggers.forEach { it.d({ "New Clock: $str1" }) { str1 = clockStr } }
 
-        clock.initialize(resources, dozeAmount, 0f)
+        clock.initialize(isDarkTheme(), dozeAmount, 0f)
 
         if (!regionSamplingEnabled) {
             updateColors()
@@ -244,30 +244,30 @@
     private val regionSamplingEnabled = featureFlags.isEnabled(REGION_SAMPLING)
     private var largeClockOnSecondaryDisplay = false
 
-    private fun updateColors() {
-        if (regionSamplingEnabled) {
-            clock?.let { clock ->
-                smallRegionSampler?.let {
-                    val isRegionDark = it.currentRegionDarkness().isDark
-                    clock.smallClock.events.onRegionDarknessChanged(isRegionDark)
-                }
+    private fun isDarkTheme(): Boolean {
+        val isLightTheme = TypedValue()
+        context.theme.resolveAttribute(android.R.attr.isLightTheme, isLightTheme, true)
+        return isLightTheme.data == 0
+    }
 
-                largeRegionSampler?.let {
-                    val isRegionDark = it.currentRegionDarkness().isDark
-                    clock.largeClock.events.onRegionDarknessChanged(isRegionDark)
-                }
+    private fun updateColors() {
+        val isDarkTheme = isDarkTheme()
+        if (regionSamplingEnabled) {
+            clock?.smallClock?.run {
+                val isDark = smallRegionSampler?.currentRegionDarkness()?.isDark ?: isDarkTheme
+                events.onThemeChanged(theme.copy(isDarkTheme = isDark))
+            }
+            clock?.largeClock?.run {
+                val isDark = largeRegionSampler?.currentRegionDarkness()?.isDark ?: isDarkTheme
+                events.onThemeChanged(theme.copy(isDarkTheme = isDark))
             }
             return
         }
 
-        val isLightTheme = TypedValue()
-        context.theme.resolveAttribute(android.R.attr.isLightTheme, isLightTheme, true)
-        val isRegionDark = isLightTheme.data == 0
-
         clock?.run {
-            Log.i(TAG, "Region isDark: $isRegionDark")
-            smallClock.events.onRegionDarknessChanged(isRegionDark)
-            largeClock.events.onRegionDarknessChanged(isRegionDark)
+            Log.i(TAG, "isThemeDark: $isDarkTheme")
+            smallClock.events.onThemeChanged(smallClock.theme.copy(isDarkTheme = isDarkTheme))
+            largeClock.events.onThemeChanged(largeClock.theme.copy(isDarkTheme = isDarkTheme))
         }
     }
 
@@ -308,7 +308,6 @@
     private val configListener =
         object : ConfigurationController.ConfigurationListener {
             override fun onThemeChanged() {
-                clock?.run { events.onColorPaletteChanged(resources) }
                 updateColors()
             }
 
@@ -505,7 +504,7 @@
         largeRegionSampler?.stopRegionSampler()
         smallTimeListener?.stop()
         largeTimeListener?.stop()
-        clock?.apply {
+        clock?.run {
             smallClock.view.removeOnAttachStateChangeListener(smallClockOnAttachStateChangeListener)
             largeClock.view.removeOnAttachStateChangeListener(largeClockOnAttachStateChangeListener)
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index c7ea980..11dde6a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -465,7 +465,8 @@
         super.onLayout(changed, l, t, r, b);
         // TODO: b/305022530
         if (mClock != null && mClock.getConfig().getId().equals("DIGITAL_CLOCK_METRO")) {
-            mClock.getEvents().onColorPaletteChanged(mContext.getResources());
+            mClock.getSmallClock().getEvents().onThemeChanged(mClock.getSmallClock().getTheme());
+            mClock.getLargeClock().getEvents().onThemeChanged(mClock.getLargeClock().getTheme());
         }
 
         if (changed) {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java b/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java
index ccd69ca..4599afa 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java
@@ -36,10 +36,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.R;
-import com.android.settingslib.Utils;
 import com.android.systemui.scrim.ScrimDrawable;
-import com.android.systemui.statusbar.BlurUtils;
-import com.android.systemui.statusbar.phone.ScrimController;
 
 import javax.inject.Inject;
 
@@ -49,13 +46,11 @@
 public class ShutdownUi {
 
     private Context mContext;
-    private BlurUtils mBlurUtils;
     private NearbyManager mNearbyManager;
 
     @Inject
-    public ShutdownUi(Context context, BlurUtils blurUtils, NearbyManager nearbyManager) {
+    public ShutdownUi(Context context, NearbyManager nearbyManager) {
         mContext = context;
-        mBlurUtils = blurUtils;
         mNearbyManager = nearbyManager;
     }
 
@@ -63,25 +58,17 @@
      * Display the shutdown UI.
      * @param isReboot Whether the device will be rebooting after this shutdown.
      * @param reason Cause for the shutdown.
+     * @return Shutdown dialog.
      */
-    public void showShutdownUi(boolean isReboot, String reason) {
+    public Dialog showShutdownUi(boolean isReboot, String reason) {
         ScrimDrawable background = new ScrimDrawable();
 
         final Dialog d = new Dialog(mContext,
                 com.android.systemui.res.R.style.Theme_SystemUI_Dialog_GlobalActions);
 
-        d.setOnShowListener(dialog -> {
-            if (mBlurUtils.supportsBlursOnWindows()) {
-                int backgroundAlpha = (int) (ScrimController.BUSY_SCRIM_ALPHA * 255);
-                background.setAlpha(backgroundAlpha);
-                mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
-                        (int) mBlurUtils.blurRadiusOfRatio(1), backgroundAlpha == 255);
-            } else {
-                float backgroundAlpha = mContext.getResources().getFloat(
-                        com.android.systemui.res.R.dimen.shutdown_scrim_behind_alpha);
-                background.setAlpha((int) (backgroundAlpha * 255));
-            }
-        });
+        float backgroundAlpha = mContext.getResources().getFloat(
+                com.android.systemui.res.R.dimen.shutdown_scrim_behind_alpha);
+        background.setAlpha((int) (backgroundAlpha * 255));
 
         // Window initialization
         Window window = d.getWindow();
@@ -110,14 +97,9 @@
         d.setContentView(getShutdownDialogContent(isReboot));
         d.setCancelable(false);
 
-        int color;
-        if (mBlurUtils.supportsBlursOnWindows()) {
-            color = Utils.getColorAttrDefaultColor(mContext,
-                    com.android.systemui.res.R.attr.wallpaperTextColor);
-        } else {
-            color = mContext.getResources().getColor(
-                    com.android.systemui.res.R.color.global_actions_shutdown_ui_text);
-        }
+        int color = mContext.getResources().getColor(
+                com.android.systemui.res.R.color.global_actions_shutdown_ui_text,
+                mContext.getTheme());
 
         ProgressBar bar = d.findViewById(R.id.progress);
         bar.getIndeterminateDrawable().setTint(color);
@@ -136,6 +118,8 @@
         }
 
         d.show();
+
+        return d;
     }
 
     /**
@@ -162,7 +146,6 @@
         }
     }
 
-
     @StringRes
     @VisibleForTesting int getRebootMessage(boolean isReboot, @Nullable String reason) {
         if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt
index e09e198..2e79249790 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt
@@ -178,7 +178,11 @@
             State.RUNNING_BACKWARDS_FROM_UP -> {
                 callback?.onEffectFinishedReversing()
                 setState(getStateForClick())
-                logEvent(qsTile?.tileSpec, state, "click action triggered")
+                logEvent(
+                    qsTile?.tileSpec,
+                    state,
+                    "click action triggered from handleAnimationComplete",
+                )
                 qsTile?.click(expandable)
             }
             State.RUNNING_BACKWARDS_FROM_CANCEL -> {
@@ -206,7 +210,7 @@
         if (keyguardStateController.isPrimaryBouncerShowing || !isStateClickable) return false
 
         setState(getStateForClick())
-        logEvent(qsTile?.tileSpec, state, "click action triggered")
+        logEvent(qsTile?.tileSpec, state, "click action triggered from onTileClick")
         qsTile?.click(expandable)
         return true
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt
index 21d1db4..46f5c05 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt
@@ -114,7 +114,18 @@
                     }
                     .invokeOnCompletion {
                         // recover seed color especially for Transit clock
-                        lastClock?.events?.onSeedColorChanged(clockRegistry.seedColor)
+                        lastClock?.apply {
+                            smallClock.run {
+                                events.onThemeChanged(
+                                    theme.copy(seedColor = clockRegistry.seedColor)
+                                )
+                            }
+                            largeClock.run {
+                                events.onThemeChanged(
+                                    theme.copy(seedColor = clockRegistry.seedColor)
+                                )
+                            }
+                        }
                     }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index 08d35a7..573ef68 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -80,6 +80,7 @@
 import com.android.systemui.monet.ColorScheme
 import com.android.systemui.monet.Style
 import com.android.systemui.plugins.clocks.ClockController
+import com.android.systemui.plugins.clocks.ThemeConfig
 import com.android.systemui.plugins.clocks.WeatherData
 import com.android.systemui.res.R
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
@@ -653,9 +654,13 @@
             // Note that when [wallpaperColors] is null, isWallpaperDark is true.
             val isWallpaperDark: Boolean =
                 (colors.colorHints.and(WallpaperColors.HINT_SUPPORTS_DARK_TEXT)) == 0
-            clock.events.onSeedColorChanged(
-                if (isWallpaperDark) lightClockColor else darkClockColor
-            )
+            val theme =
+                ThemeConfig(
+                    isWallpaperDark,
+                    if (isWallpaperDark) lightClockColor else darkClockColor,
+                )
+            clock.smallClock.events.onThemeChanged(theme)
+            clock.largeClock.events.onThemeChanged(theme)
         }
         // In clock preview, we should have a seed color for clock
         // before setting clock to clockEventController to avoid updateColor with seedColor == null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationClassificationUiFlag.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationClassificationUiFlag.kt
new file mode 100644
index 0000000..9020b76
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationClassificationUiFlag.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.notification.collection
+
+import android.app.Flags
+import com.android.systemui.flags.FlagToken
+import com.android.systemui.flags.RefactorFlagUtils
+
+/** Helper for android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION */
+@Suppress("NOTHING_TO_INLINE")
+object NotificationClassificationUiFlag {
+    const val FLAG_NAME = Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI
+
+    /** A token used for dependency declaration */
+    val token: FlagToken
+        get() = FlagToken(FLAG_NAME, isEnabled)
+
+    /** Are sections sorted by time? */
+    @JvmStatic
+    inline val isEnabled
+        get() = Flags.notificationClassificationUi()
+
+    /**
+     * Called to ensure code is only run when the flag is enabled. This protects users from the
+     * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+     * build to ensure that the refactor author catches issues in testing.
+     */
+    @JvmStatic
+    inline fun isUnexpectedlyInLegacyMode() =
+        RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
+
+    /**
+     * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+     * the flag is enabled to ensure that the refactor author catches issues in testing.
+     */
+    @JvmStatic
+    inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index c7b707d..2b167e4 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -52,6 +52,7 @@
 import com.android.systemui.plugins.clocks.ClockFaceEvents
 import com.android.systemui.plugins.clocks.ClockMessageBuffers
 import com.android.systemui.plugins.clocks.ClockTickRate
+import com.android.systemui.plugins.clocks.ThemeConfig
 import com.android.systemui.plugins.clocks.ZenData
 import com.android.systemui.plugins.clocks.ZenData.ZenMode
 import com.android.systemui.res.R
@@ -81,7 +82,6 @@
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyFloat
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
@@ -151,6 +151,8 @@
             .thenReturn(ClockFaceConfig(tickRate = ClockTickRate.PER_MINUTE))
         whenever(largeClockController.config)
             .thenReturn(ClockFaceConfig(tickRate = ClockTickRate.PER_MINUTE))
+        whenever(smallClockController.theme).thenReturn(ThemeConfig(true, null))
+        whenever(largeClockController.theme).thenReturn(ThemeConfig(true, null))
 
         zenModeRepository.addMode(MANUAL_DND_INACTIVE)
 
@@ -205,14 +207,15 @@
     @Test
     fun themeChanged_verifyClockPaletteUpdated() =
         runBlocking(IMMEDIATE) {
-            verify(smallClockEvents).onRegionDarknessChanged(anyBoolean())
-            verify(largeClockEvents).onRegionDarknessChanged(anyBoolean())
+            verify(smallClockEvents).onThemeChanged(any())
+            verify(largeClockEvents).onThemeChanged(any())
 
             val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
             verify(configurationController).addCallback(capture(captor))
             captor.value.onThemeChanged()
 
-            verify(events).onColorPaletteChanged(any())
+            verify(smallClockEvents, times(2)).onThemeChanged(any())
+            verify(largeClockEvents, times(2)).onThemeChanged(any())
         }
 
     @Test
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index ff2abd2..090ec65 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -319,6 +319,16 @@
         ":services.core.ravenwood-base{hoststubgen_services.core_apis.csv}",
         ":services.core.ravenwood-base{hoststubgen_services.core_keep_all.txt}",
         ":services.core.ravenwood-base{hoststubgen_services.core_dump.txt}",
+
+        ":framework-configinfrastructure.ravenwood-base{framework-configinfrastructure_stats.csv}",
+        ":framework-configinfrastructure.ravenwood-base{framework-configinfrastructure_apis.csv}",
+        ":framework-configinfrastructure.ravenwood-base{framework-configinfrastructure_keep_all.txt}",
+        ":framework-configinfrastructure.ravenwood-base{framework-configinfrastructure_dump.txt}",
+
+        ":framework-statsd.ravenwood-base{framework-statsd_stats.csv}",
+        ":framework-statsd.ravenwood-base{framework-statsd_apis.csv}",
+        ":framework-statsd.ravenwood-base{framework-statsd_keep_all.txt}",
+        ":framework-statsd.ravenwood-base{framework-statsd_dump.txt}",
     ],
 }
 
@@ -403,6 +413,9 @@
         // DeviceConfig
         "framework-configinfrastructure.ravenwood",
 
+        // StatsD
+        "framework-statsd.ravenwood",
+
         // Provide runtime versions of utils linked in below
         "junit",
         "truth",
diff --git a/ravenwood/Framework.bp b/ravenwood/Framework.bp
index 1bea434..d207738 100644
--- a/ravenwood/Framework.bp
+++ b/ravenwood/Framework.bp
@@ -344,3 +344,57 @@
         "framework-configinfrastructure.ravenwood.jar",
     ],
 }
+
+///////////////////////////////////
+// framework-statsd
+///////////////////////////////////
+
+java_genrule {
+    name: "framework-statsd.ravenwood-base",
+    tools: ["hoststubgen"],
+    cmd: "$(location hoststubgen) " +
+        "@$(location :ravenwood-standard-options) " +
+
+        "--debug-log $(location framework-statsd.log) " +
+        "--stats-file $(location framework-statsd_stats.csv) " +
+        "--supported-api-list-file $(location framework-statsd_apis.csv) " +
+        "--gen-keep-all-file $(location framework-statsd_keep_all.txt) " +
+        "--gen-input-dump-file $(location framework-statsd_dump.txt) " +
+
+        "--out-impl-jar $(location ravenwood.jar) " +
+        "--in-jar $(location :framework-statsd.impl{.jar}) " +
+
+        "--policy-override-file $(location :ravenwood-common-policies) " +
+        "--policy-override-file $(location :framework-statsd-ravenwood-policies) ",
+    srcs: [
+        ":framework-statsd.impl{.jar}",
+
+        ":ravenwood-common-policies",
+        ":framework-statsd-ravenwood-policies",
+        ":ravenwood-standard-options",
+    ],
+    out: [
+        "ravenwood.jar",
+
+        // Following files are created just as FYI.
+        "framework-statsd_keep_all.txt",
+        "framework-statsd_dump.txt",
+
+        "framework-statsd.log",
+        "framework-statsd_stats.csv",
+        "framework-statsd_apis.csv",
+    ],
+    visibility: ["//visibility:private"],
+}
+
+java_genrule {
+    name: "framework-statsd.ravenwood",
+    defaults: ["ravenwood-internal-only-visibility-genrule"],
+    cmd: "cp $(in) $(out)",
+    srcs: [
+        ":framework-statsd.ravenwood-base{ravenwood.jar}",
+    ],
+    out: [
+        "framework-statsd.ravenwood.jar",
+    ],
+}
diff --git a/ravenwood/runtime-helper-src/framework/android/util/StatsEvent.java b/ravenwood/runtime-helper-src/framework/android/util/StatsEvent.java
deleted file mode 100644
index 1e3b3fc..0000000
--- a/ravenwood/runtime-helper-src/framework/android/util/StatsEvent.java
+++ /dev/null
@@ -1,1035 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-// [ravenwood] This is an exact copy from StatsD, until we make StatsD available on Ravenwood.
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Build;
-import android.os.SystemClock;
-
-import androidx.annotation.RequiresApi;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-/**
- * StatsEvent builds and stores the buffer sent over the statsd socket.
- * This class defines and encapsulates the socket protocol.
- *
- * <p>Usage:</p>
- * <pre>
- *      // Pushed event
- *      StatsEvent statsEvent = StatsEvent.newBuilder()
- *          .setAtomId(atomId)
- *          .writeBoolean(false)
- *          .writeString("annotated String field")
- *          .addBooleanAnnotation(annotationId, true)
- *          .usePooledBuffer()
- *          .build();
- *      StatsLog.write(statsEvent);
- *
- *      // Pulled event
- *      StatsEvent statsEvent = StatsEvent.newBuilder()
- *          .setAtomId(atomId)
- *          .writeBoolean(false)
- *          .writeString("annotated String field")
- *          .addBooleanAnnotation(annotationId, true)
- *          .build();
- * </pre>
- * @hide
- **/
-@SystemApi
-public final class StatsEvent {
-    // Type Ids.
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_INT = 0x00;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_LONG = 0x01;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_STRING = 0x02;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_LIST = 0x03;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_FLOAT = 0x04;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_BOOLEAN = 0x05;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_BYTE_ARRAY = 0x06;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_OBJECT = 0x07;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_KEY_VALUE_PAIRS = 0x08;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_ATTRIBUTION_CHAIN = 0x09;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final byte TYPE_ERRORS = 0x0F;
-
-    // Error flags.
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_NO_TIMESTAMP = 0x1;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_NO_ATOM_ID = 0x2;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_OVERFLOW = 0x4;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_INVALID_ANNOTATION_ID = 0x40;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_TOO_MANY_FIELDS = 0x200;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x1000;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int ERROR_ATOM_ID_INVALID_POSITION = 0x2000;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting public static final int ERROR_LIST_TOO_LONG = 0x4000;
-
-    // Size limits.
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int MAX_ANNOTATION_COUNT = 15;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int MAX_ATTRIBUTION_NODES = 127;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int MAX_NUM_ELEMENTS = 127;
-
-    /**
-     * @hide
-     **/
-    @VisibleForTesting
-    public static final int MAX_KEY_VALUE_PAIRS = 127;
-
-    private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;
-
-    // Max payload size is 4 bytes less as 4 bytes are reserved for statsEventTag.
-    // See android_util_StatsLog.cpp.
-    private static final int MAX_PUSH_PAYLOAD_SIZE = LOGGER_ENTRY_MAX_PAYLOAD - 4;
-
-    private static final int MAX_PULL_PAYLOAD_SIZE = 50 * 1024; // 50 KB
-
-    private final int mAtomId;
-    private final byte[] mPayload;
-    private Buffer mBuffer;
-    private final int mNumBytes;
-
-    private StatsEvent(final int atomId, @Nullable final Buffer buffer,
-            @NonNull final byte[] payload, final int numBytes) {
-        mAtomId = atomId;
-        mBuffer = buffer;
-        mPayload = payload;
-        mNumBytes = numBytes;
-    }
-
-    /**
-     * Returns a new StatsEvent.Builder for building StatsEvent object.
-     **/
-    @NonNull
-    public static Builder newBuilder() {
-        return new Builder(Buffer.obtain());
-    }
-
-    /**
-     * Get the atom Id of the atom encoded in this StatsEvent object.
-     *
-     * @hide
-     **/
-    public int getAtomId() {
-        return mAtomId;
-    }
-
-    /**
-     * Get the byte array that contains the encoded payload that can be sent to statsd.
-     *
-     * @hide
-     **/
-    @NonNull
-    public byte[] getBytes() {
-        return mPayload;
-    }
-
-    /**
-     * Get the number of bytes used to encode the StatsEvent payload.
-     *
-     * @hide
-     **/
-    public int getNumBytes() {
-        return mNumBytes;
-    }
-
-    /**
-     * Recycle resources used by this StatsEvent object.
-     * No actions should be taken on this StatsEvent after release() is called.
-     *
-     * @hide
-     **/
-    public void release() {
-        if (mBuffer != null) {
-            mBuffer.release();
-            mBuffer = null;
-        }
-    }
-
-    /**
-     * Builder for constructing a StatsEvent object.
-     *
-     * <p>This class defines and encapsulates the socket encoding for the
-     *buffer. The write methods must be called in the same order as the order of
-     *fields in the atom definition.</p>
-     *
-     * <p>setAtomId() must be called immediately after
-     *StatsEvent.newBuilder().</p>
-     *
-     * <p>Example:</p>
-     * <pre>
-     *     // Atom definition.
-     *     message MyAtom {
-     *         optional int32 field1 = 1;
-     *         optional int64 field2 = 2;
-     *         optional string field3 = 3 [(annotation1) = true];
-     *         optional repeated int32 field4 = 4;
-     *     }
-     *
-     *     // StatsEvent construction for pushed event.
-     *     StatsEvent.newBuilder()
-     *     StatsEvent statsEvent = StatsEvent.newBuilder()
-     *         .setAtomId(atomId)
-     *         .writeInt(3) // field1
-     *         .writeLong(8L) // field2
-     *         .writeString("foo") // field 3
-     *         .addBooleanAnnotation(annotation1Id, true)
-     *         .writeIntArray({ 1, 2, 3 });
-     *         .usePooledBuffer()
-     *         .build();
-     *
-     *     // StatsEvent construction for pulled event.
-     *     StatsEvent.newBuilder()
-     *     StatsEvent statsEvent = StatsEvent.newBuilder()
-     *         .setAtomId(atomId)
-     *         .writeInt(3) // field1
-     *         .writeLong(8L) // field2
-     *         .writeString("foo") // field 3
-     *         .addBooleanAnnotation(annotation1Id, true)
-     *         .writeIntArray({ 1, 2, 3 });
-     *         .build();
-     * </pre>
-     **/
-    public static final class Builder {
-        // Fixed positions.
-        private static final int POS_NUM_ELEMENTS = 1;
-        private static final int POS_TIMESTAMP_NS = POS_NUM_ELEMENTS + Byte.BYTES;
-        private static final int POS_ATOM_ID = POS_TIMESTAMP_NS + Byte.BYTES + Long.BYTES;
-
-        private final Buffer mBuffer;
-        private long mTimestampNs;
-        private int mAtomId;
-        private byte mCurrentAnnotationCount;
-        private int mPos;
-        private int mPosLastField;
-        private byte mLastType;
-        private int mNumElements;
-        private int mErrorMask;
-        private boolean mUsePooledBuffer = false;
-
-        private Builder(final Buffer buffer) {
-            mBuffer = buffer;
-            mCurrentAnnotationCount = 0;
-            mAtomId = 0;
-            mTimestampNs = SystemClock.elapsedRealtimeNanos();
-            mNumElements = 0;
-
-            // Set mPos to 0 for writing TYPE_OBJECT at 0th position.
-            mPos = 0;
-            writeTypeId(TYPE_OBJECT);
-
-            // Write timestamp.
-            mPos = POS_TIMESTAMP_NS;
-            writeLong(mTimestampNs);
-        }
-
-        /**
-         * Sets the atom id for this StatsEvent.
-         *
-         * This should be called immediately after StatsEvent.newBuilder()
-         * and should only be called once.
-         * Not calling setAtomId will result in ERROR_NO_ATOM_ID.
-         * Calling setAtomId out of order will result in ERROR_ATOM_ID_INVALID_POSITION.
-         **/
-        @NonNull
-        public Builder setAtomId(final int atomId) {
-            if (0 == mAtomId) {
-                mAtomId = atomId;
-
-                if (1 == mNumElements) { // Only timestamp is written so far.
-                    writeInt(atomId);
-                } else {
-                    // setAtomId called out of order.
-                    mErrorMask |= ERROR_ATOM_ID_INVALID_POSITION;
-                }
-            }
-
-            return this;
-        }
-
-        /**
-         * Write a boolean field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeBoolean(final boolean value) {
-            // Write boolean typeId byte followed by boolean byte representation.
-            writeTypeId(TYPE_BOOLEAN);
-            mPos += mBuffer.putBoolean(mPos, value);
-            mNumElements++;
-            return this;
-        }
-
-        /**
-         * Write an integer field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeInt(final int value) {
-            // Write integer typeId byte followed by 4-byte representation of value.
-            writeTypeId(TYPE_INT);
-            mPos += mBuffer.putInt(mPos, value);
-            mNumElements++;
-            return this;
-        }
-
-        /**
-         * Write a long field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeLong(final long value) {
-            // Write long typeId byte followed by 8-byte representation of value.
-            writeTypeId(TYPE_LONG);
-            mPos += mBuffer.putLong(mPos, value);
-            mNumElements++;
-            return this;
-        }
-
-        /**
-         * Write a float field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeFloat(final float value) {
-            // Write float typeId byte followed by 4-byte representation of value.
-            writeTypeId(TYPE_FLOAT);
-            mPos += mBuffer.putFloat(mPos, value);
-            mNumElements++;
-            return this;
-        }
-
-        /**
-         * Write a String field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeString(@NonNull final String value) {
-            // Write String typeId byte, followed by 4-byte representation of number of bytes
-            // in the UTF-8 encoding, followed by the actual UTF-8 byte encoding of value.
-            final byte[] valueBytes = stringToBytes(value);
-            writeByteArray(valueBytes, TYPE_STRING);
-            return this;
-        }
-
-        /**
-         * Write a byte array field to this StatsEvent.
-         **/
-        @NonNull
-        public Builder writeByteArray(@NonNull final byte[] value) {
-            // Write byte array typeId byte, followed by 4-byte representation of number of bytes
-            // in value, followed by the actual byte array.
-            writeByteArray(value, TYPE_BYTE_ARRAY);
-            return this;
-        }
-
-        private void writeByteArray(@NonNull final byte[] value, final byte typeId) {
-            writeTypeId(typeId);
-            final int numBytes = value.length;
-            mPos += mBuffer.putInt(mPos, numBytes);
-            mPos += mBuffer.putByteArray(mPos, value);
-            mNumElements++;
-        }
-
-        /**
-         * Write an attribution chain field to this StatsEvent.
-         *
-         * The sizes of uids and tags must be equal. The AttributionNode at position i is
-         * made up of uids[i] and tags[i].
-         *
-         * @param uids array of uids in the attribution nodes.
-         * @param tags array of tags in the attribution nodes.
-         **/
-        @NonNull
-        public Builder writeAttributionChain(
-                @NonNull final int[] uids, @NonNull final String[] tags) {
-            final byte numUids = (byte) uids.length;
-            final byte numTags = (byte) tags.length;
-
-            if (numUids != numTags) {
-                mErrorMask |= ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL;
-            } else if (numUids > MAX_ATTRIBUTION_NODES) {
-                mErrorMask |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG;
-            } else {
-                // Write attribution chain typeId byte, followed by 1-byte representation of
-                // number of attribution nodes, followed by encoding of each attribution node.
-                writeTypeId(TYPE_ATTRIBUTION_CHAIN);
-                mPos += mBuffer.putByte(mPos, numUids);
-                for (int i = 0; i < numUids; i++) {
-                    // Each uid is encoded as 4-byte representation of its int value.
-                    mPos += mBuffer.putInt(mPos, uids[i]);
-
-                    // Each tag is encoded as 4-byte representation of number of bytes in its
-                    // UTF-8 encoding, followed by the actual UTF-8 bytes.
-                    final byte[] tagBytes = stringToBytes(tags[i]);
-                    mPos += mBuffer.putInt(mPos, tagBytes.length);
-                    mPos += mBuffer.putByteArray(mPos, tagBytes);
-                }
-                mNumElements++;
-            }
-            return this;
-        }
-
-        /**
-         * Write KeyValuePairsAtom entries to this StatsEvent.
-         *
-         * @param intMap Integer key-value pairs.
-         * @param longMap Long key-value pairs.
-         * @param stringMap String key-value pairs.
-         * @param floatMap Float key-value pairs.
-         **/
-        @NonNull
-        public Builder writeKeyValuePairs(
-                @Nullable final SparseIntArray intMap,
-                @Nullable final SparseLongArray longMap,
-                @Nullable final SparseArray<String> stringMap,
-                @Nullable final SparseArray<Float> floatMap) {
-            final int intMapSize = null == intMap ? 0 : intMap.size();
-            final int longMapSize = null == longMap ? 0 : longMap.size();
-            final int stringMapSize = null == stringMap ? 0 : stringMap.size();
-            final int floatMapSize = null == floatMap ? 0 : floatMap.size();
-            final int totalCount = intMapSize + longMapSize + stringMapSize + floatMapSize;
-
-            if (totalCount > MAX_KEY_VALUE_PAIRS) {
-                mErrorMask |= ERROR_TOO_MANY_KEY_VALUE_PAIRS;
-            } else {
-                writeTypeId(TYPE_KEY_VALUE_PAIRS);
-                mPos += mBuffer.putByte(mPos, (byte) totalCount);
-
-                for (int i = 0; i < intMapSize; i++) {
-                    final int key = intMap.keyAt(i);
-                    final int value = intMap.valueAt(i);
-                    mPos += mBuffer.putInt(mPos, key);
-                    writeTypeId(TYPE_INT);
-                    mPos += mBuffer.putInt(mPos, value);
-                }
-
-                for (int i = 0; i < longMapSize; i++) {
-                    final int key = longMap.keyAt(i);
-                    final long value = longMap.valueAt(i);
-                    mPos += mBuffer.putInt(mPos, key);
-                    writeTypeId(TYPE_LONG);
-                    mPos += mBuffer.putLong(mPos, value);
-                }
-
-                for (int i = 0; i < stringMapSize; i++) {
-                    final int key = stringMap.keyAt(i);
-                    final String value = stringMap.valueAt(i);
-                    mPos += mBuffer.putInt(mPos, key);
-                    writeTypeId(TYPE_STRING);
-                    final byte[] valueBytes = stringToBytes(value);
-                    mPos += mBuffer.putInt(mPos, valueBytes.length);
-                    mPos += mBuffer.putByteArray(mPos, valueBytes);
-                }
-
-                for (int i = 0; i < floatMapSize; i++) {
-                    final int key = floatMap.keyAt(i);
-                    final float value = floatMap.valueAt(i);
-                    mPos += mBuffer.putInt(mPos, key);
-                    writeTypeId(TYPE_FLOAT);
-                    mPos += mBuffer.putFloat(mPos, value);
-                }
-
-                mNumElements++;
-            }
-
-            return this;
-        }
-
-        /**
-         * Write a repeated boolean field to this StatsEvent.
-         *
-         * The list size must not exceed 127. Otherwise, the array isn't written
-         * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the
-         * StatsEvent errors field.
-         *
-         * @param elements array of booleans.
-         **/
-        @RequiresApi(Build.VERSION_CODES.TIRAMISU)
-        @NonNull
-        public Builder writeBooleanArray(@NonNull final boolean[] elements) {
-            final byte numElements = (byte)elements.length;
-
-            if (writeArrayInfo(numElements, TYPE_BOOLEAN)) {
-                // Write encoding of each element.
-                for (int i = 0; i < numElements; i++) {
-                    mPos += mBuffer.putBoolean(mPos, elements[i]);
-                }
-                mNumElements++;
-            }
-            return this;
-        }
-
-        /**
-         * Write a repeated int field to this StatsEvent.
-         *
-         * The list size must not exceed 127. Otherwise, the array isn't written
-         * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the
-         * StatsEvent errors field.
-         *
-         * @param elements array of ints.
-         **/
-        @RequiresApi(Build.VERSION_CODES.TIRAMISU)
-        @NonNull
-        public Builder writeIntArray(@NonNull final int[] elements) {
-            final byte numElements = (byte)elements.length;
-
-            if (writeArrayInfo(numElements, TYPE_INT)) {
-              // Write encoding of each element.
-              for (int i = 0; i < numElements; i++) {
-                mPos += mBuffer.putInt(mPos, elements[i]);
-                }
-                mNumElements++;
-            }
-            return this;
-        }
-
-        /**
-         * Write a repeated long field to this StatsEvent.
-         *
-         * The list size must not exceed 127. Otherwise, the array isn't written
-         * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the
-         * StatsEvent errors field.
-         *
-         * @param elements array of longs.
-         **/
-        @RequiresApi(Build.VERSION_CODES.TIRAMISU)
-        @NonNull
-        public Builder writeLongArray(@NonNull final long[] elements) {
-            final byte numElements = (byte)elements.length;
-
-            if (writeArrayInfo(numElements, TYPE_LONG)) {
-                // Write encoding of each element.
-                for (int i = 0; i < numElements; i++) {
-                    mPos += mBuffer.putLong(mPos, elements[i]);
-                }
-                mNumElements++;
-            }
-            return this;
-        }
-
-        /**
-         * Write a repeated float field to this StatsEvent.
-         *
-         * The list size must not exceed 127. Otherwise, the array isn't written
-         * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the
-         * StatsEvent errors field.
-         *
-         * @param elements array of floats.
-         **/
-        @RequiresApi(Build.VERSION_CODES.TIRAMISU)
-        @NonNull
-        public Builder writeFloatArray(@NonNull final float[] elements) {
-            final byte numElements = (byte)elements.length;
-
-            if (writeArrayInfo(numElements, TYPE_FLOAT)) {
-                // Write encoding of each element.
-                for (int i = 0; i < numElements; i++) {
-                  mPos += mBuffer.putFloat(mPos, elements[i]);
-                }
-                mNumElements++;
-            }
-            return this;
-        }
-
-        /**
-         * Write a repeated string field to this StatsEvent.
-         *
-         * The list size must not exceed 127. Otherwise, the array isn't written
-         * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the
-         * StatsEvent errors field.
-         *
-         * @param elements array of strings.
-         **/
-        @RequiresApi(Build.VERSION_CODES.TIRAMISU)
-        @NonNull
-        public Builder writeStringArray(@NonNull final String[] elements) {
-            final byte numElements = (byte)elements.length;
-
-            if (writeArrayInfo(numElements, TYPE_STRING)) {
-                // Write encoding of each element.
-                for (int i = 0; i < numElements; i++) {
-                    final byte[] elementBytes = stringToBytes(elements[i]);
-                    mPos += mBuffer.putInt(mPos, elementBytes.length);
-                    mPos += mBuffer.putByteArray(mPos, elementBytes);
-                }
-                mNumElements++;
-            }
-            return this;
-        }
-
-        /**
-         * Write a boolean annotation for the last field written.
-         **/
-        @NonNull
-        public Builder addBooleanAnnotation(
-                final byte annotationId, final boolean value) {
-            // Ensure there's a field written to annotate.
-            if (mNumElements < 2) {
-                mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
-            } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) {
-                mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS;
-            } else {
-                mPos += mBuffer.putByte(mPos, annotationId);
-                mPos += mBuffer.putByte(mPos, TYPE_BOOLEAN);
-                mPos += mBuffer.putBoolean(mPos, value);
-                mCurrentAnnotationCount++;
-                writeAnnotationCount();
-            }
-
-            return this;
-        }
-
-        /**
-         * Write an integer annotation for the last field written.
-         **/
-        @NonNull
-        public Builder addIntAnnotation(final byte annotationId, final int value) {
-            if (mNumElements < 2) {
-                mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
-            } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) {
-                mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS;
-            } else {
-                mPos += mBuffer.putByte(mPos, annotationId);
-                mPos += mBuffer.putByte(mPos, TYPE_INT);
-                mPos += mBuffer.putInt(mPos, value);
-                mCurrentAnnotationCount++;
-                writeAnnotationCount();
-            }
-
-            return this;
-        }
-
-        /**
-         * Indicates to reuse Buffer's byte array as the underlying payload in StatsEvent.
-         * This should be called for pushed events to reduce memory allocations and garbage
-         * collections.
-         **/
-        @NonNull
-        public Builder usePooledBuffer() {
-            mUsePooledBuffer = true;
-            mBuffer.setMaxSize(MAX_PUSH_PAYLOAD_SIZE, mPos);
-            return this;
-        }
-
-        /**
-         * Builds a StatsEvent object with values entered in this Builder.
-         **/
-        @NonNull
-        public StatsEvent build() {
-            if (0L == mTimestampNs) {
-                mErrorMask |= ERROR_NO_TIMESTAMP;
-            }
-            if (0 == mAtomId) {
-                mErrorMask |= ERROR_NO_ATOM_ID;
-            }
-            if (mBuffer.hasOverflowed()) {
-                mErrorMask |= ERROR_OVERFLOW;
-            }
-            if (mNumElements > MAX_NUM_ELEMENTS) {
-                mErrorMask |= ERROR_TOO_MANY_FIELDS;
-            }
-
-            if (0 == mErrorMask) {
-                mBuffer.putByte(POS_NUM_ELEMENTS, (byte) mNumElements);
-            } else {
-                // Write atom id and error mask. Overwrite any annotations for atom Id.
-                mPos = POS_ATOM_ID;
-                mPos += mBuffer.putByte(mPos, TYPE_INT);
-                mPos += mBuffer.putInt(mPos, mAtomId);
-                mPos += mBuffer.putByte(mPos, TYPE_ERRORS);
-                mPos += mBuffer.putInt(mPos, mErrorMask);
-                mBuffer.putByte(POS_NUM_ELEMENTS, (byte) 3);
-            }
-
-            final int size = mPos;
-
-            if (mUsePooledBuffer) {
-                return new StatsEvent(mAtomId, mBuffer, mBuffer.getBytes(), size);
-            } else {
-                // Create a copy of the buffer with the required number of bytes.
-                final byte[] payload = new byte[size];
-                System.arraycopy(mBuffer.getBytes(), 0, payload, 0, size);
-
-                // Return Buffer instance to the pool.
-                mBuffer.release();
-
-                return new StatsEvent(mAtomId, null, payload, size);
-            }
-        }
-
-        private void writeTypeId(final byte typeId) {
-            mPosLastField = mPos;
-            mLastType = typeId;
-            mCurrentAnnotationCount = 0;
-            final byte encodedId = (byte) (typeId & 0x0F);
-            mPos += mBuffer.putByte(mPos, encodedId);
-        }
-
-        private void writeAnnotationCount() {
-            // Use first 4 bits for annotation count and last 4 bits for typeId.
-            final byte encodedId = (byte) ((mCurrentAnnotationCount << 4) | (mLastType & 0x0F));
-            mBuffer.putByte(mPosLastField, encodedId);
-        }
-
-        @NonNull
-        private static byte[] stringToBytes(@Nullable final String value) {
-            return (null == value ? "" : value).getBytes(UTF_8);
-        }
-
-        private boolean writeArrayInfo(final byte numElements,
-                                       final byte elementTypeId) {
-            if (numElements > MAX_NUM_ELEMENTS) {
-                mErrorMask |= ERROR_LIST_TOO_LONG;
-                return false;
-            }
-            // Write list typeId byte, 1-byte representation of number of
-            // elements, and element typeId byte.
-            writeTypeId(TYPE_LIST);
-            mPos += mBuffer.putByte(mPos, numElements);
-            // Write element typeId byte without setting mPosLastField and mLastType (i.e. don't use
-            // #writeTypeId)
-            final byte encodedId = (byte) (elementTypeId & 0x0F);
-            mPos += mBuffer.putByte(mPos, encodedId);
-            return true;
-        }
-    }
-
-    private static final class Buffer {
-        private static Object sLock = new Object();
-
-        @GuardedBy("sLock")
-        private static Buffer sPool;
-
-        private byte[] mBytes;
-        private boolean mOverflow = false;
-        private int mMaxSize = MAX_PULL_PAYLOAD_SIZE;
-
-        @NonNull
-        private static Buffer obtain() {
-            final Buffer buffer;
-            synchronized (sLock) {
-                buffer = null == sPool ? new Buffer() : sPool;
-                sPool = null;
-            }
-            buffer.reset();
-            return buffer;
-        }
-
-        private Buffer() {
-            final ByteBuffer tempBuffer = ByteBuffer.allocateDirect(MAX_PUSH_PAYLOAD_SIZE);
-            mBytes = tempBuffer.hasArray() ? tempBuffer.array() : new byte [MAX_PUSH_PAYLOAD_SIZE];
-        }
-
-        @NonNull
-        private byte[] getBytes() {
-            return mBytes;
-        }
-
-        private void release() {
-            // Recycle this Buffer if its size is MAX_PUSH_PAYLOAD_SIZE or under.
-            if (mMaxSize <= MAX_PUSH_PAYLOAD_SIZE) {
-                synchronized (sLock) {
-                    if (null == sPool) {
-                        sPool = this;
-                    }
-                }
-            }
-        }
-
-        private void reset() {
-            mOverflow = false;
-            mMaxSize = MAX_PULL_PAYLOAD_SIZE;
-        }
-
-        private void setMaxSize(final int maxSize, final int numBytesWritten) {
-            mMaxSize = maxSize;
-            if (numBytesWritten > maxSize) {
-                mOverflow = true;
-            }
-        }
-
-        private boolean hasOverflowed() {
-            return mOverflow;
-        }
-
-        /**
-         * Checks for available space in the byte array.
-         *
-         * @param index starting position in the buffer to start the check.
-         * @param numBytes number of bytes to check from index.
-         * @return true if space is available, false otherwise.
-         **/
-        private boolean hasEnoughSpace(final int index, final int numBytes) {
-            final int totalBytesNeeded = index + numBytes;
-
-            if (totalBytesNeeded > mMaxSize) {
-                mOverflow = true;
-                return false;
-            }
-
-            // Expand buffer if needed.
-            if (mBytes.length < mMaxSize && totalBytesNeeded > mBytes.length) {
-                int newSize = mBytes.length;
-                do {
-                    newSize *= 2;
-                } while (newSize <= totalBytesNeeded);
-
-                if (newSize > mMaxSize) {
-                    newSize = mMaxSize;
-                }
-
-                mBytes = Arrays.copyOf(mBytes, newSize);
-            }
-
-            return true;
-        }
-
-        /**
-         * Writes a byte into the buffer.
-         *
-         * @param index position in the buffer where the byte is written.
-         * @param value the byte to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putByte(final int index, final byte value) {
-            if (hasEnoughSpace(index, Byte.BYTES)) {
-                mBytes[index] = (byte) (value);
-                return Byte.BYTES;
-            }
-            return 0;
-        }
-
-        /**
-         * Writes a boolean into the buffer.
-         *
-         * @param index position in the buffer where the boolean is written.
-         * @param value the boolean to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putBoolean(final int index, final boolean value) {
-            return putByte(index, (byte) (value ? 1 : 0));
-        }
-
-        /**
-         * Writes an integer into the buffer.
-         *
-         * @param index position in the buffer where the integer is written.
-         * @param value the integer to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putInt(final int index, final int value) {
-            if (hasEnoughSpace(index, Integer.BYTES)) {
-                // Use little endian byte order.
-                mBytes[index] = (byte) (value);
-                mBytes[index + 1] = (byte) (value >> 8);
-                mBytes[index + 2] = (byte) (value >> 16);
-                mBytes[index + 3] = (byte) (value >> 24);
-                return Integer.BYTES;
-            }
-            return 0;
-        }
-
-        /**
-         * Writes a long into the buffer.
-         *
-         * @param index position in the buffer where the long is written.
-         * @param value the long to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putLong(final int index, final long value) {
-            if (hasEnoughSpace(index, Long.BYTES)) {
-                // Use little endian byte order.
-                mBytes[index] = (byte) (value);
-                mBytes[index + 1] = (byte) (value >> 8);
-                mBytes[index + 2] = (byte) (value >> 16);
-                mBytes[index + 3] = (byte) (value >> 24);
-                mBytes[index + 4] = (byte) (value >> 32);
-                mBytes[index + 5] = (byte) (value >> 40);
-                mBytes[index + 6] = (byte) (value >> 48);
-                mBytes[index + 7] = (byte) (value >> 56);
-                return Long.BYTES;
-            }
-            return 0;
-        }
-
-        /**
-         * Writes a float into the buffer.
-         *
-         * @param index position in the buffer where the float is written.
-         * @param value the float to write.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putFloat(final int index, final float value) {
-            return putInt(index, Float.floatToIntBits(value));
-        }
-
-        /**
-         * Copies a byte array into the buffer.
-         *
-         * @param index position in the buffer where the byte array is copied.
-         * @param value the byte array to copy.
-         * @return number of bytes written to buffer from this write operation.
-         **/
-        private int putByteArray(final int index, @NonNull final byte[] value) {
-            final int numBytes = value.length;
-            if (hasEnoughSpace(index, numBytes)) {
-                System.arraycopy(value, 0, mBytes, index, numBytes);
-                return numBytes;
-            }
-            return 0;
-        }
-    }
-}
diff --git a/ravenwood/runtime-helper-src/framework/android/util/StatsLog.java b/ravenwood/runtime-helper-src/framework/android/util/StatsLog.java
deleted file mode 100644
index c1c20cf..0000000
--- a/ravenwood/runtime-helper-src/framework/android/util/StatsLog.java
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-/*
- * [Ravenwood] This is copied from StatsD, with the following changes:
- * - The static {} is commented out.
- * - All references to IStatsD and StatsdStatsLog are commented out.
- * - The native method is no-oped.
- */
-
-import static android.Manifest.permission.DUMP;
-import static android.Manifest.permission.PACKAGE_USAGE_STATS;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.os.Build;
-//import android.os.IStatsd;
-import android.os.Process;
-import android.util.proto.ProtoOutputStream;
-
-import androidx.annotation.RequiresApi;
-
-//import com.android.internal.statsd.StatsdStatsLog;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * StatsLog provides an API for developers to send events to statsd. The events can be used to
- * define custom metrics in side statsd.
- */
-public final class StatsLog {
-
-//    // Load JNI library
-//    static {
-//        System.loadLibrary("stats_jni");
-//    }
-    private static final String TAG = "StatsLog";
-    private static final boolean DEBUG = false;
-    private static final int EXPERIMENT_IDS_FIELD_ID = 1;
-
-    /**
-     * Annotation ID constant for logging UID field.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    public static final byte ANNOTATION_ID_IS_UID = 1;
-
-    /**
-     * Annotation ID constant to indicate logged atom event's timestamp should be truncated.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    public static final byte ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2;
-
-    /**
-     * Annotation ID constant for a state atom's primary field.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    public static final byte ANNOTATION_ID_PRIMARY_FIELD = 3;
-
-    /**
-     * Annotation ID constant for state atom's state field.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    public static final byte ANNOTATION_ID_EXCLUSIVE_STATE = 4;
-
-    /**
-     * Annotation ID constant to indicate the first UID in the attribution chain
-     * is a primary field.
-     * Should only be used for attribution chain fields.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    public static final byte ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID = 5;
-
-    /**
-     * Annotation ID constant to indicate which state is default for the state atom.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    public static final byte ANNOTATION_ID_DEFAULT_STATE = 6;
-
-    /**
-     * Annotation ID constant to signal all states should be reset to the default state.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    public static final byte ANNOTATION_ID_TRIGGER_STATE_RESET = 7;
-
-    /**
-     * Annotation ID constant to indicate state changes need to account for nesting.
-     * This should only be used with binary state atoms.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    public static final byte ANNOTATION_ID_STATE_NESTED = 8;
-
-    /**
-     * Annotation ID constant to indicate the restriction category of an atom.
-     * This annotation must only be attached to the atom id. This is an int annotation.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final byte ANNOTATION_ID_RESTRICTION_CATEGORY = 9;
-
-    /**
-     * Annotation ID to indicate that a field of an atom contains peripheral device info.
-     * This is a bool annotation.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final byte ANNOTATION_ID_FIELD_RESTRICTION_PERIPHERAL_DEVICE_INFO = 10;
-
-    /**
-     * Annotation ID to indicate that a field of an atom contains app usage information.
-     * This is a bool annotation.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final byte ANNOTATION_ID_FIELD_RESTRICTION_APP_USAGE = 11;
-
-    /**
-     * Annotation ID to indicate that a field of an atom contains app activity information.
-     * This is a bool annotation.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final byte ANNOTATION_ID_FIELD_RESTRICTION_APP_ACTIVITY = 12;
-
-    /**
-     * Annotation ID to indicate that a field of an atom contains health connect information.
-     * This is a bool annotation.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final byte ANNOTATION_ID_FIELD_RESTRICTION_HEALTH_CONNECT = 13;
-
-    /**
-     * Annotation ID to indicate that a field of an atom contains accessibility information.
-     * This is a bool annotation.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final byte ANNOTATION_ID_FIELD_RESTRICTION_ACCESSIBILITY = 14;
-
-    /**
-     * Annotation ID to indicate that a field of an atom contains system search information.
-     * This is a bool annotation.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final byte ANNOTATION_ID_FIELD_RESTRICTION_SYSTEM_SEARCH = 15;
-
-    /**
-     * Annotation ID to indicate that a field of an atom contains user engagement information.
-     * This is a bool annotation.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final byte ANNOTATION_ID_FIELD_RESTRICTION_USER_ENGAGEMENT = 16;
-
-    /**
-     * Annotation ID to indicate that a field of an atom contains ambient sensing information.
-     * This is a bool annotation.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final byte ANNOTATION_ID_FIELD_RESTRICTION_AMBIENT_SENSING = 17;
-
-    /**
-     * Annotation ID to indicate that a field of an atom contains demographic classification
-     * information. This is a bool annotation.
-     *
-     * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
-     * accept byte as the type for annotation ids to save space.
-     *
-     * @hide
-     */
-    @SuppressLint("NoByteOrShort")
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final byte ANNOTATION_ID_FIELD_RESTRICTION_DEMOGRAPHIC_CLASSIFICATION = 18;
-
-
-    /** @hide */
-    @IntDef(prefix = { "RESTRICTION_CATEGORY_" }, value = {
-            RESTRICTION_CATEGORY_DIAGNOSTIC,
-            RESTRICTION_CATEGORY_SYSTEM_INTELLIGENCE,
-            RESTRICTION_CATEGORY_AUTHENTICATION,
-            RESTRICTION_CATEGORY_FRAUD_AND_ABUSE})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface RestrictionCategory {}
-
-    /**
-     * Restriction category for atoms about diagnostics.
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final int RESTRICTION_CATEGORY_DIAGNOSTIC = 1;
-
-    /**
-     * Restriction category for atoms about system intelligence.
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final int RESTRICTION_CATEGORY_SYSTEM_INTELLIGENCE = 2;
-
-    /**
-     * Restriction category for atoms about authentication.
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final int RESTRICTION_CATEGORY_AUTHENTICATION = 3;
-
-    /**
-     * Restriction category for atoms about fraud and abuse.
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public static final int RESTRICTION_CATEGORY_FRAUD_AND_ABUSE = 4;
-
-    private StatsLog() {
-    }
-
-    /**
-     * Logs a start event.
-     *
-     * @param label developer-chosen label.
-     * @return True if the log request was sent to statsd.
-     */
-    public static boolean logStart(int label) {
-        int callingUid = Process.myUid();
-//        StatsdStatsLog.write(
-//                StatsdStatsLog.APP_BREADCRUMB_REPORTED,
-//                callingUid,
-//                label,
-//                StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__START);
-        return true;
-    }
-
-    /**
-     * Logs a stop event.
-     *
-     * @param label developer-chosen label.
-     * @return True if the log request was sent to statsd.
-     */
-    public static boolean logStop(int label) {
-        int callingUid = Process.myUid();
-//        StatsdStatsLog.write(
-//                StatsdStatsLog.APP_BREADCRUMB_REPORTED,
-//                callingUid,
-//                label,
-//                StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__STOP);
-        return true;
-    }
-
-    /**
-     * Logs an event that does not represent a start or stop boundary.
-     *
-     * @param label developer-chosen label.
-     * @return True if the log request was sent to statsd.
-     */
-    public static boolean logEvent(int label) {
-        int callingUid = Process.myUid();
-//        StatsdStatsLog.write(
-//                StatsdStatsLog.APP_BREADCRUMB_REPORTED,
-//                callingUid,
-//                label,
-//                StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__UNSPECIFIED);
-        return true;
-    }
-
-    /**
-     * Logs an event for binary push for module updates.
-     *
-     * @param trainName        name of install train.
-     * @param trainVersionCode version code of the train.
-     * @param options          optional flags about this install.
-     *                         The last 3 bits indicate options:
-     *                             0x01: FLAG_REQUIRE_STAGING
-     *                             0x02: FLAG_ROLLBACK_ENABLED
-     *                             0x04: FLAG_REQUIRE_LOW_LATENCY_MONITOR
-     * @param state            current install state. Defined as State enums in
-     *                         BinaryPushStateChanged atom in
-     *                         frameworks/proto_logging/stats/atoms.proto
-     * @param experimentIds    experiment ids.
-     * @return True if the log request was sent to statsd.
-     */
-    @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS})
-    public static boolean logBinaryPushStateChanged(@NonNull String trainName,
-            long trainVersionCode, int options, int state,
-            @NonNull long[] experimentIds) {
-        ProtoOutputStream proto = new ProtoOutputStream();
-        for (long id : experimentIds) {
-            proto.write(
-                    ProtoOutputStream.FIELD_TYPE_INT64
-                    | ProtoOutputStream.FIELD_COUNT_REPEATED
-                    | EXPERIMENT_IDS_FIELD_ID,
-                    id);
-        }
-//        StatsdStatsLog.write(StatsdStatsLog.BINARY_PUSH_STATE_CHANGED,
-//                trainName,
-//                trainVersionCode,
-//                (options & IStatsd.FLAG_REQUIRE_STAGING) > 0,
-//                (options & IStatsd.FLAG_ROLLBACK_ENABLED) > 0,
-//                (options & IStatsd.FLAG_REQUIRE_LOW_LATENCY_MONITOR) > 0,
-//                state,
-//                proto.getBytes(),
-//                0,
-//                0,
-//                false);
-        return true;
-    }
-
-    /**
-     * Write an event to stats log using the raw format.
-     *
-     * @param buffer    The encoded buffer of data to write.
-     * @param size      The number of bytes from the buffer to write.
-     * @hide
-     * @deprecated Use {@link write(final StatsEvent statsEvent)} instead.
-     *
-     */
-    @Deprecated
-    @SystemApi
-    public static void writeRaw(@NonNull byte[] buffer, int size) {
-        writeImpl(buffer, size, 0);
-    }
-
-    /**
-     * Write an event to stats log using the raw format.
-     *
-     * @param buffer    The encoded buffer of data to write.
-     * @param size      The number of bytes from the buffer to write.
-     * @param atomId    The id of the atom to which the event belongs.
-     */
-//    private static native void writeImpl(@NonNull byte[] buffer, int size, int atomId);
-    private static void writeImpl(@NonNull byte[] buffer, int size, int atomId) {
-        // no-op for now
-    }
-
-    /**
-     * Write an event to stats log using the raw format encapsulated in StatsEvent.
-     * After writing to stats log, release() is called on the StatsEvent object.
-     * No further action should be taken on the StatsEvent object following this call.
-     *
-     * @param statsEvent    The StatsEvent object containing the encoded buffer of data to write.
-     * @hide
-     */
-    @SystemApi
-    public static void write(@NonNull final StatsEvent statsEvent) {
-        writeImpl(statsEvent.getBytes(), statsEvent.getNumBytes(), statsEvent.getAtomId());
-        statsEvent.release();
-    }
-}
diff --git a/ravenwood/scripts/ravenwood-stats-collector.sh b/ravenwood/scripts/ravenwood-stats-collector.sh
index 36601bd..b83216a 100755
--- a/ravenwood/scripts/ravenwood-stats-collector.sh
+++ b/ravenwood/scripts/ravenwood-stats-collector.sh
@@ -62,6 +62,8 @@
 
         dump "framework-minus-apex" hoststubgen_framework-minus-apex_stats.csv
         dump "service.core"  hoststubgen_services.core_stats.csv
+        dump "framework-configinfrastructure"  framework-configinfrastructure_stats.csv
+        dump "framework-statsd"  framework-statsd_stats.csv
     } > "$out"
 
     echo "Stats CVS created at $out"
@@ -76,6 +78,8 @@
 
         dump "framework-minus-apex"  hoststubgen_framework-minus-apex_apis.csv
         dump "service.core"  hoststubgen_services.core_apis.csv
+        dump "framework-configinfrastructure"  framework-configinfrastructure_apis.csv
+        dump "framework-statsd"  framework-statsd_apis.csv
     } > "$out"
 
     echo "API CVS created at $out"
diff --git a/ravenwood/tests/coretest/Android.bp b/ravenwood/tests/coretest/Android.bp
index 85f1baf..412744e 100644
--- a/ravenwood/tests/coretest/Android.bp
+++ b/ravenwood/tests/coretest/Android.bp
@@ -23,6 +23,7 @@
     ],
     srcs: [
         "test/**/*.java",
+        "test/**/*.kt",
     ],
     ravenizer: {
         strip_mockito: true,
diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodStatsDTest.kt b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodStatsDTest.kt
new file mode 100644
index 0000000..d5f5e29
--- /dev/null
+++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodStatsDTest.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ravenwoodtest.coretest
+
+import com.android.internal.util.FrameworkStatsLog
+import org.junit.Test
+
+class RavenwoodStatsDTest {
+    @Test
+    fun testFrameworkStatsLog() {
+        FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, 123)
+    }
+}
\ No newline at end of file
diff --git a/ravenwood/texts/ravenwood-framework-policies.txt b/ravenwood/texts/ravenwood-framework-policies.txt
index b64944e..80126df 100644
--- a/ravenwood/texts/ravenwood-framework-policies.txt
+++ b/ravenwood/texts/ravenwood-framework-policies.txt
@@ -5,8 +5,7 @@
 rename com/.*/nano/   devicenano/
 rename android/.*/nano/   devicenano/
 
-
-# StatsD autogenerated classes. Maybe add a heuristic?
+# StatsD auto-generated
 class com.android.internal.util.FrameworkStatsLog keepclass
 
 # Exported to Mainline modules; cannot use annotations
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 65a2c18..4944caf 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -163,6 +163,7 @@
 
     static final String KEY_USE_TIERED_CACHED_ADJ = "use_tiered_cached_adj";
     static final String KEY_TIERED_CACHED_ADJ_DECAY_TIME = "tiered_cached_adj_decay_time";
+    static final String KEY_TIERED_CACHED_ADJ_UI_TIER_SIZE = "tiered_cached_adj_ui_tier_size";
 
     /**
      * Whether or not to enable the new oom adjuster implementation.
@@ -248,6 +249,8 @@
 
     private static final boolean DEFAULT_USE_TIERED_CACHED_ADJ = Flags.oomadjusterCachedAppTiers();
     private static final long DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME = 60 * 1000;
+    private static final int TIERED_CACHED_ADJ_MAX_UI_TIER_SIZE = 50;
+    private final int mDefaultTieredCachedAdjUiTierSize;
 
     /**
      * The default value to {@link #KEY_ENABLE_NEW_OOMADJ}.
@@ -1154,6 +1157,9 @@
     /** @see #KEY_TIERED_CACHED_ADJ_DECAY_TIME */
     public long TIERED_CACHED_ADJ_DECAY_TIME = DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME;
 
+    /** @see #KEY_TIERED_CACHED_ADJ_UI_TIER_SIZE */
+    public int TIERED_CACHED_ADJ_UI_TIER_SIZE;
+
     /** @see #KEY_ENABLE_NEW_OOMADJ */
     public boolean ENABLE_NEW_OOMADJ = DEFAULT_ENABLE_NEW_OOM_ADJ;
 
@@ -1363,6 +1369,7 @@
                                 break;
                             case KEY_USE_TIERED_CACHED_ADJ:
                             case KEY_TIERED_CACHED_ADJ_DECAY_TIME:
+                            case KEY_TIERED_CACHED_ADJ_UI_TIER_SIZE:
                                 updateUseTieredCachedAdj();
                                 break;
                             case KEY_DISABLE_APP_PROFILER_PSS_PROFILING:
@@ -1466,6 +1473,11 @@
         mDefaultPssToRssThresholdModifier = context.getResources().getFloat(
                 com.android.internal.R.dimen.config_am_pssToRssThresholdModifier);
         PSS_TO_RSS_THRESHOLD_MODIFIER = mDefaultPssToRssThresholdModifier;
+
+        mDefaultTieredCachedAdjUiTierSize = context.getResources().getInteger(
+                com.android.internal.R.integer.config_am_tieredCachedAdjUiTierSize);
+        TIERED_CACHED_ADJ_UI_TIER_SIZE = Math.min(
+                mDefaultTieredCachedAdjUiTierSize, TIERED_CACHED_ADJ_MAX_UI_TIER_SIZE);
     }
 
     public void start(ContentResolver resolver) {
@@ -2255,6 +2267,12 @@
             DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
             KEY_TIERED_CACHED_ADJ_DECAY_TIME,
             DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME);
+        TIERED_CACHED_ADJ_UI_TIER_SIZE = Math.min(
+                DeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                    KEY_TIERED_CACHED_ADJ_UI_TIER_SIZE,
+                    mDefaultTieredCachedAdjUiTierSize),
+                TIERED_CACHED_ADJ_MAX_UI_TIER_SIZE);
     }
 
     private void updateEnableNewOomAdj() {
@@ -2510,6 +2528,8 @@
         pw.print("="); pw.println(USE_TIERED_CACHED_ADJ);
         pw.print("  "); pw.print(KEY_TIERED_CACHED_ADJ_DECAY_TIME);
         pw.print("="); pw.println(TIERED_CACHED_ADJ_DECAY_TIME);
+        pw.print("  "); pw.print(KEY_TIERED_CACHED_ADJ_UI_TIER_SIZE);
+        pw.print("="); pw.println(TIERED_CACHED_ADJ_UI_TIER_SIZE);
 
         pw.print("  "); pw.print(KEY_ENABLE_NEW_OOMADJ);
         pw.print("="); pw.println(ENABLE_NEW_OOMADJ);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a6189d2..3e03045 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2782,23 +2782,24 @@
                 addServiceToMap(mAppBindArgs, Context.INPUT_METHOD_SERVICE);
                 addServiceToMap(mAppBindArgs, Context.INPUT_SERVICE);
                 addServiceToMap(mAppBindArgs, "graphicsstats");
-                addServiceToMap(mAppBindArgs, Context.APP_OPS_SERVICE);
                 addServiceToMap(mAppBindArgs, "content");
                 addServiceToMap(mAppBindArgs, Context.JOB_SCHEDULER_SERVICE);
                 addServiceToMap(mAppBindArgs, Context.NOTIFICATION_SERVICE);
                 addServiceToMap(mAppBindArgs, Context.VIBRATOR_SERVICE);
                 addServiceToMap(mAppBindArgs, Context.ACCOUNT_SERVICE);
                 addServiceToMap(mAppBindArgs, Context.POWER_SERVICE);
-                addServiceToMap(mAppBindArgs, Context.USER_SERVICE);
                 addServiceToMap(mAppBindArgs, "mount");
                 addServiceToMap(mAppBindArgs, Context.PLATFORM_COMPAT_SERVICE);
             }
             // See b/79378449
             // Getting the window service and package service binder from servicemanager
             // is blocked for Apps. However they are necessary for apps.
+            // Removing User Service and App Ops Service from cache breaks boot for auto.
             // TODO: remove exception
+            addServiceToMap(mAppBindArgs, Context.APP_OPS_SERVICE);
             addServiceToMap(mAppBindArgs, "package");
             addServiceToMap(mAppBindArgs, Context.WINDOW_SERVICE);
+            addServiceToMap(mAppBindArgs, Context.USER_SERVICE);
         }
         return mAppBindArgs;
     }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 7051714..8d16eb5 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1149,6 +1149,8 @@
         if (mConstants.USE_TIERED_CACHED_ADJ) {
             final long now = mInjector.getUptimeMillis();
             int uiTargetAdj = 10;
+            // mConstants.TIERED_CACHED_ADJ_UI_TIER_SIZE is 10 by default, but is configurable.
+            final int uiTierMaxAdj = 10 + mConstants.TIERED_CACHED_ADJ_UI_TIER_SIZE;
             for (int i = numLru - 1; i >= 0; i--) {
                 ProcessRecord app = lruList.get(i);
                 final ProcessStateRecord state = app.mState;
@@ -1162,17 +1164,17 @@
                     if (opt != null && opt.isFreezeExempt()) {
                         // BIND_WAIVE_PRIORITY and the like get oom_adj 900
                         targetAdj += 0;
-                    } else if (state.hasShownUi() && uiTargetAdj < 20) {
-                        // The most recent 10 apps that have shown UI get 910-919
+                    } else if (state.hasShownUi() && uiTargetAdj < uiTierMaxAdj) {
+                        // The most recent UI-showing apps get [910, 910 + ui tier size).
                         targetAdj += uiTargetAdj++;
                     } else if ((state.getSetAdj() >= CACHED_APP_MIN_ADJ)
                             && (state.getLastStateTime()
                                     + mConstants.TIERED_CACHED_ADJ_DECAY_TIME) < now) {
-                        // Older cached apps get 950
-                        targetAdj += 50;
+                        // Older cached apps get 940 + ui tier size (950 by default).
+                        targetAdj += 40 + mConstants.TIERED_CACHED_ADJ_UI_TIER_SIZE;
                     } else {
-                        // Newer cached apps get 920
-                        targetAdj += 20;
+                        // Newer cached apps get 910 + ui tier size (920 by default).
+                        targetAdj += 10 + mConstants.TIERED_CACHED_ADJ_UI_TIER_SIZE;
                     }
                     state.setCurRawAdj(targetAdj);
                     state.setCurAdj(psr.modifyRawOomAdj(targetAdj));
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index e97629b..7cf7061 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -71,6 +71,7 @@
 import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
 import static android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP;
 import static android.permission.flags.Flags.deviceAwareAppOpNewSchemaEnabled;
+import static android.permission.flags.Flags.checkOpValidatePackage;
 
 import static com.android.internal.util.FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED;
 import static com.android.internal.util.FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__CHECK_OPERATION;
@@ -2860,20 +2861,30 @@
 
     private int checkOperationImpl(int code, int uid, String packageName,
              @Nullable String attributionTag, int virtualDeviceId, boolean raw) {
-        verifyIncomingOp(code);
-        if (!isValidVirtualDeviceId(virtualDeviceId)) {
-            Slog.w(TAG,
-                    "checkOperationImpl returned MODE_IGNORED as virtualDeviceId " + virtualDeviceId
-                            + " is invalid");
-            return AppOpsManager.MODE_IGNORED;
-        }
-        if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) {
-            return AppOpsManager.opToDefaultMode(code);
-        }
+        String resolvedPackageName;
+        if (!shouldUseNewCheckOp()) {
+            verifyIncomingOp(code);
+            if (!isValidVirtualDeviceId(virtualDeviceId)) {
+                Slog.w(TAG, "checkOperationImpl returned MODE_IGNORED as virtualDeviceId "
+                        + virtualDeviceId + " is invalid");
+                return AppOpsManager.MODE_IGNORED;
+            }
+            if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) {
+                return AppOpsManager.opToDefaultMode(code);
+            }
 
-        String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
-        if (resolvedPackageName == null) {
-            return AppOpsManager.MODE_IGNORED;
+            resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
+            if (resolvedPackageName == null) {
+                return AppOpsManager.MODE_IGNORED;
+            }
+        } else {
+            // Note, this flag changes the behavior in this case: invalid packages now don't
+            // succeed checkOp
+            resolvedPackageName = validateOpRequest(code, uid, packageName,
+                    virtualDeviceId, false, "checkOperation");
+            if (resolvedPackageName == null) {
+                return AppOpsManager.MODE_IGNORED;
+            }
         }
         return checkOperationUnchecked(code, uid, resolvedPackageName, attributionTag,
                 virtualDeviceId, raw);
@@ -3147,25 +3158,37 @@
              @Nullable String attributionTag, int virtualDeviceId,
              boolean shouldCollectAsyncNotedOp, @Nullable String message,
              boolean shouldCollectMessage) {
-        verifyIncomingUid(uid);
-        verifyIncomingOp(code);
-        if (!isValidVirtualDeviceId(virtualDeviceId)) {
-            Slog.w(TAG,
-                    "checkOperationImpl returned MODE_IGNORED as virtualDeviceId " + virtualDeviceId
-                            + " is invalid");
-            return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag,
-                    packageName);
-        }
-        if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) {
-            return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
-                    packageName);
+        String resolvedPackageName;
+        if (!shouldUseNewCheckOp()) {
+            verifyIncomingUid(uid);
+            verifyIncomingOp(code);
+            if (!isValidVirtualDeviceId(virtualDeviceId)) {
+                Slog.w(TAG, "checkOperationImpl returned MODE_IGNORED as virtualDeviceId "
+                        + virtualDeviceId + " is invalid");
+                return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag,
+                        packageName);
+            }
+            if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) {
+                return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
+                        packageName);
+            }
+
+            resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
+            if (resolvedPackageName == null) {
+                return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag,
+                        packageName);
+            }
+        } else {
+            // Note, this flag changes the behavior in this case:
+            // invalid package is now IGNORE instead of ERROR for consistency
+            resolvedPackageName = validateOpRequest(code, uid, packageName,
+                    virtualDeviceId, true, "noteOperation");
+            if (resolvedPackageName == null) {
+                return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag,
+                        packageName);
+            }
         }
 
-        String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
-        if (resolvedPackageName == null) {
-            return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag,
-                    packageName);
-        }
         return noteOperationUnchecked(code, uid, resolvedPackageName, attributionTag,
                 virtualDeviceId, Process.INVALID_UID, null, null,
                 Context.DEVICE_ID_DEFAULT, AppOpsManager.OP_FLAG_SELF, shouldCollectAsyncNotedOp,
@@ -3602,24 +3625,35 @@
             boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, @NonNull String message,
             boolean shouldCollectMessage, @AttributionFlags int attributionFlags,
             int attributionChainId) {
-        verifyIncomingUid(uid);
-        verifyIncomingOp(code);
-        if (!isValidVirtualDeviceId(virtualDeviceId)) {
-            Slog.w(TAG,
-                    "startOperationImpl returned MODE_IGNORED as virtualDeviceId " + virtualDeviceId
-                            + " is invalid");
-            return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag,
-                    packageName);
-        }
-        if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) {
-            return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
-                    packageName);
-        }
+        String resolvedPackageName;
+        if (!shouldUseNewCheckOp()) {
+            verifyIncomingUid(uid);
+            verifyIncomingOp(code);
+            if (!isValidVirtualDeviceId(virtualDeviceId)) {
+                Slog.w(TAG, "startOperationImpl returned MODE_IGNORED as virtualDeviceId "
+                        + virtualDeviceId + " is invalid");
+                return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag,
+                        packageName);
+            }
+            if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) {
+                return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
+                        packageName);
+            }
 
-        String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
-        if (resolvedPackageName == null) {
-            return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag,
-                    packageName);
+            resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
+            if (resolvedPackageName == null) {
+                return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag,
+                        packageName);
+            }
+        } else {
+            // Note, this flag changes the behavior in this case:
+            // invalid package is now IGNORE instead of ERROR for consistency
+            resolvedPackageName = validateOpRequest(code, uid, packageName,
+                    virtualDeviceId, true, "startOperation");
+            if (resolvedPackageName == null) {
+                return new SyncNotedAppOp(AppOpsManager.MODE_IGNORED, code, attributionTag,
+                        packageName);
+            }
         }
 
         // As a special case for OP_RECORD_AUDIO_HOTWORD, OP_RECEIVE_AMBIENT_TRIGGER_AUDIO and
@@ -4341,6 +4375,48 @@
                 || (permInfo.getProtectionFlags() & PROTECTION_FLAG_APPOP) != 0;
     }
 
+    private boolean shouldUseNewCheckOp() {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return checkOpValidatePackage();
+        } catch (Exception e) {
+            // before device provider init, only on old storage
+            return true;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Validates arguments for a particular op request
+     * @param shouldVerifyUid - If the calling uid needs perms for other uids, due to the method
+     * being an appop write.
+     * @param methodName - For logging purposes
+     * @return The resolved package for the request, null on any failure
+     */
+    private @Nullable String validateOpRequest(int code, int uid, String packageName, int vdi,
+            boolean shouldVerifyUid, String methodName) {
+        verifyIncomingOp(code);
+        if (shouldVerifyUid) {
+            verifyIncomingUid(uid);
+        }
+        if (!isValidVirtualDeviceId(vdi)) {
+            Slog.w(TAG, methodName + ": error due to virtualDeviceId " + vdi + " is invalid");
+            return null;
+        }
+        if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) {
+            Slog.w(TAG, methodName + ": error due to package: " + packageName
+                            + " is invalid for " + uid);
+            return null;
+        }
+        String resolvedPackageName = AppOpsManager.resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            Slog.w(TAG, methodName + ": error due to unable to resolve uid: " + uid);
+            return null;
+        }
+        return resolvedPackageName;
+    }
+
     private void verifyIncomingProxyUid(@NonNull AttributionSource attributionSource) {
         if (attributionSource.getUid() == Binder.getCallingUid()) {
             return;
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 5c8430b..a9ed0aa 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -507,6 +507,9 @@
     // The time of inactivity after which the stylus can be assumed to be no longer in use.
     private long mIdleStylusTimeoutMillisConfig = 0;
 
+    // Whether wear bedtime mode is enabled in the settings.
+    private boolean mIsWearBedtimeModeEnabled;
+
     /**
      * Creates the display power controller.
      */
@@ -563,6 +566,12 @@
         mBrightnessTracker = brightnessTracker;
         mOnBrightnessChangeRunnable = onBrightnessChangeRunnable;
 
+        mIsWearBedtimeModeEnabled = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.Wearable.BEDTIME_MODE, /* def= */ 0) == 1;
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.Wearable.BEDTIME_MODE),
+                false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
+
         final Resources resources = context.getResources();
 
         // DOZE AND DIM SETTINGS
@@ -1166,8 +1175,7 @@
                     screenBrightnessThresholds, ambientBrightnessThresholdsIdle,
                     screenBrightnessThresholdsIdle, mContext, mBrightnessRangeController,
                     mBrightnessThrottler, mDisplayDeviceConfig.getAmbientHorizonShort(),
-                    mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userNits,
-                    mBrightnessClamperController, mFlags);
+                    mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userNits, mFlags);
             mDisplayBrightnessController.setUpAutoBrightness(
                     mAutomaticBrightnessController, mSensorManager, mDisplayDeviceConfig, mHandler,
                     defaultModeBrightnessMapper, mIsEnabled, mLeadDisplayId);
@@ -1386,9 +1394,12 @@
         final boolean useDozeBrightness = mFlags.isNormalBrightnessForDozeParameterEnabled()
                 ? (!mPowerRequest.useNormalBrightnessForDoze && mPowerRequest.policy == POLICY_DOZE)
                         || Display.isDozeState(state) : Display.isDozeState(state);
-
-        DisplayBrightnessState displayBrightnessState = mDisplayBrightnessController
-                .updateBrightness(mPowerRequest, state, mDisplayOffloadSession);
+        DisplayBrightnessState displayBrightnessState =
+                mDisplayBrightnessController.updateBrightness(
+                        mPowerRequest,
+                        state,
+                        mDisplayOffloadSession,
+                        mIsWearBedtimeModeEnabled);
         float brightnessState = displayBrightnessState.getBrightness();
         float rawBrightnessState = displayBrightnessState.getBrightness();
         mBrightnessReasonTemp.set(displayBrightnessState.getBrightnessReason());
@@ -1429,16 +1440,24 @@
                     && !mAutomaticBrightnessController.isInIdleMode()) {
                 // Set sendUpdate to false, we're already in updatePowerState() so there's no need
                 // to trigger it again
-                mAutomaticBrightnessController.switchMode(useDozeBrightness
-                        ? AUTO_BRIGHTNESS_MODE_DOZE : AUTO_BRIGHTNESS_MODE_DEFAULT,
-                        /* sendUpdate= */ false);
+                if (useDozeBrightness) {
+                    mAutomaticBrightnessController.switchMode(AUTO_BRIGHTNESS_MODE_DOZE,
+                            /* sendUpdate= */ false);
+                } else if (mFlags.isAutoBrightnessModeBedtimeWearEnabled()
+                        && mIsWearBedtimeModeEnabled) {
+                    mAutomaticBrightnessController.switchMode(AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR,
+                            /* sendUpdate= */ false);
+                } else {
+                    mAutomaticBrightnessController.switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT,
+                            /* sendUpdate= */ false);
+                }
             }
 
             mAutomaticBrightnessStrategy.setAutoBrightnessState(state,
                     allowAutoBrightnessWhileDozing, mBrightnessReasonTemp.getReason(),
                     mPowerRequest.policy, mPowerRequest.useNormalBrightnessForDoze,
                     mDisplayBrightnessController.getLastUserSetScreenBrightness(),
-                    userSetBrightnessChanged);
+                    userSetBrightnessChanged, mIsWearBedtimeModeEnabled);
 
             // If the brightness is already set then it's been overridden by something other than
             // the user, or is a temporary adjustment.
@@ -3172,6 +3191,12 @@
                         + autoBrightnessPresetToString(preset));
                 setUpAutoBrightness(mContext, mHandler);
                 sendUpdatePowerState();
+            } else if (uri.equals(
+                    Settings.Global.getUriFor(Settings.Global.Wearable.BEDTIME_MODE))) {
+                mIsWearBedtimeModeEnabled = Settings.Global.getInt(mContext.getContentResolver(),
+                        Settings.Global.Wearable.BEDTIME_MODE, /* def= */ 0) == 1;
+                Slog.i(mTag, "Update for bedtime mode. Enable: " + mIsWearBedtimeModeEnabled);
+                sendUpdatePowerState();
             } else {
                 handleSettingsChange();
             }
@@ -3275,7 +3300,6 @@
                 BrightnessRangeController brightnessModeController,
                 BrightnessThrottler brightnessThrottler, int ambientLightHorizonShort,
                 int ambientLightHorizonLong, float userLux, float userNits,
-                BrightnessClamperController brightnessClamperController,
                 DisplayManagerFlags displayManagerFlags) {
 
             return new AutomaticBrightnessController(callbacks, looper, sensorManager, lightSensor,
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
index 4bd9808..5b12dfb 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -150,12 +150,13 @@
     public DisplayBrightnessState updateBrightness(
             DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
             int targetDisplayState,
-            DisplayManagerInternal.DisplayOffloadSession displayOffloadSession) {
+            DisplayManagerInternal.DisplayOffloadSession displayOffloadSession,
+            boolean isBedtimeModeWearEnabled) {
         DisplayBrightnessState state;
         synchronized (mLock) {
             mDisplayBrightnessStrategy = mDisplayBrightnessStrategySelector.selectStrategy(
                     constructStrategySelectionRequest(displayPowerRequest, targetDisplayState,
-                            displayOffloadSession));
+                            displayOffloadSession, isBedtimeModeWearEnabled));
             state = mDisplayBrightnessStrategy
                         .updateBrightness(constructStrategyExecutionRequest(displayPowerRequest));
         }
@@ -629,7 +630,8 @@
     private StrategySelectionRequest constructStrategySelectionRequest(
             DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
             int targetDisplayState,
-            DisplayManagerInternal.DisplayOffloadSession displayOffloadSession) {
+            DisplayManagerInternal.DisplayOffloadSession displayOffloadSession,
+            boolean isBedtimeModeEnabled) {
         boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
         float lastUserSetScreenBrightness;
         synchronized (mLock) {
@@ -637,7 +639,7 @@
         }
         return new StrategySelectionRequest(displayPowerRequest, targetDisplayState,
                 lastUserSetScreenBrightness, userSetBrightnessChanged, displayOffloadSession,
-                mIsStylusBeingUsed);
+                mIsStylusBeingUsed, isBedtimeModeEnabled);
     }
 
     private StrategyExecutionRequest constructStrategyExecutionRequest(
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
index ded7447..60c1b8f 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessStrategySelector.java
@@ -305,7 +305,8 @@
                 strategySelectionRequest.getDisplayPowerRequest().policy,
                 strategySelectionRequest.getDisplayPowerRequest().useNormalBrightnessForDoze,
                 strategySelectionRequest.getLastUserSetScreenBrightness(),
-                strategySelectionRequest.isUserSetBrightnessChanged());
+                strategySelectionRequest.isUserSetBrightnessChanged(),
+                strategySelectionRequest.isWearBedtimeModeEnabled());
         return !strategySelectionRequest.isStylusBeingUsed()
                 && mAutomaticBrightnessStrategy1.isAutoBrightnessValid();
     }
@@ -320,7 +321,8 @@
                 strategySelectionRequest.getLastUserSetScreenBrightness(),
                 strategySelectionRequest.isUserSetBrightnessChanged(),
                 mAllowAutoBrightnessWhileDozing,
-                getAutomaticBrightnessStrategy().shouldUseAutoBrightness());
+                getAutomaticBrightnessStrategy().shouldUseAutoBrightness(),
+                strategySelectionRequest.isWearBedtimeModeEnabled());
     }
 
     private void postProcess(StrategySelectionNotifyRequest strategySelectionNotifyRequest) {
diff --git a/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java b/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java
index bfa90e2..c2bec5f 100644
--- a/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java
+++ b/services/core/java/com/android/server/display/brightness/StrategySelectionNotifyRequest.java
@@ -47,13 +47,15 @@
     private final boolean mAllowAutoBrightnessWhileDozingConfig;
     // True if the auto brightness is enabled in the settings
     private final boolean mIsAutoBrightnessEnabled;
+    // True if wear bedtime mode is enabled in the settings.
+    private final boolean mIsBedtimeModeWearEnabled;
 
     public StrategySelectionNotifyRequest(
             DisplayManagerInternal.DisplayPowerRequest displayPowerRequest, int targetDisplayState,
             DisplayBrightnessStrategy displayBrightnessStrategy,
             float lastUserSetScreenBrightness,
             boolean userSetBrightnessChanged, boolean allowAutoBrightnessWhileDozingConfig,
-            boolean isAutoBrightnessEnabled) {
+            boolean isAutoBrightnessEnabled, boolean isBedtimeModeWearEnabled) {
         mDisplayPowerRequest = displayPowerRequest;
         mTargetDisplayState = targetDisplayState;
         mSelectedDisplayBrightnessStrategy = displayBrightnessStrategy;
@@ -61,6 +63,7 @@
         mUserSetBrightnessChanged = userSetBrightnessChanged;
         mAllowAutoBrightnessWhileDozingConfig = allowAutoBrightnessWhileDozingConfig;
         mIsAutoBrightnessEnabled = isAutoBrightnessEnabled;
+        mIsBedtimeModeWearEnabled = isBedtimeModeWearEnabled;
     }
 
     public DisplayBrightnessStrategy getSelectedDisplayBrightnessStrategy() {
@@ -81,7 +84,8 @@
                 && mLastUserSetScreenBrightness == other.getLastUserSetScreenBrightness()
                 && mAllowAutoBrightnessWhileDozingConfig
                 == other.isAllowAutoBrightnessWhileDozingConfig()
-                && mIsAutoBrightnessEnabled == other.isAutoBrightnessEnabled();
+                && mIsAutoBrightnessEnabled == other.isAutoBrightnessEnabled()
+                && mIsBedtimeModeWearEnabled == other.isBedtimeModeWearEnabled();
     }
 
     @Override
@@ -99,6 +103,10 @@
         return mUserSetBrightnessChanged;
     }
 
+    public boolean isBedtimeModeWearEnabled() {
+        return mIsBedtimeModeWearEnabled;
+    }
+
     public DisplayManagerInternal.DisplayPowerRequest getDisplayPowerRequest() {
         return mDisplayPowerRequest;
     }
@@ -126,6 +134,7 @@
                 + " mLastUserSetScreenBrightness=" + mLastUserSetScreenBrightness
                 + " mUserSetBrightnessChanged=" + mUserSetBrightnessChanged
                 + " mAllowAutoBrightnessWhileDozingConfig=" + mAllowAutoBrightnessWhileDozingConfig
-                + " mIsAutoBrightnessEnabled=" + mIsAutoBrightnessEnabled;
+                + " mIsAutoBrightnessEnabled=" + mIsAutoBrightnessEnabled
+                + " mIsBedtimeModeWearEnabled" + mIsBedtimeModeWearEnabled;
     }
 }
diff --git a/services/core/java/com/android/server/display/brightness/StrategySelectionRequest.java b/services/core/java/com/android/server/display/brightness/StrategySelectionRequest.java
index 5c1f03d..2077c9d 100644
--- a/services/core/java/com/android/server/display/brightness/StrategySelectionRequest.java
+++ b/services/core/java/com/android/server/display/brightness/StrategySelectionRequest.java
@@ -42,17 +42,21 @@
 
     private boolean mIsStylusBeingUsed;
 
+    private boolean mIsWearBedtimeModeEnabled;
+
     public StrategySelectionRequest(DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
             int targetDisplayState, float lastUserSetScreenBrightness,
             boolean userSetBrightnessChanged,
             DisplayManagerInternal.DisplayOffloadSession displayOffloadSession,
-            boolean isStylusBeingUsed) {
+            boolean isStylusBeingUsed,
+            boolean isWearBedtimeModeEnabled) {
         mDisplayPowerRequest = displayPowerRequest;
         mTargetDisplayState = targetDisplayState;
         mLastUserSetScreenBrightness = lastUserSetScreenBrightness;
         mUserSetBrightnessChanged = userSetBrightnessChanged;
         mDisplayOffloadSession = displayOffloadSession;
         mIsStylusBeingUsed = isStylusBeingUsed;
+        mIsWearBedtimeModeEnabled = isWearBedtimeModeEnabled;
     }
 
     public DisplayManagerInternal.DisplayPowerRequest getDisplayPowerRequest() {
@@ -72,6 +76,10 @@
         return mUserSetBrightnessChanged;
     }
 
+    public boolean isWearBedtimeModeEnabled() {
+        return mIsWearBedtimeModeEnabled;
+    }
+
     public DisplayManagerInternal.DisplayOffloadSession getDisplayOffloadSession() {
         return mDisplayOffloadSession;
     }
@@ -91,7 +99,8 @@
                 && mLastUserSetScreenBrightness == other.getLastUserSetScreenBrightness()
                 && mUserSetBrightnessChanged == other.isUserSetBrightnessChanged()
                 && mDisplayOffloadSession.equals(other.getDisplayOffloadSession())
-                && mIsStylusBeingUsed == other.isStylusBeingUsed();
+                && mIsStylusBeingUsed == other.isStylusBeingUsed()
+                && mIsWearBedtimeModeEnabled == other.isWearBedtimeModeEnabled();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
index 2fdec78..ff73693 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
@@ -17,6 +17,7 @@
 
 import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
 
+import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR;
 import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT;
 import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE;
 
@@ -132,10 +133,11 @@
     public void setAutoBrightnessState(int targetDisplayState,
             boolean allowAutoBrightnessWhileDozingConfig, int brightnessReason, int policy,
             boolean useNormalBrightnessForDoze, float lastUserSetScreenBrightness,
-            boolean userSetBrightnessChanged) {
+            boolean userSetBrightnessChanged, boolean isBedtimeModeWearEnabled) {
         // We are still in the process of updating the power state, so there's no need to trigger
         // an update again
-        switchMode(targetDisplayState, useNormalBrightnessForDoze, policy, /* sendUpdate= */ false);
+        switchMode(targetDisplayState, useNormalBrightnessForDoze, policy, isBedtimeModeWearEnabled,
+                /* sendUpdate= */ false);
 
         // If the policy is POLICY_DOZE and the display state is not STATE_OFF, auto-brightness
         // should only be enabled if the config allows it
@@ -349,7 +351,8 @@
                     strategySelectionNotifyRequest.getDisplayPowerRequest()
                             .useNormalBrightnessForDoze,
                     strategySelectionNotifyRequest.getLastUserSetScreenBrightness(),
-                    strategySelectionNotifyRequest.isUserSetBrightnessChanged());
+                    strategySelectionNotifyRequest.isUserSetBrightnessChanged(),
+                    strategySelectionNotifyRequest.isBedtimeModeWearEnabled());
         }
         mIsConfigured = false;
     }
@@ -505,18 +508,33 @@
     }
 
     private void switchMode(int state, boolean useNormalBrightnessForDoze, int policy,
-            boolean sendUpdate) {
-        if (mDisplayManagerFlags.areAutoBrightnessModesEnabled()
-                && mAutomaticBrightnessController != null
-                && !mAutomaticBrightnessController.isInIdleMode()) {
-
-            final boolean shouldUseDozeMode =
-                    mDisplayManagerFlags.isNormalBrightnessForDozeParameterEnabled()
-                            ? (!useNormalBrightnessForDoze && policy == POLICY_DOZE)
-                                    || Display.isDozeState(state) : Display.isDozeState(state);
-            mAutomaticBrightnessController.switchMode(shouldUseDozeMode
-                    ? AUTO_BRIGHTNESS_MODE_DOZE : AUTO_BRIGHTNESS_MODE_DEFAULT, sendUpdate);
+            boolean isWearBedtimeModeEnabled, boolean sendUpdate) {
+        if (!mDisplayManagerFlags.areAutoBrightnessModesEnabled()
+                || mAutomaticBrightnessController == null
+                || mAutomaticBrightnessController.isInIdleMode()) {
+            return;
         }
+
+        final boolean shouldUseBedtimeMode =
+                mDisplayManagerFlags.isAutoBrightnessModeBedtimeWearEnabled()
+                        && isWearBedtimeModeEnabled;
+        if (shouldUseBedtimeMode) {
+            mAutomaticBrightnessController.switchMode(AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR,
+                    sendUpdate);
+            return;
+        }
+
+        final boolean shouldUseDozeMode =
+                mDisplayManagerFlags.isNormalBrightnessForDozeParameterEnabled()
+                        ? (!useNormalBrightnessForDoze && policy == POLICY_DOZE)
+                                || Display.isDozeState(state)
+                        : Display.isDozeState(state);
+        if (shouldUseDozeMode) {
+            mAutomaticBrightnessController.switchMode(AUTO_BRIGHTNESS_MODE_DOZE, sendUpdate);
+            return;
+        }
+
+        mAutomaticBrightnessController.switchMode(AUTO_BRIGHTNESS_MODE_DEFAULT, sendUpdate);
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java
index 5e79565..6e2e7e7 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2.java
@@ -109,7 +109,7 @@
     public void setAutoBrightnessState(int targetDisplayState,
             boolean allowAutoBrightnessWhileDozingConfig, int brightnessReason, int policy,
             boolean useNormalBrightnessForDoze, float lastUserSetScreenBrightness,
-            boolean userSetBrightnessChanged) {
+            boolean userSetBrightnessChanged, boolean isBedtimeModeEnabled) {
         // If the policy is POLICY_DOZE and the display state is not STATE_OFF, auto-brightness
         // should only be enabled if the config allows it
         final boolean autoBrightnessEnabledInDoze = allowAutoBrightnessWhileDozingConfig
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
index 598901e..556cc03 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
@@ -500,7 +500,7 @@
                 checkNanoappPermsAsync();
             }
 
-            if (!Flags.reliableMessageImplementation() || transactionCallback == null) {
+            if (transactionCallback == null) {
                 try {
                     result = mContextHubProxy.sendMessageToContextHub(mHostEndPointId,
                             mAttachedContextHubInfo.getId(), message);
@@ -671,10 +671,8 @@
                         .putExtra(ContextHubManager.EXTRA_MESSAGE, message);
         Consumer<Byte> onFinishedCallback = (Byte error) ->
                 sendMessageDeliveryStatusToContextHub(message.getMessageSequenceNumber(), error);
-        return sendPendingIntent(supplier, nanoAppId,
-                Flags.reliableMessageImplementation() && message.isReliable()
-                        ? onFinishedCallback
-                        : null);
+        return sendPendingIntent(
+                supplier, nanoAppId, message.isReliable() ? onFinishedCallback : null);
     }
 
     /**
@@ -1284,10 +1282,6 @@
     }
 
     private void sendMessageDeliveryStatusToContextHub(int messageSequenceNumber, byte errorCode) {
-        if (!Flags.reliableMessageImplementation()) {
-            return;
-        }
-
         MessageDeliveryStatus status = new MessageDeliveryStatus();
         status.messageSequenceNumber = messageSequenceNumber;
         status.errorCode = errorCode;
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubClientManager.java b/services/core/java/com/android/server/location/contexthub/ContextHubClientManager.java
index 7285151..0fdd0ae 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubClientManager.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubClientManager.java
@@ -236,7 +236,7 @@
         }
 
         if (message.isBroadcastMessage()) {
-            if (Flags.reliableMessageImplementation() && message.isReliable()) {
+            if (message.isReliable()) {
                 Log.e(TAG, "Received reliable broadcast message from " + message.getNanoAppId());
                 return ErrorCode.PERMANENT_ERROR;
             }
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubEventLogger.java b/services/core/java/com/android/server/location/contexthub/ContextHubEventLogger.java
index e1b1416..53a02cd 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubEventLogger.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubEventLogger.java
@@ -333,10 +333,6 @@
      */
     public synchronized void logReliableMessageToNanoappStatus(
             int messageSequenceNumber, byte errorCode) {
-        if (!Flags.reliableMessage()) {
-            return;
-        }
-
         for (NanoappMessageEvent event : mMessageToNanoappQueue) {
             if (event.message.isReliable()
                     && event.message.getMessageSequenceNumber()
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index ed69f7a..acc8f66 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -228,9 +228,8 @@
             // Only process the message normally if not using test mode manager or if
             // the test mode manager call returned false as this indicates it did not
             // process the message.
-            boolean useTestModeManager = Flags.reliableMessageImplementation()
-                    && Flags.reliableMessageTestModeBehavior()
-                    && mIsTestModeEnabled.get();
+            boolean useTestModeManager =
+                    Flags.reliableMessageTestModeBehavior() && mIsTestModeEnabled.get();
             if (!useTestModeManager
                     || !mTestModeManager.handleNanoappMessage(() -> {
                         handleClientMessageCallback(mContextHubId, hostEndpointId,
@@ -945,8 +944,7 @@
     private void handleClientMessageCallback(int contextHubId, short hostEndpointId,
             NanoAppMessage message, List<String> nanoappPermissions,
             List<String> messagePermissions) {
-        if (!Flags.reliableMessageImplementation()
-                || !Flags.reliableMessageDuplicateDetectionService()) {
+        if (!Flags.reliableMessageDuplicateDetectionService()) {
             byte errorCode = mClientManager.onMessageFromNanoApp(contextHubId, hostEndpointId,
                     message, nanoappPermissions, messagePermissions);
             if (message.isReliable() && errorCode != ErrorCode.OK) {
@@ -1040,12 +1038,8 @@
      * @param messageSequenceNumber the message sequence number
      * @param errorCode the error code, one of the enum ErrorCode
      */
-    private void sendMessageDeliveryStatusToContextHub(int contextHubId,
-            int messageSequenceNumber, byte errorCode) {
-        if (!Flags.reliableMessageImplementation()) {
-            return;
-        }
-
+    private void sendMessageDeliveryStatusToContextHub(
+            int contextHubId, int messageSequenceNumber, byte errorCode) {
         MessageDeliveryStatus status = new MessageDeliveryStatus();
         status.messageSequenceNumber = messageSequenceNumber;
         status.errorCode = errorCode;
diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
index a8ad418..5e9277a 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -494,16 +494,11 @@
             }
 
             public void handleMessageDeliveryStatus(
-                    char hostEndpointId,
-                    MessageDeliveryStatus messageDeliveryStatus) {
-                if (Flags.reliableMessageImplementation()) {
-                    mHandler.post(() -> {
-                        mCallback.handleMessageDeliveryStatus(messageDeliveryStatus);
-                    });
-                } else {
-                    Log.w(TAG, "handleMessageDeliveryStatus called when the "
-                            + "reliableMessageImplementation flag is disabled");
-                }
+                    char hostEndpointId, MessageDeliveryStatus messageDeliveryStatus) {
+                mHandler.post(
+                        () -> {
+                            mCallback.handleMessageDeliveryStatus(messageDeliveryStatus);
+                        });
             }
 
             public byte[] getUuid() {
@@ -682,9 +677,8 @@
             // Only process the message normally if not using test mode manager or if
             // the test mode manager call returned false as this indicates it did not
             // process the message.
-            boolean useTestModeManager = Flags.reliableMessageImplementation()
-                    && Flags.reliableMessageTestModeBehavior()
-                    && mIsTestModeEnabled.get();
+            boolean useTestModeManager =
+                    Flags.reliableMessageTestModeBehavior() && mIsTestModeEnabled.get();
             if (!useTestModeManager || !mTestModeManager.sendMessageToContextHub(
                     sendMessage, message)) {
                 try {
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index b0fa523..58c8450 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -42,15 +42,16 @@
     final Object mLock = new Object();
 
     Callback mCallback;
-    boolean mIsSystemRouteProvider;
+    public final boolean mIsSystemRouteProvider;
     private volatile MediaRoute2ProviderInfo mProviderInfo;
 
     @GuardedBy("mLock")
     final List<RoutingSessionInfo> mSessionInfos = new ArrayList<>();
 
-    MediaRoute2Provider(@NonNull ComponentName componentName) {
+    MediaRoute2Provider(@NonNull ComponentName componentName, boolean isSystemRouteProvider) {
         mComponentName = Objects.requireNonNull(componentName, "Component name must not be null.");
         mUniqueId = componentName.flattenToShortString();
+        mIsSystemRouteProvider = isSystemRouteProvider;
     }
 
     public void setCallback(Callback callback) {
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index 56b93e8..db1e6b4 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -96,7 +96,7 @@
             @NonNull ComponentName componentName,
             boolean isSelfScanOnlyProvider,
             int userId) {
-        super(componentName);
+        super(componentName, /* isSystemRouteProvider= */ false);
         mContext = Objects.requireNonNull(context, "Context must not be null.");
         mRequestIdToSessionCreationRequest = new LongSparseArray<>();
         mSessionOriginalIdToTransferRequest = new HashMap<>();
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 8c6273c..49897b9 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -90,8 +90,7 @@
     private volatile SessionCreationOrTransferRequest mPendingTransferRequest;
 
     SystemMediaRoute2Provider(Context context, UserHandle user, Looper looper) {
-        super(COMPONENT_NAME);
-        mIsSystemRouteProvider = true;
+        super(COMPONENT_NAME, /* isSystemRouteProvider= */ true);
         mContext = context;
         mUser = user;
         mHandler = new Handler(looper);
diff --git a/services/core/java/com/android/server/notification/EventConditionProvider.java b/services/core/java/com/android/server/notification/EventConditionProvider.java
index ecc4cf7..308f299 100644
--- a/services/core/java/com/android/server/notification/EventConditionProvider.java
+++ b/services/core/java/com/android/server/notification/EventConditionProvider.java
@@ -16,7 +16,6 @@
 
 package com.android.server.notification;
 
-import android.annotation.Nullable;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
@@ -68,7 +67,7 @@
     private final Handler mWorker;
     private final HandlerThread mThread;
 
-    @Nullable private UserHandle mCurrentUser;
+    private UserHandle mCurrentUser = UserHandle.SYSTEM;
     private boolean mConnected;
     private boolean mRegistered;
     private boolean mBootComplete;  // don't hammer the calendar provider until boot completes.
@@ -119,18 +118,19 @@
             @Override
             public void onReceive(Context context, Intent intent) {
                 if (android.app.Flags.modesHsum()) {
-                    if (mCurrentUser != null) {
-                        // Possibly the intent signals a profile added on a different user, but it
-                        // doesn't matter (except for a bit of wasted work here). We will reload
-                        // trackers for that user when we switch.
-                        reloadTrackers(mCurrentUser);
-                    }
+                    // Possibly the intent signals a profile added on a different user, but it
+                    // doesn't matter (except for a bit of wasted work here). We will reload
+                    // trackers for that user when we switch.
+                    reloadTrackers(mCurrentUser);
                 } else {
                     reloadTrackers();
                 }
             }
         }, filter);
-        if (!android.app.Flags.modesHsum()) {
+
+        if (android.app.Flags.modesHsum()) {
+            reloadTrackers(UserHandle.SYSTEM);
+        } else {
             reloadTrackers();
         }
     }
@@ -138,8 +138,10 @@
     @Override
     public void onUserSwitched(UserHandle user) {
         if (DEBUG) Slog.d(TAG, "onUserSwitched: " + user);
-        mCurrentUser = user;
-        reloadTrackers(user);
+        if (mCurrentUser.getIdentifier() != user.getIdentifier()) {
+            mCurrentUser = user;
+            reloadTrackers(user);
+        }
     }
 
     @Override
@@ -274,12 +276,23 @@
                     final int userId = EventInfo.resolveUserId(event.userId);
                     final CalendarTracker tracker = mTrackers.get(userId);
                     if (tracker == null) {
-                        Slog.w(TAG, "No calendar tracker found for user " + userId);
+                        Slog.w(TAG,
+                                "No calendar tracker found for user " + userId + " and calendar = "
+                                        + event.calName);
                         conditionsToNotify.add(createCondition(conditionId, Condition.STATE_FALSE));
                         continue;
                     }
                     result = tracker.checkEvent(event, now);
                 }
+
+                if (result == null) {
+                    Slog.e(TAG, "No CheckEventResult for userId=" + event.userId + ", calId="
+                            + event.calendarId + ", calName=" + event.calName
+                            + "; trackers count is " + mTrackers.size());
+                    conditionsToNotify.add(createCondition(conditionId, Condition.STATE_FALSE));
+                    continue;
+                }
+
                 if (result.recheckAt != 0
                         && (reevaluateAt == 0 || result.recheckAt < reevaluateAt)) {
                     reevaluateAt = result.recheckAt;
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index 9189c2f..27fd1e6 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -18,6 +18,7 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR;
 import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT;
 import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE;
 import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_IDLE;
@@ -1290,7 +1291,6 @@
                 /* ambientLightHorizonLong= */ anyInt(),
                 eq(lux),
                 eq(nits),
-                any(BrightnessClamperController.class),
                 any(DisplayManagerFlags.class)
         );
     }
@@ -1929,6 +1929,60 @@
     }
 
     @Test
+    public void testSwitchToBedtimeAutoBrightnessMode_wearBedtimeEnabledAndBrightRequest() {
+        when(mDisplayManagerFlagsMock.areAutoBrightnessModesEnabled()).thenReturn(true);
+        when(mDisplayManagerFlagsMock.isAutoBrightnessModeBedtimeWearEnabled()).thenReturn(true);
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.Wearable.BEDTIME_MODE,
+                /* value= */ 1);
+        mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        verify(mHolder.automaticBrightnessController)
+                .switchMode(eq(AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR), /* sendUpdate= */ anyBoolean());
+    }
+
+    @Test
+    public void testNotSwitchToBedtimeAutoBrightnessMode_wearBedtimeDisabled() {
+        when(mDisplayManagerFlagsMock.areAutoBrightnessModesEnabled()).thenReturn(true);
+        when(mDisplayManagerFlagsMock.isAutoBrightnessModeBedtimeWearEnabled()).thenReturn(true);
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.Wearable.BEDTIME_MODE,
+                /* value= */ 0);
+        mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        verify(mHolder.automaticBrightnessController)
+                .switchMode(eq(AUTO_BRIGHTNESS_MODE_DEFAULT), /* sendUpdate= */ anyBoolean());
+    }
+
+    @Test
+    public void testSwitchToDozeAutoBrightnessMode_wearBedtimeEnabledAndDozeRequest() {
+        when(mDisplayManagerFlagsMock.areAutoBrightnessModesEnabled()).thenReturn(true);
+        when(mDisplayManagerFlagsMock.isAutoBrightnessModeBedtimeWearEnabled()).thenReturn(true);
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.Wearable.BEDTIME_MODE,
+                /* value= */ 1);
+        mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_DOZE);
+
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        dpr.policy = DisplayPowerRequest.POLICY_DOZE;
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        verify(mHolder.automaticBrightnessController)
+                .switchMode(eq(AUTO_BRIGHTNESS_MODE_DOZE), /* sendUpdate= */ anyBoolean());
+    }
+
+    @Test
     public void testOnSwitchUserUpdatesBrightness() {
         int userSerial = 12345;
         float brightness = 0.65f;
@@ -2710,7 +2764,6 @@
                 BrightnessRangeController brightnessRangeController,
                 BrightnessThrottler brightnessThrottler, int ambientLightHorizonShort,
                 int ambientLightHorizonLong, float userLux, float userNits,
-                BrightnessClamperController brightnessClamperController,
                 DisplayManagerFlags displayManagerFlags) {
             return mAutomaticBrightnessController;
         }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
index b3baa5d..4f875c3 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
@@ -121,8 +121,9 @@
         int targetDisplayState = Display.STATE_DOZE;
         when(mDisplayBrightnessStrategySelector.selectStrategy(
                 any(StrategySelectionRequest.class))).thenReturn(displayBrightnessStrategy);
-        mDisplayBrightnessController.updateBrightness(displayPowerRequest, targetDisplayState, mock(
-                DisplayManagerInternal.DisplayOffloadSession.class));
+        mDisplayBrightnessController.updateBrightness(displayPowerRequest, targetDisplayState,
+                mock(DisplayManagerInternal.DisplayOffloadSession.class),
+                /* isBedtimeModeWearEnabled= */ false);
         verify(displayBrightnessStrategy).updateBrightness(
                 eq(new StrategyExecutionRequest(displayPowerRequest, DEFAULT_BRIGHTNESS,
                         /* userSetBrightnessChanged= */ false, /* isStylusBeingUsed */ false)));
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
index fe15051..b99a18c 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessStrategySelectorTest.java
@@ -199,7 +199,7 @@
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_DOZE,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mDozeBrightnessModeStrategy);
     }
 
@@ -216,7 +216,7 @@
         assertNotEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_DOZE,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mDozeBrightnessModeStrategy);
     }
 
@@ -231,7 +231,7 @@
         assertNotEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_DOZE,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mDozeBrightnessModeStrategy);
     }
 
@@ -255,7 +255,7 @@
         assertNotEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_DOZE,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mDozeBrightnessModeStrategy);
     }
 
@@ -266,7 +266,7 @@
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_OFF,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mScreenOffBrightnessModeStrategy);
     }
 
@@ -279,7 +279,7 @@
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mOverrideBrightnessStrategy);
     }
 
@@ -293,7 +293,7 @@
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mTemporaryBrightnessStrategy);
     }
 
@@ -308,7 +308,7 @@
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mBoostBrightnessStrategy);
     }
 
@@ -323,7 +323,7 @@
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mInvalidBrightnessStrategy);
     }
 
@@ -335,7 +335,7 @@
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mFollowerBrightnessStrategy);
     }
 
@@ -354,7 +354,7 @@
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mOffloadBrightnessStrategy);
     }
 
@@ -379,12 +379,13 @@
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mAutomaticBrightnessStrategy);
         verify(mAutomaticBrightnessStrategy).setAutoBrightnessState(Display.STATE_ON,
                 true, BrightnessReason.REASON_UNKNOWN,
                 DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT,
-                /* useNormalBrightnessForDoze= */ false, 0.1f, false);
+                /* useNormalBrightnessForDoze= */ false, 0.1f, false,
+                /* isBedtimeModeWearEnabled= */ false);
     }
 
 
@@ -409,7 +410,7 @@
         assertNotEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_BEING_USED)),
+                                STYLUS_IS_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mAutomaticBrightnessStrategy);
     }
 
@@ -430,7 +431,7 @@
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mAutoBrightnessFallbackStrategy);
     }
 
@@ -449,7 +450,7 @@
                 mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)));
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)));
     }
 
     @Test
@@ -468,7 +469,7 @@
         assertEquals(mDisplayBrightnessStrategySelector.selectStrategy(
                         new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
                                 0.1f, false, mDisplayOffloadSession,
-                                STYLUS_IS_NOT_BEING_USED)),
+                                STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false)),
                 mFallbackBrightnessStrategy);
     }
 
@@ -484,12 +485,13 @@
         mDisplayBrightnessStrategySelector.selectStrategy(
                 new StrategySelectionRequest(displayPowerRequest, Display.STATE_ON,
                         0.1f, false, mDisplayOffloadSession,
-                        STYLUS_IS_NOT_BEING_USED));
+                        STYLUS_IS_NOT_BEING_USED, /* isBedtimeModeWearEnabled= */ false));
 
         StrategySelectionNotifyRequest strategySelectionNotifyRequest =
                 new StrategySelectionNotifyRequest(displayPowerRequest, Display.STATE_ON,
                         mFollowerBrightnessStrategy, 0.1f,
-                        false, false, false);
+                        false, false, false,
+                        /* isBedtimeModeWearEnabled= */ false);
 
         for (DisplayBrightnessStrategy displayBrightnessStrategy :
                 mDisplayBrightnessStrategySelector.mDisplayBrightnessStrategies) {
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategyTest.java
index 2a71af0..e3893c8 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutoBrightnessFallbackStrategyTest.java
@@ -150,7 +150,8 @@
                 /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
                 /* userSetBrightnessChanged= */ false,
                 /* allowAutoBrightnessWhileDozingConfig= */ false,
-                /* isAutoBrightnessEnabled= */ true);
+                /* isAutoBrightnessEnabled= */ true,
+                /* isBedtimeModeWearEnabled= */ false);
         mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
 
         verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(true);
@@ -172,7 +173,8 @@
                 /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
                 /* userSetBrightnessChanged= */ false,
                 /* allowAutoBrightnessWhileDozingConfig= */ false,
-                /* isAutoBrightnessEnabled= */ true);
+                /* isAutoBrightnessEnabled= */ true,
+                /* isBedtimeModeWearEnabled= */ false);
         mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
 
         verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(true);
@@ -194,7 +196,8 @@
                 /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
                 /* userSetBrightnessChanged= */ false,
                 /* allowAutoBrightnessWhileDozingConfig= */ false,
-                /* isAutoBrightnessEnabled= */ false);
+                /* isAutoBrightnessEnabled= */ false,
+                /* isBedtimeModeWearEnabled= */ false);
         mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
 
         verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(false);
@@ -216,7 +219,8 @@
                 /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
                 /* userSetBrightnessChanged= */ false,
                 /* allowAutoBrightnessWhileDozingConfig= */ false,
-                /* isAutoBrightnessEnabled= */ true);
+                /* isAutoBrightnessEnabled= */ true,
+                /* isBedtimeModeWearEnabled= */ false);
         mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
 
         verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(false);
@@ -238,7 +242,8 @@
                 /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
                 /* userSetBrightnessChanged= */ false,
                 /* allowAutoBrightnessWhileDozingConfig= */ false,
-                /* isAutoBrightnessEnabled= */ true);
+                /* isAutoBrightnessEnabled= */ true,
+                /* isBedtimeModeWearEnabled= */ false);
         mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
 
         verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(false);
@@ -260,7 +265,8 @@
                 /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
                 /* userSetBrightnessChanged= */ false,
                 /* allowAutoBrightnessWhileDozingConfig= */ true,
-                /* isAutoBrightnessEnabled= */ true);
+                /* isAutoBrightnessEnabled= */ true,
+                /* isBedtimeModeWearEnabled= */ false);
         mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
 
         verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(false);
@@ -282,7 +288,8 @@
                 /* lastUserSetScreenBrightness= */ PowerManager.BRIGHTNESS_INVALID_FLOAT,
                 /* userSetBrightnessChanged= */ false,
                 /* allowAutoBrightnessWhileDozingConfig= */ false,
-                /* isAutoBrightnessEnabled= */ true);
+                /* isAutoBrightnessEnabled= */ true,
+                /* isBedtimeModeWearEnabled= */ false);
         mAutoBrightnessFallbackStrategy.strategySelectionPostProcessor(ssnr);
 
         verify(mScreenOffBrightnessSensorController).setLightSensorEnabled(false);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java
index e386542..ae1b019 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy2Test.java
@@ -112,7 +112,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
-                lastUserSetBrightness, userSetBrightnessChanged);
+                lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED,
                         mBrightnessConfiguration,
@@ -139,7 +140,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
-                lastUserSetBrightness, userSetBrightnessChanged);
+                lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE,
                         mBrightnessConfiguration,
@@ -167,7 +169,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 useNormalBrightnessForDoze,
-                lastUserSetBrightness, userSetBrightnessChanged);
+                lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE,
                         mBrightnessConfiguration,
@@ -193,7 +196,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
-                lastUserSetBrightness, userSetBrightnessChanged);
+                lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED,
                         mBrightnessConfiguration,
@@ -223,7 +227,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 useNormalBrightnessForDoze,
-                lastUserSetBrightness, userSetBrightnessChanged);
+                lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED,
                         mBrightnessConfiguration,
@@ -250,7 +255,8 @@
         mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments();
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
-                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged);
+                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE,
                         mBrightnessConfiguration,
@@ -278,7 +284,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
-                lastUserSetBrightness, userSetBrightnessChanged);
+                lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED,
                         mBrightnessConfiguration,
@@ -307,7 +314,8 @@
         mAutomaticBrightnessStrategy.updatePendingAutoBrightnessAdjustments();
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
-                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged);
+                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE,
                         mBrightnessConfiguration,
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
index 8a1f860..65f8ea7 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
@@ -123,7 +123,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
-                lastUserSetBrightness, userSetBrightnessChanged);
+                lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED,
                         mBrightnessConfiguration,
@@ -150,7 +151,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
-                lastUserSetBrightness, userSetBrightnessChanged);
+                lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE,
                         mBrightnessConfiguration,
@@ -177,7 +179,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
-                lastUserSetBrightness, userSetBrightnessChanged);
+                lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE,
                         mBrightnessConfiguration,
@@ -204,7 +207,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
-                lastUserSetBrightness, userSetBrightnessChanged);
+                lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED,
                         mBrightnessConfiguration,
@@ -233,7 +237,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
-                lastUserSetBrightness, userSetBrightnessChanged);
+                lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED,
                         mBrightnessConfiguration,
@@ -261,7 +266,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, lastUserSetBrightness,
-                userSetBrightnessChanged);
+                userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE,
                         mBrightnessConfiguration,
@@ -290,7 +296,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
-                lastUserSetBrightness, userSetBrightnessChanged);
+                lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED,
                         mBrightnessConfiguration,
@@ -319,7 +326,8 @@
         mAutomaticBrightnessStrategy.setAutoBrightnessState(targetDisplayState,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, lastUserSetBrightness,
-                userSetBrightnessChanged);
+                userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController)
                 .configure(AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE,
                         mBrightnessConfiguration,
@@ -352,7 +360,8 @@
         when(mAutomaticBrightnessController.isInIdleMode()).thenReturn(true);
         mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
-                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged);
+                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController, never())
                 .switchMode(anyInt(), /* sendUpdate= */ anyBoolean());
 
@@ -361,7 +370,8 @@
         when(mAutomaticBrightnessController.isInIdleMode()).thenReturn(false);
         mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
-                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged);
+                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         verify(mAutomaticBrightnessController).switchMode(
                 AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT,
                 /* sendUpdate= */ false);
@@ -375,7 +385,8 @@
         // state is DOZE, policy is DOZE and useNormalBrightnessForDoze is false.
         mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_DOZE,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
-                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged);
+                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         // 1st AUTO_BRIGHTNESS_MODE_DOZE
         verify(mAutomaticBrightnessController).switchMode(
                 AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE,
@@ -385,7 +396,8 @@
         // state is ON, policy is DOZE and useNormalBrightnessForDoze is false.
         mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
-                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged);
+                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         // 2nd AUTO_BRIGHTNESS_MODE_DOZE
         verify(mAutomaticBrightnessController, times(2)).switchMode(
                 AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE,
@@ -396,7 +408,8 @@
         // state is DOZE, policy is DOZE and useNormalBrightnessForDoze is true.
         mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_DOZE,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
-                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged);
+                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         // 3rd AUTO_BRIGHTNESS_MODE_DOZE
         verify(mAutomaticBrightnessController, times(3)).switchMode(
                 AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DOZE,
@@ -406,11 +419,42 @@
         // state is ON, policy is DOZE and useNormalBrightnessForDoze is true.
         mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON,
                 allowAutoBrightnessWhileDozing, brightnessReason, policy,
-                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged);
+                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ false);
         // AUTO_BRIGHTNESS_MODE_DEFAULT
         verify(mAutomaticBrightnessController).switchMode(
                 AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT,
                 /* sendUpdate= */ false);
+
+        // Wear Bedtime autobrightness mode feature disabled.
+        when(mDisplayManagerFlags.isAutoBrightnessModeBedtimeWearEnabled()).thenReturn(false);
+        mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON,
+                allowAutoBrightnessWhileDozing, brightnessReason, policy,
+                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ true);
+        verify(mAutomaticBrightnessController, times(2)).switchMode(
+                AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT,
+                /* sendUpdate= */ false);
+
+        // Wear Bedtime autobrightness mode feature enabled.
+        when(mDisplayManagerFlags.isAutoBrightnessModeBedtimeWearEnabled()).thenReturn(true);
+        mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_ON,
+                allowAutoBrightnessWhileDozing, brightnessReason, policy,
+                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ true);
+        verify(mAutomaticBrightnessController).switchMode(
+                AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR,
+                /* sendUpdate= */ false);
+
+        // Wear bedtime mode enabled, keep bedtime curve even though doze is requested.
+        mAutomaticBrightnessStrategy.setAutoBrightnessState(Display.STATE_DOZE,
+                allowAutoBrightnessWhileDozing, brightnessReason,
+                DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE,
+                useNormalBrightnessForDoze, lastUserSetBrightness, userSetBrightnessChanged,
+                /* isBedtimeModeWearEnabled= */ true);
+        verify(mAutomaticBrightnessController, times(2)).switchMode(
+                AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_BEDTIME_WEAR,
+                /* sendUpdate= */ false);
     }
 
     @Test
@@ -429,14 +473,14 @@
         setTemporaryAutoBrightnessAdjustment(temporaryAutoBrightnessAdjustments);
         mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(userSetBrightnessChanged,
                 lastUserSetScreenBrightness, policy, targetDisplayState,
-                        DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
+                DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
                 brightnessConfiguration, autoBrightnessState);
         verify(mAutomaticBrightnessController).configure(autoBrightnessState,
                 brightnessConfiguration,
                 lastUserSetScreenBrightness,
                 userSetBrightnessChanged, temporaryAutoBrightnessAdjustments,
                 /* userChangedAutoBrightnessAdjustment= */ false, policy, targetDisplayState,
-                        DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
+                DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
                 /* shouldResetShortTermModel= */ true);
         assertTrue(mAutomaticBrightnessStrategy.isTemporaryAutoBrightnessAdjustmentApplied());
         assertFalse(mAutomaticBrightnessStrategy.shouldResetShortTermModel());
@@ -447,7 +491,7 @@
         mAutomaticBrightnessStrategy.setShouldResetShortTermModel(true);
         mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(userSetBrightnessChanged,
                 lastUserSetScreenBrightness, policy, targetDisplayState,
-                        DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
+                DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE,
                 brightnessConfiguration, autoBrightnessState);
         assertFalse(mAutomaticBrightnessStrategy.isTemporaryAutoBrightnessAdjustmentApplied());
         assertTrue(mAutomaticBrightnessStrategy.shouldResetShortTermModel());
@@ -572,7 +616,7 @@
                 BrightnessReason.REASON_UNKNOWN,
                 DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, /* lastUserSetScreenBrightness= */ 0.1f,
-                /* userSetBrightnessChanged= */ false);
+                /* userSetBrightnessChanged= */ false,   /* isBedtimeModeWearEnabled= */ false);
         when(mAutomaticBrightnessController.getAutomaticScreenBrightness(null))
                 .thenReturn(Float.NaN);
         assertFalse(mAutomaticBrightnessStrategy.isAutoBrightnessValid());
@@ -589,7 +633,7 @@
                 BrightnessReason.REASON_UNKNOWN,
                 DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT,
                 DEFAULT_USE_NORMAL_BRIGHTNESS_FOR_DOZE, /* lastUserSetScreenBrightness= */ 0.1f,
-                /* userSetBrightnessChanged= */ false);
+                /* userSetBrightnessChanged= */ false,   /* isBedtimeModeWearEnabled= */ false);
         when(mAutomaticBrightnessController.getAutomaticScreenBrightness(null))
                 .thenReturn(0.2f);
         assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessValid());
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 250c2f9..6ab72cd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -167,8 +167,6 @@
     private static int sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ
             + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
     private static int sFirstUiCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 10;
-    private static int sFirstNonUiCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 20;
-    private static int sUiTierSize = 10;
 
     private Context mContext;
     private ProcessStateController mProcessStateController;
@@ -177,6 +175,9 @@
     private ActivityManagerService mService;
     private OomAdjusterInjector mInjector = new OomAdjusterInjector();
 
+    private int mUiTierSize;
+    private int mFirstNonUiCachedAdj;
+
     @Rule
     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
@@ -247,6 +248,9 @@
         mService.mOomAdjuster.mAdjSeq = 10000;
         mService.mWakefulness = new AtomicInteger(PowerManagerInternal.WAKEFULNESS_AWAKE);
         mSetFlagsRule.enableFlags(Flags.FLAG_NEW_FGS_RESTRICTION_LOGIC);
+
+        mUiTierSize = mService.mConstants.TIERED_CACHED_ADJ_UI_TIER_SIZE;
+        mFirstNonUiCachedAdj = sFirstUiCachedAdj + mUiTierSize;
     }
 
     @SuppressWarnings("GuardedBy")
@@ -927,8 +931,8 @@
             final int mruIndex = numberOfApps - i - 1;
             int expectedAdj;
             if (mService.mConstants.USE_TIERED_CACHED_ADJ) {
-                expectedAdj = (i < numberOfApps - sUiTierSize)
-                        ? sFirstNonUiCachedAdj : sFirstUiCachedAdj + mruIndex;
+                expectedAdj = (i < numberOfApps - mUiTierSize)
+                        ? mFirstNonUiCachedAdj : sFirstUiCachedAdj + mruIndex;
             } else {
                 expectedAdj = CACHED_APP_MIN_ADJ + (mruIndex * 2 * CACHED_APP_IMPORTANCE_LEVELS);
                 if (expectedAdj > CACHED_APP_MAX_ADJ) {
@@ -1108,7 +1112,7 @@
         updateOomAdj(app);
 
         final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
-                ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+                ? mFirstNonUiCachedAdj : sFirstCachedAdj;
         assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND);
     }
 
@@ -1545,7 +1549,7 @@
         updateOomAdj(app);
 
         final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
-                ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+                ? mFirstNonUiCachedAdj : sFirstCachedAdj;
         assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND);
     }
 
@@ -1563,7 +1567,7 @@
         updateOomAdj(app, client);
 
         final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
-                ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+                ? mFirstNonUiCachedAdj : sFirstCachedAdj;
         assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND);
     }
 
@@ -1694,7 +1698,7 @@
         mProcessStateController.runFollowUpUpdate();
 
         final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
-                ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+                ? mFirstNonUiCachedAdj : sFirstCachedAdj;
         assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND,
                 "cch-empty");
         // Follow up should not have been called again.
@@ -2741,7 +2745,7 @@
         final int userOther = 1;
 
         // cachedAdj1 and cachedAdj2 will be read if USE_TIERED_CACHED_ADJ is disabled. Otherwise,
-        // sFirstUiCachedAdj and sFirstNonUiCachedAdj are used instead.
+        // sFirstUiCachedAdj and mFirstNonUiCachedAdj are used instead.
         final int cachedAdj1 = CACHED_APP_MIN_ADJ + CACHED_APP_IMPORTANCE_LEVELS;
         final int cachedAdj2 = cachedAdj1 + CACHED_APP_IMPORTANCE_LEVELS * 2;
         doReturn(userOwner).when(mService.mUserController).getCurrentUserId();
@@ -2789,7 +2793,7 @@
                 mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstUiCachedAdj : cachedAdj1,
                 SCHED_GROUP_BACKGROUND, "cch-started-ui-services", true);
         assertProcStates(app2, PROCESS_STATE_SERVICE,
-                mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj2,
+                mService.mConstants.USE_TIERED_CACHED_ADJ ? mFirstNonUiCachedAdj : cachedAdj2,
                 SCHED_GROUP_BACKGROUND, "cch-started-services", true);
 
         app.mState.setSetProcState(PROCESS_STATE_NONEXISTENT);
@@ -2809,7 +2813,7 @@
         updateOomAdj();
 
         assertProcStates(app, PROCESS_STATE_SERVICE,
-                mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+                mService.mConstants.USE_TIERED_CACHED_ADJ ? mFirstNonUiCachedAdj : cachedAdj1,
                 SCHED_GROUP_BACKGROUND, "cch-started-services", true);
 
         mProcessStateController.stopService(app.mServices, s);
@@ -2831,7 +2835,7 @@
         assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND,
                 "started-services", false);
         assertProcStates(app2, PROCESS_STATE_SERVICE,
-                mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+                mService.mConstants.USE_TIERED_CACHED_ADJ ? mFirstNonUiCachedAdj : cachedAdj1,
                 SCHED_GROUP_BACKGROUND, "cch-started-services", true);
 
         app.mState.setSetProcState(PROCESS_STATE_NONEXISTENT);
@@ -2845,7 +2849,7 @@
         assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND,
                 "started-services", false);
         assertProcStates(app2, PROCESS_STATE_SERVICE,
-                mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+                mService.mConstants.USE_TIERED_CACHED_ADJ ? mFirstNonUiCachedAdj : cachedAdj1,
                 SCHED_GROUP_BACKGROUND, "cch-started-services", true);
 
         doReturn(userOther).when(mService.mUserController).getCurrentUserId();
@@ -2853,7 +2857,7 @@
 
         updateOomAdj();
         assertProcStates(app, PROCESS_STATE_SERVICE,
-                mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+                mService.mConstants.USE_TIERED_CACHED_ADJ ? mFirstNonUiCachedAdj : cachedAdj1,
                 SCHED_GROUP_BACKGROUND, "cch-started-services", true);
         assertProcStates(app2, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND,
                 "started-services", false);
@@ -3157,7 +3161,7 @@
         mProcessStateController.runFollowUpUpdate();
 
         final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
-                ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+                ? mFirstNonUiCachedAdj : sFirstCachedAdj;
         assertProcStates(app, PROCESS_STATE_SERVICE, expectedAdj, SCHED_GROUP_BACKGROUND,
                 "cch-started-services");
         // Follow up should not have been called again.
@@ -3192,7 +3196,7 @@
         mProcessStateController.runFollowUpUpdate();
 
         final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
-                ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+                ? mFirstNonUiCachedAdj : sFirstCachedAdj;
         assertProcStates(app1, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND,
                 "cch-empty");
 
diff --git a/services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubEventLoggerTest.java b/services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubEventLoggerTest.java
index 41cb6fd..e1dcc99 100644
--- a/services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubEventLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubEventLoggerTest.java
@@ -128,8 +128,6 @@
     }
 
     @Test
-    @EnableFlags({Flags.FLAG_RELIABLE_MESSAGE,
-                  Flags.FLAG_RELIABLE_MESSAGE_IMPLEMENTATION})
     public void testLogReliableMessageToNanoappStatus() {
         NanoAppMessage message1 = NanoAppMessage.createMessageToNanoApp(1, 0,
                 new byte[] {0x00, 0x11, 0x22, 0x33});
diff --git a/services/tests/servicestests/src/com/android/server/security/advancedprotection/OWNERS b/services/tests/servicestests/src/com/android/server/security/advancedprotection/OWNERS
new file mode 100644
index 0000000..9bf5e58
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/security/advancedprotection/OWNERS
@@ -0,0 +1 @@
+file:platform/frameworks/base:main:/core/java/android/security/advancedprotection/OWNERS
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/EventConditionProviderTest.java b/services/tests/uiservicestests/src/com/android/server/notification/EventConditionProviderTest.java
index 05210ac..fa1372d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/EventConditionProviderTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/EventConditionProviderTest.java
@@ -124,9 +124,12 @@
 
     @Test
     @EnableFlags(android.app.Flags.FLAG_MODES_HSUM)
-    public void onBootComplete_waitsForUserSwitched() {
+    public void onBootComplete_loadsTrackersForSystemUser() {
         mService.onBootComplete();
-        assertThat(mService.getTrackers().size()).isEqualTo(0);
+
+        assertThat(mService.getTrackers().size()).isEqualTo(1);
+        assertThat(mService.getTrackers().keyAt(0)).isEqualTo(UserHandle.USER_SYSTEM);
+        assertThat(mService.getTrackers().valueAt(0).getUserId()).isEqualTo(UserHandle.USER_SYSTEM);
     }
 
     @Test
@@ -158,4 +161,21 @@
         assertThat(mService.getTrackers().keyAt(1)).isEqualTo(43);
         assertThat(mService.getTrackers().valueAt(1).getUserId()).isEqualTo(43);
     }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_HSUM)
+    public void onUserSwitched_sameUser_doesNothing() {
+        UserHandle someUser = UserHandle.of(42);
+        when(mUserManager.getProfiles(eq(42))).thenReturn(List.of(new UserInfo(42, "user 42", 0)));
+
+        mService.onUserSwitched(someUser);
+        assertThat(mService.getTrackers().size()).isEqualTo(1);
+        assertThat(mService.getTrackers().keyAt(0)).isEqualTo(42);
+        CalendarTracker originalTracker = mService.getTrackers().valueAt(0);
+
+        mService.onUserSwitched(someUser);
+        assertThat(mService.getTrackers().size()).isEqualTo(1);
+        assertThat(mService.getTrackers().keyAt(0)).isEqualTo(42);
+        assertThat(mService.getTrackers().valueAt(0)).isSameInstanceAs(originalTracker);
+    }
 }