Merge "al-ov: Use F4 to toggle Overview" into main
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 7e4f95b..01b20f4 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#include <android/bitmap.h>
+#include <android/gui/DisplayCaptureArgs.h>
+#include <binder/ProcessState.h>
 #include <errno.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -33,7 +36,6 @@
 
 #include <ftl/concat.h>
 #include <ftl/optional.h>
-#include <gui/DisplayCaptureArgs.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/SyncScreenCaptureListener.h>
diff --git a/core/api/current.txt b/core/api/current.txt
index c1366a1..66a1d30 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -8741,6 +8741,31 @@
     method @NonNull public android.app.appfunctions.ExecuteAppFunctionRequest.Builder setParameters(@NonNull android.app.appsearch.GenericDocument);
   }
 
+  @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public final class ExecuteAppFunctionResponse implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public String getErrorMessage();
+    method @NonNull public android.os.Bundle getExtras();
+    method public int getResultCode();
+    method @NonNull public android.app.appsearch.GenericDocument getResultDocument();
+    method public boolean isSuccess();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.appfunctions.ExecuteAppFunctionResponse> CREATOR;
+    field public static final String PROPERTY_RETURN_VALUE = "returnValue";
+    field public static final int RESULT_APP_UNKNOWN_ERROR = 2; // 0x2
+    field public static final int RESULT_DENIED = 1; // 0x1
+    field public static final int RESULT_INTERNAL_ERROR = 3; // 0x3
+    field public static final int RESULT_INVALID_ARGUMENT = 4; // 0x4
+    field public static final int RESULT_OK = 0; // 0x0
+    field public static final int RESULT_TIMED_OUT = 5; // 0x5
+  }
+
+  @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public static final class ExecuteAppFunctionResponse.Builder {
+    ctor public ExecuteAppFunctionResponse.Builder(@NonNull android.app.appsearch.GenericDocument);
+    ctor public ExecuteAppFunctionResponse.Builder(int, @NonNull String);
+    method @NonNull public android.app.appfunctions.ExecuteAppFunctionResponse build();
+    method @NonNull public android.app.appfunctions.ExecuteAppFunctionResponse.Builder setExtras(@NonNull android.os.Bundle);
+  }
+
 }
 
 package android.app.assist {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 0db91f5..177b859 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -941,7 +941,7 @@
     method public int getAudioRecordingSessionId(int);
     method public int getDeviceIdForDisplayId(int);
     method public int getDevicePolicy(int, int);
-    method @FlaggedApi("android.companion.virtual.flags.interactive_screen_mirror") public boolean isVirtualDeviceOwnedMirrorDisplay(int);
+    method public boolean isVirtualDeviceOwnedMirrorDisplay(int);
     method public void playSoundEffect(int, int);
   }
 
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 69b5222..3d1a785 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -393,7 +393,7 @@
      * changes.
      *
      * <p>This broadcast is only sent to registered receivers and receivers in packages that have
-     * been granted Do Not Disturb access (see {@link #isNotificationPolicyAccessGranted()}).
+     * been granted Notification Policy access (see {@link #isNotificationPolicyAccessGranted()}).
      */
     @FlaggedApi(Flags.FLAG_MODES_API)
     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -1627,7 +1627,7 @@
     }
 
     /**
-     * Checks the ability to modify notification do not disturb policy for the calling package.
+     * Checks the ability to modify Notification Policy for the calling package.
      *
      * <p>
      * Returns true if the calling package can modify notification policy.
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 114a2c4..cb38cf2 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -475,7 +475,7 @@
                 if (service == null
                         && ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)
                         && android.server.Flags.allowRemovingVpnService()) {
-                    throw new ServiceNotFoundException(Context.VPN_MANAGEMENT_SERVICE);
+                    return null;
                 }
                 return new VpnManager(ctx, service);
             }});
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.aidl b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.aidl
new file mode 100644
index 0000000..42ec45d
--- /dev/null
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.aidl
@@ -0,0 +1,23 @@
+
+/*
+ * 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 android.app.appfunctions;
+
+import android.app.appfunctions.ExecuteAppFunctionAidlRequest;
+
+/** {@hide} */
+parcelable ExecuteAppFunctionAidlRequest;
\ No newline at end of file
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java
new file mode 100644
index 0000000..2f3c555
--- /dev/null
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java
@@ -0,0 +1,113 @@
+/*
+ * 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 android.app.appfunctions;
+
+import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+
+
+import java.util.Objects;
+
+/**
+ * An internal request to execute an app function.
+ *
+ * @hide
+ */
+@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
+public final class ExecuteAppFunctionAidlRequest implements Parcelable {
+
+    public static final Creator<ExecuteAppFunctionAidlRequest> CREATOR =
+            new Creator<ExecuteAppFunctionAidlRequest>() {
+                @Override
+                public ExecuteAppFunctionAidlRequest createFromParcel(Parcel in) {
+                    ExecuteAppFunctionRequest clientRequest =
+                            ExecuteAppFunctionRequest.CREATOR.createFromParcel(in);
+                    UserHandle userHandle =
+                            UserHandle.CREATOR.createFromParcel(in);
+                    String callingPackage = in.readString8();
+                    return new ExecuteAppFunctionAidlRequest(
+                            clientRequest, userHandle, callingPackage);
+                }
+
+                @Override
+                public ExecuteAppFunctionAidlRequest[] newArray(int size) {
+                    return new ExecuteAppFunctionAidlRequest[size];
+                }
+            };
+
+    /**
+     * The client request to execute an app function.
+     */
+    private final ExecuteAppFunctionRequest mClientRequest;
+
+    /**
+     * The user handle of the user to execute the app function.
+     */
+    private final UserHandle mUserHandle;
+
+    /**
+     * The package name of the app that is requesting to execute the app function.
+     */
+    private final String mCallingPackage;
+
+    public ExecuteAppFunctionAidlRequest(
+            ExecuteAppFunctionRequest clientRequest, UserHandle userHandle, String callingPackage) {
+        this.mClientRequest = Objects.requireNonNull(clientRequest);
+        this.mUserHandle = Objects.requireNonNull(userHandle);
+        this.mCallingPackage = Objects.requireNonNull(callingPackage);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        mClientRequest.writeToParcel(dest, flags);
+        mUserHandle.writeToParcel(dest, flags);
+        dest.writeString8(mCallingPackage);
+    }
+
+    /**
+     * Returns the client request to execute an app function.
+     */
+    @NonNull
+    public ExecuteAppFunctionRequest getClientRequest() {
+        return mClientRequest;
+    }
+
+    /**
+     * Returns the user handle of the user to execute the app function.
+     */
+    @NonNull
+    public UserHandle getUserHandle() {
+        return mUserHandle;
+    }
+
+    /**
+     * Returns the package name of the app that is requesting to execute the app function.
+     */
+    @NonNull
+    public String getCallingPackage() {
+        return mCallingPackage;
+    }
+}
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.aidl b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.aidl
new file mode 100644
index 0000000..5194e7a
--- /dev/null
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.aidl
@@ -0,0 +1,21 @@
+/*
+ * 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 android.app.appfunctions;
+
+import android.app.appfunctions.ExecuteAppFunctionResponse;
+
+parcelable ExecuteAppFunctionResponse;
\ No newline at end of file
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
new file mode 100644
index 0000000..72205d9
--- /dev/null
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
@@ -0,0 +1,294 @@
+/*
+ * 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 android.app.appfunctions;
+
+import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.appsearch.GenericDocument;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * The response to an app function execution.
+ */
+@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
+public final class ExecuteAppFunctionResponse implements Parcelable {
+    @NonNull
+    public static final Creator<ExecuteAppFunctionResponse> CREATOR =
+            new Creator<ExecuteAppFunctionResponse>() {
+                @Override
+                public ExecuteAppFunctionResponse createFromParcel(Parcel parcel) {
+                    GenericDocument result =
+                            Objects.requireNonNull(GenericDocument.createFromParcel(parcel));
+                    Bundle extras = Objects.requireNonNull(
+                            parcel.readBundle(Bundle.class.getClassLoader()));
+                    int resultCode = parcel.readInt();
+                    String errorMessage = parcel.readString8();
+                    return new ExecuteAppFunctionResponse(result, extras, resultCode, errorMessage);
+                }
+
+                @Override
+                public ExecuteAppFunctionResponse[] newArray(int size) {
+                    return new ExecuteAppFunctionResponse[size];
+                }
+            };
+    /**
+     * The name of the property that stores the function return value within the
+     * {@code resultDocument}.
+     *
+     * <p>See {@link GenericDocument#getProperty(String)} for more information.
+     *
+     * <p>If the function returns {@code void} or throws an error, the {@code resultDocument}
+     * will be empty {@link GenericDocument}.
+     *
+     * <p>If the {@code resultDocument} is empty, {@link GenericDocument#getProperty(String)} will
+     * return {@code null}.
+     *
+     * <p>See {@link #getResultDocument} for more information on extracting the return value.
+     */
+    public static final String PROPERTY_RETURN_VALUE = "returnValue";
+
+    /**
+     * The call was successful.
+     */
+    public static final int RESULT_OK = 0;
+
+    /**
+     * The caller does not have the permission to execute an app function.
+     */
+    public static final int RESULT_DENIED = 1;
+
+    /**
+     * An unknown error occurred while processing the call in the AppFunctionService.
+     */
+    public static final int RESULT_APP_UNKNOWN_ERROR = 2;
+
+    /**
+     * An internal error occurred within AppFunctionManagerService.
+     *
+     * <p>This error may be considered similar to {@link IllegalStateException}
+     */
+    public static final int RESULT_INTERNAL_ERROR = 3;
+
+    /**
+     * The caller supplied invalid arguments to the call.
+     *
+     * <p>This error may be considered similar to {@link IllegalArgumentException}.
+     */
+    public static final int RESULT_INVALID_ARGUMENT = 4;
+
+    /**
+     * The operation was timed out.
+     */
+    public static final int RESULT_TIMED_OUT = 5;
+
+    /**
+     * The result code of the app function execution.
+     */
+    @ResultCode
+    private final int mResultCode;
+
+    /**
+     * The error message associated with the result, if any. This is {@code null} if the result code
+     * is {@link #RESULT_OK}.
+     */
+    @Nullable
+    private final String mErrorMessage;
+
+    /**
+     * Returns the return value of the executed function.
+     *
+     * <p>The return value is stored in a {@link GenericDocument} with the key
+     * {@link #PROPERTY_RETURN_VALUE}.
+     *
+     * <p>See {@link #getResultDocument} for more information on extracting the return value.
+     */
+    @NonNull
+    private final GenericDocument mResultDocument;
+
+    /**
+     * Returns the additional metadata data relevant to this function execution response.
+     */
+    @NonNull
+    private final Bundle mExtras;
+
+    private ExecuteAppFunctionResponse(@NonNull GenericDocument resultDocument,
+                                       @NonNull Bundle extras,
+                                       @ResultCode int resultCode,
+                                       @Nullable String errorMessage) {
+        mResultDocument = Objects.requireNonNull(resultDocument);
+        mExtras = Objects.requireNonNull(extras);
+        mResultCode = resultCode;
+        mErrorMessage = errorMessage;
+    }
+
+    /**
+     * Returns a generic document containing the return value of the executed function.
+     *
+     * <p>The {@link #PROPERTY_RETURN_VALUE} key can be used to obtain the return value.</p>
+     *
+     * <p>An empty document is returned if {@link #isSuccess} is {@code false} or if the executed
+     * function does not produce a return value.
+     *
+     * <p>Sample code for extracting the return value:
+     * <pre>
+     *     GenericDocument resultDocument = response.getResultDocument();
+     *     Object returnValue = resultDocument.getProperty(PROPERTY_RETURN_VALUE);
+     *     if (returnValue != null) {
+     *       // Cast returnValue to expected type, or use {@link GenericDocument#getPropertyString},
+     *       // {@link GenericDocument#getPropertyLong} etc.
+     *       // Do something with the returnValue
+     *     }
+     * </pre>
+     */
+    @NonNull
+    public GenericDocument getResultDocument() {
+        return mResultDocument;
+    }
+
+    /**
+     * Returns the extras of the app function execution.
+     */
+    @NonNull
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    /**
+     * Returns {@code true} if {@link #getResultCode} equals
+     * {@link ExecuteAppFunctionResponse#RESULT_OK}.
+     */
+    public boolean isSuccess() {
+        return getResultCode() == RESULT_OK;
+    }
+
+    /**
+     * Returns one of the {@code RESULT} constants defined in {@link ExecuteAppFunctionResponse}.
+     */
+    @ResultCode
+    public int getResultCode() {
+        return mResultCode;
+    }
+
+    /**
+     * Returns the error message associated with this result.
+     *
+     * <p>If {@link #isSuccess} is {@code true}, the error message is always {@code null}.
+     */
+    @Nullable
+    public String getErrorMessage() {
+        return mErrorMessage;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        mResultDocument.writeToParcel(dest, flags);
+        dest.writeBundle(mExtras);
+        dest.writeInt(mResultCode);
+        dest.writeString8(mErrorMessage);
+    }
+
+    /**
+     * Result codes.
+     *
+     * @hide
+     */
+    @IntDef(
+            prefix = {"RESULT_"},
+            value = {
+                    RESULT_OK,
+                    RESULT_DENIED,
+                    RESULT_APP_UNKNOWN_ERROR,
+                    RESULT_INTERNAL_ERROR,
+                    RESULT_INVALID_ARGUMENT,
+                    RESULT_TIMED_OUT,
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ResultCode {
+    }
+
+    /**
+     * The builder for creating {@link ExecuteAppFunctionResponse} instances.
+     */
+    @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
+    public static final class Builder {
+        @NonNull
+        private GenericDocument mResultDocument = new GenericDocument.Builder<>("", "", "").build();
+        @NonNull
+        private Bundle mExtras = Bundle.EMPTY;
+        private int mResultCode;
+        @Nullable
+        private String mErrorMessage;
+
+        /**
+         * Creates a new builder for {@link ExecuteAppFunctionResponse}.
+         */
+        private Builder() {
+        }
+
+        /**
+         * Creates a new builder for {@link ExecuteAppFunctionResponse} to build a success response
+         * with a result code of {@link #RESULT_OK} and a resultDocument.
+         */
+        public Builder(@NonNull GenericDocument resultDocument) {
+            mResultDocument = Objects.requireNonNull(resultDocument);
+            mResultCode = RESULT_OK;
+        }
+
+        /**
+         * Creates a new builder for {@link ExecuteAppFunctionResponse} to build an error response
+         * with a result code and an error message.
+         */
+        public Builder(@ResultCode int resultCode,
+                       @NonNull String errorMessage) {
+            mResultCode = resultCode;
+            mErrorMessage = Objects.requireNonNull(errorMessage);
+        }
+
+        /**
+         * Sets the extras of the app function execution.
+         */
+        @NonNull
+        public Builder setExtras(@NonNull Bundle extras) {
+            mExtras = Objects.requireNonNull(extras);
+            return this;
+        }
+
+        /**
+         * Builds the {@link ExecuteAppFunctionResponse} instance.
+         */
+        @NonNull
+        public ExecuteAppFunctionResponse build() {
+            return new ExecuteAppFunctionResponse(
+                    mResultDocument, mExtras, mResultCode, mErrorMessage);
+        }
+    }
+}
diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig
index f751a23..f05c24f 100644
--- a/core/java/android/app/notification.aconfig
+++ b/core/java/android/app/notification.aconfig
@@ -21,6 +21,13 @@
 }
 
 flag {
+  name: "modes_ui_test"
+  namespace: "systemui"
+  description: "Guards new CTS tests for Modes; dependent on flags modes_api and modes_ui"
+  bug: "360862012"
+}
+
+flag {
   name: "api_tvextender"
   is_exported: true
   namespace: "systemui"
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index 8b60580..d07fb25 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -531,7 +531,6 @@
      *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR)
     @TestApi
     public boolean isVirtualDeviceOwnedMirrorDisplay(int displayId) {
         if (mService == null) {
diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig
index 91586b6..fc9c94d 100644
--- a/core/java/android/companion/virtual/flags.aconfig
+++ b/core/java/android/companion/virtual/flags.aconfig
@@ -35,13 +35,6 @@
 }
 
 flag {
-  name: "consistent_display_flags"
-  namespace: "virtual_devices"
-  description: "Make virtual display flags consistent with display manager"
-  bug: "300905478"
-}
-
-flag {
   name: "vdm_custom_ime"
   is_exported: true
   namespace: "virtual_devices"
@@ -89,14 +82,6 @@
 }
 
 flag {
-  name: "interactive_screen_mirror"
-  is_exported: true
-  namespace: "virtual_devices"
-  description: "Enable interactive screen mirroring using Virtual Devices"
-  bug: "292212199"
-}
-
-flag {
   name: "virtual_stylus"
   is_exported: true
   namespace: "virtual_devices"
diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig
index 6f1d63d8..83c4de3 100644
--- a/core/java/android/hardware/input/input_framework.aconfig
+++ b/core/java/android/hardware/input/input_framework.aconfig
@@ -92,3 +92,10 @@
   description: "Dump keyboard shortcuts in dumpsys window"
   bug: "351963350"
 }
+
+flag {
+  name: "modifier_shortcut_manager_refactor"
+  namespace: "input"
+  description: "Refactor ModifierShortcutManager internal representation of shortcuts."
+  bug: "358603902"
+}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 28f2c25..536eca6 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -969,9 +969,7 @@
 
     /**
      * Specifies if a user is disallowed from adding new users. This can only be set by device
-     * owners or profile owners on the primary user. The default value is <code>false</code>.
-     * <p>This restriction has no effect on secondary users and managed profiles since only the
-     * primary user can add other users.
+     * owners or profile owners on the main user. The default value is <code>false</code>.
      * <p> When the device is an organization-owned device provisioned with a managed profile,
      * this restriction will be set as a base restriction which cannot be removed by any admin.
      *
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7ca40ea..85d2325 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1972,10 +1972,10 @@
             "android.provider.extra.NOTIFICATION_LISTENER_COMPONENT_NAME";
 
     /**
-     * Activity Action: Show Do Not Disturb access settings.
+     * Activity Action: Show Notification Policy access settings.
      * <p>
-     * Users can grant and deny access to Do Not Disturb configuration from here. Managed
-     * profiles cannot grant Do Not Disturb access.
+     * Users can grant and deny access to Notification Policy (DND / Priority Modes) configuration
+     * from here. Managed profiles cannot grant Notification Policy access.
      * See {@link android.app.NotificationManager#isNotificationPolicyAccessGranted()} for more
      * details.
      * <p>
@@ -14953,6 +14953,7 @@
          *
          * @hide
          */
+        @Readable
         public static final String MUTE_ALARM_STREAM_WITH_RINGER_MODE =
                 "mute_alarm_stream_with_ringer_mode";
 
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 08e51a1..1734223 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1078,6 +1078,9 @@
             out.print(prefix); out.print("mDisplay="); out.println(mDisplay);
             out.print(prefix); out.print("mCreated="); out.print(mCreated);
                     out.print(" mSurfaceCreated="); out.print(mSurfaceCreated);
+                    if (noDuplicateSurfaceDestroyedEvents()) {
+                        out.print(" mReportedSurfaceCreated="); out.print(mReportedSurfaceCreated);
+                    }
                     out.print(" mIsCreating="); out.print(mIsCreating);
                     out.print(" mDrawingAllowed="); out.println(mDrawingAllowed);
             out.print(prefix); out.print("mWidth="); out.print(mWidth);
diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig
index 1c3d738..40070c7 100644
--- a/core/java/android/text/flags/flags.aconfig
+++ b/core/java/android/text/flags/flags.aconfig
@@ -259,6 +259,16 @@
 }
 
 flag {
+  name: "dont_break_email_in_nobreak_tag"
+  namespace: "text"
+  description: "Prevent line break inside email."
+  bug: "350691716"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
   name: "handwriting_gesture_with_transformation"
   namespace: "text"
   description: "Fix handwriting gesture is not working when view has transformation."
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 017e004..67a207e 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -3462,6 +3462,15 @@
         public static final int PRIVATE_FLAG_NOT_MAGNIFIABLE = 1 << 22;
 
         /**
+         * Indicates that the window should receive key events including Action/Meta key.
+         * They will not be intercepted as usual and instead will be passed to the window with other
+         * key events.
+         * TODO(b/358569822) Remove this once we have nicer API for listening to shortcuts
+         * @hide
+         */
+        public static final int PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS = 1 << 23;
+
+        /**
          * Flag to indicate that the window is color space agnostic, and the color can be
          * interpreted to any color space.
          * @hide
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 1840bcb..4742f1e 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -625,8 +625,7 @@
      *        the text you are providing so it is not possible to correctly
      *        specify locations there.
      * @param textAttribute The extra information about the text.
-     * @return true on success, false if the input connection is no longer
-     *
+     * @return true on success, false if the input connection is no longer valid.
      */
     default boolean setComposingText(@NonNull CharSequence text, int newCursorPosition,
             @Nullable TextAttribute textAttribute) {
@@ -753,7 +752,7 @@
      *        you are providing so it is not possible to correctly specify
      *        locations there.
      * @param textAttribute The extra information about the text.
-     * @return true on success, false if the input connection is no longer
+     * @return true on success, false if the input connection is no longer valid.
      */
     default boolean commitText(@NonNull CharSequence text, int newCursorPosition,
             @Nullable TextAttribute textAttribute) {
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 0e66f7a..806a593 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -878,15 +878,18 @@
 
     /**
      * Returns {@link Intent} for IME language settings activity with
-     * {@link Intent#getAction() Intent action} {@link #ACTION_IME_LANGUAGE_SETTINGS},
-     * else <code>null</code> if
-     * {@link android.R.styleable#InputMethod_languageSettingsActivity} is not defined.
+     * {@link Intent#getAction() Intent action} {@link #ACTION_IME_LANGUAGE_SETTINGS}. If
+     * {@link android.R.styleable#InputMethod_languageSettingsActivity} is not defined, tries to
+     * fall back to the IME general settings activity. If
+     * {@link android.R.styleable#InputMethod_settingsActivity} is also not defined,
+     * returns {code null}.
      *
      * <p>To launch IME language settings, use this method to get the {@link Intent} to launch
      * the IME language settings activity.</p>
      * <p>e.g.<pre><code>startActivity(createImeLanguageSettingsActivityIntent());</code></pre></p>
      *
      * @attr ref R.styleable#InputMethod_languageSettingsActivity
+     * @attr ref R.styleable#InputMethod_settingsActivity
      */
     @FlaggedApi(android.view.inputmethod.Flags.FLAG_IME_SWITCHER_REVAMP_API)
     @Nullable
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index eb35817..1922327 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -83,6 +83,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.StrictMode;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.system.Os;
 import android.text.TextUtils;
@@ -6246,6 +6247,18 @@
 
     private View inflateView(Context context, RemoteViews rv, @Nullable ViewGroup parent,
             @StyleRes int applyThemeResId, @Nullable ColorResources colorResources) {
+        try {
+            Trace.beginSection(rv.hasDrawInstructions()
+                    ? "RemoteViews#inflateViewWithDrawInstructions"
+                    : "RemoteViews#inflateView");
+            return inflateViewInternal(context, rv, parent, applyThemeResId, colorResources);
+        } finally {
+            Trace.endSection();
+        }
+    }
+
+    private View inflateViewInternal(Context context, RemoteViews rv, @Nullable ViewGroup parent,
+            @StyleRes int applyThemeResId, @Nullable ColorResources colorResources) {
         // RemoteViews may be built by an application installed in another
         // user. So build a context that loads resources from that user but
         // still returns the current users userId so settings like data / time formats
@@ -6384,7 +6397,7 @@
 
         private View mResult;
         private ViewTree mTree;
-        private Action[] mActions;
+        private List<Action> mActions;
         private Exception mError;
 
         private AsyncApplyTask(
@@ -6411,11 +6424,20 @@
 
                 if (mRV.mActions != null) {
                     int count = mRV.mActions.size();
-                    mActions = new Action[count];
-                    for (int i = 0; i < count && !isCancelled(); i++) {
-                        // TODO: check if isCancelled in nested views.
-                        mActions[i] = mRV.mActions.get(i)
-                                .initActionAsync(mTree, mParent, mApplyParams);
+                    mActions = new ArrayList<>(count);
+                    try {
+                        Trace.beginSection(hasDrawInstructions()
+                                ? "RemoteViews#initActionAsyncWithDrawInstructions"
+                                : "RemoteViews#initActionAsync");
+                        for (Action action : mRV.mActions) {
+                            if (isCancelled()) {
+                                break;
+                            }
+                            // TODO: check if isCancelled in nested views.
+                            mActions.add(action.initActionAsync(mTree, mParent, mApplyParams));
+                        }
+                    } finally {
+                        Trace.endSection();
                     }
                 } else {
                     mActions = null;
@@ -6437,14 +6459,7 @@
 
                 try {
                     if (mActions != null) {
-
-                        ActionApplyParams applyParams = mApplyParams.clone();
-                        if (applyParams.handler == null) {
-                            applyParams.handler = DEFAULT_INTERACTION_HANDLER;
-                        }
-                        for (Action a : mActions) {
-                            a.apply(viewTree.mRoot, mParent, applyParams);
-                        }
+                        mRV.performApply(viewTree.mRoot, mParent, mApplyParams, mActions);
                     }
                     // If the parent of the view is has is a root, resolve the recycling.
                     if (mTopLevel && mResult instanceof ViewGroup) {
@@ -6620,6 +6635,11 @@
     }
 
     private void performApply(View v, ViewGroup parent, ActionApplyParams params) {
+        performApply(v, parent, params, mActions);
+    }
+
+    private void performApply(
+            View v, ViewGroup parent, ActionApplyParams params, List<Action> actions) {
         params = params.clone();
         if (params.handler == null) {
             params.handler = DEFAULT_INTERACTION_HANDLER;
@@ -6630,8 +6650,15 @@
         }
         if (mActions != null) {
             final int count = mActions.size();
-            for (int i = 0; i < count; i++) {
-                mActions.get(i).apply(v, parent, params);
+            try {
+                Trace.beginSection(hasDrawInstructions()
+                        ? "RemoteViews#applyActionsWithDrawInstructions"
+                        : "RemoteViews#applyActions");
+                for (int i = 0; i < count; i++) {
+                    mActions.get(i).apply(v, parent, params);
+                }
+            } finally {
+                Trace.endSection();
             }
         }
     }
diff --git a/core/java/android/window/TransitionRequestInfo.java b/core/java/android/window/TransitionRequestInfo.java
index 253337b..fe936f7 100644
--- a/core/java/android/window/TransitionRequestInfo.java
+++ b/core/java/android/window/TransitionRequestInfo.java
@@ -115,8 +115,11 @@
     @DataClass(genToString = true, genSetters = true, genBuilder = false, genConstructor = false)
     public static final class DisplayChange implements Parcelable {
         private final int mDisplayId;
+
+        // If non-null, these bounds changes should ignore any potential rotation changes.
         @Nullable private Rect mStartAbsBounds = null;
         @Nullable private Rect mEndAbsBounds = null;
+
         private int mStartRotation = WindowConfiguration.ROTATION_UNDEFINED;
         private int mEndRotation = WindowConfiguration.ROTATION_UNDEFINED;
         private boolean mPhysicalDisplayChanged = false;
diff --git a/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java
index 987fd41..ec5ff4c 100644
--- a/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java
@@ -174,7 +174,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedProviderImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -298,9 +298,9 @@
     }
 
     @DataClass.Generated(
-            time = 1642560323360L,
+            time = 1723882842941L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedProviderImpl.java",
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java",
             inputSignatures = "private @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String authority\nprivate  boolean syncable\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String readPermission\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String writePermission\nprivate  boolean grantUriPermissions\nprivate  boolean forceUriPermissions\nprivate  boolean multiProcess\nprivate  int initOrder\nprivate @android.annotation.NonNull java.util.List<android.os.PatternMatcher> uriPermissionPatterns\nprivate @android.annotation.NonNull java.util.List<android.content.pm.PathPermission> pathPermissions\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<com.android.internal.pm.pkg.component.ParsedProviderImpl> CREATOR\npublic  com.android.internal.pm.pkg.component.ParsedProviderImpl setReadPermission(java.lang.String)\npublic  com.android.internal.pm.pkg.component.ParsedProviderImpl setWritePermission(java.lang.String)\npublic @android.annotation.NonNull com.android.internal.pm.pkg.component.ParsedProviderImpl addUriPermissionPattern(android.os.PatternMatcher)\npublic @android.annotation.NonNull com.android.internal.pm.pkg.component.ParsedProviderImpl addPathPermission(android.content.pm.PathPermission)\npublic  java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedProviderImpl extends com.android.internal.pm.pkg.component.ParsedMainComponentImpl implements [com.android.internal.pm.pkg.component.ParsedProvider, android.os.Parcelable]\n@com.android.internal.util.DataClass(genSetters=true, genGetters=true, genParcelable=false, genBuilder=false)")
     @Deprecated
     private void __metadata() {}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index ec004d0..0d0207f 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -418,6 +418,7 @@
             mElevation = preservedWindow.getElevation();
             mLoadElevation = false;
             mForceDecorInstall = true;
+            mDecorFitsSystemWindows = preservedWindow.decorFitsSystemWindows();
             setSystemBarAppearance(preservedWindow.getSystemBarAppearance());
             // If we're preserving window, carry over the app token from the preserved
             // window, as we'll be skipping the addView in handleResumeActivity(), and
diff --git a/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java b/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java
index fcc3023..2feb3d5 100644
--- a/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/LegacyProtoLogImpl.java
@@ -419,7 +419,6 @@
         return group.isLogToLogcat() || (group.isLogToProto() && isProtoEnabled());
     }
 
-    @Override
     public void registerGroups(IProtoLogGroup... protoLogGroups) {
         for (IProtoLogGroup group : protoLogGroups) {
             mLogGroups.put(group.name(), group);
diff --git a/core/java/com/android/internal/protolog/LogcatOnlyProtoLogImpl.java b/core/java/com/android/internal/protolog/LogcatOnlyProtoLogImpl.java
index ebdad6d..e8d5195 100644
--- a/core/java/com/android/internal/protolog/LogcatOnlyProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/LogcatOnlyProtoLogImpl.java
@@ -79,9 +79,4 @@
     public boolean isEnabled(IProtoLogGroup group, LogLevel level) {
         return true;
     }
-
-    @Override
-    public void registerGroups(IProtoLogGroup... protoLogGroups) {
-        // Does nothing
-    }
 }
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index 79a5469..78b5cfe 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -89,6 +89,7 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Stream;
 
 /**
  * A service for the ProtoLog logging system.
@@ -125,17 +126,18 @@
     private final Lock mBackgroundServiceLock = new ReentrantLock();
     private ExecutorService mBackgroundLoggingService = Executors.newSingleThreadExecutor();
 
-    public PerfettoProtoLogImpl() {
-        this(null, null, null, () -> {});
+    public PerfettoProtoLogImpl(@NonNull IProtoLogGroup[] groups) {
+        this(null, null, null, () -> {}, groups);
     }
 
-    public PerfettoProtoLogImpl(@NonNull Runnable cacheUpdater) {
-        this(null, null, null, cacheUpdater);
+    public PerfettoProtoLogImpl(@NonNull Runnable cacheUpdater, @NonNull IProtoLogGroup[] groups) {
+        this(null, null, null, cacheUpdater, groups);
     }
 
     public PerfettoProtoLogImpl(
             @NonNull String viewerConfigFilePath,
-            @NonNull Runnable cacheUpdater) {
+            @NonNull Runnable cacheUpdater,
+            @NonNull IProtoLogGroup[] groups) {
         this(viewerConfigFilePath,
                 null,
                 new ProtoLogViewerConfigReader(() -> {
@@ -146,22 +148,24 @@
                                 "Failed to load viewer config file " + viewerConfigFilePath, e);
                     }
                 }),
-                cacheUpdater);
+                cacheUpdater, groups);
     }
 
     @VisibleForTesting
     public PerfettoProtoLogImpl(
             @Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
             @Nullable ProtoLogViewerConfigReader viewerConfigReader,
-            @NonNull Runnable cacheUpdater) {
-        this(null, viewerConfigInputStreamProvider, viewerConfigReader, cacheUpdater);
+            @NonNull Runnable cacheUpdater,
+            @NonNull IProtoLogGroup[] groups) {
+        this(null, viewerConfigInputStreamProvider, viewerConfigReader, cacheUpdater, groups);
     }
 
     private PerfettoProtoLogImpl(
             @Nullable String viewerConfigFilePath,
             @Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
             @Nullable ProtoLogViewerConfigReader viewerConfigReader,
-            @NonNull Runnable cacheUpdater) {
+            @NonNull Runnable cacheUpdater,
+            @NonNull IProtoLogGroup[] groups) {
         if (viewerConfigFilePath != null && viewerConfigInputStreamProvider != null) {
             throw new RuntimeException("Only one of viewerConfigFilePath and "
                     + "viewerConfigInputStreamProvider can be set");
@@ -179,6 +183,8 @@
         this.mViewerConfigReader = viewerConfigReader;
         this.mCacheUpdater = cacheUpdater;
 
+        registerGroupsLocally(groups);
+
         if (android.tracing.Flags.clientSideProtoLogging()) {
             mProtoLogService =
                     IProtoLogService.Stub.asInterface(ServiceManager.getService(PROTOLOG_SERVICE));
@@ -192,6 +198,12 @@
                     args.setViewerConfigFile(viewerConfigFilePath);
                 }
 
+                final var groupArgs = Stream.of(groups)
+                        .map(group -> new ProtoLogService.RegisterClientArgs.GroupConfig(
+                                group.name(), group.isLogToLogcat()))
+                        .toArray(ProtoLogService.RegisterClientArgs.GroupConfig[]::new);
+                args.setGroups(groupArgs);
+
                 mProtoLogService.registerClient(this, args);
             } catch (RemoteException e) {
                 throw new RuntimeException("Failed to register ProtoLog client");
@@ -294,19 +306,22 @@
                 || group.isLogToLogcat();
     }
 
-    @Override
-    public void registerGroups(IProtoLogGroup... protoLogGroups) {
+    private void registerGroupsLocally(@NonNull IProtoLogGroup[] protoLogGroups) {
+        final var groupsLoggingToLogcat = new ArrayList<String>();
         for (IProtoLogGroup protoLogGroup : protoLogGroups) {
             mLogGroups.put(protoLogGroup.name(), protoLogGroup);
+
+            if (protoLogGroup.isLogToLogcat()) {
+                groupsLoggingToLogcat.add(protoLogGroup.name());
+            }
         }
 
-        final String[] groupsLoggingToLogcat = Arrays.stream(protoLogGroups)
-                .filter(IProtoLogGroup::isLogToLogcat)
-                .map(IProtoLogGroup::name)
-                .toArray(String[]::new);
-
         if (mViewerConfigReader != null) {
-            mViewerConfigReader.loadViewerConfig(groupsLoggingToLogcat);
+            // Load in background to avoid delay in boot process.
+            // The caveat is that any log message that is also logged to logcat will not be
+            // successfully decoded until this completes.
+            mBackgroundLoggingService.execute(() -> mViewerConfigReader
+                    .loadViewerConfig(groupsLoggingToLogcat.toArray(new String[0])));
         }
     }
 
diff --git a/core/java/com/android/internal/protolog/ProtoLog.java b/core/java/com/android/internal/protolog/ProtoLog.java
index 87678e5..f9b9894 100644
--- a/core/java/com/android/internal/protolog/ProtoLog.java
+++ b/core/java/com/android/internal/protolog/ProtoLog.java
@@ -50,6 +50,24 @@
     private static IProtoLog sProtoLogInstance;
 
     /**
+     * Initialize ProtoLog in this process.
+     * <p>
+     * This method MUST be called before any protologging is performed in this process.
+     * Ensure that all groups that will be used for protologging are registered.
+     *
+     * @param groups The ProtoLog groups that will be used in the process.
+     */
+    public static void init(IProtoLogGroup... groups) {
+        if (android.tracing.Flags.perfettoProtologTracing()) {
+            sProtoLogInstance = new PerfettoProtoLogImpl(groups);
+        } else {
+            // The first call to ProtoLog is likely to flip REQUIRE_PROTOLOGTOOL, which is when this
+            // static block will be executed before REQUIRE_PROTOLOGTOOL is actually set.
+            sProtoLogInstance = new LogcatOnlyProtoLogImpl();
+        }
+    }
+
+    /**
      * DEBUG level log.
      *
      * @param group         {@code IProtoLogGroup} controlling this log call.
@@ -150,14 +168,6 @@
         return sProtoLogInstance;
     }
 
-    /**
-     * Registers available protolog groups. A group must be registered before it can be used.
-     * @param protoLogGroups The groups to register for use in protolog.
-     */
-    public static void registerGroups(IProtoLogGroup... protoLogGroups) {
-        sProtoLogInstance.registerGroups(protoLogGroups);
-    }
-
     private static void logStringMessage(LogLevel logLevel, IProtoLogGroup group,
             String stringMessage, Object... args) {
         if (sProtoLogInstance == null) {
@@ -169,14 +179,4 @@
             sProtoLogInstance.log(logLevel, group, stringMessage, args);
         }
     }
-
-    static {
-        if (android.tracing.Flags.perfettoProtologTracing()) {
-            sProtoLogInstance = new PerfettoProtoLogImpl();
-        } else {
-            // The first call to ProtoLog is likely to flip REQUIRE_PROTOLOGTOOL, which is when this
-            // static block will be executed before REQUIRE_PROTOLOGTOOL is actually set.
-            sProtoLogInstance = new LogcatOnlyProtoLogImpl();
-        }
-    }
 }
diff --git a/core/java/com/android/internal/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java
index 8659a8f..da6d8cf 100644
--- a/core/java/com/android/internal/protolog/ProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java
@@ -93,35 +93,30 @@
     }
 
     /**
-     * Registers available protolog groups. A group must be registered before it can be used.
-     * @param protoLogGroups The groups to register for use in protolog.
-     */
-    public static void registerGroups(IProtoLogGroup... protoLogGroups) {
-        getSingleInstance().registerGroups(protoLogGroups);
-    }
-
-    /**
      * Returns the single instance of the ProtoLogImpl singleton class.
      */
     public static synchronized IProtoLog getSingleInstance() {
         if (sServiceInstance == null) {
+            final var groups = sLogGroups.values().toArray(new IProtoLogGroup[0]);
+
             if (android.tracing.Flags.perfettoProtologTracing()) {
                 File f = new File(sViewerConfigPath);
                 if (!ProtoLog.REQUIRE_PROTOLOGTOOL && !f.exists()) {
                     // TODO(b/353530422): Remove - temporary fix to unblock b/352290057
-                    // In so tests the viewer config file might not exist in which we don't
+                    // In some tests the viewer config file might not exist in which we don't
                     // want to provide config path to the user
-                    sServiceInstance = new PerfettoProtoLogImpl(sCacheUpdater);
+                    sServiceInstance = new PerfettoProtoLogImpl(sCacheUpdater, groups);
                 } else {
-                    sServiceInstance = new PerfettoProtoLogImpl(sViewerConfigPath, sCacheUpdater);
+                    sServiceInstance =
+                            new PerfettoProtoLogImpl(sViewerConfigPath, sCacheUpdater, groups);
                 }
             } else {
-                sServiceInstance = new LegacyProtoLogImpl(
+                var protologImpl = new LegacyProtoLogImpl(
                         sLegacyOutputFilePath, sLegacyViewerConfigPath, sCacheUpdater);
+                protologImpl.registerGroups(groups);
+                sServiceInstance = protologImpl;
             }
 
-            IProtoLogGroup[] groups = sLogGroups.values().toArray(new IProtoLogGroup[0]);
-            sServiceInstance.registerGroups(groups);
             sCacheUpdater.run();
         }
         return sServiceInstance;
diff --git a/core/java/com/android/internal/protolog/common/IProtoLog.java b/core/java/com/android/internal/protolog/common/IProtoLog.java
index f5695ac..d5c2ac1 100644
--- a/core/java/com/android/internal/protolog/common/IProtoLog.java
+++ b/core/java/com/android/internal/protolog/common/IProtoLog.java
@@ -68,10 +68,4 @@
      * @return If we need to log this group and level to either ProtoLog or Logcat.
      */
     boolean isEnabled(IProtoLogGroup group, LogLevel level);
-
-    /**
-     * Registers available protolog groups. A group must be registered before it can be used.
-     * @param protoLogGroups The groups to register for use in protolog.
-     */
-    void registerGroups(IProtoLogGroup... protoLogGroups);
 }
diff --git a/core/jni/android_window_ScreenCapture.cpp b/core/jni/android_window_ScreenCapture.cpp
index 1031542..b1a2cea 100644
--- a/core/jni/android_window_ScreenCapture.cpp
+++ b/core/jni/android_window_ScreenCapture.cpp
@@ -19,6 +19,7 @@
 
 #include <android/gui/BnScreenCaptureListener.h>
 #include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <gui/AidlStatusUtil.h>
 #include <gui/SurfaceComposerClient.h>
 #include <jni.h>
 #include <nativehelper/JNIHelp.h>
@@ -141,12 +142,13 @@
 };
 
 static void getCaptureArgs(JNIEnv* env, jobject captureArgsObject, CaptureArgs& captureArgs) {
-    captureArgs.pixelFormat = static_cast<ui::PixelFormat>(
+    captureArgs.pixelFormat = static_cast<int32_t>(
             env->GetIntField(captureArgsObject, gCaptureArgsClassInfo.pixelFormat));
-    captureArgs.sourceCrop =
+    const auto sourceCrop =
             JNICommon::rectFromObj(env,
                                    env->GetObjectField(captureArgsObject,
                                                        gCaptureArgsClassInfo.sourceCrop));
+    captureArgs.sourceCrop = gui::aidl_utils::toARect(sourceCrop);
     captureArgs.frameScaleX =
             env->GetFloatField(captureArgsObject, gCaptureArgsClassInfo.frameScaleX);
     captureArgs.frameScaleY =
@@ -172,7 +174,7 @@
                 jniThrowNullPointerException(env, "Exclude layer is null");
                 return;
             }
-            captureArgs.excludeHandles.emplace(excludeObject->getHandle());
+            captureArgs.excludeHandles.emplace_back(excludeObject->getHandle());
         }
     }
     captureArgs.hintForSeamlessTransition =
@@ -182,18 +184,18 @@
 
 static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env,
                                                        jobject displayCaptureArgsObject) {
-    DisplayCaptureArgs captureArgs;
-    getCaptureArgs(env, displayCaptureArgsObject, captureArgs);
+    DisplayCaptureArgs displayCaptureArgs;
+    getCaptureArgs(env, displayCaptureArgsObject, displayCaptureArgs.captureArgs);
 
-    captureArgs.displayToken =
+    displayCaptureArgs.displayToken =
             ibinderForJavaObject(env,
                                  env->GetObjectField(displayCaptureArgsObject,
                                                      gDisplayCaptureArgsClassInfo.displayToken));
-    captureArgs.width =
+    displayCaptureArgs.width =
             env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.width);
-    captureArgs.height =
+    displayCaptureArgs.height =
             env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.height);
-    return captureArgs;
+    return displayCaptureArgs;
 }
 
 static jint nativeCaptureDisplay(JNIEnv* env, jclass clazz, jobject displayCaptureArgsObject,
@@ -212,8 +214,8 @@
 
 static jint nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureArgsObject,
                                 jlong screenCaptureListenerObject, jboolean sync) {
-    LayerCaptureArgs captureArgs;
-    getCaptureArgs(env, layerCaptureArgsObject, captureArgs);
+    LayerCaptureArgs layerCaptureArgs;
+    getCaptureArgs(env, layerCaptureArgsObject, layerCaptureArgs.captureArgs);
 
     SurfaceControl* layer = reinterpret_cast<SurfaceControl*>(
             env->GetLongField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.layer));
@@ -221,13 +223,13 @@
         return BAD_VALUE;
     }
 
-    captureArgs.layerHandle = layer->getHandle();
-    captureArgs.childrenOnly =
+    layerCaptureArgs.layerHandle = layer->getHandle();
+    layerCaptureArgs.childrenOnly =
             env->GetBooleanField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.childrenOnly);
 
     sp<gui::IScreenCaptureListener> captureListener =
             reinterpret_cast<gui::IScreenCaptureListener*>(screenCaptureListenerObject);
-    return ScreenshotClient::captureLayers(captureArgs, captureListener, sync);
+    return ScreenshotClient::captureLayers(layerCaptureArgs, captureListener, sync);
 }
 
 static jlong nativeCreateScreenCaptureListener(JNIEnv* env, jclass clazz, jobject consumerObj) {
diff --git a/core/res/Android.bp b/core/res/Android.bp
index c1edb15..bcc0a97 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -165,6 +165,7 @@
         "com.android.window.flags.window-aconfig",
         "android.permission.flags-aconfig",
         "android.os.flags-aconfig",
+        "android.os.vibrator.flags-aconfig",
         "android.media.tv.flags-aconfig",
     ],
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 55c66e2..160f651 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2617,7 +2617,8 @@
          @hide
     -->
     <permission android:name="android.permission.VIBRATE_VENDOR_EFFECTS"
-        android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged"
+        android:featureFlag="android.os.vibrator.vendor_vibration_effects" />
 
     <!-- @SystemApi Allows access to the vibrator state.
          <p>Protection level: signature
diff --git a/core/res/res/layout/input_method_switch_dialog_new.xml b/core/res/res/layout/input_method_switch_dialog_new.xml
index 610a212..058fe3f 100644
--- a/core/res/res/layout/input_method_switch_dialog_new.xml
+++ b/core/res/res/layout/input_method_switch_dialog_new.xml
@@ -71,9 +71,10 @@
             android:layout_height="wrap_content"
             android:background="@drawable/input_method_switch_button"
             android:layout_gravity="end"
-            android:text="@string/input_method_language_settings"
+            android:text="@string/input_method_switcher_settings_button"
             android:fontFamily="google-sans-text"
             android:textAppearance="?attr/textAppearance"
+            android:contentDescription="@string/input_method_language_settings"
             android:visibility="gone"/>
 
     </LinearLayout>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index cb58339..f404666 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3280,6 +3280,9 @@
     <!-- Accessibility text for the long click action on the switch input method button. This will
          be used following "Double-tap and hold to..." [CHAR LIMIT=NONE] -->
     <string name="input_method_ime_switch_long_click_action_desc">Open input method picker</string>
+    <!-- Button to access the language settings of the current input method
+         from the Input Method Switcher menu. [CHAR LIMIT=50]-->
+    <string name="input_method_switcher_settings_button">Settings</string>
 
     <!-- If the device is getting low on internal storage, a notification is shown to the user.  This is the title of that notification. -->
     <string name="low_internal_storage_view_title">Storage space running out</string>
@@ -3883,7 +3886,8 @@
 
     <!-- Title of the pop-up dialog in which the user switches keyboard, also known as input method. -->
     <string name="select_input_method">Choose input method</string>
-    <!-- Button to access the language settings of the current input method. [CHAR LIMIT=50]-->
+    <!-- Content description of the button to access the language settings of the current input method
+         from the Input Method Switcher menu, for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
     <string name="input_method_language_settings">Language Settings</string>
     <!-- Summary text of a toggle switch to enable/disable use of the IME while a physical
          keyboard is connected -->
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index f5c6738..452ae04 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -212,30 +212,30 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
         <item name="colorPopupBackground">?attr/colorBackgroundFloating</item>
         <item name="panelColorBackground">?attr/colorBackgroundFloating</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -314,28 +314,28 @@
     <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Material.NoActionBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -431,28 +431,28 @@
     <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Material.NoActionBar.Fullscreen">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -550,28 +550,28 @@
     <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Material.NoActionBar.Overscan">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -668,28 +668,28 @@
     <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Material.NoActionBar.TranslucentDecor">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -801,28 +801,28 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -911,28 +911,28 @@
     <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Material.Dialog.MinWidth">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -1027,28 +1027,28 @@
     <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Material.Dialog.NoActionBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -1144,28 +1144,28 @@
     <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Dialog.NoActionBar.MinWidth">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -1277,28 +1277,28 @@
     <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Material.DialogWhenLarge">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -1395,28 +1395,28 @@
     <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Material.DialogWhenLarge.NoActionBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -1511,28 +1511,28 @@
     <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Material.Dialog.Presentation">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -1629,28 +1629,28 @@
     <style name="Theme.DeviceDefault.Panel" parent="Theme.Material.Panel">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -1746,28 +1746,28 @@
     <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Material.Wallpaper">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -1863,28 +1863,28 @@
     <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Material.Wallpaper.NoTitleBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -1980,28 +1980,28 @@
     <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Material.InputMethod">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -2097,28 +2097,28 @@
     <style name="Theme.DeviceDefault.VoiceInteractionSession" parent="Theme.Material.VoiceInteractionSession">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -2218,28 +2218,28 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -2336,28 +2336,28 @@
     <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Material.SearchBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -2451,28 +2451,28 @@
     <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Material.Dialog.NoFrame">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -2720,28 +2720,28 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
         <item name="colorPopupBackground">?attr/colorBackgroundFloating</item>
@@ -2821,28 +2821,28 @@
     <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Material.Light.DarkActionBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_dark</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -2937,28 +2937,28 @@
     <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Material.Light.NoActionBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -3054,28 +3054,28 @@
     <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Material.Light.NoActionBar.Fullscreen">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -3173,28 +3173,28 @@
     <style name="Theme.DeviceDefault.Light.NoActionBar.Overscan" parent="Theme.Material.Light.NoActionBar.Overscan">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -3291,28 +3291,28 @@
     <style name="Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor" parent="Theme.Material.Light.NoActionBar.TranslucentDecor">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -3426,28 +3426,28 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -3535,28 +3535,28 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -3654,28 +3654,28 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -3774,28 +3774,28 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -3895,26 +3895,26 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -3996,26 +3996,26 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -4096,28 +4096,28 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -4217,28 +4217,28 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -4336,28 +4336,28 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -4454,28 +4454,28 @@
     <style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Material.Light.Panel">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -4571,28 +4571,28 @@
 
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -4688,28 +4688,28 @@
     <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Material.Light.SearchBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -4803,28 +4803,28 @@
     <style name="Theme.DeviceDefault.Light.Voice" parent="Theme.Material.Light.Voice">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_light</item>
-        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_device_default_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -4932,21 +4932,21 @@
         <item name="popupTheme">@style/ThemeOverlay.DeviceDefault.Popup.Light</item>
 
         <!-- Color palette -->
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorPrimary">@color/primary_device_default_settings_light</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
         <item name="colorSecondary">@color/secondary_device_default_settings_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
         <item name="colorEdgeEffect">@color/edge_effect_device_default_light</item>
 
@@ -5044,16 +5044,16 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
         <item name="colorSecondary">@color/secondary_device_default_settings_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
         <item name="colorControlNormal">?attr/textColorPrimary</item>
         <item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
@@ -5148,16 +5148,16 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
         <item name="colorSecondary">@color/secondary_device_default_settings_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
         <item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
 
@@ -5245,26 +5245,26 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_dark_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_dark_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_dark_device_default</item>
-        <item name="colorSurface">@color/surface_dark</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_dark</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_dark</item>
-        <item name="colorSurfaceHeader">@color/surface_header_dark</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_dark</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_dark</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_dark</item>
+        <item name="colorSurface">@color/system_surface_container_dark</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_dark</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_dark</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
-        <item name="colorBackground">@color/background_device_default_dark</item>
+        <item name="colorBackground">@color/system_surface_container_dark</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_dark</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiary">@color/system_outline_dark</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_light</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_light</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_dark</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_light</item>
 
@@ -5361,26 +5361,26 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -5487,26 +5487,26 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -5606,26 +5606,26 @@
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
         <item name="colorSecondary">@color/secondary_device_default_settings</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
-        <item name="colorAccentPrimaryVariant">@color/accent_primary_variant_light_device_default</item>
-        <item name="colorAccentSecondaryVariant">@color/accent_secondary_variant_light_device_default</item>
-        <item name="colorAccentTertiaryVariant">@color/accent_tertiary_variant_light_device_default</item>
-        <item name="colorSurface">@color/surface_light</item>
-        <item name="colorSurfaceHighlight">@color/surface_highlight_light</item>
-        <item name="colorSurfaceVariant">@color/surface_variant_light</item>
-        <item name="colorSurfaceHeader">@color/surface_header_light</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
+        <item name="colorAccentPrimaryVariant">@color/system_primary_container_light</item>
+        <item name="colorAccentSecondaryVariant">@color/system_secondary_container_light</item>
+        <item name="colorAccentTertiaryVariant">@color/system_tertiary_container_light</item>
+        <item name="colorSurface">@color/system_surface_container_light</item>
+        <item name="colorSurfaceHighlight">@color/system_surface_bright_light</item>
+        <item name="colorSurfaceVariant">@color/system_surface_container_high_light</item>
+        <item name="colorSurfaceHeader">@color/system_surface_container_highest_light</item>
         <item name="colorError">@color/error_color_device_default_light</item>
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
-        <item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
-        <item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
-        <item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
-        <item name="textColorPrimaryInverse">@color/text_color_primary_device_default_dark</item>
-        <item name="textColorSecondaryInverse">@color/text_color_secondary_device_default_dark</item>
-        <item name="textColorTertiaryInverse">@color/text_color_tertiary_device_default_dark</item>
-        <item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
+        <item name="textColorPrimary">@color/system_on_surface_light</item>
+        <item name="textColorSecondary">@color/system_on_surface_variant_light</item>
+        <item name="textColorTertiary">@color/system_outline_light</item>
+        <item name="textColorPrimaryInverse">@color/system_on_surface_dark</item>
+        <item name="textColorSecondaryInverse">@color/system_on_surface_variant_dark</item>
+        <item name="textColorTertiaryInverse">@color/system_outline_dark</item>
+        <item name="textColorOnAccent">@color/system_on_primary_dark</item>
         <item name="colorForeground">@color/foreground_device_default_light</item>
         <item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
 
@@ -5788,9 +5788,9 @@
 
     <style name="ThemeOverlay.DeviceDefault.Accent">
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
 
         <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant</item>
         <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant</item>
@@ -5863,9 +5863,9 @@
 
     <style name="ThemeOverlay.DeviceDefault.Accent.Light">
         <item name="colorAccent">@color/accent_device_default_light</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
 
         <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant</item>
         <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant</item>
@@ -5938,13 +5938,13 @@
 
     <!-- Theme overlay that replaces colorAccent with the colorAccent from {@link #Theme_DeviceDefault_DayNight}. -->
     <style name="ThemeOverlay.DeviceDefault.Accent.DayNight"
-           parent="@style/ThemeOverlay.DeviceDefault.Accent.Light" />
+        parent="@style/ThemeOverlay.DeviceDefault.Accent.Light" />
 
     <style name="ThemeOverlay.DeviceDefault.Dark.ActionBar.Accent" parent="ThemeOverlay.Material.Dark.ActionBar">
         <item name="colorAccent">@color/accent_device_default_dark</item>
-        <item name="colorAccentPrimary">@color/accent_primary_device_default</item>
-        <item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
-        <item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
+        <item name="colorAccentPrimary">@color/system_primary_dark</item>
+        <item name="colorAccentSecondary">@color/system_secondary_dark</item>
+        <item name="colorAccentTertiary">@color/system_tertiary_dark</item>
 
         <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant</item>
         <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant</item>
@@ -6016,7 +6016,7 @@
     </style>
 
     <style name="Theme.DeviceDefault.Light.Dialog.Alert.UserSwitchingDialog" parent="Theme.DeviceDefault.NoActionBar.Fullscreen">
-        <item name="colorBackground">@color/background_device_default_light</item>
+        <item name="colorBackground">@color/system_surface_container_light</item>
         <item name="colorBackgroundFloating">@color/background_device_default_light</item>
         <item name="layout_gravity">center</item>
         <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index a115c65..38ea4ac 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -93,5 +93,6 @@
         <permission name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS" />
         <permission name="android.permission.CONTROL_UI_TRACING" />
         <permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND" />
+        <permission name="android.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW"/>
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 1fe6ca7..9a55b80 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -592,6 +592,10 @@
         <permission name="android.permission.INTERACT_ACROSS_USERS" />
     </privapp-permissions>
 
+    <privapp-permissions package="com.android.providers.tv">
+        <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+    </privapp-permissions>
+
     <privapp-permissions package="com.android.tv">
         <permission name="android.permission.CHANGE_HDMI_CEC_ACTIVE_SOURCE"/>
         <permission name="android.permission.DVB_DEVICE"/>
diff --git a/data/fonts/font_fallback.xml b/data/fonts/font_fallback.xml
index 53024ab..ae50da1 100644
--- a/data/fonts/font_fallback.xml
+++ b/data/fonts/font_fallback.xml
@@ -304,7 +304,7 @@
         <font postScriptName="NotoSansBengali-Regular" supportedAxes="wght">
             NotoSansBengali-VF.ttf
         </font>
-        <font fallbackFor="serif" postScriptName="NotoSerifBengali-Regular">
+        <font fallbackFor="serif" postScriptName="NotoSerifBengali-Regular" supportedAxes="wght">
             NotoSerifBengali-VF.ttf
         </font>
     </family>
@@ -354,7 +354,7 @@
         <font postScriptName="NotoSansSinhala-Regular" supportedAxes="wght">
             NotoSansSinhala-VF.ttf
         </font>
-        <font fallbackFor="serif" postScriptName="NotoSerifSinhala-Regular">
+        <font fallbackFor="serif" postScriptName="NotoSerifSinhala-Regular" supportedAxes="wght">
             NotoSerifSinhala-VF.ttf
         </font>
     </family>
@@ -927,23 +927,23 @@
             NotoSansMedefaidrin-VF.ttf
         </font>
     </family>
-    <family lang="und-Soyo" supportedAxes="wght">
-        <font postScriptName="NotoSansSoyombo-Regular">
+    <family lang="und-Soyo">
+        <font postScriptName="NotoSansSoyombo-Regular" supportedAxes="wght">
             NotoSansSoyombo-VF.ttf
         </font>
     </family>
-    <family lang="und-Takr" supportedAxes="wght">
-        <font postScriptName="NotoSansTakri-Regular">
+    <family lang="und-Takr">
+        <font postScriptName="NotoSansTakri-Regular" supportedAxes="wght">
             NotoSansTakri-VF.ttf
         </font>
     </family>
-    <family lang="und-Hmnp" supportedAxes="wght">
-        <font postScriptName="NotoSerifHmongNyiakeng-Regular">
+    <family lang="und-Hmnp">
+        <font postScriptName="NotoSerifHmongNyiakeng-Regular" supportedAxes="wght">
             NotoSerifNyiakengPuachueHmong-VF.ttf
         </font>
     </family>
-    <family lang="und-Yezi" supportedAxes="wght">
-        <font postScriptName="NotoSerifYezidi-Regular">
+    <family lang="und-Yezi">
+        <font postScriptName="NotoSerifYezidi-Regular" supportedAxes="wght">
             NotoSerifYezidi-VF.ttf
         </font>
     </family>
diff --git a/data/fonts/font_fallback_cjkvf.xml b/data/fonts/font_fallback_cjkvf.xml
index a4ee825..407d704 100644
--- a/data/fonts/font_fallback_cjkvf.xml
+++ b/data/fonts/font_fallback_cjkvf.xml
@@ -304,7 +304,7 @@
         <font postScriptName="NotoSansBengali-Regular" supportedAxes="wght">
             NotoSansBengali-VF.ttf
         </font>
-        <font fallbackFor="serif" postScriptName="NotoSerifBengali-Regular">
+        <font fallbackFor="serif" postScriptName="NotoSerifBengali-Regular" supportedAxes="wght">
             NotoSerifBengali-VF.ttf
         </font>
     </family>
@@ -354,7 +354,7 @@
         <font postScriptName="NotoSansSinhala-Regular" supportedAxes="wght">
             NotoSansSinhala-VF.ttf
         </font>
-        <font fallbackFor="serif" postScriptName="NotoSerifSinhala-Regular">
+        <font fallbackFor="serif" postScriptName="NotoSerifSinhala-Regular" supportedAxes="wght">
             NotoSerifSinhala-VF.ttf
         </font>
     </family>
@@ -943,23 +943,23 @@
             NotoSansMedefaidrin-VF.ttf
         </font>
     </family>
-    <family lang="und-Soyo" supportedAxes="wght">
-        <font postScriptName="NotoSansSoyombo-Regular">
+    <family lang="und-Soyo">
+        <font postScriptName="NotoSansSoyombo-Regular" supportedAxes="wght">
             NotoSansSoyombo-VF.ttf
         </font>
     </family>
-    <family lang="und-Takr" supportedAxes="wght">
-        <font postScriptName="NotoSansTakri-Regular">
+    <family lang="und-Takr">
+        <font postScriptName="NotoSansTakri-Regular" supportedAxes="wght">
             NotoSansTakri-VF.ttf
         </font>
     </family>
-    <family lang="und-Hmnp" supportedAxes="wght">
-        <font postScriptName="NotoSerifHmongNyiakeng-Regular">
+    <family lang="und-Hmnp">
+        <font postScriptName="NotoSerifHmongNyiakeng-Regular" supportedAxes="wght">
             NotoSerifNyiakengPuachueHmong-VF.ttf
         </font>
     </family>
-    <family lang="und-Yezi" supportedAxes="wght">
-        <font postScriptName="NotoSerifYezidi-Regular">
+    <family lang="und-Yezi">
+        <font postScriptName="NotoSerifYezidi-Regular" supportedAxes="wght">
             NotoSerifYezidi-VF.ttf
         </font>
     </family>
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
new file mode 100644
index 0000000..69a68c8
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
@@ -0,0 +1,101 @@
+/*
+ * 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 androidx.window.extensions.embedding;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.MessageQueue;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.util.List;
+
+/**
+ * Helper class to back up and restore the TaskFragmentOrganizer state, in order to resume
+ * organizing the TaskFragments if the app process is restarted.
+ */
+@SuppressWarnings("GuardedBy")
+class BackupHelper {
+    private static final String TAG = "BackupHelper";
+    private static final boolean DEBUG = Build.isDebuggable();
+
+    private static final String KEY_TASK_CONTAINERS = "KEY_TASK_CONTAINERS";
+    @NonNull
+    private final SplitController mController;
+    @NonNull
+    private final BackupIdler mBackupIdler = new BackupIdler();
+    private boolean mBackupIdlerScheduled;
+
+    BackupHelper(@NonNull SplitController splitController, @NonNull Bundle savedState) {
+        mController = splitController;
+
+        if (!savedState.isEmpty()) {
+            restoreState(savedState);
+        }
+    }
+
+    /**
+     * Schedules a back-up request. It is no-op if there was a request scheduled and not yet
+     * completed.
+     */
+    void scheduleBackup() {
+        if (!mBackupIdlerScheduled) {
+            mBackupIdlerScheduled = true;
+            Looper.myQueue().addIdleHandler(mBackupIdler);
+        }
+    }
+
+    final class BackupIdler implements MessageQueue.IdleHandler {
+        @Override
+        public boolean queueIdle() {
+            synchronized (mController.mLock) {
+                mBackupIdlerScheduled = false;
+                startBackup();
+            }
+            return false;
+        }
+    }
+
+    private void startBackup() {
+        final List<TaskContainer> taskContainers = mController.getTaskContainers();
+        if (taskContainers.isEmpty()) {
+            Log.w(TAG, "No task-container to back up");
+            return;
+        }
+
+        if (DEBUG) Log.d(TAG, "Start to back up " + taskContainers);
+        final Bundle state = new Bundle();
+        state.setClassLoader(TaskContainer.class.getClassLoader());
+        state.putParcelableList(KEY_TASK_CONTAINERS, taskContainers);
+        mController.setSavedState(state);
+    }
+
+    private void restoreState(@NonNull Bundle savedState) {
+        if (savedState.isEmpty()) {
+            return;
+        }
+
+        final List<TaskContainer> taskContainers = savedState.getParcelableArrayList(
+                KEY_TASK_CONTAINERS, TaskContainer.class);
+        for (TaskContainer taskContainer : taskContainers) {
+            if (DEBUG) Log.d(TAG, "restore task " + taskContainer.getTaskId());
+            // TODO(b/289875940): implement the TaskContainer restoration.
+        }
+    }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 26d180c..bb384c5 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -2536,6 +2536,21 @@
         return mTaskContainers.get(taskId);
     }
 
+    @NonNull
+    @GuardedBy("mLock")
+    List<TaskContainer> getTaskContainers() {
+        final ArrayList<TaskContainer> taskContainers = new ArrayList<>();
+        for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
+            taskContainers.add(mTaskContainers.valueAt(i));
+        }
+        return taskContainers;
+    }
+
+    @GuardedBy("mLock")
+    void setSavedState(@NonNull Bundle savedState) {
+        mPresenter.setSavedState(savedState);
+    }
+
     @GuardedBy("mLock")
     void addTaskContainer(int taskId, TaskContainer taskContainer) {
         mTaskContainers.put(taskId, taskContainer);
@@ -2829,6 +2844,12 @@
         return getActiveSplitForContainer(container) != null;
     }
 
+    void scheduleBackup() {
+        synchronized (mLock) {
+            mPresenter.scheduleBackup();
+        }
+    }
+
     private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter {
 
         @Override
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 99716e7..fb8efc4 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -158,6 +158,8 @@
 
     private final WindowLayoutComponentImpl mWindowLayoutComponent;
     private final SplitController mController;
+    @NonNull
+    private final BackupHelper mBackupHelper;
 
     SplitPresenter(@NonNull Executor executor,
             @NonNull WindowLayoutComponentImpl windowLayoutComponent,
@@ -165,7 +167,18 @@
         super(executor, controller);
         mWindowLayoutComponent = windowLayoutComponent;
         mController = controller;
-        registerOrganizer();
+        final Bundle outSavedState = new Bundle();
+        if (Flags.aeBackStackRestore()) {
+            outSavedState.setClassLoader(TaskContainer.class.getClassLoader());
+            registerOrganizer(false /* isSystemOrganizer */, outSavedState);
+        } else {
+            registerOrganizer();
+        }
+        mBackupHelper = new BackupHelper(controller, outSavedState);
+    }
+
+    void scheduleBackup() {
+        mBackupHelper.scheduleBackup();
     }
 
     /**
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 20ad53e..5795e8d 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -32,6 +32,8 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -48,12 +50,14 @@
 import androidx.window.extensions.embedding.SplitAttributes.SplitType.ExpandContainersSplitType;
 import androidx.window.extensions.embedding.SplitAttributes.SplitType.RatioSplitType;
 
+import com.android.window.flags.Flags;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
 /** Represents TaskFragments and split pairs below a Task. */
-class TaskContainer {
+class TaskContainer implements Parcelable {
     private static final String TAG = TaskContainer.class.getSimpleName();
 
     /** The unique task id. */
@@ -80,6 +84,9 @@
     @NonNull
     private TaskFragmentParentInfo mInfo;
 
+    @NonNull
+    private SplitController mSplitController;
+
     /**
      * TaskFragments that the organizer has requested to be closed. They should be removed when
      * the organizer receives
@@ -116,12 +123,14 @@
     /**
      * The {@link TaskContainer} constructor
      *
-     * @param taskId         The ID of the Task, which must match {@link Activity#getTaskId()} with
-     *                       {@code activityInTask}.
-     * @param activityInTask The {@link Activity} in the Task with {@code taskId}. It is used to
-     *                       initialize the {@link TaskContainer} properties.
+     * @param taskId          The ID of the Task, which must match {@link Activity#getTaskId()} with
+     *                        {@code activityInTask}.
+     * @param activityInTask  The {@link Activity} in the Task with {@code taskId}. It is used to
+     *                        initialize the {@link TaskContainer} properties.
+     * @param splitController The {@link SplitController}.
      */
-    TaskContainer(int taskId, @NonNull Activity activityInTask) {
+    TaskContainer(int taskId, @NonNull Activity activityInTask,
+            @Nullable SplitController splitController) {
         if (taskId == INVALID_TASK_ID) {
             throw new IllegalArgumentException("Invalid Task id");
         }
@@ -136,6 +145,7 @@
                 true /* visible */,
                 true /* hasDirectActivity */,
                 null /* decorSurface */);
+        mSplitController = splitController;
     }
 
     int getTaskId() {
@@ -571,6 +581,12 @@
         // Update overlay container after split pin container since the overlay should be on top of
         // pin container.
         updateAlwaysOnTopOverlayIfNecessary();
+
+        // TODO(b/289875940): Making backup-restore as an opt-in solution, before the flag goes
+        //  to next-food.
+        if (Flags.aeBackStackRestore()) {
+            mSplitController.scheduleBackup();
+        }
     }
 
     private void updateAlwaysOnTopOverlayIfNecessary() {
@@ -664,6 +680,34 @@
         return activityStacks;
     }
 
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mTaskId);
+        // TODO(b/289875940)
+    }
+
+    protected TaskContainer(Parcel in) {
+        mTaskId = in.readInt();
+        // TODO(b/289875940)
+    }
+
+    public static final Creator<TaskContainer> CREATOR = new Creator<>() {
+        @Override
+        public TaskContainer createFromParcel(Parcel in) {
+            return new TaskContainer(in);
+        }
+
+        @Override
+        public TaskContainer[] newArray(int size) {
+            return new TaskContainer[size];
+        }
+    };
+
     /** A wrapper class which contains the information of {@link TaskContainer} */
     static final class TaskProperties {
         private final int mDisplayId;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index ee3e6f3..dc6506b 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -1203,7 +1203,7 @@
 
             if (taskContainer == null) {
                 // Adding a TaskContainer if no existed one.
-                taskContainer = new TaskContainer(mTaskId, mActivityInTask);
+                taskContainer = new TaskContainer(mTaskId, mActivityInTask, mSplitController);
                 mSplitController.addTaskContainer(mTaskId, taskContainer);
             }
 
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
index 7dc78fd..5c85778 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
@@ -222,7 +222,7 @@
         doReturn(resources).when(activity).getResources();
         doReturn(DEFAULT_DISPLAY).when(activity).getDisplayId();
 
-        return new TaskContainer(TASK_ID, activity);
+        return new TaskContainer(TASK_ID, activity, mock(SplitController.class));
     }
 
     static TaskContainer createTestTaskContainer(@NonNull SplitController controller) {
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 53ab2d5..08a746f 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -92,8 +92,11 @@
     <dimen name="docked_divider_handle_width">16dp</dimen>
     <dimen name="docked_divider_handle_height">2dp</dimen>
 
-    <dimen name="split_divider_handle_region_width">96dp</dimen>
+    <dimen name="split_divider_handle_region_width">80dp</dimen>
     <dimen name="split_divider_handle_region_height">48dp</dimen>
+    <!-- The divider touch zone height is intentionally halved in portrait to avoid colliding
+         with the app handle.-->
+    <dimen name="desktop_mode_portrait_split_divider_handle_region_height">24dp</dimen>
 
     <!-- Divider handle size for split screen -->
     <dimen name="split_divider_handle_width">40dp</dimen>
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/split/SplitScreenConstants.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/split/SplitScreenConstants.java
index ebca5df..498dc8b 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/split/SplitScreenConstants.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/split/SplitScreenConstants.java
@@ -30,7 +30,7 @@
     /** Duration used for every split fade-in or fade-out. */
     public static final int FADE_DURATION = 133;
     /** Duration where we keep an app veiled to allow it to redraw itself behind the scenes. */
-    public static final int VEIL_DELAY_DURATION = 400;
+    public static final int VEIL_DELAY_DURATION = 300;
 
     /** Key for passing in widget intents when invoking split from launcher workspace. */
     public static final String KEY_EXTRA_WIDGET_INTENT = "key_extra_widget_intent";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationBackground.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationBackground.java
index d754d04..26f7b36 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationBackground.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationBackground.java
@@ -20,6 +20,7 @@
 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.view.SurfaceControl;
@@ -59,6 +60,23 @@
      */
     public void ensureBackground(Rect startRect, int color,
             @NonNull SurfaceControl.Transaction transaction, int statusbarHeight) {
+        ensureBackground(startRect, color, transaction, statusbarHeight,
+                null /* cropBounds */, 0 /* cornerRadius */);
+    }
+
+    /**
+     * Ensures the back animation background color layer is present.
+     *
+     * @param startRect The start bounds of the closing target.
+     * @param color The background color.
+     * @param transaction The animation transaction.
+     * @param statusbarHeight The height of the statusbar (in px).
+     * @param cropBounds The crop bounds of the surface, set to non-empty to show wallpaper.
+     * @param cornerRadius The radius of corner, only work when cropBounds is not empty.
+     */
+    public void ensureBackground(Rect startRect, int color,
+            @NonNull SurfaceControl.Transaction transaction, int statusbarHeight,
+            @Nullable Rect cropBounds, float cornerRadius) {
         if (mBackgroundSurface != null) {
             return;
         }
@@ -78,6 +96,10 @@
         transaction.setColor(mBackgroundSurface, colorComponents)
                 .setLayer(mBackgroundSurface, BACKGROUND_LAYER)
                 .show(mBackgroundSurface);
+        if (cropBounds != null && !cropBounds.isEmpty()) {
+            transaction.setCrop(mBackgroundSurface, cropBounds)
+                    .setCornerRadius(mBackgroundSurface, cornerRadius);
+        }
         mStartBounds = startRect;
         mIsRequestingStatusBarAppearance = false;
         mStatusbarHeight = statusbarHeight;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 356ecb3..d7da051 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -1313,15 +1313,18 @@
                         info.getChanges().remove(j);
                     }
                 }
-                tmpSize = info.getChanges().size();
-                for (int i = 0; i < tmpSize; ++i) {
-                    final TransitionInfo.Change change = init.getChanges().get(i);
-                    if (moveToTop) {
-                        if (isSameChangeTarget(openComponent, openTaskId, change)) {
-                            change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP);
+                // Ignore merge if there is no close target
+                if (!info.getChanges().isEmpty()) {
+                    tmpSize = init.getChanges().size();
+                    for (int i = 0; i < tmpSize; ++i) {
+                        final TransitionInfo.Change change = init.getChanges().get(i);
+                        if (moveToTop) {
+                            if (isSameChangeTarget(openComponent, openTaskId, change)) {
+                                change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP);
+                            }
                         }
+                        info.getChanges().add(i, change);
                     }
-                    info.getChanges().add(i, change);
                 }
             } else {
                 // Open transition, the transition info should be:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
index 4fd8b8a..32e809a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
@@ -189,10 +189,13 @@
         preparePreCommitEnteringRectMovement()
 
         background.ensureBackground(
-            closingTarget!!.windowConfiguration.bounds,
-            getBackgroundColor(),
-            transaction,
-            statusbarHeight
+                closingTarget!!.windowConfiguration.bounds,
+                getBackgroundColor(),
+                transaction,
+                statusbarHeight,
+                if (closingTarget!!.windowConfiguration.tasksAreFloating())
+                    closingTarget!!.localBounds else null,
+                cornerRadius
         )
         ensureScrimLayer()
         if (isLetterboxed && enteringHasSameLetterbox) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index dabfeeb..3dc33c2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -2217,7 +2217,6 @@
         // And since all children are removed, remove the summary.
         removeCallback.accept(-1);
 
-        // TODO: (b/145659174) remove references to mSuppressedGroupKeys once fully migrated
         mBubbleData.addSummaryToSuppress(summary.getStatusBarNotification().getGroupKey(),
                 summary.getKey());
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
index dcbc72a..7c51a69 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
@@ -23,6 +23,7 @@
 import android.hardware.display.DisplayManager;
 import android.os.RemoteException;
 import android.util.ArraySet;
+import android.util.Size;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
@@ -193,8 +194,8 @@
 
 
     /** Called when a display rotate requested. */
-    public void onDisplayRotateRequested(WindowContainerTransaction wct, int displayId,
-            int fromRotation, int toRotation) {
+    public void onDisplayChangeRequested(WindowContainerTransaction wct, int displayId,
+            Rect startAbsBounds, Rect endAbsBounds, int fromRotation, int toRotation) {
         synchronized (mDisplays) {
             final DisplayRecord dr = mDisplays.get(displayId);
             if (dr == null) {
@@ -203,6 +204,13 @@
             }
 
             if (dr.mDisplayLayout != null) {
+                if (endAbsBounds != null) {
+                    // If there is a change in the display dimensions update the layout as well;
+                    // note that endAbsBounds should ignore any potential rotation changes, so
+                    // we still need to rotate the layout after if needed.
+                    dr.mDisplayLayout.resizeTo(dr.mContext.getResources(),
+                            new Size(endAbsBounds.width(), endAbsBounds.height()));
+                }
                 dr.mDisplayLayout.rotateTo(dr.mContext.getResources(), toRotation);
             }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index 84e32a2..b6a1686 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -35,6 +35,7 @@
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
+import android.util.Size;
 import android.view.Display;
 import android.view.DisplayCutout;
 import android.view.DisplayInfo;
@@ -244,6 +245,16 @@
         recalcInsets(res);
     }
 
+    /**
+     * Update the dimensions of this layout.
+     */
+    public void resizeTo(Resources res, Size displaySize) {
+        mWidth = displaySize.getWidth();
+        mHeight = displaySize.getHeight();
+
+        recalcInsets(res);
+    }
+
     /** Get this layout's non-decor insets. */
     public Rect nonDecorInsets() {
         return mNonDecorInsets;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 442036ff..e7848e2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -58,6 +58,7 @@
 import com.android.wm.shell.R;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.shared.animation.Interpolators;
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
 
 /**
  * Divider for multi window splits.
@@ -228,7 +229,9 @@
                 : R.dimen.split_divider_handle_region_width);
         mHandleRegionHeight = getResources().getDimensionPixelSize(isLeftRightSplit
                 ? R.dimen.split_divider_handle_region_width
-                : R.dimen.split_divider_handle_region_height);
+                : DesktopModeStatus.canEnterDesktopMode(mContext)
+                        ? R.dimen.desktop_mode_portrait_split_divider_handle_region_height
+                        : R.dimen.split_divider_handle_region_height);
     }
 
     void onInsetsChanged(InsetsState insetsState, boolean animate) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index e807afb..2a934cb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -27,6 +27,8 @@
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLIT_SCREEN_RESIZE;
 import static com.android.wm.shell.shared.animation.Interpolators.DIM_INTERPOLATOR;
+import static com.android.wm.shell.shared.animation.Interpolators.EMPHASIZED;
+import static com.android.wm.shell.shared.animation.Interpolators.LINEAR;
 import static com.android.wm.shell.shared.animation.Interpolators.SLOWDOWN_INTERPOLATOR;
 import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_END_AND_DISMISS;
 import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_START_AND_DISMISS;
@@ -813,7 +815,9 @@
         float growPortion = 1 - shrinkPortion;
 
         ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
-        animator.setInterpolator(Interpolators.EMPHASIZED);
+        // Set the base animation to proceed linearly. Each component of the animation (movement,
+        // shrinking, growing) overrides it with a different interpolator later.
+        animator.setInterpolator(LINEAR);
         animator.addUpdateListener(animation -> {
             if (leash == null) return;
             if (roundCorners) {
@@ -822,10 +826,11 @@
             }
 
             final float progress = (float) animation.getAnimatedValue();
-            float instantaneousX = tempStart.left + progress * diffX;
-            float instantaneousY = tempStart.top + progress * diffY;
-            int width = (int) (tempStart.width() + progress * diffWidth);
-            int height = (int) (tempStart.height() + progress * diffHeight);
+            final float moveProgress = EMPHASIZED.getInterpolation(progress);
+            float instantaneousX = tempStart.left + moveProgress * diffX;
+            float instantaneousY = tempStart.top + moveProgress * diffY;
+            int width = (int) (tempStart.width() + moveProgress * diffWidth);
+            int height = (int) (tempStart.height() + moveProgress * diffHeight);
 
             if (isGoingBehind) {
                 float shrinkDiffX; // the position adjustments needed for this frame
@@ -897,8 +902,8 @@
                             taskInfo, mTempRect, t, isGoingBehind, leash, 0, 0);
                 }
             } else {
-                final int diffOffsetX = (int) (progress * offsetX);
-                final int diffOffsetY = (int) (progress * offsetY);
+                final int diffOffsetX = (int) (moveProgress * offsetX);
+                final int diffOffsetY = (int) (moveProgress * offsetY);
                 t.setPosition(leash, instantaneousX + diffOffsetX, instantaneousY + diffOffsetY);
                 mTempRect.set(0, 0, width, height);
                 mTempRect.offsetTo(-diffOffsetX, -diffOffsetY);
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 aa42c67..ce054a8 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
@@ -304,6 +304,7 @@
             ShellInit shellInit,
             ShellTaskOrganizer shellTaskOrganizer,
             Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
+            LaunchAdjacentController launchAdjacentController,
             WindowDecorViewModel windowDecorViewModel) {
         // TODO(b/238217847): Temporarily add this check here until we can remove the dynamic
         //                    override for this controller from the base module
@@ -311,7 +312,7 @@
                 ? shellInit
                 : null;
         return new FreeformTaskListener(context, init, shellTaskOrganizer,
-                desktopModeTaskRepository, windowDecorViewModel);
+                desktopModeTaskRepository, launchAdjacentController, windowDecorViewModel);
     }
 
     @WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index f36e620..33794d2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -150,12 +150,6 @@
             visualIndicator?.releaseVisualIndicator(t)
             visualIndicator = null
         }
-    private val taskVisibilityListener =
-        object : VisibleTasksListener {
-            override fun onTasksVisibilityChanged(displayId: Int, visibleTasksCount: Int) {
-                launchAdjacentController.launchAdjacentEnabled = visibleTasksCount == 0
-            }
-        }
     private val dragToDesktopStateListener =
         object : DragToDesktopStateListener {
             override fun onCommitToDesktopAnimationStart(tx: SurfaceControl.Transaction) {
@@ -201,7 +195,6 @@
             this
         )
         transitions.addHandler(this)
-        taskRepository.addVisibleTasksListener(taskVisibilityListener, mainExecutor)
         dragToDesktopTransitionHandler.dragToDesktopStateListener = dragToDesktopStateListener
         recentsTransitionHandler.addTransitionStateListener(
             object : RecentsTransitionStateListener {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index 456767a..83cc18b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -27,6 +27,7 @@
 
 import com.android.internal.protolog.ProtoLog;
 import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
@@ -49,6 +50,7 @@
     private final ShellTaskOrganizer mShellTaskOrganizer;
     private final Optional<DesktopModeTaskRepository> mDesktopModeTaskRepository;
     private final WindowDecorViewModel mWindowDecorationViewModel;
+    private final LaunchAdjacentController mLaunchAdjacentController;
 
     private final SparseArray<State> mTasks = new SparseArray<>();
 
@@ -62,11 +64,13 @@
             ShellInit shellInit,
             ShellTaskOrganizer shellTaskOrganizer,
             Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
+            LaunchAdjacentController launchAdjacentController,
             WindowDecorViewModel windowDecorationViewModel) {
         mContext = context;
         mShellTaskOrganizer = shellTaskOrganizer;
         mWindowDecorationViewModel = windowDecorationViewModel;
         mDesktopModeTaskRepository = desktopModeTaskRepository;
+        mLaunchAdjacentController = launchAdjacentController;
         if (shellInit != null) {
             shellInit.addInitCallback(this::onInit, this);
         }
@@ -106,6 +110,7 @@
                 }
             });
         }
+        updateLaunchAdjacentController();
     }
 
     @Override
@@ -123,6 +128,7 @@
         if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
             mWindowDecorationViewModel.destroyWindowDecoration(taskInfo);
         }
+        updateLaunchAdjacentController();
     }
 
     @Override
@@ -144,6 +150,17 @@
                         taskInfo.isVisible);
             });
         }
+        updateLaunchAdjacentController();
+    }
+
+    private void updateLaunchAdjacentController() {
+        for (int i = 0; i < mTasks.size(); i++) {
+            if (mTasks.valueAt(i).mTaskInfo.isVisible) {
+                mLaunchAdjacentController.setLaunchAdjacentEnabled(false);
+                return;
+            }
+        }
+        mLaunchAdjacentController.setLaunchAdjacentEnabled(true);
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
index eb6caba..e9c4c14 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
@@ -29,7 +29,6 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Bundle;
-import android.view.InsetsState;
 import android.view.SurfaceControl;
 import android.window.DisplayAreaInfo;
 import android.window.WindowContainerTransaction;
@@ -200,17 +199,8 @@
         DisplayLayout layout = new DisplayLayout(mContext, mContext.getDisplay());
         mPipDisplayLayoutState.setDisplayLayout(layout);
 
-        mDisplayController.addDisplayWindowListener(this);
         mDisplayController.addDisplayChangingController(this);
         mDisplayInsetsController.addInsetsChangedListener(mPipDisplayLayoutState.getDisplayId(),
-                new DisplayInsetsController.OnInsetsChangedListener() {
-                    @Override
-                    public void insetsChanged(InsetsState insetsState) {
-                        setDisplayLayout(mDisplayController
-                                        .getDisplayLayout(mPipDisplayLayoutState.getDisplayId()));
-                    }
-                });
-        mDisplayInsetsController.addInsetsChangedListener(mPipDisplayLayoutState.getDisplayId(),
                 new ImeListener(mDisplayController, mPipDisplayLayoutState.getDisplayId()) {
                     @Override
                     public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
@@ -285,34 +275,37 @@
         setDisplayLayout(mDisplayController.getDisplayLayout(displayId));
     }
 
-    @Override
-    public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
-        if (displayId != mPipDisplayLayoutState.getDisplayId()) {
-            return;
-        }
-        setDisplayLayout(mDisplayController.getDisplayLayout(displayId));
-    }
-
     /**
      * A callback for any observed transition that contains a display change in its
-     * {@link android.window.TransitionRequestInfo} with a non-zero rotation delta.
+     * {@link android.window.TransitionRequestInfo},
      */
     @Override
     public void onDisplayChange(int displayId, int fromRotation, int toRotation,
             @Nullable DisplayAreaInfo newDisplayAreaInfo, WindowContainerTransaction t) {
+        if (displayId != mPipDisplayLayoutState.getDisplayId()) {
+            return;
+        }
+        final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(mPipBoundsState.getBounds());
+        final float boundsScale = mPipBoundsState.getBoundsScale();
+
+        // Update the display layout caches even if we are not in PiP.
+        setDisplayLayout(mDisplayController.getDisplayLayout(displayId));
+
         if (!mPipTransitionState.isInPip()) {
             return;
         }
 
-        // Calculate the snap fraction pre-rotation.
-        float snapFraction = mPipBoundsAlgorithm.getSnapFraction(mPipBoundsState.getBounds());
+        mPipTouchHandler.updateMinMaxSize(mPipBoundsState.getAspectRatio());
 
-        // Update the caches to reflect the new display layout and movement bounds.
-        mPipDisplayLayoutState.rotateTo(toRotation);
+        // Update the caches to reflect the new display layout in the movement bounds;
+        // temporarily update bounds to be at the top left for the movement bounds calculation.
+        Rect toBounds = new Rect(0, 0,
+                (int) Math.ceil(mPipBoundsState.getMaxSize().x * boundsScale),
+                (int) Math.ceil(mPipBoundsState.getMaxSize().y * boundsScale));
+        mPipBoundsState.setBounds(toBounds);
         mPipTouchHandler.updateMovementBounds();
 
-        // The policy is to keep PiP width, height and snap fraction invariant.
-        Rect toBounds = mPipBoundsState.getBounds();
+        // The policy is to keep PiP snap fraction invariant.
         mPipBoundsAlgorithm.applySnapFraction(toBounds, snapFraction);
         mPipBoundsState.setBounds(toBounds);
         t.setBounds(mPipTransitionState.mPipTaskToken, toBounds);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
index 287e779..1140c82 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
@@ -48,7 +48,7 @@
 
     public ShellInit(ShellExecutor mainExecutor) {
         mMainExecutor = mainExecutor;
-        ProtoLog.registerGroups(ShellProtoLogGroup.values());
+        ProtoLog.init(ShellProtoLogGroup.values());
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
index b7b42c7..209fc39 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
@@ -114,7 +114,6 @@
                 t.clear();
                 mMainExecutor.execute(() -> {
                     finishCallback.onTransitionFinished(wct);
-                    mRemote = null;
                 });
             }
         };
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 68217c0..f0d3668 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -1187,12 +1187,15 @@
             }
             if (request.getDisplayChange() != null) {
                 TransitionRequestInfo.DisplayChange change = request.getDisplayChange();
-                if (change.getEndRotation() != change.getStartRotation()) {
-                    // Is a rotation, so dispatch to all displayChange listeners
+                if (change.getStartRotation() != change.getEndRotation()
+                        || (change.getStartAbsBounds() != null
+                        && !change.getStartAbsBounds().equals(change.getEndAbsBounds()))) {
+                    // Is a display change, so dispatch to all displayChange listeners
                     if (wct == null) {
                         wct = new WindowContainerTransaction();
                     }
-                    mDisplayController.onDisplayRotateRequested(wct, change.getDisplayId(),
+                    mDisplayController.onDisplayChangeRequested(wct, change.getDisplayId(),
+                            change.getStartAbsBounds(), change.getEndAbsBounds(),
                             change.getStartRotation(), change.getEndRotation());
                 }
             }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
index 0f2de70..cb9781e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
@@ -82,32 +82,26 @@
         final int oldRight = repositionTaskBounds.right;
         final int oldBottom = repositionTaskBounds.bottom;
 
-
         repositionTaskBounds.set(taskBoundsAtDragStart);
 
         // Make sure the new resizing destination in any direction falls within the stable bounds.
-        // If not, set the bounds back to the old location that was valid to avoid conflicts with
-        // some regions such as the gesture area.
         if ((ctrlType & CTRL_TYPE_LEFT) != 0) {
-            final int candidateLeft = repositionTaskBounds.left + (int) delta.x;
-            repositionTaskBounds.left = (candidateLeft > stableBounds.left)
-                    ? candidateLeft : oldLeft;
+            repositionTaskBounds.left = Math.max(repositionTaskBounds.left + (int) delta.x,
+                    stableBounds.left);
         }
         if ((ctrlType & CTRL_TYPE_RIGHT) != 0) {
-            final int candidateRight = repositionTaskBounds.right + (int) delta.x;
-            repositionTaskBounds.right = (candidateRight < stableBounds.right)
-                    ? candidateRight : oldRight;
+            repositionTaskBounds.right = Math.min(repositionTaskBounds.right + (int) delta.x,
+                    stableBounds.right);
         }
         if ((ctrlType & CTRL_TYPE_TOP) != 0) {
-            final int candidateTop = repositionTaskBounds.top + (int) delta.y;
-            repositionTaskBounds.top = (candidateTop > stableBounds.top)
-                    ? candidateTop : oldTop;
+            repositionTaskBounds.top = Math.max(repositionTaskBounds.top + (int) delta.y,
+                    stableBounds.top);
         }
         if ((ctrlType & CTRL_TYPE_BOTTOM) != 0) {
-            final int candidateBottom = repositionTaskBounds.bottom + (int) delta.y;
-            repositionTaskBounds.bottom = (candidateBottom < stableBounds.bottom)
-                    ? candidateBottom : oldBottom;
+            repositionTaskBounds.bottom = Math.min(repositionTaskBounds.bottom + (int) delta.y,
+                    stableBounds.bottom);
         }
+
         // If width or height are negative or exceeding the width or height constraints, revert the
         // respective bounds to use previous bound dimensions.
         if (isExceedingWidthConstraint(repositionTaskBounds, stableBounds, displayController,
@@ -120,14 +114,12 @@
             repositionTaskBounds.top = oldTop;
             repositionTaskBounds.bottom = oldBottom;
         }
-        // If there are no changes to the bounds after checking new bounds against minimum width
-        // and height, do not set bounds and return false
-        if (oldLeft == repositionTaskBounds.left && oldTop == repositionTaskBounds.top
-                && oldRight == repositionTaskBounds.right
-                && oldBottom == repositionTaskBounds.bottom) {
-            return false;
-        }
-        return true;
+
+        // If there are no changes to the bounds after checking new bounds against minimum and
+        // maximum width and height, do not set bounds and return false
+        return oldLeft != repositionTaskBounds.left || oldTop != repositionTaskBounds.top
+                || oldRight != repositionTaskBounds.right
+                || oldBottom != repositionTaskBounds.bottom;
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
index fd7bed7..6dedf6d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.windowdecor;
 
+import static android.view.InputDevice.SOURCE_MOUSE;
 import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
 
 import static com.android.wm.shell.shared.desktopmode.DesktopModeFlags.EDGE_DRAG_RESIZE;
@@ -166,7 +167,10 @@
     static boolean isEdgeResizePermitted(@NonNull Context context, @NonNull MotionEvent e) {
         if (EDGE_DRAG_RESIZE.isEnabled(context)) {
             return e.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
-                    || e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE;
+                    || e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE
+                    // Touchpad input
+                    || (e.isFromSource(SOURCE_MOUSE)
+                        && e.getToolType(0) == MotionEvent.TOOL_TYPE_FINGER);
         } else {
             return e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE;
         }
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindowAndPip.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindowAndPip.kt
new file mode 100644
index 0000000..6d52a11
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindowAndPip.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.wm.shell.scenarios
+
+import android.platform.test.annotations.Postsubmit
+import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.helpers.MailAppHelper
+import com.android.server.wm.flicker.helpers.NewTasksAppHelper
+import com.android.server.wm.flicker.helpers.PipAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.window.flags.Flags
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class DragAppWindowMultiWindowAndPip : DragAppWindowScenarioTestBase()
+{
+    private val imeAppHelper = ImeAppHelper(instrumentation)
+    private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
+    private val pipApp = PipAppHelper(instrumentation)
+    private val mailApp = DesktopModeAppHelper(MailAppHelper(instrumentation))
+    private val newTasksApp = DesktopModeAppHelper(NewTasksAppHelper(instrumentation))
+    private val imeApp = DesktopModeAppHelper(ImeAppHelper(instrumentation))
+
+    @Before
+    fun setup() {
+        Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
+        // Set string extra to ensure the app is on PiP mode at launch
+        pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = mapOf("enter_pip" to "true"))
+        testApp.enterDesktopWithDrag(wmHelper, device)
+        mailApp.launchViaIntent(wmHelper)
+        newTasksApp.launchViaIntent(wmHelper)
+        imeApp.launchViaIntent(wmHelper)
+    }
+
+    @Test
+    override fun dragAppWindow() {
+        val (startXIme, startYIme) = getWindowDragStartCoordinate(imeAppHelper)
+
+        imeApp.dragWindow(startXIme, startYIme,
+            endX = startXIme + 150, endY = startYIme + 150,
+            wmHelper, device)
+    }
+
+    @After
+    fun teardown() {
+        testApp.exit(wmHelper)
+        pipApp.exit(wmHelper)
+        mailApp.exit(wmHelper)
+        newTasksApp.exit(wmHelper)
+        imeApp.exit(wmHelper)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt
new file mode 100644
index 0000000..b6bca7a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt
@@ -0,0 +1,90 @@
+/*
+ * 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.wm.shell.scenarios
+
+import android.platform.test.annotations.Postsubmit
+import android.app.Instrumentation
+import android.tools.NavBar
+import android.tools.Rotation
+import android.tools.traces.parsers.WindowManagerStateHelper
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.helpers.MailAppHelper
+import com.android.server.wm.flicker.helpers.NewTasksAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.window.flags.Flags
+import com.android.wm.shell.Utils
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class ResizeAppCornerMultiWindow
+@JvmOverloads
+constructor(val rotation: Rotation = Rotation.ROTATION_0,
+    val horizontalChange: Int = 50,
+    val verticalChange: Int = -50) {
+
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val tapl = LauncherInstrumentation()
+    private val wmHelper = WindowManagerStateHelper(instrumentation)
+    private val device = UiDevice.getInstance(instrumentation)
+    private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
+    private val mailApp = DesktopModeAppHelper(MailAppHelper(instrumentation))
+    private val newTasksApp = DesktopModeAppHelper(NewTasksAppHelper(instrumentation))
+    private val imeApp = DesktopModeAppHelper(ImeAppHelper(instrumentation))
+
+    @Rule
+    @JvmField
+    val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
+
+    @Before
+    fun setup() {
+        Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
+        tapl.setEnableRotation(true)
+        tapl.setExpectedRotation(rotation.value)
+        testApp.enterDesktopWithDrag(wmHelper, device)
+        mailApp.launchViaIntent(wmHelper)
+        newTasksApp.launchViaIntent(wmHelper)
+        imeApp.launchViaIntent(wmHelper)
+    }
+
+    @Test
+    open fun resizeAppWithCornerResize() {
+        imeApp.cornerResize(wmHelper,
+            device,
+            DesktopModeAppHelper.Corners.RIGHT_TOP,
+            horizontalChange,
+            verticalChange)
+    }
+
+    @After
+    fun teardown() {
+        testApp.exit(wmHelper)
+        mailApp.exit(wmHelper)
+        newTasksApp.exit(wmHelper)
+        imeApp.exit(wmHelper)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt
new file mode 100644
index 0000000..285ea13
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt
@@ -0,0 +1,95 @@
+/*
+ * 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.wm.shell.scenarios
+
+import android.platform.test.annotations.Postsubmit
+import android.app.Instrumentation
+import android.tools.NavBar
+import android.tools.Rotation
+import android.tools.traces.parsers.WindowManagerStateHelper
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.helpers.MailAppHelper
+import com.android.server.wm.flicker.helpers.NewTasksAppHelper
+import com.android.server.wm.flicker.helpers.PipAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.window.flags.Flags
+import com.android.wm.shell.Utils
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+open class ResizeAppCornerMultiWindowAndPip
+@JvmOverloads
+constructor(val rotation: Rotation = Rotation.ROTATION_0,
+    val horizontalChange: Int = 50,
+    val verticalChange: Int = -50) {
+
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val tapl = LauncherInstrumentation()
+    private val wmHelper = WindowManagerStateHelper(instrumentation)
+    private val device = UiDevice.getInstance(instrumentation)
+    private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
+    private val pipApp = PipAppHelper(instrumentation)
+    private val mailApp = DesktopModeAppHelper(MailAppHelper(instrumentation))
+    private val newTasksApp = DesktopModeAppHelper(NewTasksAppHelper(instrumentation))
+    private val imeApp = DesktopModeAppHelper(ImeAppHelper(instrumentation))
+
+    @Rule
+    @JvmField
+    val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
+
+    @Before
+    fun setup() {
+        Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
+        tapl.setEnableRotation(true)
+        tapl.setExpectedRotation(rotation.value)
+        // Set string extra to ensure the app is on PiP mode at launch
+        pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = mapOf("enter_pip" to "true"))
+        testApp.enterDesktopWithDrag(wmHelper, device)
+        mailApp.launchViaIntent(wmHelper)
+        newTasksApp.launchViaIntent(wmHelper)
+        imeApp.launchViaIntent(wmHelper)
+    }
+
+    @Test
+    open fun resizeAppWithCornerResize() {
+        imeApp.cornerResize(wmHelper,
+            device,
+            DesktopModeAppHelper.Corners.RIGHT_TOP,
+            horizontalChange,
+            verticalChange)
+    }
+
+    @After
+    fun teardown() {
+        testApp.exit(wmHelper)
+        pipApp.exit(wmHelper)
+        mailApp.exit(wmHelper)
+        newTasksApp.exit(wmHelper)
+        imeApp.exit(wmHelper)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index ff52480..a841e16 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -2264,27 +2264,6 @@
   }
 
   @Test
-  fun desktopTasksVisibilityChange_visible_setLaunchAdjacentDisabled() {
-    val task = setUpFreeformTask()
-    clearInvocations(launchAdjacentController)
-
-    markTaskVisible(task)
-    shellExecutor.flushAll()
-    verify(launchAdjacentController).launchAdjacentEnabled = false
-  }
-
-  @Test
-  fun desktopTasksVisibilityChange_invisible_setLaunchAdjacentEnabled() {
-    val task = setUpFreeformTask()
-    markTaskVisible(task)
-    clearInvocations(launchAdjacentController)
-
-    markTaskHidden(task)
-    shellExecutor.flushAll()
-    verify(launchAdjacentController).launchAdjacentEnabled = true
-  }
-
-  @Test
   fun moveFocusedTaskToDesktop_fullscreenTaskIsMovedToDesktop() {
     val task1 = setUpFullscreenTask()
     val task2 = setUpFullscreenTask()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java
index 6ec6bed..763d015 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java
@@ -27,6 +27,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityManager;
+import android.view.SurfaceControl;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
@@ -35,6 +36,7 @@
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.TestRunningTaskInfoBuilder;
+import com.android.wm.shell.common.LaunchAdjacentController;
 import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
 import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.sysui.ShellInit;
@@ -65,7 +67,11 @@
     @Mock
     private WindowDecorViewModel mWindowDecorViewModel;
     @Mock
+    private SurfaceControl mMockSurfaceControl;
+    @Mock
     private DesktopModeTaskRepository mDesktopModeTaskRepository;
+    @Mock
+    private LaunchAdjacentController mLaunchAdjacentController;
     private FreeformTaskListener mFreeformTaskListener;
     private StaticMockitoSession mMockitoSession;
 
@@ -80,6 +86,7 @@
                 mShellInit,
                 mTaskOrganizer,
                 Optional.of(mDesktopModeTaskRepository),
+                mLaunchAdjacentController,
                 mWindowDecorViewModel);
     }
 
@@ -107,6 +114,31 @@
                 .addOrMoveFreeformTaskToTop(fullscreenTask.displayId, fullscreenTask.taskId);
     }
 
+    @Test
+    public void testVisibilityTaskChanged_visible_setLaunchAdjacentDisabled() {
+        ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder()
+                .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
+        task.isVisible = true;
+
+        mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl);
+
+        verify(mLaunchAdjacentController).setLaunchAdjacentEnabled(false);
+    }
+
+    @Test
+    public void testVisibilityTaskChanged_NotVisible_setLaunchAdjacentEnabled() {
+        ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder()
+                .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
+        task.isVisible = true;
+
+        mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl);
+
+        task.isVisible = false;
+        mFreeformTaskListener.onTaskInfoChanged(task);
+
+        verify(mLaunchAdjacentController).setLaunchAdjacentEnabled(true);
+    }
+
     @After
     public void tearDown() {
         mMockitoSession.finishMocking();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index b3d56b1..0054cb6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -25,7 +25,6 @@
 import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN;
 import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
 import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
-import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
 import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_DISMISS;
 
 import static com.google.common.truth.Truth.assertThat;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
index e529711..1f33ae6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
@@ -93,7 +93,7 @@
     fun setup() {
         MockitoAnnotations.initMocks(this)
         mockitoSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
-                .spyStatic(DesktopModeStatus::class.java).startMocking()
+            .spyStatic(DesktopModeStatus::class.java).startMocking()
 
         whenever(taskToken.asBinder()).thenReturn(taskBinder)
         whenever(mockDisplayController.getDisplayLayout(DISPLAY_ID)).thenReturn(mockDisplayLayout)
@@ -108,9 +108,9 @@
         whenever(mockContext.getResources()).thenReturn(mockResources)
         whenever(mockWindowDecoration.mDecorWindowContext.resources).thenReturn(mockResources)
         whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_width))
-                .thenReturn(DESKTOP_MODE_MIN_WIDTH)
+            .thenReturn(DESKTOP_MODE_MIN_WIDTH)
         whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_height))
-                .thenReturn(DESKTOP_MODE_MIN_HEIGHT)
+            .thenReturn(DESKTOP_MODE_MIN_HEIGHT)
         whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
     }
 
@@ -129,9 +129,11 @@
         val newY = STARTING_BOUNDS.top.toFloat() + 95
         val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
 
-        DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
+        DragPositioningCallbackUtility.changeBounds(
+            CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
             repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
-            mockWindowDecoration)
+            mockWindowDecoration
+        )
 
         assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
         assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
@@ -149,9 +151,11 @@
         val newY = STARTING_BOUNDS.top.toFloat() + 5
         val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
 
-        DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
+        DragPositioningCallbackUtility.changeBounds(
+            CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
             repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
-            mockWindowDecoration)
+            mockWindowDecoration
+        )
 
         assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
         assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top + 5)
@@ -169,9 +173,11 @@
         val newY = STARTING_BOUNDS.top.toFloat() + 105
         val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
 
-        DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
+        DragPositioningCallbackUtility.changeBounds(
+            CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
             repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
-            mockWindowDecoration)
+            mockWindowDecoration
+        )
 
         assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
         assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
@@ -189,9 +195,11 @@
         val newY = STARTING_BOUNDS.top.toFloat() + 80
         val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
 
-        DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
+        DragPositioningCallbackUtility.changeBounds(
+            CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
             repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
-            mockWindowDecoration)
+            mockWindowDecoration
+        )
         assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
         assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top + 80)
         assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 80)
@@ -208,9 +216,11 @@
 
         val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
 
-        DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
+        DragPositioningCallbackUtility.changeBounds(
+            CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
             repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
-            mockWindowDecoration)
+            mockWindowDecoration
+        )
         assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
         assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
         assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right)
@@ -221,52 +231,95 @@
     fun testDragEndSnapsTaskBoundsWhenOutsideValidDragArea() {
         val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.top.toFloat())
         val repositionTaskBounds = Rect(STARTING_BOUNDS)
-        val validDragArea = Rect(DISPLAY_BOUNDS.left - 100,
+        val validDragArea = Rect(
+            DISPLAY_BOUNDS.left - 100,
             STABLE_BOUNDS.top,
             DISPLAY_BOUNDS.right - 100,
-            DISPLAY_BOUNDS.bottom - 100)
+            DISPLAY_BOUNDS.bottom - 100
+        )
 
-        DragPositioningCallbackUtility.updateTaskBounds(repositionTaskBounds, STARTING_BOUNDS,
-            startingPoint, startingPoint.x - 1000, (DISPLAY_BOUNDS.bottom + 1000).toFloat())
-        DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(repositionTaskBounds,
-            validDragArea)
+        DragPositioningCallbackUtility.updateTaskBounds(
+            repositionTaskBounds, STARTING_BOUNDS,
+            startingPoint, startingPoint.x - 1000, (DISPLAY_BOUNDS.bottom + 1000).toFloat()
+        )
+        DragPositioningCallbackUtility.snapTaskBoundsIfNecessary(
+            repositionTaskBounds,
+            validDragArea
+        )
         assertThat(repositionTaskBounds.left).isEqualTo(validDragArea.left)
         assertThat(repositionTaskBounds.top).isEqualTo(validDragArea.bottom)
         assertThat(repositionTaskBounds.right)
-                .isEqualTo(validDragArea.left + STARTING_BOUNDS.width())
+            .isEqualTo(validDragArea.left + STARTING_BOUNDS.width())
         assertThat(repositionTaskBounds.bottom)
-                .isEqualTo(validDragArea.bottom + STARTING_BOUNDS.height())
+            .isEqualTo(validDragArea.bottom + STARTING_BOUNDS.height())
     }
 
     @Test
     fun testChangeBounds_toDisallowedBounds_freezesAtLimit() {
-        val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(),
-            STARTING_BOUNDS.bottom.toFloat())
+        val startingPoint = PointF(
+            STARTING_BOUNDS.right.toFloat(),
+            STARTING_BOUNDS.bottom.toFloat()
+        )
         val repositionTaskBounds = Rect(STARTING_BOUNDS)
         // Initial resize to width and height 110px.
         var newX = STARTING_BOUNDS.right.toFloat() + 10
         var newY = STARTING_BOUNDS.bottom.toFloat() + 10
         var delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
-        assertTrue(DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
-            repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
-            mockWindowDecoration))
+        assertTrue(
+            DragPositioningCallbackUtility.changeBounds(
+                CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+                repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
+                mockWindowDecoration
+            )
+        )
         // Resize width to 120px, height to disallowed area which should not result in a change.
         newX += 10
         newY = DISALLOWED_RESIZE_AREA.top.toFloat()
         delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
-        assertTrue(DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
-            repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
-            mockWindowDecoration))
+        assertTrue(
+            DragPositioningCallbackUtility.changeBounds(
+                CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+                repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
+                mockWindowDecoration
+            )
+        )
         assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
         assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
         assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right + 20)
-        assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom + 10)
+        assertThat(repositionTaskBounds.bottom).isEqualTo(STABLE_BOUNDS.bottom)
+    }
+
+
+    @Test
+    fun testChangeBounds_beyondStableBounds_freezesAtStableBounds() {
+        val startingPoint = PointF(
+            STARTING_BOUNDS.right.toFloat(),
+            STARTING_BOUNDS.bottom.toFloat()
+        )
+        val repositionTaskBounds = Rect(STARTING_BOUNDS)
+
+        // Resize to beyond stable bounds.
+        val newX = STARTING_BOUNDS.right.toFloat() + STABLE_BOUNDS.width()
+        val newY = STARTING_BOUNDS.bottom.toFloat() + STABLE_BOUNDS.height()
+
+        val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
+        assertTrue(
+            DragPositioningCallbackUtility.changeBounds(
+                CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+                repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
+                mockWindowDecoration
+            )
+        )
+        assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
+        assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
+        assertThat(repositionTaskBounds.right).isEqualTo(STABLE_BOUNDS.right)
+        assertThat(repositionTaskBounds.bottom).isEqualTo(STABLE_BOUNDS.bottom)
     }
 
     @Test
     @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS)
     fun taskMinWidthHeightUndefined_changeBoundsInDesktopModeLessThanMin_shouldNotChangeBounds() {
-        doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(mockContext) }
+        doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(mockContext) }
         initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1)
         val startingPoint =
             PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat())
@@ -277,9 +330,11 @@
         val newY = STARTING_BOUNDS.bottom.toFloat() - 99
         val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
 
-        DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+        DragPositioningCallbackUtility.changeBounds(
+            CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
             repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
-            mockWindowDecoration)
+            mockWindowDecoration
+        )
         assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
         assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
         assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right)
@@ -289,7 +344,7 @@
     @Test
     @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS)
     fun taskMinWidthHeightUndefined_changeBoundsInDesktopModeAllowedSize_shouldChangeBounds() {
-        doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(mockContext) }
+        doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(mockContext) }
         initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1)
         val startingPoint =
             PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat())
@@ -300,9 +355,11 @@
         val newY = STARTING_BOUNDS.bottom.toFloat() - 80
         val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
 
-        DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+        DragPositioningCallbackUtility.changeBounds(
+            CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
             repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
-            mockWindowDecoration)
+            mockWindowDecoration
+        )
         assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
         assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
         assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 80)
@@ -321,9 +378,11 @@
         val newY = STARTING_BOUNDS.bottom.toFloat() - 99
         val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
 
-        DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+        DragPositioningCallbackUtility.changeBounds(
+            CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
             repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
-            mockWindowDecoration)
+            mockWindowDecoration
+        )
         assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
         assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
         assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right)
@@ -342,9 +401,11 @@
         val newY = STARTING_BOUNDS.bottom.toFloat() - 50
         val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
 
-        DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+        DragPositioningCallbackUtility.changeBounds(
+            CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
             repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController,
-            mockWindowDecoration)
+            mockWindowDecoration
+        )
         assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left)
         assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top)
         assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 50)
@@ -355,8 +416,10 @@
     @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS)
     fun testChangeBounds_windowSizeExceedsStableBounds_shouldBeAllowedToChangeBounds() {
         val startingPoint =
-            PointF(OFF_CENTER_STARTING_BOUNDS.right.toFloat(),
-                OFF_CENTER_STARTING_BOUNDS.bottom.toFloat())
+            PointF(
+                OFF_CENTER_STARTING_BOUNDS.right.toFloat(),
+                OFF_CENTER_STARTING_BOUNDS.bottom.toFloat()
+            )
         val repositionTaskBounds = Rect(OFF_CENTER_STARTING_BOUNDS)
         // Increase height and width by STABLE_BOUNDS. Subtract by 5px so that it doesn't reach
         // the disallowed drag area.
@@ -365,9 +428,11 @@
         val newY = STABLE_BOUNDS.bottom.toFloat() - offset
         val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
 
-        DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+        DragPositioningCallbackUtility.changeBounds(
+            CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
             repositionTaskBounds, OFF_CENTER_STARTING_BOUNDS, STABLE_BOUNDS, delta,
-            mockDisplayController, mockWindowDecoration)
+            mockDisplayController, mockWindowDecoration
+        )
         assertThat(repositionTaskBounds.width()).isGreaterThan(STABLE_BOUNDS.right)
         assertThat(repositionTaskBounds.height()).isGreaterThan(STABLE_BOUNDS.bottom)
     }
@@ -375,10 +440,12 @@
     @Test
     @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS)
     fun testChangeBoundsInDesktopMode_windowSizeExceedsStableBounds_shouldBeLimitedToDisplaySize() {
-        doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(mockContext) }
+        doReturn(true).`when` { DesktopModeStatus.canEnterDesktopMode(mockContext) }
         val startingPoint =
-            PointF(OFF_CENTER_STARTING_BOUNDS.right.toFloat(),
-                OFF_CENTER_STARTING_BOUNDS.bottom.toFloat())
+            PointF(
+                OFF_CENTER_STARTING_BOUNDS.right.toFloat(),
+                OFF_CENTER_STARTING_BOUNDS.bottom.toFloat()
+            )
         val repositionTaskBounds = Rect(OFF_CENTER_STARTING_BOUNDS)
         // Increase height and width by STABLE_BOUNDS. Subtract by 5px so that it doesn't reach
         // the disallowed drag area.
@@ -387,9 +454,11 @@
         val newY = STABLE_BOUNDS.bottom.toFloat() - offset
         val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
 
-        DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
+        DragPositioningCallbackUtility.changeBounds(
+            CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
             repositionTaskBounds, OFF_CENTER_STARTING_BOUNDS, STABLE_BOUNDS, delta,
-            mockDisplayController, mockWindowDecoration)
+            mockDisplayController, mockWindowDecoration
+        )
         assertThat(repositionTaskBounds.width()).isLessThan(STABLE_BOUNDS.right)
         assertThat(repositionTaskBounds.height()).isLessThan(STABLE_BOUNDS.bottom)
     }
@@ -423,7 +492,8 @@
             DISPLAY_BOUNDS.left,
             DISPLAY_BOUNDS.bottom - NAVBAR_HEIGHT,
             DISPLAY_BOUNDS.right,
-            DISPLAY_BOUNDS.bottom)
+            DISPLAY_BOUNDS.bottom
+        )
         private val STABLE_BOUNDS = Rect(
             DISPLAY_BOUNDS.left,
             DISPLAY_BOUNDS.top,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
index 2ce59ff..3a3e965 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
@@ -678,6 +678,7 @@
             CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM)
         val rectAfterDrag = Rect(STARTING_BOUNDS)
         rectAfterDrag.right += 2000
+        rectAfterDrag.bottom = STABLE_BOUNDS_LANDSCAPE.bottom
         // First drag; we should fetch stable bounds.
         verify(mockDisplayLayout, Mockito.times(1)).getStableBounds(any())
         verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
@@ -705,8 +706,8 @@
             STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat(),
             STARTING_BOUNDS.right.toFloat() + 2000, STARTING_BOUNDS.bottom.toFloat() + 2000,
             CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM)
-        rectAfterDrag.right -= 2000
-        rectAfterDrag.bottom += 2000
+        rectAfterDrag.right = STABLE_BOUNDS_PORTRAIT.right
+        rectAfterDrag.bottom = STARTING_BOUNDS.bottom + 2000
 
         verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
             return@argThat wct.changes.any { (token, change) ->
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
index 08a6e1b..6ae16ed 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
@@ -372,6 +372,7 @@
             CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM)
         val rectAfterDrag = Rect(STARTING_BOUNDS)
         rectAfterDrag.right += 2000
+        rectAfterDrag.bottom = STABLE_BOUNDS_LANDSCAPE.bottom
         // First drag; we should fetch stable bounds.
         verify(mockDisplayLayout, times(1)).getStableBounds(any())
         verify(mockTransitions).startTransition(eq(TRANSIT_CHANGE), argThat { wct ->
@@ -396,8 +397,8 @@
         performDrag(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat(),
             STARTING_BOUNDS.right.toFloat() + 2000, STARTING_BOUNDS.bottom.toFloat() + 2000,
             CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM)
-        rectAfterDrag.right -= 2000
-        rectAfterDrag.bottom += 2000
+        rectAfterDrag.right = STABLE_BOUNDS_PORTRAIT.right
+        rectAfterDrag.bottom = STARTING_BOUNDS.bottom + 2000
 
         verify(mockTransitions).startTransition(eq(TRANSIT_CHANGE), argThat { wct ->
             return@argThat wct.changes.any { (token, change) ->
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index c36eda9..ca468fc 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1027,7 +1027,7 @@
      * <p>This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
      * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed
-     * unless the app has been granted Do Not Disturb Access.
+     * unless the app has been granted Notification Policy Access.
      * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
      *
      * @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL},
@@ -1379,7 +1379,7 @@
      * <p>This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
      * * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed
-     * unless the app has been granted Do Not Disturb Access.
+     * unless the app has been granted Notification Policy Access.
      * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
      * @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL},
      *            {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
@@ -1403,7 +1403,7 @@
      * <p>This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
      * <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless
-     * the app has been granted Do Not Disturb Access.
+     * the app has been granted Notification Policy Access.
      * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
      * @param streamType The stream whose volume index should be set.
      * @param index The volume index to set. See
@@ -8829,7 +8829,7 @@
      * <p>This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
      * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed
-     * unless the app has been granted Do Not Disturb Access.
+     * unless the app has been granted Notification Policy Access.
      * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
      * <p>This API checks if the caller has the necessary permissions based on the provided
      * component name, uid, and pid values.
@@ -8870,7 +8870,7 @@
      * <p>This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
      * <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless
-     * the app has been granted Do Not Disturb Access.
+     * the app has been granted Notification Policy Access.
      * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
      * <p>This API checks if the caller has the necessary permissions based on the provided
      * component name, uid, and pid values.
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index be93abb..87cb3e7 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -70,6 +70,7 @@
     void releaseSession(in IBinder sessionToken, int userId);
     int getClientPid(in String sessionId);
     int getClientPriority(int useCase, in String sessionId);
+    int getClientUserId(in String sessionId);
 
     void setMainSession(in IBinder sessionToken, int userId);
     void setSurface(in IBinder sessionToken, in Surface surface, int userId);
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index aed3e60e..25b6bfa 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -760,6 +760,14 @@
      * @hide
      */
     public static final int UNKNOWN_CLIENT_PID = -1;
+    /**
+     * An unknown state of the client userId gets from the TvInputManager. Client gets this value
+     * when query through {@link #getClientUserId(String sessionId)} fails.
+     *
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_KIDS_MODE_TVDB_SHARING)
+    public static final int UNKNOWN_CLIENT_USER_ID = -1;
 
     /**
      * Broadcast intent action when the user blocked content ratings change. For use with the
@@ -2510,6 +2518,21 @@
     };
 
     /**
+     * Get a the client user id when creating the session with the session id provided.
+     *
+     * @param sessionId a String of session id that is used to query the client user id.
+     * @return the client pid when created the session. Returns {@link #UNKNOWN_CLIENT_USER_ID}
+     *         if the call fails.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.TUNER_RESOURCE_ACCESS)
+    @FlaggedApi(Flags.FLAG_KIDS_MODE_TVDB_SHARING)
+    public int getClientUserId(@NonNull String sessionId) {
+        return getClientUserIdInternal(sessionId);
+    }
+
+    /**
      * Returns a priority for the given use case type and the client's foreground or background
      * status.
      *
@@ -2599,6 +2622,18 @@
         return clientPid;
     }
 
+    @FlaggedApi(Flags.FLAG_KIDS_MODE_TVDB_SHARING)
+    private int getClientUserIdInternal(String sessionId) {
+        Preconditions.checkNotNull(sessionId);
+        int clientUserId = UNKNOWN_CLIENT_USER_ID;
+        try {
+            clientUserId = mService.getClientUserId(sessionId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+        return clientUserId;
+    }
+
     private int getClientPriorityInternal(int useCase, String sessionId) {
         try {
             return mService.getClientPriority(useCase, sessionId);
diff --git a/media/java/android/media/tv/flags/media_tv.aconfig b/media/java/android/media/tv/flags/media_tv.aconfig
index 3196ba1..d6e9e4e 100644
--- a/media/java/android/media/tv/flags/media_tv.aconfig
+++ b/media/java/android/media/tv/flags/media_tv.aconfig
@@ -31,4 +31,12 @@
     namespace: "media_tv"
     description: "Introduce ALWAYS_BOUND_TV_INPUT for TIS."
     bug: "332201346"
+}
+
+flag {
+    name: "kids_mode_tvdb_sharing"
+    is_exported: true
+    namespace: "media_tv"
+    description: "Performance and Storage Optimization in Google TV Kids Mode."
+    bug: "288383796"
 }
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
index 69ef718..0d4ce5b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
@@ -53,9 +53,11 @@
 import com.android.settingslib.R;
 
 import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 
+import java.util.Comparator;
 import java.util.Objects;
 
 /**
@@ -88,6 +90,33 @@
                     .allowPriorityChannels(false)
                     .build();
 
+    private static final Comparator<Integer> PRIORITIZED_TYPE_COMPARATOR = new Comparator<>() {
+
+        private static final ImmutableList</* @AutomaticZenRule.Type */ Integer>
+                PRIORITIZED_TYPES = ImmutableList.of(
+                        AutomaticZenRule.TYPE_BEDTIME,
+                        AutomaticZenRule.TYPE_DRIVING);
+
+        @Override
+        public int compare(Integer first, Integer second) {
+            if (PRIORITIZED_TYPES.contains(first) && PRIORITIZED_TYPES.contains(second)) {
+                return PRIORITIZED_TYPES.indexOf(first) - PRIORITIZED_TYPES.indexOf(second);
+            } else if (PRIORITIZED_TYPES.contains(first)) {
+                return -1;
+            } else if (PRIORITIZED_TYPES.contains(second)) {
+                return 1;
+            } else {
+                return 0;
+            }
+        }
+    };
+
+    // Manual DND first, Bedtime/Driving, then alphabetically.
+    static final Comparator<ZenMode> PRIORITIZING_COMPARATOR = Comparator
+            .comparing(ZenMode::isManualDnd).reversed()
+            .thenComparing(ZenMode::getType, PRIORITIZED_TYPE_COMPARATOR)
+            .thenComparing(ZenMode::getName);
+
     public enum Status {
         ENABLED,
         ENABLED_AND_ACTIVE,
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java
index 64e503b32..c8a12f4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java
@@ -34,7 +34,6 @@
 
 import java.time.Duration;
 import java.util.ArrayList;
-import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 
@@ -92,10 +91,7 @@
             }
         }
 
-        // Manual DND first, then alphabetically.
-        modes.sort(Comparator.comparing(ZenMode::isManualDnd).reversed()
-                .thenComparing(ZenMode::getName));
-
+        modes.sort(ZenMode.PRIORITIZING_COMPARATOR);
         return modes;
     }
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
index f464247..bab4bc3b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
@@ -16,6 +16,12 @@
 
 package com.android.settingslib.notification.modes;
 
+import static android.app.AutomaticZenRule.TYPE_BEDTIME;
+import static android.app.AutomaticZenRule.TYPE_DRIVING;
+import static android.app.AutomaticZenRule.TYPE_IMMERSIVE;
+import static android.app.AutomaticZenRule.TYPE_OTHER;
+import static android.app.AutomaticZenRule.TYPE_THEATER;
+import static android.app.AutomaticZenRule.TYPE_UNKNOWN;
 import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS;
 import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE;
 import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
@@ -38,6 +44,9 @@
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(RobolectricTestRunner.class)
 public class ZenModeTest {
 
@@ -46,7 +55,7 @@
     private static final AutomaticZenRule ZEN_RULE =
             new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
                     .setPackage("com.some.driving.thing")
-                    .setType(AutomaticZenRule.TYPE_DRIVING)
+                    .setType(TYPE_DRIVING)
                     .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
                     .setZenPolicy(ZEN_POLICY)
                     .build();
@@ -226,6 +235,28 @@
     }
 
     @Test
+    public void comparator_prioritizes() {
+        ZenMode manualDnd = TestModeBuilder.MANUAL_DND_INACTIVE;
+        ZenMode driving1 = new TestModeBuilder().setName("b1").setType(TYPE_DRIVING).build();
+        ZenMode driving2 = new TestModeBuilder().setName("b2").setType(TYPE_DRIVING).build();
+        ZenMode bedtime1 = new TestModeBuilder().setName("c1").setType(TYPE_BEDTIME).build();
+        ZenMode bedtime2 = new TestModeBuilder().setName("c2").setType(TYPE_BEDTIME).build();
+        ZenMode other = new TestModeBuilder().setName("a1").setType(TYPE_OTHER).build();
+        ZenMode immersive = new TestModeBuilder().setName("a2").setType(TYPE_IMMERSIVE).build();
+        ZenMode unknown = new TestModeBuilder().setName("a3").setType(TYPE_UNKNOWN).build();
+        ZenMode theater = new TestModeBuilder().setName("a4").setType(TYPE_THEATER).build();
+
+        ArrayList<ZenMode> list = new ArrayList<>(List.of(other, theater, bedtime1, unknown,
+                driving2, manualDnd, driving1, bedtime2, immersive));
+        list.sort(ZenMode.PRIORITIZING_COMPARATOR);
+
+        assertThat(list)
+                .containsExactly(manualDnd, bedtime1, bedtime2, driving1, driving2, other,
+                        immersive, unknown, theater)
+                .inOrder();
+    }
+
+    @Test
     public void writeToParcel_equals() {
         assertUnparceledIsEqualToOriginal("example",
                 new ZenMode("id", ZEN_RULE, zenConfigRuleFor(ZEN_RULE, false)));
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 398c915..2e98c1f 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -376,6 +376,10 @@
     <!-- Listen to (dis-)connection of external displays and enable / disable them. -->
     <uses-permission android:name="android.permission.MANAGE_DISPLAYS" />
 
+    <!-- To be able to intercept meta key events, might need to be removed once b/358569822
+         is ready -->
+    <uses-permission android:name="android.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW" />
+
     <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" />
     <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" />
     <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" />
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 047c097..476fd8b 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -541,6 +541,16 @@
 }
 
 flag {
+    name: "clipboard_image_timeout"
+    namespace: "systemui"
+    description: "Wait for clipboard image to load before showing UI"
+    bug: "359864629"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
     name: "screenshot_action_dismiss_system_windows"
     namespace: "systemui"
     description: "Dismiss existing system windows when starting action from screenshot UI"
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
index 069113b..163b355 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
@@ -511,7 +511,7 @@
 private const val SELECTED_DOT_DIAMETER_DP = (DOT_DIAMETER_DP * 1.5).toInt()
 private const val SELECTED_DOT_REACTION_ANIMATION_DURATION_MS = 83
 private const val SELECTED_DOT_RETRACT_ANIMATION_DURATION_MS = 750
-private const val LINE_STROKE_WIDTH_DP = DOT_DIAMETER_DP
+private const val LINE_STROKE_WIDTH_DP = 22
 private const val FAILURE_ANIMATION_DOT_DIAMETER_DP = (DOT_DIAMETER_DP * 0.81f).toInt()
 private const val FAILURE_ANIMATION_DOT_SHRINK_ANIMATION_DURATION_MS = 50
 private const val FAILURE_ANIMATION_DOT_SHRINK_STAGGER_DELAY_MS = 33
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 7472d81..91a88bc 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -170,7 +170,6 @@
 import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
 import com.android.systemui.communal.util.DensityUtils.Companion.adjustedDp
-import com.android.systemui.communal.util.DensityUtils.Companion.scalingAdjustment
 import com.android.systemui.communal.widgets.SmartspaceAppWidgetHostView
 import com.android.systemui.communal.widgets.WidgetConfigurator
 import com.android.systemui.res.R
@@ -478,8 +477,7 @@
 }
 
 val hubDimensions: Dimensions
-    @Composable
-    get() = Dimensions(LocalContext.current, LocalConfiguration.current, LocalDensity.current)
+    @Composable get() = Dimensions(LocalContext.current, LocalConfiguration.current)
 
 @Composable
 private fun DisclaimerBottomSheetContent(onButtonClicked: () -> Unit) {
@@ -1288,8 +1286,9 @@
         modifier =
             modifier
                 .background(
-                    MaterialTheme.colorScheme.surfaceVariant,
-                    RoundedCornerShape(dimensionResource(system_app_widget_background_radius))
+                    color = MaterialTheme.colorScheme.surfaceVariant,
+                    shape =
+                        RoundedCornerShape(dimensionResource(system_app_widget_background_radius))
                 )
                 .clickable(
                     enabled = !viewModel.isEditMode,
@@ -1325,10 +1324,8 @@
     Column(
         modifier =
             modifier.background(
-                MaterialTheme.colorScheme.surfaceVariant,
-                RoundedCornerShape(
-                    dimensionResource(system_app_widget_background_radius) * scalingAdjustment
-                )
+                color = MaterialTheme.colorScheme.surfaceVariant,
+                shape = RoundedCornerShape(dimensionResource(system_app_widget_background_radius))
             ),
         verticalArrangement = Arrangement.Center,
         horizontalAlignment = Alignment.CenterHorizontally,
@@ -1514,21 +1511,24 @@
     fun toOffset(): Offset = Offset(start, top)
 }
 
-class Dimensions(val context: Context, val config: Configuration, val density: Density) {
+class Dimensions(val context: Context, val config: Configuration) {
     val GridTopSpacing: Dp
         get() {
-            if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
-                return 114.adjustedDp
-            } else {
-                val windowMetrics =
-                    WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
-                val screenHeight = with(density) { windowMetrics.bounds.height().adjustedDp }
-
-                return (screenHeight - CardHeightFull) / 2
-            }
+            val result =
+                if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+                    114.dp
+                } else {
+                    val windowMetrics =
+                        WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
+                    val density = context.resources.displayMetrics.density
+                    val screenHeight = (windowMetrics.bounds.height() / density).dp
+                    ((screenHeight - CardHeightFull) / 2)
+                }
+            return result
         }
 
-    val GridHeight = CardHeightFull + GridTopSpacing
+    val GridHeight: Dp
+        get() = CardHeightFull + GridTopSpacing
 
     companion object {
         val CardHeightFull
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardPreviewConstants.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardPreviewConstants.kt
index 08ee602..a3f40d4 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardPreviewConstants.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardPreviewConstants.kt
@@ -18,10 +18,17 @@
 package com.android.systemui.shared.quickaffordance.shared.model
 
 object KeyguardPreviewConstants {
+    const val MESSAGE_ID_DEFAULT_PREVIEW = 707
     const val MESSAGE_ID_HIDE_SMART_SPACE = 1111
-    const val KEY_HIDE_SMART_SPACE = "hide_smart_space"
+    const val MESSAGE_ID_PREVIEW_QUICK_AFFORDANCE_SELECTED = 1988
     const val MESSAGE_ID_SLOT_SELECTED = 1337
-    const val KEY_SLOT_ID = "slot_id"
-    const val KEY_INITIALLY_SELECTED_SLOT_ID = "initially_selected_slot_id"
+    const val MESSAGE_ID_START_CUSTOMIZING_QUICK_AFFORDANCES = 214
+
+    const val KEY_HIDE_SMART_SPACE = "hide_smart_space"
     const val KEY_HIGHLIGHT_QUICK_AFFORDANCES = "highlight_quick_affordances"
+    const val KEY_INITIALLY_SELECTED_SLOT_ID = "initially_selected_slot_id"
+    const val KEY_QUICK_AFFORDANCE_ID = "quick_affordance_id"
+    const val KEY_SLOT_ID = "slot_id"
+
+    const val KEYGUARD_QUICK_AFFORDANCE_ID_NONE = "none"
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt
index b83ab7e..c161525 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt
@@ -430,6 +430,22 @@
                 .isEqualTo("Can’t unlock with face. Too many attempts.")
         }
 
+    @Test
+    fun startLockdownCountdown_onActivated() =
+        testScope.runTest {
+            val bouncerMessage by collectLastValue(underTest.message)
+            val lockoutSeconds = 200 * 1000 // 200 second lockout
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(Pin)
+            kosmos.fakeAuthenticationRepository.reportLockoutStarted(lockoutSeconds)
+            runCurrent()
+
+            assertThat(bouncerMessage?.text).isEqualTo("Try again in 200 seconds.")
+            advanceTimeBy(100.seconds)
+            assertThat(bouncerMessage?.text).isEqualTo("Try again in 100 seconds.")
+            advanceTimeBy(101.seconds)
+            assertThat(bouncerMessage?.text).isEqualTo("Enter PIN")
+        }
+
     private fun TestScope.verifyMessagesForAuthFlags(
         vararg authFlagToMessagePair: Pair<Int, Pair<String, String?>>
     ) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt
index d6712f0..c5518b0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt
@@ -53,6 +53,7 @@
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
+import kotlin.time.Duration.Companion.seconds
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -78,6 +79,7 @@
 
     private val underTest by lazy { kosmos.communalSceneTransitionInteractor }
     private val keyguardTransitionRepository by lazy { kosmos.realKeyguardTransitionRepository }
+    private val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
 
     private val ownerName = CommunalSceneTransitionInteractor::class.java.simpleName
     private val progress = MutableSharedFlow<Float>()
@@ -789,4 +791,47 @@
                     )
                 )
         }
+
+    /** Verifies that we correctly transition to GONE after keyguard goes away */
+    @Test
+    fun transition_to_blank_after_unlock_should_go_to_gone() =
+        testScope.runTest {
+            keyguardRepository.setKeyguardShowing(true)
+            sceneTransitions.value = Idle(CommunalScenes.Communal)
+
+            val currentStep by collectLastValue(keyguardTransitionRepository.transitions)
+
+            assertThat(currentStep)
+                .isEqualTo(
+                    TransitionStep(
+                        from = LOCKSCREEN,
+                        to = GLANCEABLE_HUB,
+                        transitionState = FINISHED,
+                        value = 1f,
+                        ownerName = ownerName,
+                    )
+                )
+
+            // Keyguard starts exiting after a while, then fully exits after some time.
+            advanceTimeBy(1.seconds)
+            keyguardRepository.setKeyguardGoingAway(true)
+            advanceTimeBy(2.seconds)
+            keyguardRepository.setKeyguardGoingAway(false)
+            keyguardRepository.setKeyguardShowing(false)
+            runCurrent()
+
+            // We snap to the blank scene as a result of keyguard going away.
+            sceneTransitions.value = Idle(CommunalScenes.Blank)
+
+            assertThat(currentStep)
+                .isEqualTo(
+                    TransitionStep(
+                        from = GLANCEABLE_HUB,
+                        to = GONE,
+                        transitionState = FINISHED,
+                        value = 1f,
+                        ownerName = ownerName,
+                    )
+                )
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
index 8e109b4..c85cd66 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
@@ -308,6 +308,15 @@
             )
         }
 
+    @Test
+    fun getConfig() =
+        testScope.runTest {
+            assertThat(underTest.getConfig(FakeCustomizationProviderClient.AFFORDANCE_1))
+                .isEqualTo(config1)
+            assertThat(underTest.getConfig(FakeCustomizationProviderClient.AFFORDANCE_2))
+                .isEqualTo(config2)
+        }
+
     private fun assertSelections(
         observed: Map<String, List<KeyguardQuickAffordanceConfig>>?,
         expected: Map<String, List<KeyguardQuickAffordanceConfig>>,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index 75c0d3b..ad07c1c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -426,6 +426,64 @@
         }
 
     @Test
+    fun quickAffordanceAlwaysVisible_withNonNullOverrideKeyguardQuickAffordanceId() =
+        testScope.runTest {
+            quickAccessWallet.setState(
+                KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+                    icon = ICON,
+                    activationState = ActivationState.Active,
+                )
+            )
+            homeControls.setState(
+                KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+                    icon = ICON,
+                    activationState = ActivationState.Active,
+                )
+            )
+
+            // The default case
+            val collectedValue =
+                collectLastValue(
+                    underTest.quickAffordanceAlwaysVisible(
+                        KeyguardQuickAffordancePosition.BOTTOM_START,
+                    )
+                )
+            assertThat(collectedValue())
+                .isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java)
+            val visibleModel = collectedValue() as KeyguardQuickAffordanceModel.Visible
+            assertThat(visibleModel.configKey)
+                .isEqualTo(
+                    "${KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START}::${homeControls.key}"
+                )
+            assertThat(visibleModel.icon).isEqualTo(ICON)
+            assertThat(visibleModel.icon.contentDescription)
+                .isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID))
+            assertThat(visibleModel.activationState).isEqualTo(ActivationState.Active)
+
+            // With override
+            val collectedValueWithOverride =
+                collectLastValue(
+                    underTest.quickAffordanceAlwaysVisible(
+                        position = KeyguardQuickAffordancePosition.BOTTOM_START,
+                        overrideQuickAffordanceId =
+                            BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET,
+                    )
+                )
+            assertThat(collectedValueWithOverride())
+                .isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java)
+            val visibleModelWithOverride =
+                collectedValueWithOverride() as KeyguardQuickAffordanceModel.Visible
+            assertThat(visibleModelWithOverride.configKey)
+                .isEqualTo(
+                    "${KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START}::${quickAccessWallet.key}"
+                )
+            assertThat(visibleModelWithOverride.icon).isEqualTo(ICON)
+            assertThat(visibleModelWithOverride.icon.contentDescription)
+                .isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID))
+            assertThat(visibleModelWithOverride.activationState).isEqualTo(ActivationState.Active)
+        }
+
+    @Test
     fun select() =
         testScope.runTest {
             overrideResource(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index 9792c28..1bc2e24 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -60,6 +60,7 @@
 import com.android.systemui.shade.shadeTestUtil
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.whenever
+import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.cancelChildren
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -2135,6 +2136,14 @@
     @EnableFlags(FLAG_COMMUNAL_SCENE_KTF_REFACTOR)
     fun glanceableHubToOccluded_communalKtfRefactor() =
         testScope.runTest {
+            // GIVEN device is not dreaming
+            powerInteractor.setAwakeForTest()
+            keyguardRepository.setDreaming(false)
+            keyguardRepository.setDozeTransitionModel(
+                DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
+            )
+            advanceTimeBy(600.milliseconds)
+
             // GIVEN a prior transition has run to GLANCEABLE_HUB
             communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
             runCurrent()
@@ -2298,6 +2307,54 @@
             coroutineContext.cancelChildren()
         }
 
+    @Test
+    @BrokenWithSceneContainer(339465026)
+    @EnableFlags(FLAG_COMMUNAL_SCENE_KTF_REFACTOR)
+    fun glanceableHubToOccludedDoesNotTriggerWhenDreamStateChanges_communalKtfRefactor() =
+        testScope.runTest {
+            // GIVEN that we are dreaming and not dozing
+            powerInteractor.setAwakeForTest()
+            keyguardRepository.setDreaming(true)
+            keyguardRepository.setKeyguardOccluded(true)
+            keyguardRepository.setDozeTransitionModel(
+                DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
+            )
+            advanceTimeBy(700.milliseconds)
+            clearInvocations(transitionRepository)
+
+            // GIVEN a prior transition has run to GLANCEABLE_HUB
+            communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
+            runCurrent()
+            assertThat(transitionRepository)
+                .startedTransition(
+                    ownerName = CommunalSceneTransitionInteractor::class.simpleName,
+                    from = KeyguardState.DREAMING,
+                    to = KeyguardState.GLANCEABLE_HUB,
+                )
+            clearInvocations(transitionRepository)
+
+            // WHEN dream ends but we are still occluded
+            keyguardRepository.setDreaming(false)
+            runCurrent()
+            assertThat(transitionRepository).noTransitionsStarted()
+
+            // Simulate occlusion signal changing due to dream terminating and then occluding again
+            // due to a new activity starting a couple milliseconds later.
+            keyguardRepository.setKeyguardOccluded(false)
+            advanceTimeBy(10.milliseconds)
+            keyguardRepository.setKeyguardOccluded(true)
+            advanceTimeBy(200.milliseconds)
+
+            assertThat(transitionRepository)
+                .startedTransition(
+                    ownerName = CommunalSceneTransitionInteractor::class.simpleName,
+                    from = KeyguardState.GLANCEABLE_HUB,
+                    to = KeyguardState.OCCLUDED,
+                )
+
+            coroutineContext.cancelChildren()
+        }
+
     private suspend fun TestScope.runTransitionAndSetWakefulness(
         from: KeyguardState,
         to: KeyguardState
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/BaseActivatableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/BaseActivatableTest.kt
new file mode 100644
index 0000000..f6f58c9
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/BaseActivatableTest.kt
@@ -0,0 +1,328 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.lifecycle
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class BaseActivatableTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+
+    private val underTest = FakeActivatable()
+
+    @Test
+    fun activate() =
+        testScope.runTest {
+            assertThat(underTest.isActive).isFalse()
+            assertThat(underTest.activationCount).isEqualTo(0)
+            assertThat(underTest.cancellationCount).isEqualTo(0)
+
+            underTest.activateIn(testScope)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+            assertThat(underTest.activationCount).isEqualTo(1)
+            assertThat(underTest.cancellationCount).isEqualTo(0)
+        }
+
+    @Test
+    fun activate_andCancel() =
+        testScope.runTest {
+            assertThat(underTest.isActive).isFalse()
+            assertThat(underTest.activationCount).isEqualTo(0)
+            assertThat(underTest.cancellationCount).isEqualTo(0)
+
+            val job = Job()
+            underTest.activateIn(testScope, context = job)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+            assertThat(underTest.activationCount).isEqualTo(1)
+            assertThat(underTest.cancellationCount).isEqualTo(0)
+
+            job.cancel()
+            runCurrent()
+            assertThat(underTest.isActive).isFalse()
+            assertThat(underTest.activationCount).isEqualTo(1)
+            assertThat(underTest.cancellationCount).isEqualTo(1)
+        }
+
+    @Test
+    fun activate_afterCancellation() =
+        testScope.runTest {
+            assertThat(underTest.isActive).isFalse()
+            assertThat(underTest.activationCount).isEqualTo(0)
+            assertThat(underTest.cancellationCount).isEqualTo(0)
+
+            val job = Job()
+            underTest.activateIn(testScope, context = job)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+            assertThat(underTest.activationCount).isEqualTo(1)
+            assertThat(underTest.cancellationCount).isEqualTo(0)
+
+            job.cancel()
+            runCurrent()
+            assertThat(underTest.isActive).isFalse()
+            assertThat(underTest.activationCount).isEqualTo(1)
+            assertThat(underTest.cancellationCount).isEqualTo(1)
+
+            underTest.activateIn(testScope)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+            assertThat(underTest.activationCount).isEqualTo(2)
+            assertThat(underTest.cancellationCount).isEqualTo(1)
+        }
+
+    @Test(expected = IllegalStateException::class)
+    fun activate_whileActive_throws() =
+        testScope.runTest {
+            assertThat(underTest.isActive).isFalse()
+            assertThat(underTest.activationCount).isEqualTo(0)
+            assertThat(underTest.cancellationCount).isEqualTo(0)
+
+            underTest.activateIn(testScope)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+            assertThat(underTest.activationCount).isEqualTo(1)
+            assertThat(underTest.cancellationCount).isEqualTo(0)
+
+            underTest.activateIn(testScope)
+            runCurrent()
+        }
+
+    @Test
+    fun addChild_beforeActive_activatesChildrenOnceActivated() =
+        testScope.runTest {
+            val child1 = FakeActivatable()
+            val child2 = FakeActivatable()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            assertThat(underTest.isActive).isFalse()
+            underTest.addChild(child1)
+            underTest.addChild(child2)
+            assertThat(underTest.isActive).isFalse()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            underTest.activateIn(this)
+            runCurrent()
+
+            assertThat(underTest.isActive).isTrue()
+            assertThat(child1.isActive).isTrue()
+            assertThat(child2.isActive).isTrue()
+        }
+
+    @Test
+    fun addChild_whileActive_activatesChildrenImmediately() =
+        testScope.runTest {
+            underTest.activateIn(this)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+
+            val child1 = FakeActivatable()
+            val child2 = FakeActivatable()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            underTest.addChild(child1)
+            underTest.addChild(child2)
+            runCurrent()
+
+            assertThat(child1.isActive).isTrue()
+            assertThat(child2.isActive).isTrue()
+        }
+
+    @Test
+    fun addChild_afterCancellation_doesNotActivateChildren() =
+        testScope.runTest {
+            val job = Job()
+            underTest.activateIn(this, context = job)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+            job.cancel()
+            runCurrent()
+            assertThat(underTest.isActive).isFalse()
+
+            val child1 = FakeActivatable()
+            val child2 = FakeActivatable()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            underTest.addChild(child1)
+            underTest.addChild(child2)
+            runCurrent()
+
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+        }
+
+    @Test
+    fun activate_cancellation_cancelsCurrentChildren() =
+        testScope.runTest {
+            val job = Job()
+            underTest.activateIn(this, context = job)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+
+            val child1 = FakeActivatable()
+            val child2 = FakeActivatable()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            underTest.addChild(child1)
+            underTest.addChild(child2)
+            runCurrent()
+
+            assertThat(child1.isActive).isTrue()
+            assertThat(child2.isActive).isTrue()
+
+            job.cancel()
+            runCurrent()
+            assertThat(underTest.isActive).isFalse()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+        }
+
+    @Test
+    fun activate_afterCancellation_reactivatesCurrentChildren() =
+        testScope.runTest {
+            val job = Job()
+            underTest.activateIn(this, context = job)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+
+            val child1 = FakeActivatable()
+            val child2 = FakeActivatable()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            underTest.addChild(child1)
+            underTest.addChild(child2)
+            runCurrent()
+
+            assertThat(child1.isActive).isTrue()
+            assertThat(child2.isActive).isTrue()
+
+            job.cancel()
+            runCurrent()
+            assertThat(underTest.isActive).isFalse()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            underTest.activateIn(this)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+            assertThat(child1.isActive).isTrue()
+            assertThat(child2.isActive).isTrue()
+        }
+
+    @Test
+    fun removeChild_beforeActive_neverActivatesChild() =
+        testScope.runTest {
+            val child1 = FakeActivatable()
+            val child2 = FakeActivatable()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            assertThat(underTest.isActive).isFalse()
+            underTest.addChild(child1)
+            underTest.addChild(child2)
+            assertThat(underTest.isActive).isFalse()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+        }
+
+    @Test
+    fun removeChild_whileActive_cancelsChild() =
+        testScope.runTest {
+            val child1 = FakeActivatable()
+            val child2 = FakeActivatable()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            assertThat(underTest.isActive).isFalse()
+            underTest.addChild(child1)
+            underTest.addChild(child2)
+            assertThat(underTest.isActive).isFalse()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            underTest.activateIn(this)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+            assertThat(child1.isActive).isTrue()
+            assertThat(child2.isActive).isTrue()
+
+            underTest.removeChild(child1)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isTrue()
+        }
+
+    @Test
+    fun removeChild_afterCancellation_doesNotReactivateChildren() =
+        testScope.runTest {
+            val child1 = FakeActivatable()
+            val child2 = FakeActivatable()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            assertThat(underTest.isActive).isFalse()
+            underTest.addChild(child1)
+            underTest.addChild(child2)
+            assertThat(underTest.isActive).isFalse()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            val job = Job()
+            underTest.activateIn(this, context = job)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+            assertThat(child1.isActive).isTrue()
+            assertThat(child2.isActive).isTrue()
+
+            job.cancel()
+            runCurrent()
+            assertThat(underTest.isActive).isFalse()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isFalse()
+
+            underTest.removeChild(child1)
+            underTest.activateIn(this)
+            runCurrent()
+            assertThat(underTest.isActive).isTrue()
+            assertThat(child1.isActive).isFalse()
+            assertThat(child2.isActive).isTrue()
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SafeActivatableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SafeActivatableTest.kt
deleted file mode 100644
index 9484821..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/lifecycle/SafeActivatableTest.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
-package com.android.systemui.lifecycle
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.testKosmos
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class SafeActivatableTest : SysuiTestCase() {
-
-    private val kosmos = testKosmos()
-    private val testScope = kosmos.testScope
-
-    private val underTest = FakeActivatable()
-
-    @Test
-    fun activate() =
-        testScope.runTest {
-            assertThat(underTest.isActive).isFalse()
-            assertThat(underTest.activationCount).isEqualTo(0)
-            assertThat(underTest.cancellationCount).isEqualTo(0)
-
-            underTest.activateIn(testScope)
-            runCurrent()
-            assertThat(underTest.isActive).isTrue()
-            assertThat(underTest.activationCount).isEqualTo(1)
-            assertThat(underTest.cancellationCount).isEqualTo(0)
-        }
-
-    @Test
-    fun activate_andCancel() =
-        testScope.runTest {
-            assertThat(underTest.isActive).isFalse()
-            assertThat(underTest.activationCount).isEqualTo(0)
-            assertThat(underTest.cancellationCount).isEqualTo(0)
-
-            val job = Job()
-            underTest.activateIn(testScope, context = job)
-            runCurrent()
-            assertThat(underTest.isActive).isTrue()
-            assertThat(underTest.activationCount).isEqualTo(1)
-            assertThat(underTest.cancellationCount).isEqualTo(0)
-
-            job.cancel()
-            runCurrent()
-            assertThat(underTest.isActive).isFalse()
-            assertThat(underTest.activationCount).isEqualTo(1)
-            assertThat(underTest.cancellationCount).isEqualTo(1)
-        }
-
-    @Test
-    fun activate_afterCancellation() =
-        testScope.runTest {
-            assertThat(underTest.isActive).isFalse()
-            assertThat(underTest.activationCount).isEqualTo(0)
-            assertThat(underTest.cancellationCount).isEqualTo(0)
-
-            val job = Job()
-            underTest.activateIn(testScope, context = job)
-            runCurrent()
-            assertThat(underTest.isActive).isTrue()
-            assertThat(underTest.activationCount).isEqualTo(1)
-            assertThat(underTest.cancellationCount).isEqualTo(0)
-
-            job.cancel()
-            runCurrent()
-            assertThat(underTest.isActive).isFalse()
-            assertThat(underTest.activationCount).isEqualTo(1)
-            assertThat(underTest.cancellationCount).isEqualTo(1)
-
-            underTest.activateIn(testScope)
-            runCurrent()
-            assertThat(underTest.isActive).isTrue()
-            assertThat(underTest.activationCount).isEqualTo(2)
-            assertThat(underTest.cancellationCount).isEqualTo(1)
-        }
-
-    @Test(expected = IllegalStateException::class)
-    fun activate_whileActive_throws() =
-        testScope.runTest {
-            assertThat(underTest.isActive).isFalse()
-            assertThat(underTest.activationCount).isEqualTo(0)
-            assertThat(underTest.cancellationCount).isEqualTo(0)
-
-            underTest.activateIn(testScope)
-            runCurrent()
-            assertThat(underTest.isActive).isTrue()
-            assertThat(underTest.activationCount).isEqualTo(1)
-            assertThat(underTest.cancellationCount).isEqualTo(0)
-
-            underTest.activateIn(testScope)
-            runCurrent()
-        }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt
index 4d1dd1c..d9faa30 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt
@@ -32,6 +32,7 @@
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.onNodeWithText
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.shared.model.ContentDescription
@@ -45,6 +46,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 
+@FlakyTest(bugId = 360351805)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class DragAndDropTest : SysuiTestCase() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt
index dfc004a..c9869bdb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt
@@ -280,9 +280,12 @@
         }
 
     @Test
-    fun isActiveFollowsPackageManagerAdapter() =
+    fun isActiveFollowsPackageManagerAdapter_user0() =
         with(kosmos) {
             testScope.runTest {
+                packageManagerAdapterFacade.setExclusiveForUser(0)
+
+                underTest.updateWithDefaults(UserHandle.of(0), TEST_DEFAULTS_1, true)
                 packageManagerAdapterFacade.setIsActive(false)
                 assertThat(underTest.isTileActive()).isFalse()
 
@@ -295,6 +298,7 @@
     fun isToggleableFollowsPackageManagerAdapter() =
         with(kosmos) {
             testScope.runTest {
+                underTest.updateWithDefaults(UserHandle.of(0), TEST_DEFAULTS_1, true)
                 packageManagerAdapterFacade.setIsToggleable(false)
                 assertThat(underTest.isTileToggleable()).isFalse()
 
@@ -303,6 +307,66 @@
             }
         }
 
+    @Test
+    fun isActiveFollowsPackageManagerAdapter_user10_withAdapterForUser10() =
+        with(kosmos) {
+            testScope.runTest {
+                packageManagerAdapterFacade.setExclusiveForUser(10)
+
+                underTest.updateWithDefaults(UserHandle.of(10), TEST_DEFAULTS_1, true)
+                packageManagerAdapterFacade.setIsActive(false)
+                assertThat(underTest.isTileActive()).isFalse()
+
+                packageManagerAdapterFacade.setIsActive(true)
+                assertThat(underTest.isTileActive()).isTrue()
+            }
+        }
+
+    @Test
+    fun isToggleableFollowsPackageManagerAdapter_user10_withAdapterForUser10() =
+        with(kosmos) {
+            testScope.runTest {
+                packageManagerAdapterFacade.setExclusiveForUser(10)
+
+                underTest.updateWithDefaults(UserHandle.of(10), TEST_DEFAULTS_1, true)
+                packageManagerAdapterFacade.setIsToggleable(false)
+                assertThat(underTest.isTileToggleable()).isFalse()
+
+                packageManagerAdapterFacade.setIsToggleable(true)
+                assertThat(underTest.isTileToggleable()).isTrue()
+            }
+        }
+
+    @Test
+    fun isActiveDoesntFollowPackageManagerAdapter_user10() =
+        with(kosmos) {
+            testScope.runTest {
+                packageManagerAdapterFacade.setExclusiveForUser(0)
+
+                underTest.updateWithDefaults(UserHandle.of(10), TEST_DEFAULTS_1, true)
+                packageManagerAdapterFacade.setIsActive(false)
+                assertThat(underTest.isTileActive()).isFalse()
+
+                packageManagerAdapterFacade.setIsActive(true)
+                assertThat(underTest.isTileActive()).isFalse()
+            }
+        }
+
+    @Test
+    fun isToggleableDoesntFollowPackageManagerAdapter_user10() =
+        with(kosmos) {
+            testScope.runTest {
+                packageManagerAdapterFacade.setExclusiveForUser(0)
+
+                underTest.updateWithDefaults(UserHandle.of(10), TEST_DEFAULTS_1, true)
+                packageManagerAdapterFacade.setIsToggleable(false)
+                assertThat(underTest.isTileToggleable()).isFalse()
+
+                packageManagerAdapterFacade.setIsToggleable(true)
+                assertThat(underTest.isTileToggleable()).isFalse()
+            }
+        }
+
     private companion object {
 
         val TEST_COMPONENT = ComponentName("test.pkg", "test.cls")
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index bbb467f..64a13de 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -28,9 +28,7 @@
 import com.android.internal.logging.uiEventLoggerFake
 import com.android.internal.policy.IKeyguardDismissCallback
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
 import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
-import com.android.systemui.authentication.domain.interactor.authenticationInteractor
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
 import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
@@ -357,6 +355,7 @@
             kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
                 SuccessFingerprintAuthenticationStatus(0, true)
             )
+            runCurrent()
 
             assertThat(currentSceneKey).isEqualTo(Scenes.QuickSettings)
             assertThat(alternateBouncerVisible).isFalse()
@@ -507,6 +506,33 @@
         }
 
     @Test
+    fun hideAlternateBouncerAndNotifyDismissCancelledWhenDeviceSleeps() =
+        testScope.runTest {
+            val alternateBouncerVisible by
+                collectLastValue(bouncerRepository.alternateBouncerVisible)
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            prepareState(
+                isDeviceUnlocked = false,
+                initialSceneKey = Scenes.Shade,
+            )
+            assertThat(currentSceneKey).isEqualTo(Scenes.Shade)
+            bouncerRepository.setAlternateVisible(true)
+            underTest.start()
+
+            // run all pending dismiss succeeded/cancelled calls from setup:
+            kosmos.fakeExecutor.runAllReady()
+
+            val dismissCallback: IKeyguardDismissCallback = mock()
+            kosmos.dismissCallbackRegistry.addCallback(dismissCallback)
+            powerInteractor.setAsleepForTest()
+            runCurrent()
+            kosmos.fakeExecutor.runAllReady()
+
+            assertThat(alternateBouncerVisible).isFalse()
+            verify(dismissCallback).onDismissCancelled()
+        }
+
+    @Test
     fun switchToLockscreenWhenDeviceSleepsLocked() =
         testScope.runTest {
             val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
@@ -1644,19 +1670,27 @@
         }
 
     @Test
-    fun notifyKeyguardDismissCallbacks_whenUnlocking_onDismissSucceeded() =
+    fun notifyKeyguardDismissCallbacks_whenUnlockingFromBouncer_onDismissSucceeded() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.currentScene)
-            prepareState()
+            val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+            prepareState(
+                authenticationMethod = AuthenticationMethodModel.Pin,
+                isDeviceUnlocked = false,
+                initialSceneKey = Scenes.Bouncer,
+            )
+            assertThat(currentSceneKey).isEqualTo(Scenes.Bouncer)
             underTest.start()
+
+            // run all pending dismiss succeeded/cancelled calls from setup:
+            kosmos.fakeExecutor.runAllReady()
+
             val dismissCallback: IKeyguardDismissCallback = mock()
             kosmos.dismissCallbackRegistry.addCallback(dismissCallback)
 
-            // Switch to bouncer and unlock device:
-            sceneInteractor.changeScene(Scenes.Bouncer, "")
-            assertThat(currentScene).isEqualTo(Scenes.Bouncer)
-            kosmos.authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
-            assertThat(currentScene).isEqualTo(Scenes.Gone)
+            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+                SuccessFingerprintAuthenticationStatus(0, true)
+            )
+            runCurrent()
             kosmos.fakeExecutor.runAllReady()
 
             verify(dismissCallback).onDismissSucceeded()
@@ -1665,19 +1699,26 @@
     @Test
     fun notifyKeyguardDismissCallbacks_whenLeavingBouncer_onDismissCancelled() =
         testScope.runTest {
+            val isUnlocked by collectLastValue(kosmos.deviceEntryInteractor.isUnlocked)
             val currentScene by collectLastValue(sceneInteractor.currentScene)
             prepareState()
             underTest.start()
+
+            // run all pending dismiss succeeded/cancelled calls from setup:
+            kosmos.fakeExecutor.runAllReady()
+
             val dismissCallback: IKeyguardDismissCallback = mock()
             kosmos.dismissCallbackRegistry.addCallback(dismissCallback)
 
             // Switch to bouncer:
             sceneInteractor.changeScene(Scenes.Bouncer, "")
             assertThat(currentScene).isEqualTo(Scenes.Bouncer)
+            runCurrent()
 
-            // Return to lockscreen:
+            // Return to lockscreen when isUnlocked=false:
             sceneInteractor.changeScene(Scenes.Lockscreen, "")
             assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+            assertThat(isUnlocked).isFalse()
             runCurrent()
             kosmos.fakeExecutor.runAllReady()
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f8303ea..8a2e767 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -756,6 +756,8 @@
     <string name="quick_settings_bluetooth_audio_sharing_button">Share audio</string>
     <!-- QuickSettings: Bluetooth dialog audio sharing button text when sharing audio [CHAR LIMIT=50]-->
     <string name="quick_settings_bluetooth_audio_sharing_button_sharing">Sharing audio</string>
+    <!-- QuickSettings: Bluetooth dialog audio sharing button text accessibility label. Used as part of the string "Double tap to enter audio sharing settings". [CHAR LIMIT=50]-->
+    <string name="quick_settings_bluetooth_audio_sharing_button_accessibility">enter audio sharing settings</string>
 
     <!-- QuickSettings: Bluetooth secondary label for the battery level of a connected device [CHAR LIMIT=20]-->
     <string name="quick_settings_bluetooth_secondary_label_battery_level"><xliff:g id="battery_level_as_percentage">%s</xliff:g> battery</string>
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
index f4a1f05..e4b7b7e 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
@@ -37,6 +37,7 @@
 import com.android.systemui.accessibility.AccessibilityButtonModeObserver.AccessibilityButtonMode;
 import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.util.settings.SecureSettings;
 
@@ -61,6 +62,7 @@
 
     private final SecureSettings mSecureSettings;
     private final DisplayTracker mDisplayTracker;
+    private final NavigationModeController mNavigationModeController;
     @VisibleForTesting
     IAccessibilityFloatingMenu mFloatingMenu;
     private int mBtnMode;
@@ -106,7 +108,8 @@
             AccessibilityButtonModeObserver accessibilityButtonModeObserver,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
             SecureSettings secureSettings,
-            DisplayTracker displayTracker) {
+            DisplayTracker displayTracker,
+            NavigationModeController navigationModeController) {
         mContext = context;
         mWindowManager = windowManager;
         mViewCaptureAwareWindowManager = viewCaptureAwareWindowManager;
@@ -117,6 +120,7 @@
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mSecureSettings = secureSettings;
         mDisplayTracker = displayTracker;
+        mNavigationModeController = navigationModeController;
 
         mIsKeyguardVisible = false;
     }
@@ -191,7 +195,8 @@
             final Context windowContext = mContext.createWindowContext(defaultDisplay,
                     TYPE_NAVIGATION_BAR_PANEL, /* options= */ null);
             mFloatingMenu = new MenuViewLayerController(windowContext, mWindowManager,
-                    mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings);
+                    mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings,
+                    mNavigationModeController);
         }
 
         mFloatingMenu.show();
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
index f4b6bfb..d62162b 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
@@ -77,6 +77,7 @@
 import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.internal.util.Preconditions;
 import com.android.systemui.Flags;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.res.R;
 import com.android.systemui.util.settings.SecureSettings;
 import com.android.wm.shell.bubbles.DismissViewUtils;
@@ -142,6 +143,8 @@
     private boolean mIsNotificationShown;
     private Optional<MenuEduTooltipView> mEduTooltipView = Optional.empty();
     private BroadcastReceiver mNotificationActionReceiver;
+    private NavigationModeController mNavigationModeController;
+    private NavigationModeController.ModeChangedListener mNavigationModeChangedListender;
 
     @IntDef({
             LayerIndex.MENU_VIEW,
@@ -220,7 +223,8 @@
             MenuViewModel menuViewModel,
             MenuViewAppearance menuViewAppearance, MenuView menuView,
             IAccessibilityFloatingMenu floatingMenu,
-            SecureSettings secureSettings) {
+            SecureSettings secureSettings,
+            NavigationModeController navigationModeController) {
         super(context);
 
         // Simplifies the translation positioning and animations
@@ -253,6 +257,8 @@
         mNotificationFactory = new MenuNotificationFactory(context);
         mNotificationManager = context.getSystemService(NotificationManager.class);
         mStatusBarManager = context.getSystemService(StatusBarManager.class);
+        mNavigationModeController = navigationModeController;
+        mNavigationModeChangedListender = (mode -> mMenuView.onPositionChanged());
 
         if (Flags.floatingMenuDragToEdit()) {
             mDragToInteractAnimationController = new DragToInteractAnimationController(
@@ -381,6 +387,7 @@
                 mMigrationTooltipObserver);
         mMessageView.setUndoListener(view -> undo());
         getContext().registerComponentCallbacks(this);
+        mNavigationModeController.addListener(mNavigationModeChangedListender);
     }
 
     @Override
@@ -396,6 +403,7 @@
                 mMigrationTooltipObserver);
         mHandler.removeCallbacksAndMessages(/* token= */ null);
         getContext().unregisterComponentCallbacks(this);
+        mNavigationModeController.removeListener(mNavigationModeChangedListender);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
index 623536f..cb96e78 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
@@ -24,6 +24,7 @@
 import android.view.accessibility.AccessibilityManager;
 
 import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.util.settings.SecureSettings;
 
 /**
@@ -37,7 +38,8 @@
 
     MenuViewLayerController(Context context, WindowManager windowManager,
             ViewCaptureAwareWindowManager viewCaptureAwareWindowManager,
-            AccessibilityManager accessibilityManager, SecureSettings secureSettings) {
+            AccessibilityManager accessibilityManager, SecureSettings secureSettings,
+            NavigationModeController navigationModeController) {
         mWindowManager = viewCaptureAwareWindowManager;
 
         MenuViewModel menuViewModel = new MenuViewModel(
@@ -49,7 +51,8 @@
                 menuViewAppearance,
                 new MenuView(context, menuViewModel, menuViewAppearance, secureSettings),
                 this,
-                secureSettings);
+                secureSettings,
+                navigationModeController);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
index a5c5bec..f4e2b82 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
@@ -33,6 +33,7 @@
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.app.animation.Interpolators;
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
 import com.android.systemui.res.R;
 
 /**
@@ -40,16 +41,17 @@
  */
 public class AssistDisclosure {
     private final Context mContext;
-    private final WindowManager mWm;
+    private final ViewCaptureAwareWindowManager mWm;
     private final Handler mHandler;
 
     private AssistDisclosureView mView;
     private boolean mViewAdded;
 
-    public AssistDisclosure(Context context, Handler handler) {
+    public AssistDisclosure(Context context, Handler handler,
+            ViewCaptureAwareWindowManager viewCaptureAwareWindowManager) {
         mContext = context;
         mHandler = handler;
-        mWm = mContext.getSystemService(WindowManager.class);
+        mWm = viewCaptureAwareWindowManager;
     }
 
     public void postShow() {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index a67dcdb..939d96e 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -25,6 +25,7 @@
 import android.service.voice.VoiceInteractionSession;
 import android.util.Log;
 
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
 import com.android.internal.app.AssistUtils;
 import com.android.internal.app.IVisualQueryDetectionAttentionListener;
 import com.android.internal.app.IVisualQueryRecognitionStatusListener;
@@ -195,12 +196,13 @@
             SecureSettings secureSettings,
             SelectedUserInteractor selectedUserInteractor,
             ActivityManager activityManager,
-            AssistInteractor interactor) {
+            AssistInteractor interactor,
+            ViewCaptureAwareWindowManager viewCaptureAwareWindowManager) {
         mContext = context;
         mDeviceProvisionedController = controller;
         mCommandQueue = commandQueue;
         mAssistUtils = assistUtils;
-        mAssistDisclosure = new AssistDisclosure(context, uiHandler);
+        mAssistDisclosure = new AssistDisclosure(context, uiHandler, viewCaptureAwareWindowManager);
         mOverviewProxyService = overviewProxyService;
         mPhoneStateMonitor = phoneStateMonitor;
         mAssistLogger = assistLogger;
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt
new file mode 100644
index 0000000..d69e416
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractor.kt
@@ -0,0 +1,91 @@
+/*
+ * 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.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothDevice
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChangedBy
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.merge
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class BluetoothDeviceMetadataInteractor
+@Inject
+constructor(
+    deviceItemInteractor: DeviceItemInteractor,
+    private val bluetoothAdapter: BluetoothAdapter?,
+    private val logger: BluetoothTileDialogLogger,
+    @Background private val executor: Executor,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+) {
+    private fun metadataUpdateForDevice(bluetoothDevice: BluetoothDevice): Flow<Unit> =
+        conflatedCallbackFlow {
+            val metadataChangedListener =
+                BluetoothAdapter.OnMetadataChangedListener { device, key, value ->
+                    when (key) {
+                        BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY,
+                        BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY,
+                        BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY,
+                        BluetoothDevice.METADATA_MAIN_BATTERY -> {
+                            trySendWithFailureLogging(Unit, TAG, "onMetadataChanged")
+                            logger.logBatteryChanged(device.address, key, value)
+                        }
+                    }
+                }
+            bluetoothAdapter?.addOnMetadataChangedListener(
+                bluetoothDevice,
+                executor,
+                metadataChangedListener
+            )
+            awaitClose {
+                bluetoothAdapter?.removeOnMetadataChangedListener(
+                    bluetoothDevice,
+                    metadataChangedListener
+                )
+            }
+        }
+
+    val metadataUpdate: Flow<Unit> =
+        deviceItemInteractor.deviceItemUpdate
+            .distinctUntilChangedBy { it.bluetoothDevices }
+            .flatMapLatest { items ->
+                items.bluetoothDevices.map { device -> metadataUpdateForDevice(device) }.merge()
+            }
+            .flowOn(backgroundDispatcher)
+
+    private companion object {
+        private const val TAG = "BluetoothDeviceMetadataInteractor"
+        private val List<DeviceItem>.bluetoothDevices: Set<BluetoothDevice>
+            get() =
+                flatMapTo(mutableSetOf()) { item ->
+                    listOf(item.cachedBluetoothDevice.device) +
+                        item.cachedBluetoothDevice.memberDevice.map { it.device }
+                }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt
index 2808dbe..7deea73 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt
@@ -129,8 +129,26 @@
         getPairNewDeviceButton(dialog).setOnClickListener {
             bluetoothTileDialogCallback.onPairNewDeviceClicked(it)
         }
-        getAudioSharingButtonView(dialog).setOnClickListener {
-            bluetoothTileDialogCallback.onAudioSharingButtonClicked(it)
+        getAudioSharingButtonView(dialog).apply {
+            setOnClickListener { bluetoothTileDialogCallback.onAudioSharingButtonClicked(it) }
+            accessibilityDelegate =
+                object : AccessibilityDelegate() {
+                    override fun onInitializeAccessibilityNodeInfo(
+                        host: View,
+                        info: AccessibilityNodeInfo
+                    ) {
+                        super.onInitializeAccessibilityNodeInfo(host, info)
+                        info.addAction(
+                            AccessibilityAction(
+                                AccessibilityAction.ACTION_CLICK.id,
+                                context.getString(
+                                    R.string
+                                        .quick_settings_bluetooth_audio_sharing_button_accessibility
+                                )
+                            )
+                        )
+                    }
+                }
         }
         getScrollViewContent(dialog).apply {
             minimumHeight =
@@ -445,7 +463,6 @@
 
     internal companion object {
         const val MIN_HEIGHT_CHANGE_INTERVAL_MS = 800L
-        const val MAX_DEVICE_ITEM_ENTRY = 3
         const val ACTION_BLUETOOTH_DEVICE_DETAILS =
             "com.android.settings.BLUETOOTH_DEVICE_DETAIL_SETTINGS"
         const val ACTION_PREVIOUSLY_CONNECTED_DEVICE =
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt
index 72312b8..06116f0 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogLogger.kt
@@ -90,6 +90,18 @@
             { "ProfileConnectionStateChanged. address=$str1 state=$str2 profileId=$int1" }
         )
 
+    fun logBatteryChanged(address: String, key: Int, value: ByteArray?) =
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                str1 = address
+                int1 = key
+                str2 = value?.toString() ?: ""
+            },
+            { "BatteryChanged. address=$str1 key=$int1 value=$str2" }
+        )
+
     fun logDeviceFetch(status: JobStatus, trigger: DeviceFetchTrigger, duration: Long) =
         logBuffer.log(
             TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt
index 6e51915..56b79d1 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogRepository.kt
@@ -24,7 +24,7 @@
 
 /** Repository to get CachedBluetoothDevices for the Bluetooth Dialog. */
 @SysUISingleton
-internal class BluetoothTileDialogRepository
+class BluetoothTileDialogRepository
 @Inject
 constructor(
     private val localBluetoothManager: LocalBluetoothManager?,
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
index 985b158..8b2449a 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModel.kt
@@ -37,7 +37,6 @@
 import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_BLUETOOTH_DEVICE_DETAILS
 import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_PAIR_NEW_DEVICE
 import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.ACTION_PREVIOUSLY_CONNECTED_DEVICE
-import com.android.systemui.bluetooth.qsdialog.BluetoothTileDialogDelegate.Companion.MAX_DEVICE_ITEM_ENTRY
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
@@ -50,8 +49,10 @@
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.channels.produce
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.merge
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
@@ -66,6 +67,7 @@
     private val bluetoothStateInteractor: BluetoothStateInteractor,
     private val bluetoothAutoOnInteractor: BluetoothAutoOnInteractor,
     private val audioSharingInteractor: AudioSharingInteractor,
+    private val bluetoothDeviceMetadataInteractor: BluetoothDeviceMetadataInteractor,
     private val dialogTransitionAnimator: DialogTransitionAnimator,
     private val activityStarter: ActivityStarter,
     private val uiEventLogger: UiEventLogger,
@@ -112,15 +114,17 @@
 
                 // deviceItemUpdate is emitted when device item list is done fetching, update UI and
                 // stop the progress bar.
-                deviceItemInteractor.deviceItemUpdate
-                    .onEach {
+                combine(
+                        deviceItemInteractor.deviceItemUpdate,
+                        deviceItemInteractor.showSeeAllUpdate
+                    ) { deviceItem, showSeeAll ->
                         updateDialogUiJob?.cancel()
                         updateDialogUiJob = launch {
                             dialogDelegate.apply {
                                 onDeviceItemUpdated(
                                     dialog,
-                                    it.take(MAX_DEVICE_ITEM_ENTRY),
-                                    showSeeAll = it.size > MAX_DEVICE_ITEM_ENTRY,
+                                    deviceItem,
+                                    showSeeAll,
                                     showPairNewDevice =
                                         bluetoothStateInteractor.isBluetoothEnabled()
                                 )
@@ -131,8 +135,11 @@
                     .launchIn(this)
 
                 // deviceItemUpdateRequest is emitted when a bluetooth callback is called, re-fetch
-                // the device item list and animiate the progress bar.
-                deviceItemInteractor.deviceItemUpdateRequest
+                // the device item list and animate the progress bar.
+                merge(
+                        deviceItemInteractor.deviceItemUpdateRequest,
+                        bluetoothDeviceMetadataInteractor.metadataUpdate
+                    )
                     .onEach {
                         dialogDelegate.animateProgressBar(dialog, true)
                         updateDeviceItemJob?.cancel()
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
index d7893db..e846bf7 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
@@ -38,7 +38,7 @@
     R.string.accessibility_quick_settings_bluetooth_device_tap_to_disconnect
 
 /** Factories to create different types of Bluetooth device items from CachedBluetoothDevice. */
-internal abstract class DeviceItemFactory {
+abstract class DeviceItemFactory {
     abstract fun isFilterMatched(
         context: Context,
         cachedDevice: CachedBluetoothDevice,
@@ -136,7 +136,7 @@
     }
 }
 
-internal open class AvailableMediaDeviceItemFactory : DeviceItemFactory() {
+open class AvailableMediaDeviceItemFactory : DeviceItemFactory() {
     override fun isFilterMatched(
         context: Context,
         cachedDevice: CachedBluetoothDevice,
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
index 1526cd9..9524496 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
@@ -34,16 +34,18 @@
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.asSharedFlow
+import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.shareIn
 import kotlinx.coroutines.isActive
 import kotlinx.coroutines.withContext
 
 /** Holds business logic for the Bluetooth Dialog after clicking on the Bluetooth QS tile. */
 @SysUISingleton
-internal class DeviceItemInteractor
+class DeviceItemInteractor
 @Inject
 constructor(
     private val bluetoothTileDialogRepository: BluetoothTileDialogRepository,
@@ -58,9 +60,13 @@
 
     private val mutableDeviceItemUpdate: MutableSharedFlow<List<DeviceItem>> =
         MutableSharedFlow(extraBufferCapacity = 1)
-    internal val deviceItemUpdate
+    val deviceItemUpdate
         get() = mutableDeviceItemUpdate.asSharedFlow()
 
+    private val mutableShowSeeAllUpdate: MutableStateFlow<Boolean> = MutableStateFlow(false)
+    internal val showSeeAllUpdate
+        get() = mutableShowSeeAllUpdate.asStateFlow()
+
     internal val deviceItemUpdateRequest: SharedFlow<Unit> =
         conflatedCallbackFlow {
                 val listener =
@@ -139,7 +145,8 @@
                     .sort(displayPriority, bluetoothAdapter?.mostRecentlyConnectedDevices)
             // Only emit when the job is not cancelled
             if (isActive) {
-                mutableDeviceItemUpdate.tryEmit(deviceItems)
+                mutableDeviceItemUpdate.tryEmit(deviceItems.take(MAX_DEVICE_ITEM_ENTRY))
+                mutableShowSeeAllUpdate.tryEmit(deviceItems.size > MAX_DEVICE_ITEM_ENTRY)
                 logger.logDeviceFetch(
                     JobStatus.FINISHED,
                     trigger,
@@ -177,5 +184,6 @@
 
     companion object {
         private const val TAG = "DeviceItemInteractor"
+        private const val MAX_DEVICE_ITEM_ENTRY = 3
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt
index d746220..cfd4f50 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt
@@ -264,6 +264,9 @@
             // Keeps the lockout message up-to-date.
             launch { bouncerInteractor.onLockoutStarted.collect { startLockoutCountdown() } }
 
+            // Start already active lockdown if it exists
+            launch { startLockoutCountdown() }
+
             // Listens to relevant bouncer events
             launch {
                 bouncerInteractor.onIncorrectBouncerInput
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index 04c6fa9..040af90 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -19,6 +19,7 @@
 import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
 
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_ACTIONS;
+import static com.android.systemui.Flags.clipboardImageTimeout;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_SHOWN;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_TAPPED;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISSED_OTHER;
@@ -32,7 +33,6 @@
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SWIPE_DISMISSED;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TAP_OUTSIDE;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TIMED_OUT;
-import static com.android.systemui.flags.Flags.CLIPBOARD_IMAGE_TIMEOUT;
 import static com.android.systemui.flags.Flags.CLIPBOARD_SHARED_TRANSITIONS;
 
 import android.animation.Animator;
@@ -288,7 +288,7 @@
         boolean shouldAnimate = !model.dataMatches(mClipboardModel) || wasExiting;
         mClipboardModel = model;
         mClipboardLogger.setClipSource(mClipboardModel.getSource());
-        if (mFeatureFlags.isEnabled(CLIPBOARD_IMAGE_TIMEOUT)) {
+        if (clipboardImageTimeout()) {
             if (shouldAnimate) {
                 reset();
                 mClipboardLogger.setClipSource(mClipboardModel.getSource());
@@ -452,7 +452,7 @@
                     mClipboardLogger.logUnguarded(CLIPBOARD_OVERLAY_EXPANDED_FROM_MINIMIZED);
                     mIsMinimized = false;
                 }
-                if (mFeatureFlags.isEnabled(CLIPBOARD_IMAGE_TIMEOUT)) {
+                if (clipboardImageTimeout()) {
                     setExpandedView(() -> animateIn());
                 } else {
                     setExpandedView();
@@ -522,7 +522,7 @@
                 mInputMonitor.getInputChannel(), Looper.getMainLooper()) {
             @Override
             public void onInputEvent(InputEvent event) {
-                if ((!mFeatureFlags.isEnabled(CLIPBOARD_IMAGE_TIMEOUT) || mShowingUi)
+                if ((!clipboardImageTimeout() || mShowingUi)
                         && event instanceof MotionEvent) {
                     MotionEvent motionEvent = (MotionEvent) event;
                     if (motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) {
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt
index c780aac..6343752 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt
@@ -41,6 +41,8 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 
@@ -85,25 +87,29 @@
      */
     private val nextKeyguardStateInternal =
         combine(
-            keyguardInteractor.isAbleToDream,
-            keyguardInteractor.isKeyguardOccluded,
-            keyguardInteractor.isKeyguardGoingAway,
-        ) { dreaming, occluded, keyguardGoingAway ->
-            if (keyguardGoingAway) {
-                KeyguardState.GONE
-            } else if (occluded && !dreaming) {
-                KeyguardState.OCCLUDED
-            } else if (dreaming) {
-                KeyguardState.DREAMING
-            } else {
-                KeyguardState.LOCKSCREEN
+                keyguardInteractor.isAbleToDream,
+                keyguardInteractor.isKeyguardOccluded,
+                keyguardInteractor.isKeyguardGoingAway,
+                keyguardInteractor.isKeyguardShowing,
+            ) { dreaming, occluded, keyguardGoingAway, keyguardShowing ->
+                if (keyguardGoingAway) {
+                    KeyguardState.GONE
+                } else if (occluded && !dreaming) {
+                    KeyguardState.OCCLUDED
+                } else if (dreaming) {
+                    KeyguardState.DREAMING
+                } else if (keyguardShowing) {
+                    KeyguardState.LOCKSCREEN
+                } else {
+                    null
+                }
             }
-        }
+            .filterNotNull()
 
     private val nextKeyguardState: StateFlow<KeyguardState> =
         combine(
                 repository.nextLockscreenTargetState,
-                nextKeyguardStateInternal,
+                nextKeyguardStateInternal.onStart { emit(KeyguardState.LOCKSCREEN) },
             ) { override, nextState ->
                 override ?: nextState
             }
diff --git a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt
index e4b290d..15a3cbd 100644
--- a/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.display.domain.interactor
 
 import android.companion.virtual.VirtualDeviceManager
-import android.companion.virtual.flags.Flags
 import android.view.Display
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
@@ -155,8 +154,7 @@
     }
 
     private fun isVirtualDeviceOwnedMirrorDisplay(display: Display): Boolean {
-        return Flags.interactiveScreenMirror() &&
-            virtualDeviceManager != null &&
+        return virtualDeviceManager != null &&
             virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(display.displayId)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt
index 9f46846..1dbe83a 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt
@@ -16,7 +16,23 @@
 
 package com.android.systemui.inputdevice.tutorial.data.model
 
-data class DeviceSchedulerInfo(var isLaunched: Boolean = false, var connectTime: Long? = null) {
+import java.time.Instant
+
+data class DeviceSchedulerInfo(
+    var launchTime: Instant? = null,
+    var firstConnectionTime: Instant? = null
+) {
+    constructor(
+        launchTimeSec: Long?,
+        firstConnectionTimeSec: Long?
+    ) : this(
+        launchTimeSec?.let { Instant.ofEpochSecond(it) },
+        firstConnectionTimeSec?.let { Instant.ofEpochSecond(it) }
+    )
+
     val wasEverConnected: Boolean
-        get() = connectTime != null
+        get() = firstConnectionTime != null
+
+    val isLaunched: Boolean
+        get() = launchTime != null
 }
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt
index 36b9ac7..d8d4bd6 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt
@@ -20,7 +20,6 @@
 import androidx.annotation.VisibleForTesting
 import androidx.datastore.core.DataStore
 import androidx.datastore.preferences.core.Preferences
-import androidx.datastore.preferences.core.booleanPreferencesKey
 import androidx.datastore.preferences.core.edit
 import androidx.datastore.preferences.core.longPreferencesKey
 import androidx.datastore.preferences.preferencesDataStore
@@ -28,6 +27,7 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.inputdevice.tutorial.data.model.DeviceSchedulerInfo
+import java.time.Instant
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.first
@@ -43,28 +43,31 @@
     constructor(
         @Application applicationContext: Context,
         @Background backgroundScope: CoroutineScope
-    ) : this(applicationContext, backgroundScope, dataStoreName = "TutorialScheduler")
+    ) : this(applicationContext, backgroundScope, dataStoreName = DATASTORE_NAME)
 
     private val Context.dataStore: DataStore<Preferences> by
         preferencesDataStore(name = dataStoreName, scope = backgroundScope)
 
     suspend fun isLaunched(deviceType: DeviceType): Boolean = loadData()[deviceType]!!.isLaunched
 
+    suspend fun launchTime(deviceType: DeviceType): Instant? = loadData()[deviceType]!!.launchTime
+
     suspend fun wasEverConnected(deviceType: DeviceType): Boolean =
         loadData()[deviceType]!!.wasEverConnected
 
-    suspend fun connectTime(deviceType: DeviceType): Long = loadData()[deviceType]!!.connectTime!!
+    suspend fun firstConnectionTime(deviceType: DeviceType): Instant? =
+        loadData()[deviceType]!!.firstConnectionTime
 
     private suspend fun loadData(): Map<DeviceType, DeviceSchedulerInfo> {
         return applicationContext.dataStore.data.map { pref -> getSchedulerInfo(pref) }.first()
     }
 
-    suspend fun updateConnectTime(device: DeviceType, time: Long) {
-        applicationContext.dataStore.edit { pref -> pref[getConnectKey(device)] = time }
+    suspend fun updateFirstConnectionTime(device: DeviceType, time: Instant) {
+        applicationContext.dataStore.edit { pref -> pref[getConnectKey(device)] = time.epochSecond }
     }
 
-    suspend fun updateLaunch(device: DeviceType) {
-        applicationContext.dataStore.edit { pref -> pref[getLaunchedKey(device)] = true }
+    suspend fun updateLaunchTime(device: DeviceType, time: Instant) {
+        applicationContext.dataStore.edit { pref -> pref[getLaunchKey(device)] = time.epochSecond }
     }
 
     private fun getSchedulerInfo(pref: Preferences): Map<DeviceType, DeviceSchedulerInfo> {
@@ -75,13 +78,13 @@
     }
 
     private fun getDeviceSchedulerInfo(pref: Preferences, device: DeviceType): DeviceSchedulerInfo {
-        val isLaunched = pref[getLaunchedKey(device)] ?: false
-        val connectionTime = pref[getConnectKey(device)] ?: null
-        return DeviceSchedulerInfo(isLaunched, connectionTime)
+        val launchTime = pref[getLaunchKey(device)]
+        val connectionTime = pref[getConnectKey(device)]
+        return DeviceSchedulerInfo(launchTime, connectionTime)
     }
 
-    private fun getLaunchedKey(device: DeviceType) =
-        booleanPreferencesKey(device.name + IS_LAUNCHED_SUFFIX)
+    private fun getLaunchKey(device: DeviceType) =
+        longPreferencesKey(device.name + LAUNCH_TIME_SUFFIX)
 
     private fun getConnectKey(device: DeviceType) =
         longPreferencesKey(device.name + CONNECT_TIME_SUFFIX)
@@ -92,8 +95,9 @@
     }
 
     companion object {
-        const val IS_LAUNCHED_SUFFIX = "_IS_LAUNCHED"
-        const val CONNECT_TIME_SUFFIX = "_CONNECTED_TIME"
+        const val DATASTORE_NAME = "TutorialScheduler"
+        const val LAUNCH_TIME_SUFFIX = "_LAUNCH_TIME"
+        const val CONNECT_TIME_SUFFIX = "_CONNECT_TIME"
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
index b3b8f21..a8d7dad 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
@@ -26,9 +26,11 @@
 import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository
 import com.android.systemui.keyboard.data.repository.KeyboardRepository
 import com.android.systemui.touchpad.data.repository.TouchpadRepository
+import java.time.Duration
 import java.time.Instant
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.hours
+import kotlin.time.toKotlinDuration
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.filter
@@ -84,9 +86,9 @@
     private suspend fun schedule(deviceType: DeviceType) {
         if (!repo.wasEverConnected(deviceType)) {
             waitForDeviceConnection(deviceType)
-            repo.updateConnectTime(deviceType, Instant.now().toEpochMilli())
+            repo.updateFirstConnectionTime(deviceType, Instant.now())
         }
-        delay(remainingTimeMillis(start = repo.connectTime(deviceType)))
+        delay(remainingTime(start = repo.firstConnectionTime(deviceType)!!))
         waitForDeviceConnection(deviceType)
     }
 
@@ -95,9 +97,9 @@
 
     private suspend fun launchTutorial(tutorialType: TutorialType) {
         if (tutorialType == TutorialType.KEYBOARD || tutorialType == TutorialType.BOTH)
-            repo.updateLaunch(KEYBOARD)
+            repo.updateLaunchTime(KEYBOARD, Instant.now())
         if (tutorialType == TutorialType.TOUCHPAD || tutorialType == TutorialType.BOTH)
-            repo.updateLaunch(TOUCHPAD)
+            repo.updateLaunchTime(TOUCHPAD, Instant.now())
         // TODO: launch tutorial
         Log.d(TAG, "Launch tutorial for $tutorialType")
     }
@@ -113,19 +115,21 @@
         return if (deviceType == KEYBOARD) TutorialType.KEYBOARD else TutorialType.TOUCHPAD
     }
 
-    private fun remainingTimeMillis(start: Long): Long {
-        val elapsed = Instant.now().toEpochMilli() - start
-        return LAUNCH_DELAY - elapsed
+    private fun remainingTime(start: Instant): kotlin.time.Duration {
+        val elapsed = Duration.between(start, Instant.now())
+        return LAUNCH_DELAY.minus(elapsed).toKotlinDuration()
     }
 
     companion object {
         const val TAG = "TutorialSchedulerInteractor"
-        private val DEFAULT_LAUNCH_DELAY = 72.hours.inWholeMilliseconds
-        private val LAUNCH_DELAY: Long
+        private val DEFAULT_LAUNCH_DELAY_SEC = 72.hours.inWholeSeconds
+        private val LAUNCH_DELAY: Duration
             get() =
-                SystemProperties.getLong(
-                    "persist.peripheral_tutorial_delay_ms",
-                    DEFAULT_LAUNCH_DELAY
+                Duration.ofSeconds(
+                    SystemProperties.getLong(
+                        "persist.peripheral_tutorial_delay_sec",
+                        DEFAULT_LAUNCH_DELAY_SEC
+                    )
                 )
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/NewPickerUiKeyguardPreview.kt b/packages/SystemUI/src/com/android/systemui/keyguard/NewPickerUiKeyguardPreview.kt
new file mode 100644
index 0000000..7e09a10
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/NewPickerUiKeyguardPreview.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.keyguard
+
+import com.android.systemui.Flags
+
+/** Helper for reading or using the new picker UI flag. */
+@Suppress("NOTHING_TO_INLINE")
+object NewPickerUiKeyguardPreview {
+
+    /** Is the new picker UI enabled */
+    @JvmStatic
+    inline val isEnabled
+        get() = Flags.newPickerUi()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
index 698328e..d49550e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt
@@ -22,7 +22,6 @@
 import android.os.UserHandle
 import android.util.LayoutDirection
 import com.android.systemui.Dumpable
-import com.android.systemui.res.R
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
@@ -35,6 +34,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
 import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation
 import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation
+import com.android.systemui.res.R
 import com.android.systemui.settings.UserTracker
 import java.io.PrintWriter
 import javax.inject.Inject
@@ -61,10 +61,13 @@
     private val remoteUserSelectionManager: KeyguardQuickAffordanceRemoteUserSelectionManager,
     private val userTracker: UserTracker,
     legacySettingSyncer: KeyguardQuickAffordanceLegacySettingSyncer,
-    private val configs: Set<@JvmSuppressWildcards KeyguardQuickAffordanceConfig>,
+    configs: Set<@JvmSuppressWildcards KeyguardQuickAffordanceConfig>,
     dumpManager: DumpManager,
     userHandle: UserHandle,
 ) {
+    // Configs for all keyguard quick affordances, mapped by the quick affordance ID as key
+    private val configsByAffordanceId: Map<String, KeyguardQuickAffordanceConfig> =
+        configs.associateBy { it.key }
     private val userId: Flow<Int> =
         ConflatedCallbackFlow.conflatedCallbackFlow {
             val callback =
@@ -126,7 +129,7 @@
      */
     fun getCurrentSelections(slotId: String): List<KeyguardQuickAffordanceConfig> {
         val selections = selectionManager.value.getSelections().getOrDefault(slotId, emptyList())
-        return configs.filter { selections.contains(it.key) }
+        return configsByAffordanceId.values.filter { selections.contains(it.key) }
     }
 
     /**
@@ -159,7 +162,7 @@
      */
     suspend fun getAffordancePickerRepresentations():
         List<KeyguardQuickAffordancePickerRepresentation> {
-        return configs
+        return configsByAffordanceId.values
             .associateWith { config -> config.getPickerScreenState() }
             .filterNot { (_, pickerState) ->
                 pickerState is KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
@@ -226,6 +229,11 @@
         }
     }
 
+    /** Get the config of a quick affordance. */
+    fun getConfig(quickAffordanceId: String): KeyguardQuickAffordanceConfig? {
+        return configsByAffordanceId[quickAffordanceId]
+    }
+
     private inner class Dumpster : Dumpable {
         override fun dump(pw: PrintWriter, args: Array<out String>) {
             val slotPickerRepresentations = getSlotPickerRepresentations()
@@ -246,7 +254,7 @@
                 pw.println("    $slotId$selectionText (capacity = $capacity)")
             }
             pw.println("Available affordances on device:")
-            configs.forEach { config ->
+            configsByAffordanceId.values.forEach { config ->
                 pw.println("    ${config.key} (\"${config.pickerName()}\")")
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
index 0aa50e0..199caa1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
@@ -37,16 +37,21 @@
 import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
 import com.android.systemui.util.kotlin.BooleanFlowOperators.noneOf
 import com.android.systemui.util.kotlin.BooleanFlowOperators.not
+import com.android.systemui.util.kotlin.Utils.Companion.sampleFilter
 import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlin.time.Duration.Companion.seconds
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.FlowPreview
 import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.debounce
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 
+@OptIn(FlowPreview::class)
 @SysUISingleton
 class FromGlanceableHubTransitionInteractor
 @Inject
@@ -196,19 +201,26 @@
             }
         } else if (communalSceneKtfRefactor()) {
             scope.launch {
-                allOf(
+                combine(
                         keyguardInteractor.isKeyguardOccluded,
-                        noneOf(
-                            // Dream is a special-case of occluded, so filter out the dreaming
-                            // case here.
-                            keyguardInteractor.isDreaming,
-                            // When launching activities from widgets on the hub, we have a
-                            // custom occlusion animation.
-                            communalSceneInteractor.isLaunchingWidget,
-                        ),
+                        keyguardInteractor.isAbleToDream
+                            // Debounce the dreaming signal since there is a race condition between
+                            // the occluded and dreaming signals. We therefore add a small delay
+                            // to give enough time for occluded to flip to false when the dream
+                            // ends, to avoid transitioning to OCCLUDED erroneously when exiting
+                            // the dream.
+                            .debounce(100.milliseconds),
+                        ::Pair
                     )
-                    .filterRelevantKeyguardStateAnd { isOccludedAndNotDreamingNorLaunchingWidget ->
-                        isOccludedAndNotDreamingNorLaunchingWidget
+                    .sampleFilter(
+                        // When launching activities from widgets on the hub, we have a
+                        // custom occlusion animation.
+                        communalSceneInteractor.isLaunchingWidget,
+                    ) { launchingWidget ->
+                        !launchingWidget
+                    }
+                    .filterRelevantKeyguardStateAnd { (isOccluded, isDreaming) ->
+                        isOccluded && !isDreaming
                     }
                     .collect { _ ->
                         communalSceneInteractor.changeScene(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
index 1c445a7..7801c00 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
@@ -17,15 +17,16 @@
 
 package com.android.systemui.keyguard.domain.interactor
 
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
 import com.android.systemui.keyguard.data.repository.KeyguardRepository
 import com.android.systemui.keyguard.shared.model.DismissAction
 import com.android.systemui.keyguard.shared.model.KeyguardDone
-import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER
 import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
+import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.scene.domain.interactor.SceneInteractor
 import com.android.systemui.scene.domain.resolver.NotifShadeSceneFamilyResolver
 import com.android.systemui.scene.domain.resolver.QuickSettingsSceneFamilyResolver
@@ -61,6 +62,8 @@
     deviceEntryInteractor: DeviceEntryInteractor,
     quickSettingsSceneFamilyResolver: QuickSettingsSceneFamilyResolver,
     notifShadeSceneFamilyResolver: NotifShadeSceneFamilyResolver,
+    powerInteractor: PowerInteractor,
+    alternateBouncerInteractor: AlternateBouncerInteractor,
 ) {
     val dismissAction: Flow<DismissAction> = repository.dismissAction
 
@@ -124,10 +127,12 @@
                     scene = Scenes.Bouncer,
                     stateWithoutSceneContainer = PRIMARY_BOUNCER
                 ),
-                transitionInteractor.isFinishedIn(state = ALTERNATE_BOUNCER),
+                alternateBouncerInteractor.isVisible,
                 isOnShadeWhileUnlocked,
-            ) { isOnGone, isOnBouncer, isOnAltBouncer, isOnShadeWhileUnlocked ->
-                !isOnGone && !isOnBouncer && !isOnAltBouncer && !isOnShadeWhileUnlocked
+                powerInteractor.isAsleep,
+            ) { isOnGone, isOnBouncer, isOnAltBouncer, isOnShadeWhileUnlocked, isAsleep ->
+                (!isOnGone && !isOnBouncer && !isOnAltBouncer && !isOnShadeWhileUnlocked) ||
+                    isAsleep
             }
             .filter { it }
             .sampleFilter(dismissAction) { it !is DismissAction.None }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
index 0682d87..2af95f2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -53,6 +53,7 @@
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEYGUARD_QUICK_AFFORDANCE_ID_NONE
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import dagger.Lazy
@@ -142,14 +143,18 @@
      *
      * This is useful for experiences like the lock screen preview mode, where the affordances must
      * always be visible.
+     *
+     * @param overrideQuickAffordanceId If null, return the currently-set quick affordance;
+     *   otherwise, override and return the correspondent [KeyguardQuickAffordanceModel].
      */
     suspend fun quickAffordanceAlwaysVisible(
         position: KeyguardQuickAffordancePosition,
+        overrideQuickAffordanceId: String? = null,
     ): Flow<KeyguardQuickAffordanceModel> {
         return if (isFeatureDisabledByDevicePolicy()) {
             flowOf(KeyguardQuickAffordanceModel.Hidden)
         } else {
-            quickAffordanceInternal(position)
+            quickAffordanceInternal(position, overrideQuickAffordanceId)
         }
     }
 
@@ -299,12 +304,24 @@
     }
 
     private fun quickAffordanceInternal(
-        position: KeyguardQuickAffordancePosition
+        position: KeyguardQuickAffordancePosition,
+        overrideAffordanceId: String? = null,
     ): Flow<KeyguardQuickAffordanceModel> =
         repository
             .get()
             .selections
-            .map { it[position.toSlotId()] ?: emptyList() }
+            .map { selections ->
+                val overrideQuickAffordanceConfigs =
+                    overrideAffordanceId?.let {
+                        if (it == KEYGUARD_QUICK_AFFORDANCE_ID_NONE) {
+                            emptyList()
+                        } else {
+                            val config = repository.get().getConfig(it)
+                            listOfNotNull(config)
+                        }
+                    }
+                overrideQuickAffordanceConfigs ?: selections[position.toSlotId()] ?: emptyList()
+            }
             .flatMapLatest { configs -> combinedConfigs(position, configs) }
 
     private fun combinedConfigs(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancePosition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancePosition.kt
index 2581b59..1bbe843 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancePosition.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancePosition.kt
@@ -16,7 +16,8 @@
 
 package com.android.systemui.keyguard.shared.quickaffordance
 
-import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
+import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END
+import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
 
 /** Enumerates all possible positions for quick affordances that can appear on the lock-screen. */
 enum class KeyguardQuickAffordancePosition {
@@ -25,8 +26,19 @@
 
     fun toSlotId(): String {
         return when (this) {
-            BOTTOM_START -> KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
-            BOTTOM_END -> KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END
+            BOTTOM_START -> SLOT_ID_BOTTOM_START
+            BOTTOM_END -> SLOT_ID_BOTTOM_END
         }
     }
+
+    companion object {
+
+        /** If the slot ID does not match any string, return null. */
+        fun parseKeyguardQuickAffordancePosition(slotId: String): KeyguardQuickAffordancePosition? =
+            when (slotId) {
+                SLOT_ID_BOTTOM_START -> BOTTOM_START
+                SLOT_ID_BOTTOM_END -> BOTTOM_END
+                else -> null
+            }
+    }
 }
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 6031ef6..51ce355 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
@@ -275,6 +275,15 @@
         }
     }
 
+    fun onStartCustomizingQuickAffordances(
+        initiallySelectedSlotId: String?,
+    ) {
+        quickAffordancesCombinedViewModel.enablePreviewMode(
+            initiallySelectedSlotId = initiallySelectedSlotId,
+            shouldHighlightSelectedAffordance = true,
+        )
+    }
+
     fun onSlotSelected(slotId: String) {
         if (KeyguardBottomAreaRefactor.isEnabled) {
             quickAffordancesCombinedViewModel.onPreviewSlotSelected(slotId = slotId)
@@ -283,6 +292,21 @@
         }
     }
 
+    fun onPreviewQuickAffordanceSelected(slotId: String, quickAffordanceId: String) {
+        quickAffordancesCombinedViewModel.onPreviewQuickAffordanceSelected(
+            slotId,
+            quickAffordanceId,
+        )
+    }
+
+    fun onDefaultPreview() {
+        quickAffordancesCombinedViewModel.onClearPreviewQuickAffordances()
+        quickAffordancesCombinedViewModel.enablePreviewMode(
+            initiallySelectedSlotId = null,
+            shouldHighlightSelectedAffordance = false,
+        )
+    }
+
     fun destroy() {
         isDestroyed = true
         lockscreenSmartspaceController.disconnect()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
index 0532ee2..a6108c4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
@@ -31,7 +31,16 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants
+import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_HIDE_SMART_SPACE
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_QUICK_AFFORDANCE_ID
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.KEY_SLOT_ID
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_DEFAULT_PREVIEW
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_HIDE_SMART_SPACE
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_PREVIEW_QUICK_AFFORDANCE_SELECTED
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_SLOT_SELECTED
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants.MESSAGE_ID_START_CUSTOMIZING_QUICK_AFFORDANCES
 import com.android.systemui.util.kotlin.logD
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
@@ -59,7 +68,7 @@
         return try {
             val renderer =
                 if (Flags.lockscreenPreviewRendererCreateOnMainThread()) {
-                    runBlocking ("$TAG#previewRendererFactory.create", mainDispatcher) {
+                    runBlocking("$TAG#previewRendererFactory.create", mainDispatcher) {
                         previewRendererFactory.create(request)
                     }
                 } else {
@@ -157,16 +166,35 @@
         }
 
         when (message.what) {
-            KeyguardPreviewConstants.MESSAGE_ID_SLOT_SELECTED -> {
-                message.data.getString(KeyguardPreviewConstants.KEY_SLOT_ID)?.let { slotId ->
+            MESSAGE_ID_START_CUSTOMIZING_QUICK_AFFORDANCES -> {
+                checkNotNull(renderer)
+                    .onStartCustomizingQuickAffordances(
+                        initiallySelectedSlotId =
+                            message.data.getString(KEY_INITIALLY_SELECTED_SLOT_ID)
+                                ?: SLOT_ID_BOTTOM_START
+                    )
+            }
+            MESSAGE_ID_SLOT_SELECTED -> {
+                message.data.getString(KEY_SLOT_ID)?.let { slotId ->
                     checkNotNull(renderer).onSlotSelected(slotId = slotId)
                 }
             }
-            KeyguardPreviewConstants.MESSAGE_ID_HIDE_SMART_SPACE -> {
-                checkNotNull(renderer)
-                    .hideSmartspace(
-                        message.data.getBoolean(KeyguardPreviewConstants.KEY_HIDE_SMART_SPACE)
-                    )
+            MESSAGE_ID_PREVIEW_QUICK_AFFORDANCE_SELECTED -> {
+                val slotId = message.data.getString(KEY_SLOT_ID)
+                val quickAffordanceId = message.data.getString(KEY_QUICK_AFFORDANCE_ID)
+                if (slotId != null && quickAffordanceId != null) {
+                    checkNotNull(renderer)
+                        .onPreviewQuickAffordanceSelected(
+                            slotId = slotId,
+                            quickAffordanceId = quickAffordanceId,
+                        )
+                }
+            }
+            MESSAGE_ID_DEFAULT_PREVIEW -> {
+                checkNotNull(renderer).onDefaultPreview()
+            }
+            MESSAGE_ID_HIDE_SMART_SPACE -> {
+                checkNotNull(renderer).hideSmartspace(message.data.getBoolean(KEY_HIDE_SMART_SPACE))
             }
             else -> checkNotNull(onDestroy).invoke(this)
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
index 2426f97..c885c9a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
@@ -20,6 +20,7 @@
 import androidx.annotation.VisibleForTesting
 import com.android.app.tracing.FlowTracing.traceEmissionCount
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.NewPickerUiKeyguardPreview
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -29,6 +30,7 @@
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
+import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -164,13 +166,36 @@
             .map { alpha -> alpha >= AFFORDANCE_FULLY_OPAQUE_ALPHA_THRESHOLD }
             .distinctUntilChanged()
 
+    private val previewAffordances =
+        MutableStateFlow<Map<KeyguardQuickAffordancePosition, String>>(emptyMap())
+
     /** An observable for the view-model of the "start button" quick affordance. */
     val startButton: Flow<KeyguardQuickAffordanceViewModel> =
-        button(KeyguardQuickAffordancePosition.BOTTOM_START)
+        if (NewPickerUiKeyguardPreview.isEnabled) {
+            previewAffordances.flatMapLatestConflated {
+                button(
+                    position = KeyguardQuickAffordancePosition.BOTTOM_START,
+                    overrideQuickAffordanceId = it[KeyguardQuickAffordancePosition.BOTTOM_START],
+                )
+            }
+        } else {
+            button(
+                KeyguardQuickAffordancePosition.BOTTOM_START,
+            )
+        }
 
     /** An observable for the view-model of the "end button" quick affordance. */
     val endButton: Flow<KeyguardQuickAffordanceViewModel> =
-        button(KeyguardQuickAffordancePosition.BOTTOM_END)
+        if (NewPickerUiKeyguardPreview.isEnabled) {
+            previewAffordances.flatMapLatestConflated {
+                button(
+                    position = KeyguardQuickAffordancePosition.BOTTOM_END,
+                    overrideQuickAffordanceId = it[KeyguardQuickAffordancePosition.BOTTOM_END],
+                )
+            }
+        } else {
+            button(KeyguardQuickAffordancePosition.BOTTOM_END)
+        }
 
     /**
      * Notifies that a slot with the given ID has been selected in the preview experience that is
@@ -183,6 +208,28 @@
     }
 
     /**
+     * Notifies to preview an affordance at a given slot ID. This is ignored for the real lock
+     * screen experience.
+     */
+    fun onPreviewQuickAffordanceSelected(slotId: String, affordanceId: String) {
+        val position =
+            KeyguardQuickAffordancePosition.parseKeyguardQuickAffordancePosition(slotId) ?: return
+        previewAffordances.value =
+            previewAffordances.value.toMutableMap().let {
+                it[position] = affordanceId
+                HashMap(it)
+            }
+    }
+
+    /**
+     * Notifies to clear up the preview affordances map. This is ignored for the real lock screen
+     * experience.
+     */
+    fun onClearPreviewQuickAffordances() {
+        previewAffordances.value = emptyMap()
+    }
+
+    /**
      * Puts this view-model in "preview mode", which means it's being used for UI that is rendering
      * the lock screen preview in wallpaper picker / settings and not the real experience on the
      * lock screen.
@@ -207,14 +254,16 @@
     }
 
     private fun button(
-        position: KeyguardQuickAffordancePosition
+        position: KeyguardQuickAffordancePosition,
+        overrideQuickAffordanceId: String? = null,
     ): Flow<KeyguardQuickAffordanceViewModel> {
         return previewMode
             .flatMapLatest { previewMode ->
                 combine(
                         if (previewMode.isInPreviewMode) {
                             quickAffordanceInteractor.quickAffordanceAlwaysVisible(
-                                position = position
+                                position = position,
+                                overrideQuickAffordanceId = overrideQuickAffordanceId,
                             )
                         } else {
                             quickAffordanceInteractor.quickAffordance(position = position)
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/BaseActivatable.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/BaseActivatable.kt
new file mode 100644
index 0000000..03476ec
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/BaseActivatable.kt
@@ -0,0 +1,115 @@
+/*
+ * 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.lifecycle
+
+import java.util.concurrent.atomic.AtomicBoolean
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.receiveAsFlow
+import kotlinx.coroutines.launch
+
+/**
+ * A base [Activatable] with the following characteristics:
+ * 1. **Can be concurrently activated by no more than one owner.** A previous call to [activate]
+ *    must be canceled before a new call to [activate] can be made. Trying to call [activate] while
+ *    already active will fail with an error
+ * 2. **Can manage child [Activatable]s**. See [addChild] and [removeChild]. Added children
+ *    automatically track the activation state of the parent such that when the parent is active,
+ *    the children are active and vice-versa. Children are also retained such that deactivating the
+ *    parent and reactivating it also cancels and reactivates the children.
+ */
+abstract class BaseActivatable : Activatable {
+
+    private val _isActive = AtomicBoolean(false)
+
+    var isActive: Boolean
+        get() = _isActive.get()
+        private set(value) {
+            _isActive.set(value)
+        }
+
+    final override suspend fun activate(): Nothing {
+        val allowed = _isActive.compareAndSet(false, true)
+        check(allowed) { "Cannot activate an already active activatable!" }
+
+        coroutineScope {
+            try {
+                launch { manageChildren() }
+                onActivated()
+            } finally {
+                isActive = false
+            }
+        }
+    }
+
+    /**
+     * Notifies that the [Activatable] has been activated.
+     *
+     * Serves as an entrypoint to kick off coroutine work that the object requires in order to keep
+     * its state fresh and/or perform side-effects.
+     *
+     * The method suspends and doesn't return until all work required by the object is finished. In
+     * most cases, it's expected for the work to remain ongoing forever so this method will forever
+     * suspend its caller until the coroutine that called it is canceled.
+     *
+     * Implementations could follow this pattern:
+     * ```kotlin
+     * override suspend fun onActivated(): Nothing {
+     *     coroutineScope {
+     *         launch { ... }
+     *         launch { ... }
+     *         launch { ... }
+     *     }
+     * }
+     * ```
+     *
+     * @see activate
+     */
+    protected abstract suspend fun onActivated(): Nothing
+
+    private val newChildren = Channel<Activatable>(Channel.BUFFERED)
+    private val jobByChild: MutableMap<Activatable, Job> by lazy { mutableMapOf() }
+
+    private suspend fun manageChildren(): Nothing {
+        coroutineScope {
+            // Reactivate children that were added during a previous activation:
+            jobByChild.keys.forEach { child -> jobByChild[child] = launch { child.activate() } }
+
+            // Process requests to add more children:
+            newChildren.receiveAsFlow().collect { newChild ->
+                removeChildInternal(newChild)
+                jobByChild[newChild] = launch { newChild.activate() }
+            }
+
+            awaitCancellation()
+        }
+    }
+
+    fun addChild(child: Activatable) {
+        newChildren.trySend(child)
+    }
+
+    fun removeChild(child: Activatable) {
+        removeChildInternal(child)
+    }
+
+    private fun removeChildInternal(child: Activatable) {
+        jobByChild.remove(child)?.cancel()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt
deleted file mode 100644
index 4dd76f8..0000000
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/SafeActivatable.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.lifecycle
-
-import java.util.concurrent.atomic.AtomicBoolean
-
-/**
- * An [Activatable] that can be concurrently activated by no more than one owner.
- *
- * A previous call to [activate] must be canceled before a new call to [activate] can be made.
- * Trying to call [activate] while already active will fail with an error.
- */
-abstract class SafeActivatable : Activatable {
-
-    private val _isActive = AtomicBoolean(false)
-
-    var isActive: Boolean
-        get() = _isActive.get()
-        private set(value) {
-            _isActive.set(value)
-        }
-
-    final override suspend fun activate(): Nothing {
-        val allowed = _isActive.compareAndSet(false, true)
-        check(allowed) { "Cannot activate an already active activatable!" }
-
-        try {
-            onActivated()
-        } finally {
-            isActive = false
-        }
-    }
-
-    /**
-     * Notifies that the [Activatable] has been activated.
-     *
-     * Serves as an entrypoint to kick off coroutine work that the object requires in order to keep
-     * its state fresh and/or perform side-effects.
-     *
-     * The method suspends and doesn't return until all work required by the object is finished. In
-     * most cases, it's expected for the work to remain ongoing forever so this method will forever
-     * suspend its caller until the coroutine that called it is canceled.
-     *
-     * Implementations could follow this pattern:
-     * ```kotlin
-     * override suspend fun onActivated(): Nothing {
-     *     coroutineScope {
-     *         launch { ... }
-     *         launch { ... }
-     *         launch { ... }
-     *     }
-     * }
-     * ```
-     *
-     * @see activate
-     */
-    protected abstract suspend fun onActivated(): Nothing
-}
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt
index 2edde4a..104b076 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/SysUiViewModel.kt
@@ -23,7 +23,7 @@
 import kotlinx.coroutines.launch
 
 /** Base class for all System UI view-models. */
-abstract class SysUiViewModel : SafeActivatable() {
+abstract class SysUiViewModel : BaseActivatable() {
 
     override suspend fun onActivated(): Nothing {
         awaitCancellation()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java
index 6cf4441..28e4fd0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java
@@ -26,6 +26,8 @@
 import android.content.pm.ServiceInfo;
 import android.os.RemoteException;
 
+import androidx.annotation.Nullable;
+
 import javax.inject.Inject;
 
 // Adapter that wraps calls to PackageManager or IPackageManager for {@link TileLifecycleManager}.
@@ -45,6 +47,7 @@
         mIPackageManager = AppGlobals.getPackageManager();
     }
 
+    @Nullable
     public ServiceInfo getServiceInfo(ComponentName className, int flags, int userId)
             throws RemoteException {
         return mIPackageManager.getServiceInfo(className, flags, userId);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 96df728..cbcf68c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -188,10 +188,10 @@
     public boolean isActiveTile() {
         try {
             ServiceInfo info = mPackageManagerAdapter.getServiceInfo(mIntent.getComponent(),
-                    META_DATA_QUERY_FLAGS);
-            return info.metaData != null
+                    META_DATA_QUERY_FLAGS, mUser.getIdentifier());
+            return info != null && info.metaData != null
                     && info.metaData.getBoolean(TileService.META_DATA_ACTIVE_TILE, false);
-        } catch (PackageManager.NameNotFoundException e) {
+        } catch (RemoteException e) {
             return false;
         }
     }
@@ -206,10 +206,10 @@
     public boolean isToggleableTile() {
         try {
             ServiceInfo info = mPackageManagerAdapter.getServiceInfo(mIntent.getComponent(),
-                    META_DATA_QUERY_FLAGS);
-            return info.metaData != null
+                    META_DATA_QUERY_FLAGS, mUser.getIdentifier());
+            return info != null && info.metaData != null
                     && info.metaData.getBoolean(TileService.META_DATA_TOGGLEABLE_TILE, false);
-        } catch (PackageManager.NameNotFoundException e) {
+        } catch (RemoteException e) {
             return false;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepository.kt
index c932cee..0aaea8f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepository.kt
@@ -17,8 +17,8 @@
 package com.android.systemui.qs.tiles.impl.custom.data.repository
 
 import android.content.pm.PackageManager
-import android.content.pm.ServiceInfo
 import android.graphics.drawable.Icon
+import android.os.RemoteException
 import android.os.UserHandle
 import android.service.quicksettings.Tile
 import android.service.quicksettings.TileService
@@ -163,13 +163,14 @@
     override suspend fun isTileActive(): Boolean =
         withContext(backgroundContext) {
             try {
-                val info: ServiceInfo =
+                val info =
                     packageManagerAdapter.getServiceInfo(
                         tileSpec.componentName,
-                        META_DATA_QUERY_FLAGS
+                        META_DATA_QUERY_FLAGS,
+                        getCurrentTileWithUser()?.user?.identifier ?: UserHandle.USER_CURRENT,
                     )
-                info.metaData?.getBoolean(TileService.META_DATA_ACTIVE_TILE, false) == true
-            } catch (e: PackageManager.NameNotFoundException) {
+                info?.metaData?.getBoolean(TileService.META_DATA_ACTIVE_TILE, false) == true
+            } catch (e: RemoteException) {
                 false
             }
         }
@@ -177,13 +178,14 @@
     override suspend fun isTileToggleable(): Boolean =
         withContext(backgroundContext) {
             try {
-                val info: ServiceInfo =
+                val info =
                     packageManagerAdapter.getServiceInfo(
                         tileSpec.componentName,
-                        META_DATA_QUERY_FLAGS
+                        META_DATA_QUERY_FLAGS,
+                        getCurrentTileWithUser()?.user?.identifier ?: UserHandle.USER_CURRENT
                     )
-                info.metaData?.getBoolean(TileService.META_DATA_TOGGLEABLE_TILE, false) == true
-            } catch (e: PackageManager.NameNotFoundException) {
+                info?.metaData?.getBoolean(TileService.META_DATA_TOGGLEABLE_TILE, false) == true
+            } catch (e: RemoteException) {
                 false
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index e73664d..cc46216 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -152,7 +152,7 @@
             hydrateBackStack()
             resetShadeSessions()
             handleKeyguardEnabledness()
-            notifyKeyguardDismissCallbacks()
+            notifyKeyguardDismissCancelledCallbacks()
             refreshLockscreenEnabled()
         } else {
             sceneLogger.logFrameworkEnabled(
@@ -379,8 +379,10 @@
                     when {
                         isAlternateBouncerVisible -> {
                             // When the device becomes unlocked when the alternate bouncer is
-                            // showing, always hide the alternate bouncer...
+                            // showing, always hide the alternate bouncer and notify dismiss
+                            // succeeded
                             alternateBouncerInteractor.hide()
+                            dismissCallbackRegistry.notifyDismissSucceeded()
 
                             // ... and go to Gone or stay on the current scene
                             if (
@@ -394,9 +396,11 @@
                                 null
                             }
                         }
-                        isOnPrimaryBouncer ->
+                        isOnPrimaryBouncer -> {
                             // When the device becomes unlocked in primary Bouncer,
+                            // notify dismiss succeeded and
                             // go to previous scene or Gone.
+                            dismissCallbackRegistry.notifyDismissSucceeded()
                             if (
                                 previousScene.value == Scenes.Lockscreen ||
                                     !statusBarStateController.leaveOpenOnKeyguardHide()
@@ -410,6 +414,7 @@
                                     "device was unlocked with primary bouncer showing," +
                                         " from sceneKey=$prevScene"
                             }
+                        }
                         isOnLockscreen ->
                             // The lockscreen should be dismissed automatically in 2 scenarios:
                             // 1. When face auth bypass is enabled and authentication happens while
@@ -468,6 +473,9 @@
         applicationScope.launch {
             powerInteractor.isAsleep.collect { isAsleep ->
                 if (isAsleep) {
+                    alternateBouncerInteractor.hide()
+                    dismissCallbackRegistry.notifyDismissCancelled()
+
                     switchToScene(
                         targetSceneKey = Scenes.Lockscreen,
                         loggingReason = "device is starting to sleep",
@@ -771,15 +779,23 @@
         }
     }
 
-    private fun notifyKeyguardDismissCallbacks() {
+    private fun notifyKeyguardDismissCancelledCallbacks() {
         applicationScope.launch {
-            sceneInteractor.currentScene.pairwise().collect { (from, to) ->
-                when {
-                    from != Scenes.Bouncer -> Unit
-                    to == Scenes.Gone -> dismissCallbackRegistry.notifyDismissSucceeded()
-                    else -> dismissCallbackRegistry.notifyDismissCancelled()
+            combine(
+                    deviceEntryInteractor.isUnlocked,
+                    sceneInteractor.currentScene.pairwise(),
+                ) { isUnlocked, (from, to) ->
+                    when {
+                        from != Scenes.Bouncer -> false
+                        to != Scenes.Gone && !isUnlocked -> true
+                        else -> false
+                    }
                 }
-            }
+                .collect { notifyKeyguardDismissCancelled ->
+                    if (notifyKeyguardDismissCancelled) {
+                        dismissCallbackRegistry.notifyDismissCancelled()
+                    }
+                }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 65a59f5..c023b83 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -4536,6 +4536,13 @@
     private final class StatusBarStateListener implements StateListener {
         @Override
         public void onStateChanged(int statusBarState) {
+            onStateChanged(statusBarState, false);
+        }
+
+        private void onStateChanged(
+                int statusBarState,
+                boolean animatingUnlockedShadeToKeyguardBypass
+        ) {
             boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
             boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway();
             int oldState = mBarState;
@@ -4607,15 +4614,14 @@
                 //  - getting notified again about the current SHADE or KEYGUARD state
                 final boolean animatingUnlockedShadeToKeyguard = oldState == SHADE
                         && statusBarState == KEYGUARD
-                        && mScreenOffAnimationController.isKeyguardShowDelayed();
+                        && mScreenOffAnimationController.isKeyguardShowDelayed()
+                        //Bypasses animatingUnlockedShadeToKeyguard for b/337742708
+                        && !animatingUnlockedShadeToKeyguardBypass;
                 if (!animatingUnlockedShadeToKeyguard) {
                     // Only make the status bar visible if we're not animating the screen off, since
                     // we only want to be showing the clock/notifications during the animation.
-                    if (keyguardShowing) {
-                        mShadeLog.v("Updating keyguard status bar state to visible");
-                    } else {
-                        mShadeLog.v("Updating keyguard status bar state to invisible");
-                    }
+                    mShadeLog.logKeyguardStatudBarVisibiliy(keyguardShowing, isOnAod(),
+                            animatingUnlockedShadeToKeyguardBypass, oldState, statusBarState);
                     mKeyguardStatusBarViewController.updateViewState(
                             /* alpha= */ 1f,
                             keyguardShowing ? View.VISIBLE : View.INVISIBLE);
@@ -4692,7 +4698,8 @@
                     .addTagListener(QS.TAG, mQsController.getQsFragmentListener());
             if (!SceneContainerFlag.isEnabled()) {
                 mStatusBarStateController.addCallback(mStatusBarStateListener);
-                mStatusBarStateListener.onStateChanged(mStatusBarStateController.getState());
+                // Bypass animatingUnlockedShadeToKeyguard in onStateChanged for b/337742708
+                mStatusBarStateListener.onStateChanged(mStatusBarStateController.getState(), true);
             }
             mConfigurationController.addCallback(mConfigurationListener);
             // Theme might have changed between inflating this view and attaching it to the
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
index 66a310c..f1eaec8 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
@@ -411,4 +411,29 @@
             }
         )
     }
+
+    fun logKeyguardStatudBarVisibiliy(
+        visibility: Boolean,
+        isOnAod: Boolean,
+        animatingUnlockedShadeToKeyguardBypass: Boolean,
+        oldShadeState: Int,
+        newShadeState: Int,
+    ) {
+        buffer.log(
+            TAG,
+            LogLevel.VERBOSE,
+            {
+                bool1 = visibility
+                bool2 = isOnAod
+                bool3 = animatingUnlockedShadeToKeyguardBypass
+                int1 = oldShadeState
+                int2 = newShadeState
+            },
+            {
+                "Setting keyguard status bar visibility to: $bool1, isOnAod: $bool2" +
+                    "oldShadeState: $int1, newShadeState: $int2," +
+                    "animatingUnlockedShadeToKeyguardBypass: $bool3"
+            }
+        )
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
index c4f539a..408fc6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/OWNERS
@@ -13,4 +13,12 @@
 per-file *Keyboard* = set noparent
 per-file *Keyboard* = file:../keyguard/OWNERS
 per-file *Keyguard* = set noparent
-per-file *Keyguard* = file:../keyguard/OWNERS
\ No newline at end of file
+per-file *Keyguard* = file:../keyguard/OWNERS
+per-file *Notification* = set noparent
+per-file *Notification* = file:notification/OWNERS
+per-file *Mode* = set noparent
+per-file *Mode* = file:notification/OWNERS
+per-file *RemoteInput* = set noparent
+per-file *RemoteInput* = file:notification/OWNERS
+per-file *EmptyShadeView* = set noparent
+per-file *EmptyShadeView* = file:notification/OWNERS
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollection.java
index fc7d682..0d209d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollection.java
@@ -27,9 +27,6 @@
 /**
  * A notification collection that manages the list of {@link NotificationEntry}s that will be
  * rendered.
- *
- * TODO: (b/145659174) Once we fully migrate to {@link NotifPipeline}, we probably won't need this,
- * but having it for now makes it easy to switch between the two.
  */
 public interface CommonNotifCollection {
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 20b1fff..e802076 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -258,7 +258,7 @@
     private float mOverScrolledBottomPixels;
     private final ListenerSet<Runnable> mStackHeightChangedListeners = new ListenerSet<>();
     private final ListenerSet<Runnable> mHeadsUpHeightChangedListeners = new ListenerSet<>();
-    private NotificationLogger.OnChildLocationsChangedListener mListener;
+    private NotificationLogger.OnChildLocationsChangedListener mLegacyLocationsChangedListener;
     private OnNotificationLocationsChangedListener mLocationsChangedListener;
     private OnOverscrollTopChangedListener mOverscrollTopChangedListener;
     private ExpandableView.OnHeightChangedListener mOnHeightChangedListener;
@@ -1281,7 +1281,7 @@
     public void setChildLocationsChangedListener(
             NotificationLogger.OnChildLocationsChangedListener listener) {
         NotificationsLiveDataStoreRefactor.assertInLegacyMode();
-        mListener = listener;
+        mLegacyLocationsChangedListener = listener;
     }
 
     private void setMaxLayoutHeight(int maxLayoutHeight) {
@@ -4433,8 +4433,8 @@
                 mLocationsChangedListener.onChildLocationsChanged(collectVisibleLocationsCallable);
             }
         } else {
-            if (mListener != null) {
-                mListener.onChildLocationsChanged();
+            if (mLegacyLocationsChangedListener != null) {
+                mLegacyLocationsChangedListener.onChildLocationsChanged();
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index de4d14d..0f93ff2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -545,6 +545,7 @@
 
     @VisibleForTesting
     void consumeFromAlternateBouncerTransitionSteps(TransitionStep step) {
+        SceneContainerFlag.assertInLegacyMode();
         hideAlternateBouncer(false);
     }
 
@@ -554,6 +555,7 @@
      */
     @VisibleForTesting
     void consumeKeyguardAuthenticatedBiometricsHandled(Unit handled) {
+        SceneContainerFlag.assertInLegacyMode();
         if (mAlternateBouncerInteractor.isVisibleState()) {
             hideAlternateBouncer(false);
         }
@@ -981,7 +983,7 @@
             } else {
                 showBouncerOrKeyguard(hideBouncerWhenShowing, isFalsingReset);
             }
-            if (hideBouncerWhenShowing) {
+            if (!SceneContainerFlag.isEnabled() && hideBouncerWhenShowing) {
                 hideAlternateBouncer(true);
             }
             mKeyguardUpdateManager.sendKeyguardReset();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt
index 4f7749b..e1dcc52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt
@@ -21,7 +21,11 @@
 import android.util.Log
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.testTagsAsResourceId
 import androidx.lifecycle.DefaultLifecycleObserver
 import androidx.lifecycle.LifecycleOwner
 import com.android.compose.PlatformButton
@@ -88,7 +92,15 @@
     @Composable
     private fun ModesDialogContent(dialog: SystemUIDialog) {
         AlertDialogContent(
-            title = { Text(stringResource(R.string.zen_modes_dialog_title)) },
+            modifier = Modifier.semantics {
+                testTagsAsResourceId = true
+            },
+            title = {
+                Text(
+                    modifier = Modifier.testTag("modes_title"),
+                    text = stringResource(R.string.zen_modes_dialog_title)
+                )
+            },
             content = { ModeTileGrid(viewModel.get()) },
             neutralButton = {
                 PlatformOutlinedButton(onClick = { openSettings(dialog) }) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
index 3b392c8..3fffd9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
@@ -32,6 +32,7 @@
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.unit.dp
 import com.android.systemui.common.ui.compose.Icon
@@ -70,12 +71,12 @@
                     Text(
                         viewModel.text,
                         fontWeight = FontWeight.W500,
-                        modifier = Modifier.tileMarquee()
+                        modifier = Modifier.tileMarquee().testTag("name")
                     )
                     Text(
                         viewModel.subtext,
                         fontWeight = FontWeight.W400,
-                        modifier = Modifier.tileMarquee()
+                        modifier = Modifier.tileMarquee().testTag("state")
                     )
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/FlowDumper.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/FlowDumper.kt
index ef9f8ff..ae0061b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/FlowDumper.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/FlowDumper.kt
@@ -19,7 +19,7 @@
 import android.util.IndentingPrintWriter
 import com.android.systemui.Dumpable
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.lifecycle.SafeActivatable
+import com.android.systemui.lifecycle.BaseActivatable
 import com.android.systemui.lifecycle.SysUiViewModel
 import com.android.systemui.util.asIndenting
 import com.android.systemui.util.printCollection
@@ -189,7 +189,7 @@
 ) : SimpleFlowDumper(), ActivatableFlowDumper {
 
     private val registration =
-        object : SafeActivatable() {
+        object : BaseActivatable() {
             override suspend fun onActivated(): Nothing {
                 try {
                     dumpManager.registerCriticalDumpable(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
index fa40059..0451ce6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
@@ -19,6 +19,7 @@
 import android.media.AudioDeviceInfo
 import android.media.AudioManager
 import com.android.settingslib.volume.data.repository.AudioRepository
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
 import com.android.settingslib.volume.shared.model.AudioStream
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
@@ -42,6 +43,7 @@
     @VolumePanelScope scope: CoroutineScope,
     mediaOutputInteractor: MediaOutputInteractor,
     audioRepository: AudioRepository,
+    audioModeInteractor: AudioModeInteractor,
 ) {
 
     val volumePanelSliders: StateFlow<List<SliderType>> =
@@ -49,9 +51,14 @@
                 mediaOutputInteractor.activeMediaDeviceSessions,
                 mediaOutputInteractor.defaultActiveMediaSession.filterData(),
                 audioRepository.communicationDevice,
-            ) { activeSessions, defaultSession, communicationDevice ->
+                audioModeInteractor.isOngoingCall,
+            ) { activeSessions, defaultSession, communicationDevice, isOngoingCall ->
                 coroutineScope {
                     val viewModels = buildList {
+                        if (isOngoingCall) {
+                            addCall(communicationDevice?.type)
+                        }
+
                         if (defaultSession?.isTheSameSession(activeSessions.remote) == true) {
                             addSession(activeSessions.remote)
                             addStream(AudioManager.STREAM_MUSIC)
@@ -60,11 +67,10 @@
                             addSession(activeSessions.remote)
                         }
 
-                        if (communicationDevice?.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
-                            addStream(AudioManager.STREAM_BLUETOOTH_SCO)
-                        } else {
-                            addStream(AudioManager.STREAM_VOICE_CALL)
+                        if (!isOngoingCall) {
+                            addCall(communicationDevice?.type)
                         }
+
                         addStream(AudioManager.STREAM_RING)
                         addStream(AudioManager.STREAM_NOTIFICATION)
                         addStream(AudioManager.STREAM_ALARM)
@@ -74,6 +80,14 @@
             }
             .stateIn(scope, SharingStarted.Eagerly, emptyList())
 
+    private fun MutableList<SliderType>.addCall(communicationDeviceType: Int?) {
+        if (communicationDeviceType == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
+            addStream(AudioManager.STREAM_BLUETOOTH_SCO)
+        } else {
+            addStream(AudioManager.STREAM_VOICE_CALL)
+        }
+    }
+
     private fun MutableList<SliderType>.addSession(remoteMediaDeviceSession: MediaDeviceSession?) {
         if (remoteMediaDeviceSession?.canAdjustVolume == true) {
             add(SliderType.MediaDeviceCast(remoteMediaDeviceSession))
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
index 4b4d69a..45732de 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.volume.panel.component.volume.ui.viewmodel
 
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
 import com.android.settingslib.volume.shared.model.AudioStream
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
@@ -35,9 +36,11 @@
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
@@ -58,24 +61,31 @@
     mediaDeviceSessionInteractor: MediaDeviceSessionInteractor,
     private val streamSliderViewModelFactory: AudioStreamSliderViewModel.Factory,
     private val castVolumeSliderViewModelFactory: CastVolumeSliderViewModel.Factory,
+    audioModeInteractor: AudioModeInteractor,
     streamsInteractor: AudioSlidersInteractor,
 ) {
 
     private val mutableIsExpanded = MutableStateFlow<Boolean?>(null)
-    private val isPlaybackActive: Flow<Boolean?> =
-        mediaOutputInteractor.defaultActiveMediaSession
-            .filterData()
-            .flatMapLatest { session ->
-                if (session == null) {
-                    flowOf(false)
-                } else {
-                    mediaDeviceSessionInteractor.playbackState(session).map { it?.isActive == true }
-                }
+    private val isActive: Flow<Boolean?> =
+        combine(
+                audioModeInteractor.isOngoingCall,
+                mediaOutputInteractor.defaultActiveMediaSession.filterData().flatMapLatest { session
+                    ->
+                    if (session == null) {
+                        flowOf(false)
+                    } else {
+                        mediaDeviceSessionInteractor.playbackState(session).map {
+                            it?.isActive == true
+                        }
+                    }
+                },
+            ) { isOngoingCall, isPlaybackActive ->
+                isOngoingCall || isPlaybackActive
             }
-            .onEach { isPlaybackActive -> mutableIsExpanded.value = !isPlaybackActive }
             .stateIn(scope, SharingStarted.Eagerly, null)
+
     private val portraitExpandable: Flow<SlidersExpandableViewModel> =
-        isPlaybackActive
+        isActive
             .filterNotNull()
             .flatMapLatest { isActive ->
                 if (isActive) {
@@ -105,6 +115,10 @@
             }
             .stateIn(scope, SharingStarted.Eagerly, emptyList())
 
+    init {
+        isActive.filterNotNull().onEach { mutableIsExpanded.value = !it }.launchIn(scope)
+    }
+
     fun isExpandable(isPortrait: Boolean): Flow<SlidersExpandableViewModel> {
         return if (isPortrait) {
             portraitExpandable
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index 45799b2..7385b82 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -115,7 +115,6 @@
     private final Executor mSysuiUiBgExecutor;
 
     private final Bubbles.SysuiProxy mSysuiProxy;
-    // TODO (b/145659174): allow for multiple callbacks to support the "shadow" new notif pipeline
     private final List<NotifCallback> mCallbacks = new ArrayList<>();
     private final StatusBarWindowCallback mStatusBarWindowCallback;
     private final Runnable mSensitiveStateChangedListener;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
index 5ff3915..113a8c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
@@ -45,6 +45,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
 import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.settings.FakeDisplayTracker;
 import com.android.systemui.util.settings.SecureSettings;
 
@@ -90,6 +91,8 @@
     private SecureSettings mSecureSettings;
     @Mock
     private Lazy<ViewCapture> mLazyViewCapture;
+    @Mock
+    private NavigationModeController mNavigationModeController;
 
     @Before
     public void setUp() throws Exception {
@@ -163,7 +166,8 @@
         enableAccessibilityFloatingMenuConfig();
         mController = setUpController();
         mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager,
-                mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings);
+                mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings,
+                mNavigationModeController);
         captureKeyguardUpdateMonitorCallback();
         mKeyguardCallback.onUserUnlocked();
 
@@ -190,7 +194,8 @@
         enableAccessibilityFloatingMenuConfig();
         mController = setUpController();
         mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager,
-                mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings);
+                mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings,
+                mNavigationModeController);
         captureKeyguardUpdateMonitorCallback();
 
         mKeyguardCallback.onUserSwitching(fakeUserId);
@@ -204,7 +209,8 @@
         enableAccessibilityFloatingMenuConfig();
         mController = setUpController();
         mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager,
-                mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings);
+                mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings,
+                mNavigationModeController);
         captureKeyguardUpdateMonitorCallback();
         mKeyguardCallback.onUserUnlocked();
         mKeyguardCallback.onKeyguardVisibilityChanged(true);
@@ -340,7 +346,7 @@
                 new AccessibilityFloatingMenuController(mContextWrapper, windowManager,
                         viewCaptureAwareWindowManager, displayManager, mAccessibilityManager,
                         mTargetsObserver, mModeObserver, mKeyguardUpdateMonitor, mSecureSettings,
-                        displayTracker);
+                        displayTracker, mNavigationModeController);
         controller.init();
 
         return controller;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java
index c5509ac..157cccc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java
@@ -44,6 +44,7 @@
 import com.android.systemui.Flags;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.accessibility.utils.TestUtils;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.res.R;
 import com.android.systemui.util.settings.SecureSettings;
 
@@ -94,7 +95,8 @@
         mMenuViewLayer = spy(new MenuViewLayer(
                 mContext, stubWindowManager, mAccessibilityManager,
                 stubMenuViewModel, stubMenuViewAppearance, mMenuView,
-                mock(IAccessibilityFloatingMenu.class), mSecureSettings));
+                mock(IAccessibilityFloatingMenu.class), mSecureSettings,
+                mock(NavigationModeController.class)));
         doNothing().when(mMenuViewLayer).gotoEditScreen();
 
         doReturn(mDraggableBounds).when(mMenuView).getMenuDraggableBounds();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java
index 07ce7b9..fcdeff9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java
@@ -21,6 +21,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -41,6 +42,7 @@
 import com.android.app.viewcapture.ViewCapture;
 import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.util.settings.SecureSettings;
 
 import kotlin.Lazy;
@@ -90,7 +92,8 @@
         when(mWindowMetrics.getBounds()).thenReturn(new Rect(0, 0, 1080, 2340));
         when(mWindowMetrics.getWindowInsets()).thenReturn(stubDisplayInsets());
         mMenuViewLayerController = new MenuViewLayerController(mContext, mWindowManager,
-                viewCaptureAwareWm, mAccessibilityManager, mSecureSettings);
+                viewCaptureAwareWm, mAccessibilityManager, mSecureSettings,
+                mock(NavigationModeController.class));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
index e1e6139..c451c32 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
@@ -81,6 +81,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.SysuiTestableContext;
 import com.android.systemui.accessibility.utils.TestUtils;
+import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.res.R;
 import com.android.systemui.util.settings.SecureSettings;
 import com.android.wm.shell.shared.magnetictarget.MagnetizedObject;
@@ -169,7 +170,7 @@
 
         mMenuViewLayer = spy(new MenuViewLayer(mSpyContext, mStubWindowManager,
                 mStubAccessibilityManager, mMenuViewModel, menuViewAppearance, mMenuView,
-                mFloatingMenu, mSecureSettings));
+                mFloatingMenu, mSecureSettings, mock(NavigationModeController.class)));
         mMenuAnimationController = mMenuView.getMenuAnimationController();
 
         doNothing().when(mSpyContext).startActivity(any());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorKosmos.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorKosmos.kt
new file mode 100644
index 0000000..969e26a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorKosmos.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.bluetooth.qsdialog
+
+import com.android.systemui.bluetooth.bluetoothAdapter
+import com.android.systemui.concurrency.fakeExecutor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testDispatcher
+import org.mockito.kotlin.mock
+
+val Kosmos.deviceItemInteractor: DeviceItemInteractor by
+    Kosmos.Fixture { mock<DeviceItemInteractor>() }
+
+val Kosmos.bluetoothDeviceMetadataInteractor by
+    Kosmos.Fixture {
+        BluetoothDeviceMetadataInteractor(
+            deviceItemInteractor,
+            bluetoothAdapter,
+            bluetoothTileDialogLogger,
+            fakeExecutor,
+            testDispatcher,
+        )
+    }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorTest.kt
new file mode 100644
index 0000000..f06b105
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDeviceMetadataInteractorTest.kt
@@ -0,0 +1,226 @@
+/*
+ * 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.bluetooth.qsdialog
+
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothDevice
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bluetooth.bluetoothAdapter
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.never
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class BluetoothDeviceMetadataInteractorTest : SysuiTestCase() {
+    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+    private val kosmos = testKosmos().apply { testDispatcher = UnconfinedTestDispatcher() }
+
+    private val deviceItemUpdate: MutableSharedFlow<List<DeviceItem>> = MutableSharedFlow()
+    @Mock private lateinit var cachedDevice1: CachedBluetoothDevice
+    @Mock private lateinit var bluetoothDevice1: BluetoothDevice
+    @Mock private lateinit var cachedDevice2: CachedBluetoothDevice
+    @Mock private lateinit var bluetoothDevice2: BluetoothDevice
+    @Captor
+    private lateinit var argumentCaptor: ArgumentCaptor<BluetoothAdapter.OnMetadataChangedListener>
+    private lateinit var interactor: BluetoothDeviceMetadataInteractor
+
+    @Before
+    fun setUp() {
+        with(kosmos) {
+            whenever(deviceItemInteractor.deviceItemUpdate).thenReturn(deviceItemUpdate)
+
+            whenever(cachedDevice1.device).thenReturn(bluetoothDevice1)
+            whenever(cachedDevice1.name).thenReturn(DEVICE_NAME)
+            whenever(cachedDevice1.address).thenReturn(DEVICE_ADDRESS)
+            whenever(cachedDevice1.connectionSummary).thenReturn(CONNECTION_SUMMARY)
+            whenever(bluetoothDevice1.address).thenReturn(DEVICE_ADDRESS)
+
+            whenever(cachedDevice2.device).thenReturn(bluetoothDevice2)
+            whenever(cachedDevice2.name).thenReturn(DEVICE_NAME)
+            whenever(cachedDevice2.address).thenReturn(DEVICE_ADDRESS)
+            whenever(cachedDevice2.connectionSummary).thenReturn(CONNECTION_SUMMARY)
+            whenever(bluetoothDevice2.address).thenReturn(DEVICE_ADDRESS)
+
+            interactor = bluetoothDeviceMetadataInteractor
+        }
+    }
+
+    @Test
+    fun deviceItemUpdateEmpty_doNothing() {
+        with(kosmos) {
+            testScope.runTest {
+                val update by collectLastValue(interactor.metadataUpdate)
+                deviceItemUpdate.emit(emptyList())
+                runCurrent()
+
+                assertThat(update).isNull()
+                verify(bluetoothAdapter, never()).addOnMetadataChangedListener(any(), any(), any())
+                verify(bluetoothAdapter, never()).removeOnMetadataChangedListener(any(), any())
+            }
+        }
+    }
+
+    @Test
+    fun deviceItemUpdate_registerListener() {
+        with(kosmos) {
+            testScope.runTest {
+                val deviceItem = AvailableMediaDeviceItemFactory().create(context, cachedDevice1)
+                val update by collectLastValue(interactor.metadataUpdate)
+                deviceItemUpdate.emit(listOf(deviceItem))
+                runCurrent()
+
+                assertThat(update).isNull()
+                verify(bluetoothAdapter)
+                    .addOnMetadataChangedListener(eq(bluetoothDevice1), any(), any())
+                verify(bluetoothAdapter, never()).removeOnMetadataChangedListener(any(), any())
+            }
+        }
+    }
+
+    @Test
+    fun deviceItemUpdate_sameDeviceItems_registerListenerOnce() {
+        with(kosmos) {
+            testScope.runTest {
+                val deviceItem = AvailableMediaDeviceItemFactory().create(context, cachedDevice1)
+                val update by collectLastValue(interactor.metadataUpdate)
+                deviceItemUpdate.emit(listOf(deviceItem))
+                deviceItemUpdate.emit(listOf(deviceItem))
+                runCurrent()
+
+                assertThat(update).isNull()
+                verify(bluetoothAdapter)
+                    .addOnMetadataChangedListener(eq(bluetoothDevice1), any(), any())
+                verify(bluetoothAdapter, never()).removeOnMetadataChangedListener(any(), any())
+            }
+        }
+    }
+
+    @Test
+    fun deviceItemUpdate_differentDeviceItems_unregisterOldAndRegisterNew() {
+        with(kosmos) {
+            testScope.runTest {
+                val deviceItem1 = AvailableMediaDeviceItemFactory().create(context, cachedDevice1)
+                val deviceItem2 = AvailableMediaDeviceItemFactory().create(context, cachedDevice2)
+                val update by collectLastValue(interactor.metadataUpdate)
+                deviceItemUpdate.emit(listOf(deviceItem1))
+                deviceItemUpdate.emit(listOf(deviceItem1, deviceItem2))
+                runCurrent()
+
+                assertThat(update).isNull()
+                verify(bluetoothAdapter, times(2))
+                    .addOnMetadataChangedListener(eq(bluetoothDevice1), any(), any())
+                verify(bluetoothAdapter)
+                    .addOnMetadataChangedListener(eq(bluetoothDevice2), any(), any())
+                verify(bluetoothAdapter)
+                    .removeOnMetadataChangedListener(eq(bluetoothDevice1), any())
+            }
+        }
+    }
+
+    @Test
+    fun metadataUpdate_triggerCallback_emit() {
+        with(kosmos) {
+            testScope.runTest {
+                val deviceItem = AvailableMediaDeviceItemFactory().create(context, cachedDevice1)
+                val update by collectLastValue(interactor.metadataUpdate)
+                deviceItemUpdate.emit(listOf(deviceItem))
+                runCurrent()
+
+                assertThat(update).isNull()
+                verify(bluetoothAdapter)
+                    .addOnMetadataChangedListener(
+                        eq(bluetoothDevice1),
+                        any(),
+                        argumentCaptor.capture()
+                    )
+
+                val listener = argumentCaptor.value
+                listener.onMetadataChanged(
+                    bluetoothDevice1,
+                    BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY,
+                    ByteArray(0)
+                )
+                assertThat(update).isEqualTo(Unit)
+            }
+        }
+    }
+
+    @Test
+    fun metadataUpdate_triggerCallbackNonBatteryKey_doNothing() {
+        with(kosmos) {
+            testScope.runTest {
+                val deviceItem = AvailableMediaDeviceItemFactory().create(context, cachedDevice1)
+                val update by collectLastValue(interactor.metadataUpdate)
+                deviceItemUpdate.emit(listOf(deviceItem))
+                runCurrent()
+
+                assertThat(update).isNull()
+                verify(bluetoothAdapter)
+                    .addOnMetadataChangedListener(
+                        eq(bluetoothDevice1),
+                        any(),
+                        argumentCaptor.capture()
+                    )
+
+                val listener = argumentCaptor.value
+                listener.onMetadataChanged(
+                    bluetoothDevice1,
+                    BluetoothDevice.METADATA_MODEL_NAME,
+                    ByteArray(0)
+                )
+
+                assertThat(update).isNull()
+            }
+        }
+    }
+
+    companion object {
+        private const val DEVICE_NAME = "DeviceName"
+        private const val CONNECTION_SUMMARY = "ConnectionSummary"
+        private const val DEVICE_ADDRESS = "04:52:C7:0B:D8:3C"
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt
index 9abb85d..d7bea66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogViewModelTest.kt
@@ -77,6 +77,8 @@
 
     @Mock private lateinit var audioSharingInteractor: AudioSharingInteractor
 
+    @Mock private lateinit var bluetoothDeviceMetadataInteractor: BluetoothDeviceMetadataInteractor
+
     @Mock private lateinit var deviceItemInteractor: DeviceItemInteractor
 
     @Mock private lateinit var deviceItemActionInteractor: DeviceItemActionInteractor
@@ -138,6 +140,7 @@
                     )
                 ),
                 audioSharingInteractor,
+                bluetoothDeviceMetadataInteractor,
                 mDialogTransitionAnimator,
                 activityStarter,
                 uiEventLogger,
@@ -150,6 +153,8 @@
         whenever(deviceItemInteractor.deviceItemUpdate).thenReturn(MutableSharedFlow())
         whenever(deviceItemInteractor.deviceItemUpdateRequest)
             .thenReturn(MutableStateFlow(Unit).asStateFlow())
+        whenever(deviceItemInteractor.showSeeAllUpdate).thenReturn(getMutableStateFlow(false))
+        whenever(bluetoothDeviceMetadataInteractor.metadataUpdate).thenReturn(MutableSharedFlow())
         whenever(mBluetoothTileDialogDelegateDelegateFactory.create(any(), anyInt(), any(), any()))
             .thenReturn(bluetoothTileDialogDelegate)
         whenever(bluetoothTileDialogDelegate.createDialog()).thenReturn(sysuiDialog)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
index 7f7abaf..194590c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
@@ -113,9 +113,11 @@
             )
 
             val latest by collectLastValue(interactor.deviceItemUpdate)
+            val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
             interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
 
             assertThat(latest).isEqualTo(emptyList<DeviceItem>())
+            assertThat(latestShowSeeAll).isFalse()
         }
     }
 
@@ -128,9 +130,11 @@
             )
 
             val latest by collectLastValue(interactor.deviceItemUpdate)
+            val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
             interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
 
             assertThat(latest).isEqualTo(emptyList<DeviceItem>())
+            assertThat(latestShowSeeAll).isFalse()
         }
     }
 
@@ -143,9 +147,11 @@
             )
 
             val latest by collectLastValue(interactor.deviceItemUpdate)
+            val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
             interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
 
             assertThat(latest).isEqualTo(listOf(deviceItem1))
+            assertThat(latestShowSeeAll).isFalse()
         }
     }
 
@@ -158,9 +164,11 @@
             )
 
             val latest by collectLastValue(interactor.deviceItemUpdate)
+            val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
             interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
 
             assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem2))
+            assertThat(latestShowSeeAll).isFalse()
         }
     }
 
@@ -184,9 +192,11 @@
             `when`(deviceItem2.type).thenReturn(DeviceItemType.SAVED_BLUETOOTH_DEVICE)
 
             val latest by collectLastValue(interactor.deviceItemUpdate)
+            val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
             interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
 
             assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem1))
+            assertThat(latestShowSeeAll).isFalse()
         }
     }
 
@@ -207,9 +217,30 @@
             `when`(deviceItem2.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
 
             val latest by collectLastValue(interactor.deviceItemUpdate)
+            val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
             interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
 
             assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem1))
+            assertThat(latestShowSeeAll).isFalse()
+        }
+    }
+
+    @Test
+    fun testUpdateDeviceItems_showMaxDeviceItems_showSeeAll() {
+        testScope.runTest {
+            `when`(bluetoothTileDialogRepository.cachedDevices)
+                .thenReturn(listOf(cachedDevice2, cachedDevice2, cachedDevice2, cachedDevice2))
+            `when`(adapter.mostRecentlyConnectedDevices).thenReturn(null)
+            interactor.setDeviceItemFactoryListForTesting(
+                listOf(createFactory({ true }, deviceItem2))
+            )
+
+            val latest by collectLastValue(interactor.deviceItemUpdate)
+            val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
+            interactor.updateDeviceItems(mContext, DeviceFetchTrigger.FIRST_LOAD)
+
+            assertThat(latest).isEqualTo(listOf(deviceItem2, deviceItem2, deviceItem2))
+            assertThat(latestShowSeeAll).isTrue()
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
index fd9964f..a2b50fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
@@ -17,8 +17,6 @@
 package com.android.systemui.display.domain.interactor
 
 import android.companion.virtual.VirtualDeviceManager
-import android.companion.virtual.flags.Flags.FLAG_INTERACTIVE_SCREEN_MIRROR
-import android.platform.test.annotations.EnableFlags
 import android.testing.TestableLooper
 import android.view.Display
 import android.view.Display.TYPE_EXTERNAL
@@ -160,7 +158,6 @@
         }
 
     @Test
-    @EnableFlags(FLAG_INTERACTIVE_SCREEN_MIRROR)
     fun displayState_virtualDeviceOwnedMirrorVirtualDisplay_connected() =
         testScope.runTest {
             whenever(virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(anyInt()))
@@ -183,7 +180,6 @@
         }
 
     @Test
-    @EnableFlags(FLAG_INTERACTIVE_SCREEN_MIRROR)
     fun virtualDeviceOwnedMirrorVirtualDisplay_emitsConnectedDisplayAddition() =
         testScope.runTest {
             whenever(virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(anyInt()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
index 7583399..1d96c4d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
@@ -68,20 +68,23 @@
     @Test
     fun connectKeyboard() =
         testScope.runTest {
-            val now = Instant.now().toEpochMilli()
-            underTest.updateConnectTime(KEYBOARD, now)
+            val now = Instant.now()
+            underTest.updateFirstConnectionTime(KEYBOARD, now)
 
             assertThat(underTest.wasEverConnected(KEYBOARD)).isTrue()
-            assertThat(underTest.connectTime(KEYBOARD)).isEqualTo(now)
+            assertThat(underTest.firstConnectionTime(KEYBOARD)!!.epochSecond)
+                .isEqualTo(now.epochSecond)
             assertThat(underTest.wasEverConnected(TOUCHPAD)).isFalse()
         }
 
     @Test
     fun launchKeyboard() =
         testScope.runTest {
-            underTest.updateLaunch(KEYBOARD)
+            val now = Instant.now()
+            underTest.updateLaunchTime(KEYBOARD, now)
 
             assertThat(underTest.isLaunched(KEYBOARD)).isTrue()
+            assertThat(underTest.launchTime(KEYBOARD)!!.epochSecond).isEqualTo(now.epochSecond)
             assertThat(underTest.isLaunched(TOUCHPAD)).isFalse()
         }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
index 32d059b..a0fe538b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.flags.EnableSceneContainer
@@ -29,6 +30,10 @@
 import com.android.systemui.keyguard.shared.model.DismissAction
 import com.android.systemui.keyguard.shared.model.KeyguardDone
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.data.repository.fakePowerRepository
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessState
 import com.android.systemui.scene.data.repository.Idle
 import com.android.systemui.scene.data.repository.Transition
 import com.android.systemui.scene.data.repository.setSceneTransition
@@ -82,6 +87,8 @@
                 deviceEntryInteractor = kosmos.deviceEntryInteractor,
                 quickSettingsSceneFamilyResolver = kosmos.quickSettingsSceneFamilyResolver,
                 notifShadeSceneFamilyResolver = kosmos.notifShadeSceneFamilyResolver,
+                powerInteractor = kosmos.powerInteractor,
+                alternateBouncerInteractor = kosmos.alternateBouncerInteractor,
             )
     }
 
@@ -234,6 +241,32 @@
         }
 
     @Test
+    fun resetDismissAction_onBouncer_OnAsleep() =
+        testScope.runTest {
+            kosmos.setSceneTransition(Idle(Scenes.Bouncer))
+            kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.None
+            )
+            val resetDismissAction by collectLastValue(underTest.resetDismissAction)
+            keyguardRepository.setDismissAction(
+                DismissAction.RunAfterKeyguardGone(
+                    dismissAction = {},
+                    onCancelAction = {},
+                    message = "message",
+                    willAnimateOnLockscreen = true,
+                )
+            )
+            assertThat(resetDismissAction).isNull()
+            kosmos.fakePowerRepository.updateWakefulness(
+                rawState = WakefulnessState.ASLEEP,
+                lastWakeReason = WakeSleepReason.POWER_BUTTON,
+                lastSleepReason = WakeSleepReason.TIMEOUT,
+                powerButtonLaunchGestureTriggered = false,
+            )
+            assertThat(resetDismissAction).isEqualTo(Unit)
+        }
+
+    @Test
     fun setDismissAction_callsCancelRunnableOnPreviousDismissAction() =
         testScope.runTest {
             val dismissAction by collectLastValue(underTest.dismissAction)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
index 24bea2c..73b9f57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
@@ -20,6 +20,7 @@
 import android.app.admin.DevicePolicyManager
 import android.content.Intent
 import android.os.UserHandle
+import android.platform.test.annotations.EnableFlags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.internal.widget.LockPatternUtils
@@ -402,6 +403,67 @@
         }
 
     @Test
+    @EnableFlags(com.android.systemui.Flags.FLAG_NEW_PICKER_UI)
+    fun startButton_inPreviewMode_onPreviewQuickAffordanceSelected() =
+        testScope.runTest {
+            underTest.onPreviewSlotSelected(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START)
+            underTest.enablePreviewMode(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, true)
+
+            repository.setKeyguardShowing(false)
+            val latest = collectLastValue(underTest.startButton)
+
+            val icon: Icon = mock()
+            val testConfig =
+                TestConfig(
+                    isVisible = true,
+                    isClickable = true,
+                    isActivated = true,
+                    icon = icon,
+                    canShowWhileLocked = false,
+                    intent = null,
+                    slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
+                )
+            val defaultConfigKey =
+                setUpQuickAffordanceModel(
+                    position = KeyguardQuickAffordancePosition.BOTTOM_START,
+                    testConfig = testConfig,
+                )
+
+            // Set up the quick access wallet config
+            val quickAccessWalletAffordanceConfigKey =
+                quickAccessWalletAffordanceConfig
+                    .apply {
+                        onTriggeredResult =
+                            KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity(
+                                intent = Intent("action"),
+                                canShowWhileLocked = false,
+                            )
+                        setState(
+                            KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+                                icon = icon,
+                                activationState = ActivationState.Active,
+                            )
+                        )
+                    }
+                    .let {
+                        KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId() +
+                            "::${quickAccessWalletAffordanceConfig.key}"
+                    }
+
+            // onPreviewQuickAffordanceSelected should trigger the override with the quick access
+            // wallet quick affordance
+            underTest.onPreviewQuickAffordanceSelected(
+                KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+                BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET,
+            )
+            Truth.assertThat(latest()?.configKey).isEqualTo(quickAccessWalletAffordanceConfigKey)
+
+            // onClearPreviewQuickAffordances should make the default quick affordance shows again
+            underTest.onClearPreviewQuickAffordances()
+            Truth.assertThat(latest()?.configKey).isEqualTo(defaultConfigKey)
+        }
+
+    @Test
     fun startButton_inPreviewMode_visibleEvenWhenKeyguardNotShowing() =
         testScope.runTest {
             underTest.onPreviewSlotSelected(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START)
@@ -445,7 +507,7 @@
         }
 
     @Test
-    fun endButton_inHiglightedPreviewMode_dimmedWhenOtherIsSelected() =
+    fun endButton_inHighlightedPreviewMode_dimmedWhenOtherIsSelected() =
         testScope.runTest {
             underTest.onPreviewSlotSelected(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START)
             underTest.enablePreviewMode(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
index 68307b1..c1cf91d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
@@ -23,6 +23,8 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.systemui.Flags.FLAG_QS_CUSTOM_TILE_CLICK_GUARANTEED_BUG_FIX;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
@@ -50,6 +52,7 @@
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.net.Uri;
 import android.os.Bundle;
@@ -183,6 +186,40 @@
                 .thenReturn(defaultPackageInfo);
     }
 
+    private void setPackageInstalledForUser(
+            boolean installed,
+            boolean active,
+            boolean toggleable,
+            int user
+    ) throws Exception {
+        ServiceInfo defaultServiceInfo = null;
+        if (installed) {
+            defaultServiceInfo = new ServiceInfo();
+            defaultServiceInfo.metaData = new Bundle();
+            defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_ACTIVE_TILE, active);
+            defaultServiceInfo.metaData
+                    .putBoolean(TileService.META_DATA_TOGGLEABLE_TILE, toggleable);
+            when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt(), eq(user)))
+                    .thenReturn(defaultServiceInfo);
+            if (user == 0) {
+                when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt()))
+                        .thenReturn(defaultServiceInfo);
+            }
+            PackageInfo defaultPackageInfo = new PackageInfo();
+            when(mMockPackageManagerAdapter.getPackageInfoAsUser(anyString(), anyInt(), eq(user)))
+                    .thenReturn(defaultPackageInfo);
+        } else {
+            when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt(), eq(user)))
+                    .thenReturn(null);
+            if (user == 0) {
+                when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt()))
+                        .thenThrow(new PackageManager.NameNotFoundException());
+            }
+            when(mMockPackageManagerAdapter.getPackageInfoAsUser(anyString(), anyInt(), eq(user)))
+                    .thenThrow(new PackageManager.NameNotFoundException());
+        }
+    }
+
     private void verifyBind(int times) {
         assertEquals(times > 0, mContext.isBound(mTileServiceComponentName));
     }
@@ -557,6 +594,100 @@
         verify(mockContext).unbindService(captor.getValue());
     }
 
+    @Test
+    public void testIsActive_user0_packageInstalled() throws Exception {
+        setPackageInstalledForUser(true, true, false, 0);
+        mUser = UserHandle.of(0);
+
+        TileLifecycleManager manager = new TileLifecycleManager(mHandler, mWrappedContext,
+                mock(IQSService.class),
+                mMockPackageManagerAdapter,
+                mMockBroadcastDispatcher,
+                mTileServiceIntent,
+                mUser,
+                mActivityManager,
+                mDeviceIdleController,
+                mExecutor);
+
+        assertThat(manager.isActiveTile()).isTrue();
+    }
+
+    @Test
+    public void testIsActive_user10_packageInstalled_notForUser0() throws Exception {
+        setPackageInstalledForUser(true, true, false, 10);
+        setPackageInstalledForUser(false, false, false, 0);
+        mUser = UserHandle.of(10);
+
+        TileLifecycleManager manager = new TileLifecycleManager(mHandler, mWrappedContext,
+                mock(IQSService.class),
+                mMockPackageManagerAdapter,
+                mMockBroadcastDispatcher,
+                mTileServiceIntent,
+                mUser,
+                mActivityManager,
+                mDeviceIdleController,
+                mExecutor);
+
+        assertThat(manager.isActiveTile()).isTrue();
+    }
+
+    @Test
+    public void testIsToggleable_user0_packageInstalled() throws Exception {
+        setPackageInstalledForUser(true, false, true, 0);
+        mUser = UserHandle.of(0);
+
+        TileLifecycleManager manager = new TileLifecycleManager(mHandler, mWrappedContext,
+                mock(IQSService.class),
+                mMockPackageManagerAdapter,
+                mMockBroadcastDispatcher,
+                mTileServiceIntent,
+                mUser,
+                mActivityManager,
+                mDeviceIdleController,
+                mExecutor);
+
+        assertThat(manager.isToggleableTile()).isTrue();
+    }
+
+    @Test
+    public void testIsToggleable_user10_packageInstalled_notForUser0() throws Exception {
+        setPackageInstalledForUser(true, false, true, 10);
+        setPackageInstalledForUser(false, false, false, 0);
+        mUser = UserHandle.of(10);
+
+        TileLifecycleManager manager = new TileLifecycleManager(mHandler, mWrappedContext,
+                mock(IQSService.class),
+                mMockPackageManagerAdapter,
+                mMockBroadcastDispatcher,
+                mTileServiceIntent,
+                mUser,
+                mActivityManager,
+                mDeviceIdleController,
+                mExecutor);
+
+        assertThat(manager.isToggleableTile()).isTrue();
+    }
+
+    @Test
+    public void testIsToggleableActive_installedForDifferentUser() throws Exception {
+        setPackageInstalledForUser(true, false, false, 10);
+        setPackageInstalledForUser(false, true, true, 0);
+        mUser = UserHandle.of(10);
+
+        TileLifecycleManager manager = new TileLifecycleManager(mHandler, mWrappedContext,
+                mock(IQSService.class),
+                mMockPackageManagerAdapter,
+                mMockBroadcastDispatcher,
+                mTileServiceIntent,
+                mUser,
+                mActivityManager,
+                mDeviceIdleController,
+                mExecutor);
+
+        assertThat(manager.isToggleableTile()).isFalse();
+        assertThat(manager.isActiveTile()).isFalse();
+    }
+
     private void mockChangeEnabled(long changeId, boolean enabled) {
         doReturn(enabled).when(() -> CompatChanges.isChangeEnabled(eq(changeId), anyString(),
                 any(UserHandle.class)));
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt
index 957f092..27eadb1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt
@@ -16,10 +16,12 @@
 
 package com.android.systemui.keyguard.domain.interactor
 
+import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.keyguard.data.repository.keyguardRepository
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.scene.domain.resolver.notifShadeSceneFamilyResolver
 import com.android.systemui.scene.domain.resolver.quickSettingsSceneFamilyResolver
@@ -37,5 +39,7 @@
             deviceEntryInteractor = deviceEntryInteractor,
             quickSettingsSceneFamilyResolver = quickSettingsSceneFamilyResolver,
             notifShadeSceneFamilyResolver = notifShadeSceneFamilyResolver,
+            powerInteractor = powerInteractor,
+            alternateBouncerInteractor = alternateBouncerInteractor,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt
index bcc7393..4c05939 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/lifecycle/FakeActivatable.kt
@@ -21,7 +21,7 @@
 class FakeActivatable(
     private val onActivation: () -> Unit = {},
     private val onDeactivation: () -> Unit = {},
-) : SafeActivatable() {
+) : BaseActivatable() {
     var activationCount = 0
     var cancellationCount = 0
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakePackageManagerAdapterFacade.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakePackageManagerAdapterFacade.kt
index fa8d363..5ac7c39 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakePackageManagerAdapterFacade.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakePackageManagerAdapterFacade.kt
@@ -18,14 +18,19 @@
 
 import android.content.ComponentName
 import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
 import android.content.pm.ServiceInfo
 import android.os.Bundle
+import android.os.UserHandle
 import com.android.systemui.qs.external.PackageManagerAdapter
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
+import org.hamcrest.BaseMatcher
+import org.hamcrest.Description
 import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.hamcrest.MockitoHamcrest.intThat
 
 /**
  * Facade for [PackageManagerAdapter] to provide a fake-like behaviour. You can create this class
@@ -36,29 +41,26 @@
  * [com.android.systemui.qs.external.TileServiceManager.isToggleableTile] or
  * [com.android.systemui.qs.external.TileServiceManager.isActiveTile] when the real objects are
  * used.
+ *
+ * The user this is set up must be a real user (`user >= 0`) or [UserHandle.USER_ALL].
  */
 class FakePackageManagerAdapterFacade(
     val componentName: ComponentName,
     val packageManagerAdapter: PackageManagerAdapter = mock {},
+    user: Int = UserHandle.USER_ALL,
 ) {
 
     private var isToggleable: Boolean = false
     private var isActive: Boolean = false
 
     init {
-        whenever(packageManagerAdapter.getServiceInfo(eq(componentName), any())).thenAnswer {
-            createServiceInfo()
+        if (user == UserHandle.USER_ALL) {
+            setForAllUsers()
+        } else if (user >= 0) {
+            setExclusiveForUser(user)
+        } else {
+            throw IllegalArgumentException("User must be a real user or UserHandle.USER_ALL")
         }
-        whenever(
-                packageManagerAdapter.getPackageInfoAsUser(
-                    eq(componentName.packageName),
-                    anyInt(),
-                    anyInt()
-                )
-            )
-            .thenAnswer { PackageInfo().apply { packageName = componentName.packageName } }
-        whenever(packageManagerAdapter.getServiceInfo(eq(componentName), anyInt(), anyInt()))
-            .thenAnswer { createServiceInfo() }
     }
 
     private fun createServiceInfo(): ServiceInfo {
@@ -84,4 +86,67 @@
     fun setIsToggleable(isToggleable: Boolean) {
         this.isToggleable = isToggleable
     }
+
+    fun setExclusiveForUser(newUser: Int) {
+        check(newUser >= 0)
+        val notEqualMatcher = NotEqualMatcher(newUser)
+        if (newUser == 0) {
+            whenever(packageManagerAdapter.getServiceInfo(eq(componentName), any())).thenAnswer {
+                createServiceInfo()
+            }
+        }
+        whenever(
+                packageManagerAdapter.getPackageInfoAsUser(
+                    eq(componentName.packageName),
+                    anyInt(),
+                    eq(newUser)
+                )
+            )
+            .thenAnswer { PackageInfo().apply { packageName = componentName.packageName } }
+        whenever(
+                packageManagerAdapter.getPackageInfoAsUser(
+                    eq(componentName.packageName),
+                    anyInt(),
+                    intThat(notEqualMatcher),
+                )
+            )
+            .thenThrow(PackageManager.NameNotFoundException())
+
+        whenever(
+                packageManagerAdapter.getServiceInfo(
+                    eq(componentName),
+                    anyInt(),
+                    intThat(notEqualMatcher)
+                )
+            )
+            .thenAnswer { null }
+        whenever(packageManagerAdapter.getServiceInfo(eq(componentName), anyInt(), eq(newUser)))
+            .thenAnswer { createServiceInfo() }
+    }
+
+    fun setForAllUsers() {
+        whenever(packageManagerAdapter.getServiceInfo(eq(componentName), any())).thenAnswer {
+            createServiceInfo()
+        }
+        whenever(
+                packageManagerAdapter.getPackageInfoAsUser(
+                    eq(componentName.packageName),
+                    anyInt(),
+                    anyInt()
+                )
+            )
+            .thenAnswer { PackageInfo().apply { packageName = componentName.packageName } }
+        whenever(packageManagerAdapter.getServiceInfo(eq(componentName), anyInt(), anyInt()))
+            .thenAnswer { createServiceInfo() }
+    }
+}
+
+private class NotEqualMatcher(private val notEqualValue: Int) : BaseMatcher<Int>() {
+    override fun describeTo(description: Description?) {
+        description?.appendText("!= $notEqualValue")
+    }
+
+    override fun matches(item: Any?): Boolean {
+        return (item as? Int)?.equals(notEqualValue)?.not() ?: true
+    }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt
index a0a39d1..63386d0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt
@@ -17,15 +17,17 @@
 package com.android.systemui.volume.panel.component.volume.domain.interactor
 
 import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.volume.data.repository.audioRepository
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
 import com.android.systemui.volume.mediaOutputInteractor
 
 val Kosmos.audioSlidersInteractor by
     Kosmos.Fixture {
         AudioSlidersInteractor(
-            testScope.backgroundScope,
+            applicationCoroutineScope,
             mediaOutputInteractor,
             audioRepository,
+            audioModeInteractor,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt
index 45a291e..6e848ce 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt
@@ -18,6 +18,7 @@
 
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
 import com.android.systemui.volume.mediaDeviceSessionInteractor
 import com.android.systemui.volume.mediaOutputInteractor
 import com.android.systemui.volume.panel.component.volume.domain.interactor.audioSlidersInteractor
@@ -32,6 +33,7 @@
             mediaDeviceSessionInteractor,
             audioStreamSliderViewModelFactory,
             castVolumeSliderViewModelFactory,
+            audioModeInteractor,
             audioSlidersInteractor,
         )
     }
diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
index 531fa45..09068d5 100644
--- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
+++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
@@ -171,7 +171,7 @@
             EXTENSIONS_VERSION.startsWith(LATENCY_VERSION_PREFIX) ||
             EXTENSIONS_VERSION.startsWith(EFV_VERSION_PREFIX));
 
-    private HashMap<String, Long> mMetadataVendorIdMap = new HashMap<>();
+    private static HashMap<String, Long> mMetadataVendorIdMap = new HashMap<>();
     private CameraManager mCameraManager;
 
     private static boolean checkForLatencyAPI() {
@@ -820,7 +820,7 @@
             mCameraManager = getSystemService(CameraManager.class);
 
             String [] cameraIds = mCameraManager.getCameraIdListNoLazy();
-            if (cameraIds != null) {
+            if (cameraIds != null && mMetadataVendorIdMap.isEmpty()) {
                 for (String cameraId : cameraIds) {
                     CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId);
                     Object thisClass = CameraCharacteristics.Key.class;
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 6150343..58cd2e4 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -166,6 +166,14 @@
     jarjar_rules: ":ravenwood-services-jarjar-rules",
 }
 
+java_device_for_host {
+    name: "ravenwood-junit-impl-for-ravenizer",
+    libs: [
+        "ravenwood-junit-impl",
+    ],
+    visibility: [":__subpackages__"],
+}
+
 // Separated out from ravenwood-junit-impl since it needs to compile
 // against `module_current`
 java_library {
diff --git a/ravenwood/minimum-test/test/com/android/ravenwood/RavenwoodMinimumTest.java b/ravenwood/minimum-test/test/com/android/ravenwoodtest/RavenwoodMinimumTest.java
similarity index 97%
rename from ravenwood/minimum-test/test/com/android/ravenwood/RavenwoodMinimumTest.java
rename to ravenwood/minimum-test/test/com/android/ravenwoodtest/RavenwoodMinimumTest.java
index b477117..30abaa2 100644
--- a/ravenwood/minimum-test/test/com/android/ravenwood/RavenwoodMinimumTest.java
+++ b/ravenwood/minimum-test/test/com/android/ravenwoodtest/RavenwoodMinimumTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.ravenwood;
+package com.android.ravenwoodtest;
 
 import android.platform.test.annotations.IgnoreUnderRavenwood;
 import android.platform.test.ravenwood.RavenwoodRule;
diff --git a/ravenwood/resapk_test/test/com/android/ravenwood/resapk_test/RavenwoodResApkTest.java b/ravenwood/resapk_test/test/com/android/ravenwoodtest/resapk_test/RavenwoodResApkTest.java
similarity index 96%
rename from ravenwood/resapk_test/test/com/android/ravenwood/resapk_test/RavenwoodResApkTest.java
rename to ravenwood/resapk_test/test/com/android/ravenwoodtest/resapk_test/RavenwoodResApkTest.java
index 1029ed2..e547114 100644
--- a/ravenwood/resapk_test/test/com/android/ravenwood/resapk_test/RavenwoodResApkTest.java
+++ b/ravenwood/resapk_test/test/com/android/ravenwoodtest/resapk_test/RavenwoodResApkTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.ravenwood.resapk_test;
+package com.android.ravenwoodtest.resapk_test;
 
 
 import static junit.framework.TestCase.assertTrue;
diff --git a/ravenwood/runtime-test/test/com/android/ravenwood/runtimetest/OsConstantsTest.java b/ravenwood/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsConstantsTest.java
similarity index 99%
rename from ravenwood/runtime-test/test/com/android/ravenwood/runtimetest/OsConstantsTest.java
rename to ravenwood/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsConstantsTest.java
index 3332e24..633ed4e 100644
--- a/ravenwood/runtime-test/test/com/android/ravenwood/runtimetest/OsConstantsTest.java
+++ b/ravenwood/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsConstantsTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.ravenwood.runtimetest;
+package com.android.ravenwoodtest.runtimetest;
 
 // Copied from libcore/luni/src/test/java/libcore/android/system/OsConstantsTest.java
 
diff --git a/ravenwood/runtime-test/test/com/android/ravenwood/runtimetest/OsTest.java b/ravenwood/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsTest.java
similarity index 99%
rename from ravenwood/runtime-test/test/com/android/ravenwood/runtimetest/OsTest.java
rename to ravenwood/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsTest.java
index 05275b2..c2230c7 100644
--- a/ravenwood/runtime-test/test/com/android/ravenwood/runtimetest/OsTest.java
+++ b/ravenwood/runtime-test/test/com/android/ravenwoodtest/runtimetest/OsTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.ravenwood.runtimetest;
+package com.android.ravenwoodtest.runtimetest;
 
 import static android.system.OsConstants.S_ISBLK;
 import static android.system.OsConstants.S_ISCHR;
diff --git a/ravenwood/scripts/shrink-systemui-test b/ravenwood/scripts/shrink-systemui-test
new file mode 100755
index 0000000..8589c1d
--- /dev/null
+++ b/ravenwood/scripts/shrink-systemui-test
@@ -0,0 +1,131 @@
+#!/bin/bash
+# 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.
+
+set -e
+
+SCRIPT_NAME="${0##*/}"
+
+usage() {
+    cat <<"EOF"
+
+$SCRIPT_NAME: Shrink / unshrink SystemUiRavenTests.
+
+    SystemUiRavenTests has a lot of kotlin source files, so it's slow to build,
+    which is painful when you want to run it after updating ravenwood code
+    that SystemUiRavenTests depends on. (example: junit-src/)
+
+    This script basically removes the test files in SystemUI/multivalentTests
+    that don't have @EnabledOnRavenwood. But if we actaully remove them,
+    soong would re-generate the ninja file, which will take a long time,
+    so instead it'll truncate them.
+
+    This script will also tell git to ignore these files, so they won't shw up
+    in `git status`.
+    (Use `git ls-files -v | sed -ne "s/^[a-zS] //p"` to show ignored filse.)
+
+Usage:
+    $SCRIPT_NAME -s # Shrink the test files.
+
+    $SCRIPT_NAME -u # Undo it.
+
+EOF
+}
+
+TEST_PATH=${ANDROID_BUILD_TOP}/frameworks/base/packages/SystemUI/multivalentTests
+cd "$TEST_PATH"
+
+command=""
+case "$1" in
+    "-s") command=shrink ;;
+    "-u") command=unshrink ;;
+    *) usage ; exit 1 ;;
+esac
+
+
+echo "Listing test files...."
+files=( $(find . -name '*Test.kt' -o -name '*Test.java') )
+
+exemption='(BaseHeadsUpManagerTest)'
+
+shrink() {
+    local target=()
+    for file in ${files[@]}; do
+        # Check for exemption
+        if echo $file | egrep -q "$exemption"; then
+            echo "  Skip exempted file"
+            continue
+        fi
+
+        echo "Checking $file"
+        if ! [[ -f $file ]] ; then
+            echo "  Skip non regular file"
+            continue
+        fi
+
+        if ! [[ -s $file ]] ; then
+            echo "  Skip empty file"
+            continue
+        fi
+
+        if grep -q '@EnabledOnRavenwood' $file ; then
+            echo "  Skip ravenwood test file".
+            continue
+        fi
+
+        # It's a non ravenwood test file. Empty it.
+        : > $file
+
+        # Tell git to ignore the file
+
+        target+=($file)
+
+        echo "  Emptied"
+
+    done
+    if (( ${#target[@]} == 0 )) ; then
+        echo "No files emptied."
+        return 0
+    fi
+
+    git update-index --skip-worktree ${target[@]}
+
+    echo "Emptied ${#target[@]} files"
+    return 0
+}
+
+unshrink() {
+    local target=()
+
+    # Collect empty files
+    for file in ${files[@]}; do
+        if [[ -s $file ]] ; then
+            continue
+        fi
+
+        target+=($file)
+        : > $file
+    done
+    if (( ${#target[@]} == 0 )) ; then
+        echo "No files to restore."
+        return 0
+    fi
+    # Un-ignore the files, and check out the original files
+    echo "Restoring ${#target[@]} files..."
+    git update-index --no-skip-worktree ${target[@]}
+    git checkout goog/main ${target[@]}
+    return 0
+}
+
+$command
diff --git a/ravenwood/tools/ravenizer/Android.bp b/ravenwood/tools/ravenizer/Android.bp
new file mode 100644
index 0000000..2892d07
--- /dev/null
+++ b/ravenwood/tools/ravenizer/Android.bp
@@ -0,0 +1,25 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_binary_host {
+    name: "ravenizer",
+    main_class: "com.android.platform.test.ravenwood.ravenizer.RavenizerMain",
+    srcs: ["src/**/*.kt"],
+    static_libs: [
+        "hoststubgen-lib",
+        "ow2-asm",
+        "ow2-asm-analysis",
+        "ow2-asm-commons",
+        "ow2-asm-tree",
+        "ow2-asm-util",
+        "junit",
+        "ravenwood-junit-impl-for-ravenizer",
+    ],
+    visibility: ["//visibility:public"],
+}
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt
new file mode 100644
index 0000000..da9c7d9
--- /dev/null
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt
@@ -0,0 +1,212 @@
+/*
+ * 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.platform.test.ravenwood.ravenizer
+
+import com.android.hoststubgen.GeneralUserErrorException
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.zipEntryNameToClassName
+import com.android.hoststubgen.executableName
+import com.android.hoststubgen.log
+import com.android.platform.test.ravenwood.ravenizer.adapter.TestRunnerRewritingAdapter
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.ClassWriter
+import org.objectweb.asm.util.CheckClassAdapter
+import java.io.BufferedInputStream
+import java.io.BufferedOutputStream
+import java.io.FileOutputStream
+import java.io.InputStream
+import java.io.OutputStream
+import java.util.zip.ZipEntry
+import java.util.zip.ZipFile
+import java.util.zip.ZipOutputStream
+
+/**
+ * Various stats on Ravenizer.
+ */
+data class RavenizerStats(
+    /** Total end-to-end time. */
+    var totalTime: Double = .0,
+
+    /** Time took to build [ClasNodes] */
+    var loadStructureTime: Double = .0,
+
+    /** Total real time spent for converting the jar file */
+    var totalProcessTime: Double = .0,
+
+    /** Total real time spent for converting class files (except for I/O time). */
+    var totalConversionTime: Double = .0,
+
+    /** Total real time spent for copying class files without modification. */
+    var totalCopyTime: Double = .0,
+
+    /** # of entries in the input jar file */
+    var totalEntiries: Int = 0,
+
+    /** # of *.class files in the input jar file */
+    var totalClasses: Int = 0,
+
+    /** # of *.class files that have been processed. */
+    var processedClasses: Int = 0,
+) {
+    override fun toString(): String {
+        return """
+            RavenizerStats{
+              totalTime=$totalTime,
+              loadStructureTime=$loadStructureTime,
+              totalProcessTime=$totalProcessTime,
+              totalConversionTime=$totalConversionTime,
+              totalCopyTime=$totalCopyTime,
+              totalEntiries=$totalEntiries,
+              totalClasses=$totalClasses,
+              processedClasses=$processedClasses,
+            }
+            """.trimIndent()
+    }
+}
+
+/**
+ * Main class.
+ */
+class Ravenizer(val options: RavenizerOptions) {
+    fun run() {
+        val stats = RavenizerStats()
+        stats.totalTime = log.nTime {
+            process(options.inJar.get, options.outJar.get, stats)
+        }
+        log.i(stats.toString())
+    }
+
+    private fun process(inJar: String, outJar: String, stats: RavenizerStats) {
+        var allClasses = ClassNodes.loadClassStructures(inJar) {
+            time -> stats.loadStructureTime = time
+        }
+
+        stats.totalProcessTime = log.iTime("$executableName processing $inJar") {
+            ZipFile(inJar).use { inZip ->
+                val inEntries = inZip.entries()
+
+                stats.totalEntiries = inZip.size()
+
+                ZipOutputStream(BufferedOutputStream(FileOutputStream(outJar))).use { outZip ->
+                    while (inEntries.hasMoreElements()) {
+                        val entry = inEntries.nextElement()
+
+                        if (entry.name.endsWith(".dex")) {
+                            // Seems like it's an ART jar file. We can't process it.
+                            // It's a fatal error.
+                            throw GeneralUserErrorException(
+                                "$inJar is not a desktop jar file. It contains a *.dex file."
+                            )
+                        }
+
+                        val className = zipEntryNameToClassName(entry.name)
+
+                        if (className != null) {
+                            stats.totalClasses += 1
+                        }
+
+                        if (className != null && shouldProcessClass(allClasses, className)) {
+                            stats.processedClasses += 1
+                            processSingleClass(inZip, entry, outZip, allClasses, stats)
+                        } else {
+                            // Too slow, let's use merge_zips to bring back the original classes.
+                            copyZipEntry(inZip, entry, outZip, stats)
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Copy a single ZIP entry to the output.
+     */
+    private fun copyZipEntry(
+        inZip: ZipFile,
+        entry: ZipEntry,
+        out: ZipOutputStream,
+        stats: RavenizerStats,
+    ) {
+        stats.totalCopyTime += log.nTime {
+            inZip.getInputStream(entry).use { ins ->
+                // Copy unknown entries as is to the impl out. (but not to the stub out.)
+                val outEntry = ZipEntry(entry.name)
+                outEntry.method = 0
+                outEntry.size = entry.size
+                outEntry.crc = entry.crc
+                out.putNextEntry(outEntry)
+
+                ins.transferTo(out)
+
+                out.closeEntry()
+            }
+        }
+    }
+
+    private fun processSingleClass(
+        inZip: ZipFile,
+        entry: ZipEntry,
+        outZip: ZipOutputStream,
+        allClasses: ClassNodes,
+        stats: RavenizerStats,
+    ) {
+        val newEntry = ZipEntry(entry.name)
+        outZip.putNextEntry(newEntry)
+
+        BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+            processSingleClass(entry, bis, outZip, allClasses, stats)
+        }
+        outZip.closeEntry()
+    }
+
+    /**
+     * Whether a class needs to be processed. This must be kept in sync with [processSingleClass].
+     */
+    private fun shouldProcessClass(classes: ClassNodes, classInternalName: String): Boolean {
+        return TestRunnerRewritingAdapter.shouldProcess(classes, classInternalName)
+    }
+
+    private fun processSingleClass(
+        entry: ZipEntry,
+        input: InputStream,
+        output: OutputStream,
+        allClasses: ClassNodes,
+        stats: RavenizerStats,
+    ) {
+        val cr = ClassReader(input)
+
+        lateinit var data: ByteArray
+        stats.totalConversionTime += log.vTime("Modify ${entry.name}") {
+            val flags = ClassWriter.COMPUTE_MAXS
+            val cw = ClassWriter(flags)
+            var outVisitor: ClassVisitor = cw
+
+            val enableChecker = false
+            if (enableChecker) {
+                outVisitor = CheckClassAdapter(outVisitor)
+            }
+
+            // This must be kept in sync with shouldProcessClass.
+            outVisitor = TestRunnerRewritingAdapter(allClasses, outVisitor)
+
+            cr.accept(outVisitor, ClassReader.EXPAND_FRAMES)
+
+            data = cw.toByteArray()
+        }
+        output.write(data)
+    }
+}
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt
new file mode 100644
index 0000000..ff41818
--- /dev/null
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+@file:JvmName("RavenizerMain")
+
+package com.android.platform.test.ravenwood.ravenizer
+
+import com.android.hoststubgen.LogLevel
+import com.android.hoststubgen.executableName
+import com.android.hoststubgen.log
+import com.android.hoststubgen.runMainWithBoilerplate
+
+/**
+ * Entry point.
+ */
+fun main(args: Array<String>) {
+    executableName = "Ravenizer"
+    log.setConsoleLogLevel(LogLevel.Info)
+
+    runMainWithBoilerplate {
+        val options = RavenizerOptions.parseArgs(args)
+
+        log.i("$executableName started")
+        log.v("Options: $options")
+
+        // Run.
+        Ravenizer(options).run()
+    }
+}
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt
new file mode 100644
index 0000000..e85e3be
--- /dev/null
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt
@@ -0,0 +1,80 @@
+/*
+ * 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.platform.test.ravenwood.ravenizer
+
+import com.android.hoststubgen.ArgIterator
+import com.android.hoststubgen.ArgumentsException
+import com.android.hoststubgen.SetOnce
+import com.android.hoststubgen.ensureFileExists
+import com.android.hoststubgen.log
+
+class RavenizerOptions(
+    /** Input jar file*/
+    var inJar: SetOnce<String> = SetOnce(""),
+
+    /** Output jar file */
+    var outJar: SetOnce<String> = SetOnce(""),
+) {
+    companion object {
+        fun parseArgs(args: Array<String>): RavenizerOptions {
+            val ret = RavenizerOptions()
+            val ai = ArgIterator.withAtFiles(args)
+
+            while (true) {
+                val arg = ai.nextArgOptional()
+                if (arg == null) {
+                    break
+                }
+
+                fun nextArg(): String = ai.nextArgRequired(arg)
+
+                if (log.maybeHandleCommandLineArg(arg) { nextArg() }) {
+                    continue
+                }
+                try {
+                    when (arg) {
+                        // TODO: Write help
+                        "-h", "--help" -> TODO("Help is not implemented yet")
+
+                        "--in-jar" -> ret.inJar.set(nextArg()).ensureFileExists()
+                        "--out-jar" -> ret.outJar.set(nextArg())
+
+                        else -> throw ArgumentsException("Unknown option: $arg")
+                    }
+                } catch (e: SetOnce.SetMoreThanOnceException) {
+                    throw ArgumentsException("Duplicate or conflicting argument found: $arg")
+                }
+            }
+
+            if (!ret.inJar.isSet) {
+                throw ArgumentsException("Required option missing: --in-jar")
+            }
+            if (!ret.outJar.isSet) {
+                throw ArgumentsException("Required option missing: --out-jar")
+            }
+           return ret
+        }
+    }
+
+    override fun toString(): String {
+        return """
+            RavenizerOptions{
+              inJar=$inJar,
+              outJar=$outJar,
+            }
+            """.trimIndent()
+    }
+}
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt
new file mode 100644
index 0000000..0018648
--- /dev/null
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt
@@ -0,0 +1,54 @@
+/*
+ * 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.platform.test.ravenwood.ravenizer
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.findAnyAnnotation
+import org.objectweb.asm.Type
+
+val junitTestMethodType = Type.getType(org.junit.Test::class.java)
+val junitRunWithType = Type.getType(org.junit.runner.RunWith::class.java)
+
+val junitTestMethodDescriptor = junitTestMethodType.descriptor
+val junitRunWithDescriptor = junitRunWithType.descriptor
+
+val junitTestMethodDescriptors = setOf<String>(junitTestMethodDescriptor)
+val junitRunWithDescriptors = setOf<String>(junitRunWithDescriptor)
+
+/**
+ * Returns true, if a test looks like it's a test class which needs to be processed.
+ */
+fun isTestLookingClass(classes: ClassNodes, className: String): Boolean {
+    // Similar to  com.android.tradefed.lite.HostUtils.testLoadClass(), except it's more lenient,
+    // and accept non-public and/or abstract classes.
+    // HostUtils also checks "Suppress" or "SuiteClasses" but this one doesn't.
+    // TODO: SuiteClasses may need to be supported.
+
+    val cn = classes.findClass(className) ?: return false
+
+    if (cn.findAnyAnnotation(junitRunWithDescriptors) != null) {
+        return true
+    }
+    cn.methods?.forEach { method ->
+        if (method.findAnyAnnotation(junitTestMethodDescriptors) != null) {
+            return true
+        }
+    }
+    if (cn.superName == null) {
+        return false
+    }
+    return isTestLookingClass(classes, cn.superName)
+}
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/adapter/TestRunnerRewritingAdapter.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/adapter/TestRunnerRewritingAdapter.kt
new file mode 100644
index 0000000..c539908
--- /dev/null
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/adapter/TestRunnerRewritingAdapter.kt
@@ -0,0 +1,40 @@
+/*
+ * 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.platform.test.ravenwood.ravenizer.adapter
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.visitors.OPCODE_VERSION
+import com.android.platform.test.ravenwood.ravenizer.isTestLookingClass
+import org.objectweb.asm.ClassVisitor
+
+/**
+ * Class visitor to rewrite the test runner for Ravenwood
+ *
+ * TODO: Implement it.
+ */
+class TestRunnerRewritingAdapter(
+    protected val classes: ClassNodes,
+    nextVisitor: ClassVisitor,
+) : ClassVisitor(OPCODE_VERSION, nextVisitor) {
+   companion object {
+       /**
+        * Returns true if a target class is interesting to this adapter.
+        */
+       fun shouldProcess(classes: ClassNodes, className: String): Boolean {
+            return isTestLookingClass(classes, className)
+       }
+    }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index 5c6f99a..aa57e0b 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -305,12 +305,8 @@
         }
 
         mDelegatingState = new DelegatingState();
-        mDetectingState = Flags.enableMagnificationMultipleFingerMultipleTapGesture()
-                ? new DetectingStateWithMultiFinger(context)
-                : new DetectingState(context);
-        mViewportDraggingState = Flags.enableMagnificationMultipleFingerMultipleTapGesture()
-                ? new ViewportDraggingStateWithMultiFinger()
-                : new ViewportDraggingState();
+        mDetectingState = new DetectingState(context);
+        mViewportDraggingState = new ViewportDraggingState();
         mPanningScalingState = new PanningScalingState(context);
         mSinglePanningState = new SinglePanningState(context);
         mFullScreenMagnificationVibrationHelper = fullScreenMagnificationVibrationHelper;
@@ -701,62 +697,6 @@
         }
     }
 
-    final class ViewportDraggingStateWithMultiFinger extends ViewportDraggingState {
-        // LINT.IfChange(viewport_dragging_state_with_multi_finger)
-        @Override
-        public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags)
-                throws GestureException {
-            final int action = event.getActionMasked();
-            switch (action) {
-                case ACTION_POINTER_DOWN: {
-                    clearAndTransitToPanningScalingState();
-                }
-                break;
-                case ACTION_MOVE: {
-                    if (event.getPointerCount() > 2) {
-                        throw new GestureException("Should have one pointer down.");
-                    }
-                    final float eventX = event.getX();
-                    final float eventY = event.getY();
-                    if (mFullScreenMagnificationController.magnificationRegionContains(
-                            mDisplayId, eventX, eventY)) {
-                        mFullScreenMagnificationController.setCenter(mDisplayId, eventX, eventY,
-                                /* animate */ mLastMoveOutsideMagnifiedRegion,
-                                AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
-                        mLastMoveOutsideMagnifiedRegion = false;
-                    } else {
-                        mLastMoveOutsideMagnifiedRegion = true;
-                    }
-                }
-                break;
-
-                case ACTION_UP:
-                case ACTION_CANCEL: {
-                    // If mScaleToRecoverAfterDraggingEnd >= 1.0, the dragging state is triggered
-                    // by zoom in temporary, and the magnifier needs to recover to original scale
-                    // after exiting dragging state.
-                    // Otherwise, the magnifier should be disabled.
-                    if (mScaleToRecoverAfterDraggingEnd >= 1.0f) {
-                        zoomToScale(mScaleToRecoverAfterDraggingEnd, event.getX(),
-                                event.getY());
-                    } else {
-                        zoomOff();
-                    }
-                    clear();
-                    mScaleToRecoverAfterDraggingEnd = Float.NaN;
-                    transitionTo(mDetectingState);
-                }
-                    break;
-
-                case ACTION_DOWN: {
-                    throw new GestureException(
-                            "Unexpected event type: " + MotionEvent.actionToString(action));
-                }
-            }
-        }
-        // LINT.ThenChange(:viewport_dragging_state)
-    }
-
     /**
      * This class handles motion events when the event dispatcher has
      * determined that the user is performing a single-finger drag of the
@@ -777,7 +717,6 @@
 
         protected boolean mLastMoveOutsideMagnifiedRegion;
 
-        // LINT.IfChange(viewport_dragging_state)
         @Override
         public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags)
                 throws GestureException {
@@ -788,7 +727,11 @@
                 }
                 break;
                 case ACTION_MOVE: {
-                    if (event.getPointerCount() != 1) {
+                    if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
+                        if (event.getPointerCount() > 2) {
+                            throw new GestureException("Should have at most two pointers down.");
+                        }
+                    } else if (event.getPointerCount() != 1) {
                         throw new GestureException("Should have one pointer down.");
                     }
                     final float eventX = event.getX();
@@ -823,14 +766,20 @@
                 }
                     break;
 
-                case ACTION_DOWN:
                 case ACTION_POINTER_UP: {
+                    if (!Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
+                        throw new GestureException(
+                                "Unexpected event type: " + MotionEvent.actionToString(action));
+                    }
+                }
+                break;
+
+                case ACTION_DOWN: {
                     throw new GestureException(
                             "Unexpected event type: " + MotionEvent.actionToString(action));
                 }
             }
         }
-        // LINT.ThenChange(:viewport_dragging_state_with_multi_finger)
 
         private boolean isAlwaysOnMagnificationEnabled() {
             return mFullScreenMagnificationController.isAlwaysOnMagnificationEnabled();
@@ -916,270 +865,31 @@
         }
     }
 
-    final class DetectingStateWithMultiFinger extends DetectingState {
-        private static final int TWO_FINGER_GESTURE_MAX_TAPS = 2;
-        // A flag set to true when two fingers have touched down.
-        // Used to indicate what next finger action should be.
-        private boolean mIsTwoFingerCountReached = false;
-        // A tap counts when two fingers are down and up once.
-        private int mCompletedTapCount = 0;
-        DetectingStateWithMultiFinger(Context context) {
-            super(context);
-        }
-
-        // LINT.IfChange(detecting_state_with_multi_finger)
-        @Override
-        public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
-            cacheDelayedMotionEvent(event, rawEvent, policyFlags);
-            switch (event.getActionMasked()) {
-                case MotionEvent.ACTION_DOWN: {
-                    mLastDetectingDownEventTime = event.getDownTime();
-                    mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
-
-                    mFirstPointerDownLocation.set(event.getX(), event.getY());
-
-                    if (!mFullScreenMagnificationController.magnificationRegionContains(
-                            mDisplayId, event.getX(), event.getY())) {
-
-                        transitionToDelegatingStateAndClear();
-
-                    } else if (isMultiTapTriggered(2 /* taps */)) {
-
-                        // 3tap and hold
-                        afterLongTapTimeoutTransitionToDraggingState(event);
-
-                    } else if (isTapOutOfDistanceSlop()) {
-
-                        transitionToDelegatingStateAndClear();
-
-                    } else if (mDetectSingleFingerTripleTap
-                            || mDetectTwoFingerTripleTap
-                            // If activated, delay an ACTION_DOWN for mMultiTapMaxDelay
-                            // to ensure reachability of
-                            // STATE_PANNING_SCALING(triggerable with ACTION_POINTER_DOWN)
-                            || isActivated()) {
-
-                        afterMultiTapTimeoutTransitionToDelegatingState();
-
-                    } else {
-
-                        // Delegate pending events without delay
-                        transitionToDelegatingStateAndClear();
-                    }
-                }
-                break;
-                case ACTION_POINTER_DOWN: {
-                    mIsTwoFingerCountReached = mDetectTwoFingerTripleTap
-                            && event.getPointerCount() == 2;
-                    mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
-
-                    if (event.getPointerCount() == 2) {
-                        if (isMultiFingerMultiTapTriggered(
-                                TWO_FINGER_GESTURE_MAX_TAPS - 1, event)) {
-                            // 3tap and hold
-                            afterLongTapTimeoutTransitionToDraggingState(event);
-                        } else {
-                            if (mDetectTwoFingerTripleTap) {
-                                // If mDetectTwoFingerTripleTap, delay transition to the delegating
-                                // state for mMultiTapMaxDelay to ensure reachability of
-                                // multi finger multi tap
-                                afterMultiTapTimeoutTransitionToDelegatingState();
-                            }
-
-                            if (isActivated()) {
-                                // If activated, delay transition to the panning scaling
-                                // state for tap timeout to ensure reachability of
-                                // multi finger multi tap
-                                storePointerDownLocation(mSecondPointerDownLocation, event);
-                                mHandler.sendEmptyMessageDelayed(
-                                        MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
-                                        ViewConfiguration.getTapTimeout());
-                            }
-                        }
-                    } else {
-                        transitionToDelegatingStateAndClear();
-                    }
-                }
-                break;
-                case ACTION_POINTER_UP: {
-                    // If it is a two-finger gesture, do not transition to the delegating state
-                    // to ensure the reachability of
-                    // the two-finger triple tap (triggerable with ACTION_MOVE and ACTION_UP)
-                    if (!mIsTwoFingerCountReached) {
-                        transitionToDelegatingStateAndClear();
-                    }
-                }
-                break;
-                case ACTION_MOVE: {
-                    if (isFingerDown()
-                            && distance(mLastDown, /* move */ event) > mSwipeMinDistance) {
-                        // Swipe detected - transition immediately
-
-                        // For convenience, viewport dragging takes precedence
-                        // over insta-delegating on 3tap&swipe
-                        // (which is a rare combo to be used aside from magnification)
-                        if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) {
-                            transitionToViewportDraggingStateAndClear(event);
-                        } else if (isMultiFingerMultiTapTriggered(
-                                TWO_FINGER_GESTURE_MAX_TAPS - 1, event)
-                                && event.getPointerCount() == 2) {
-                            transitionToViewportDraggingStateAndClear(event);
-                        } else if (isActivated() && event.getPointerCount() == 2) {
-                            if (mOverscrollHandler != null
-                                    && overscrollState(event, mFirstPointerDownLocation)
-                                    == OVERSCROLL_VERTICAL_EDGE) {
-                                transitionToDelegatingStateAndClear();
-                            } else {
-                                //Primary pointer is swiping, so transit to PanningScalingState
-                                transitToPanningScalingStateAndClear();
-                            }
-                        } else if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled()
-                                && isActivated()
-                                && event.getPointerCount() == 1) {
-                            if (mOverscrollHandler != null
-                                    && overscrollState(event, mFirstPointerDownLocation)
-                                    == OVERSCROLL_VERTICAL_EDGE) {
-                                transitionToDelegatingStateAndClear();
-                            } else if (overscrollState(event, mFirstPointerDownLocation)
-                                    != OVERSCROLL_NONE) {
-                                transitionToDelegatingStateAndClear();
-                            } else {
-                                transitToSinglePanningStateAndClear();
-                            }
-                        } else if (!mIsTwoFingerCountReached) {
-                            // If it is a two-finger gesture, do not transition to the
-                            // delegating state to ensure the reachability of
-                            // the two-finger triple tap (triggerable with ACTION_UP)
-                            transitionToDelegatingStateAndClear();
-                        }
-                    } else if (isActivated() && pointerDownValid(mSecondPointerDownLocation)
-                            && distanceClosestPointerToPoint(
-                            mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance) {
-                        // Second pointer is swiping, so transit to PanningScalingState
-                        // Delay an ACTION_MOVE for tap timeout to ensure it is not trigger from
-                        // multi finger multi tap
-                        storePointerDownLocation(mSecondPointerDownLocation, event);
-                        mHandler.sendEmptyMessageDelayed(
-                                MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
-                                ViewConfiguration.getTapTimeout());
-                    }
-                }
-                break;
-                case ACTION_UP: {
-
-                    mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD);
-                    mHandler.removeMessages(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE);
-
-                    if (!mFullScreenMagnificationController.magnificationRegionContains(
-                            mDisplayId, event.getX(), event.getY())) {
-                        transitionToDelegatingStateAndClear();
-
-                    } else if (isMultiFingerMultiTapTriggered(TWO_FINGER_GESTURE_MAX_TAPS, event)) {
-                        // Placing multiple fingers before a single finger, because achieving a
-                        // multi finger multi tap also means achieving a single finger triple tap
-                        onTripleTap(event);
-
-                    } else if (isMultiTapTriggered(3 /* taps */)) {
-                        onTripleTap(/* up */ event);
-
-                    } else if (
-                            // Possible to be false on: 3tap&drag -> scale -> PTR_UP -> UP
-                            isFingerDown()
-                            //TODO long tap should never happen here
-                            && ((timeBetween(mLastDown, mLastUp) >= mLongTapMinDelay)
-                                    || (distance(mLastDown, mLastUp) >= mSwipeMinDistance))
-                            // If it is a two-finger but not reach 3 tap, do not transition to the
-                            // delegating state to ensure the reachability of the triple tap
-                            && mCompletedTapCount == 0) {
-                        transitionToDelegatingStateAndClear();
-
-                    }
-                }
-                break;
-            }
-        }
-        // LINT.ThenChange(:detecting_state)
-
-        @Override
-        public void clear() {
-            mCompletedTapCount = 0;
-            setShortcutTriggered(false);
-            removePendingDelayedMessages();
-            clearDelayedMotionEvents();
-            mFirstPointerDownLocation.set(Float.NaN, Float.NaN);
-            mSecondPointerDownLocation.set(Float.NaN, Float.NaN);
-        }
-
-        private boolean isMultiFingerMultiTapTriggered(int targetTapCount, MotionEvent event) {
-            if (event.getActionMasked() == ACTION_UP && mIsTwoFingerCountReached) {
-                mCompletedTapCount++;
-                mIsTwoFingerCountReached = false;
-            }
-
-            if (mDetectTwoFingerTripleTap && mCompletedTapCount > TWO_FINGER_GESTURE_MAX_TAPS - 1) {
-                final boolean enabled = !isActivated();
-                mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled);
-            }
-            return mDetectTwoFingerTripleTap && mCompletedTapCount == targetTapCount;
-        }
-
-        void transitionToDelegatingStateAndClear() {
-            mCompletedTapCount = 0;
-            transitionTo(mDelegatingState);
-            sendDelayedMotionEvents();
-            removePendingDelayedMessages();
-            mFirstPointerDownLocation.set(Float.NaN, Float.NaN);
-            mSecondPointerDownLocation.set(Float.NaN, Float.NaN);
-        }
-
-        void transitionToViewportDraggingStateAndClear(MotionEvent down) {
-
-            if (DEBUG_DETECTING) Slog.i(mLogTag, "onTripleTapAndHold()");
-            final boolean shortcutTriggered = mShortcutTriggered;
-
-            // Only log the 3tap and hold event
-            if (!shortcutTriggered) {
-                final boolean enabled = !isActivated();
-                if (mCompletedTapCount == TWO_FINGER_GESTURE_MAX_TAPS - 1) {
-                    // Two finger triple tap and hold
-                    mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled);
-                } else {
-                    // Triple tap and hold also belongs to triple tap event
-                    mMagnificationLogger.logMagnificationTripleTap(enabled);
-                }
-            }
-            clear();
-
-            mViewportDraggingState.prepareForZoomInTemporary(shortcutTriggered);
-            zoomInTemporary(down.getX(), down.getY(), shortcutTriggered);
-            transitionTo(mViewportDraggingState);
-        }
-    }
-
     /**
      * This class handles motion events when the event dispatch has not yet
      * determined what the user is doing. It watches for various tap events.
      */
     class DetectingState implements State, Handler.Callback {
 
-        protected static final int MESSAGE_ON_TRIPLE_TAP_AND_HOLD = 1;
-        protected static final int MESSAGE_TRANSITION_TO_DELEGATING_STATE = 2;
-        protected static final int MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE = 3;
+        private static final int MESSAGE_ON_TRIPLE_TAP_AND_HOLD = 1;
+        private static final int MESSAGE_TRANSITION_TO_DELEGATING_STATE = 2;
+        private static final int MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE = 3;
 
         final int mLongTapMinDelay;
         final int mSwipeMinDistance;
         final int mMultiTapMaxDelay;
         final int mMultiTapMaxDistance;
+        @Nullable final TwoFingerDoubleTapHandler mTwoFingerDoubleTapHandler;
 
-        protected MotionEventInfo mDelayedEventQueue;
-        protected MotionEvent mLastDown;
-        protected MotionEvent mPreLastDown;
-        protected MotionEvent mLastUp;
-        protected MotionEvent mPreLastUp;
+        private MotionEventInfo mDelayedEventQueue;
+        private MotionEvent mLastDown;
+        private MotionEvent mPreLastDown;
+        private MotionEvent mLastUp;
+        private MotionEvent mPreLastUp;
 
-        protected PointF mFirstPointerDownLocation = new PointF(Float.NaN, Float.NaN);
-        protected PointF mSecondPointerDownLocation = new PointF(Float.NaN, Float.NaN);
-        protected long mLastDetectingDownEventTime;
+        private PointF mFirstPointerDownLocation = new PointF(Float.NaN, Float.NaN);
+        private PointF mSecondPointerDownLocation = new PointF(Float.NaN, Float.NaN);
+        private long mLastDetectingDownEventTime;
 
         @VisibleForTesting boolean mShortcutTriggered;
 
@@ -1191,6 +901,9 @@
                     MagnificationGestureMatcher.getMagnificationMultiTapTimeout(context);
             mSwipeMinDistance = ViewConfiguration.get(context).getScaledTouchSlop();
             mMultiTapMaxDistance = ViewConfiguration.get(context).getScaledDoubleTapSlop();
+            mTwoFingerDoubleTapHandler =
+                    Flags.enableMagnificationMultipleFingerMultipleTapGesture()
+                            ? new TwoFingerDoubleTapHandler() : null;
         }
 
         @Override
@@ -1218,7 +931,6 @@
             return true;
         }
 
-        // LINT.IfChange(detecting_state)
         @Override
         public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
             cacheDelayedMotionEvent(event, rawEvent, policyFlags);
@@ -1244,6 +956,7 @@
                         transitionToDelegatingStateAndClear();
 
                     } else if (mDetectSingleFingerTripleTap
+                            || (mTwoFingerDoubleTapHandler != null && mDetectTwoFingerTripleTap)
                             // If activated, delay an ACTION_DOWN for mMultiTapMaxDelay
                             // to ensure reachability of
                             // STATE_PANNING_SCALING(triggerable with ACTION_POINTER_DOWN)
@@ -1259,6 +972,12 @@
                 }
                 break;
                 case ACTION_POINTER_DOWN: {
+                    if (mTwoFingerDoubleTapHandler != null) {
+                        mTwoFingerDoubleTapHandler.onPointerDown(event);
+                        break;
+                    }
+
+                    // LINT.IfChange(action_pointer_down)
                     if (isActivated() && event.getPointerCount() == 2) {
                         storePointerDownLocation(mSecondPointerDownLocation, event);
                         mHandler.sendEmptyMessageDelayed(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
@@ -1266,13 +985,26 @@
                     } else {
                         transitionToDelegatingStateAndClear();
                     }
+                    // LINT.ThenChange(:action_pointer_down_with_multi_finger)
                 }
                 break;
                 case ACTION_POINTER_UP: {
+                    if (mTwoFingerDoubleTapHandler != null) {
+                        mTwoFingerDoubleTapHandler.onPointerUp();
+                        break;
+                    }
+                    // LINT.IfChange(action_pointer_up)
                     transitionToDelegatingStateAndClear();
+                    // LINT.ThenChange(:action_pointer_up_with_multi_finger)
                 }
                 break;
                 case ACTION_MOVE: {
+                    if (mTwoFingerDoubleTapHandler != null) {
+                        mTwoFingerDoubleTapHandler.onMove(event);
+                        break;
+                    }
+
+                    // LINT.IfChange(action_move)
                     if (isFingerDown()
                             && distance(mLastDown, /* move */ event) > mSwipeMinDistance) {
                         // Swipe detected - transition immediately
@@ -1313,12 +1045,20 @@
                         //Second pointer is swiping, so transit to PanningScalingState
                         transitToPanningScalingStateAndClear();
                     }
+                    // LINT.ThenChange(:action_move_with_multi_finger)
                 }
                 break;
                 case ACTION_UP: {
 
                     mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD);
 
+                    if (mTwoFingerDoubleTapHandler != null) {
+                        mHandler.removeMessages(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE);
+                        mTwoFingerDoubleTapHandler.onUp(event);
+                        break;
+                    }
+
+                    // LINT.IfChange(action_up)
                     if (!mFullScreenMagnificationController.magnificationRegionContains(
                             mDisplayId, event.getX(), event.getY())) {
                         transitionToDelegatingStateAndClear();
@@ -1335,11 +1075,11 @@
                         transitionToDelegatingStateAndClear();
 
                     }
+                    // LINT.ThenChange(:action_up_with_multi_finger)
                 }
                 break;
             }
         }
-        // LINT.ThenChange(:detecting_state_with_multi_finger)
 
         protected void storePointerDownLocation(PointF pointerDownLocation, MotionEvent event) {
             final int index = event.getActionIndex();
@@ -1425,6 +1165,9 @@
 
         @Override
         public void clear() {
+            if (mTwoFingerDoubleTapHandler != null) {
+                mTwoFingerDoubleTapHandler.mCompletedTapCount = 0;
+            }
             setShortcutTriggered(false);
             removePendingDelayedMessages();
             clearDelayedMotionEvents();
@@ -1501,9 +1244,13 @@
         }
 
         void transitionToDelegatingStateAndClear() {
+            if (mTwoFingerDoubleTapHandler != null) {
+                mTwoFingerDoubleTapHandler.mCompletedTapCount = 0;
+            }
             transitionTo(mDelegatingState);
             sendDelayedMotionEvents();
             removePendingDelayedMessages();
+            mFirstPointerDownLocation.set(Float.NaN, Float.NaN);
             mSecondPointerDownLocation.set(Float.NaN, Float.NaN);
         }
 
@@ -1543,9 +1290,15 @@
 
             // Only log the 3tap and hold event
             if (!shortcutTriggered) {
-                // Triple tap and hold also belongs to triple tap event
                 final boolean enabled = !isActivated();
-                mMagnificationLogger.logMagnificationTripleTap(enabled);
+                if (mTwoFingerDoubleTapHandler != null
+                        && mTwoFingerDoubleTapHandler.shouldLogTwoFingerDoubleTap()) {
+                    // Two finger double tap and hold
+                    mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled);
+                } else {
+                    // Triple tap and hold also belongs to triple tap event
+                    mMagnificationLogger.logMagnificationTripleTap(enabled);
+                }
             }
             clear();
 
@@ -1604,6 +1357,173 @@
             }
             return false;
         }
+
+        final class TwoFingerDoubleTapHandler {
+            private static final int TWO_FINGER_GESTURE_MAX_TAPS = 2;
+            // A tap counts when two fingers are down and up once.
+            private int mCompletedTapCount;
+            // A flag set to true when two fingers have touched down.
+            // Used to indicate what next finger action should be.
+            private boolean mIsTwoFingerCountReached;
+
+            TwoFingerDoubleTapHandler() {
+                mCompletedTapCount = 0;
+                mIsTwoFingerCountReached = false;
+            }
+
+            private void onPointerDown(MotionEvent event) {
+                mIsTwoFingerCountReached = mDetectTwoFingerTripleTap
+                        && event.getPointerCount() == 2;
+                mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
+
+                // LINT.IfChange(action_pointer_down_with_multi_finger)
+                if (event.getPointerCount() == 2) {
+                    if (isMultiFingerMultiTapTriggered(
+                            TWO_FINGER_GESTURE_MAX_TAPS - 1, event)) {
+                        // 3tap and hold
+                        afterLongTapTimeoutTransitionToDraggingState(event);
+                    } else {
+                        if (mDetectTwoFingerTripleTap) {
+                            // If mDetectTwoFingerTripleTap, delay transition to the delegating
+                            // state for mMultiTapMaxDelay to ensure reachability of
+                            // multi finger multi tap
+                            afterMultiTapTimeoutTransitionToDelegatingState();
+                        }
+
+                        if (isActivated()) {
+                            // If activated, delay transition to the panning scaling
+                            // state for tap timeout to ensure reachability of
+                            // multi finger multi tap
+                            storePointerDownLocation(mSecondPointerDownLocation, event);
+                            mHandler.sendEmptyMessageDelayed(
+                                    MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
+                                    ViewConfiguration.getTapTimeout());
+                        }
+                    }
+                } else {
+                    transitionToDelegatingStateAndClear();
+                }
+                // LINT.ThenChange(:action_pointer_down)
+            }
+
+            private void onMove(MotionEvent event) {
+                // LINT.IfChange(action_move_with_multi_finger)
+                if (isFingerDown()
+                        && distance(mLastDown, /* move */ event) > mSwipeMinDistance) {
+                    // Swipe detected - transition immediately
+
+                    // For convenience, viewport dragging takes precedence
+                    // over insta-delegating on 3tap&swipe
+                    // (which is a rare combo to be used aside from magnification)
+                    if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) {
+                        transitionToViewportDraggingStateAndClear(event);
+                    } else if (isMultiFingerMultiTapTriggered(
+                            TWO_FINGER_GESTURE_MAX_TAPS - 1, event)
+                            && event.getPointerCount() == 2) {
+                        transitionToViewportDraggingStateAndClear(event);
+                    } else if (isActivated() && event.getPointerCount() == 2) {
+                        if (mOverscrollHandler != null
+                                && overscrollState(event, mFirstPointerDownLocation)
+                                == OVERSCROLL_VERTICAL_EDGE) {
+                            transitionToDelegatingStateAndClear();
+                        } else {
+                            //Primary pointer is swiping, so transit to PanningScalingState
+                            transitToPanningScalingStateAndClear();
+                        }
+                    } else if (mOneFingerPanningSettingsProvider.isOneFingerPanningEnabled()
+                            && isActivated()
+                            && event.getPointerCount() == 1) {
+                        if (mOverscrollHandler != null
+                                && overscrollState(event, mFirstPointerDownLocation)
+                                == OVERSCROLL_VERTICAL_EDGE) {
+                            transitionToDelegatingStateAndClear();
+                        } else if (overscrollState(event, mFirstPointerDownLocation)
+                                != OVERSCROLL_NONE) {
+                            transitionToDelegatingStateAndClear();
+                        } else {
+                            transitToSinglePanningStateAndClear();
+                        }
+                    } else if (!mIsTwoFingerCountReached) {
+                        // If it is a two-finger gesture, do not transition to the
+                        // delegating state to ensure the reachability of
+                        // the two-finger triple tap (triggerable with ACTION_UP)
+                        transitionToDelegatingStateAndClear();
+                    }
+                } else if (isActivated() && pointerDownValid(mSecondPointerDownLocation)
+                        && distanceClosestPointerToPoint(
+                        mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance) {
+                    // Second pointer is swiping, so transit to PanningScalingState
+                    // Delay an ACTION_MOVE for tap timeout to ensure it is not trigger from
+                    // multi finger multi tap
+                    storePointerDownLocation(mSecondPointerDownLocation, event);
+                    mHandler.sendEmptyMessageDelayed(
+                            MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
+                            ViewConfiguration.getTapTimeout());
+                }
+                // LINT.ThenChange(:action_move)
+            }
+
+            private void onPointerUp() {
+                // If it is a two-finger gesture, do not transition to the delegating state
+                // to ensure the reachability of
+                // the two-finger triple tap (triggerable with ACTION_MOVE and ACTION_UP)
+                // LINT.IfChange(action_pointer_up_with_multi_finger)
+                if (!mIsTwoFingerCountReached) {
+                    transitionToDelegatingStateAndClear();
+                }
+                // LINT.ThenChange(:action_pointer_up)
+            }
+
+            private void onUp(MotionEvent event) {
+                // LINT.IfChange(action_up_with_multi_finger)
+                if (!mFullScreenMagnificationController.magnificationRegionContains(
+                        mDisplayId, event.getX(), event.getY())) {
+                    transitionToDelegatingStateAndClear();
+
+                } else if (isMultiFingerMultiTapTriggered(
+                        TWO_FINGER_GESTURE_MAX_TAPS, event)) {
+                    // Placing multiple fingers before a single finger, because achieving a
+                    // multi finger multi tap also means achieving a single finger
+                    // triple tap
+                    onTripleTap(event);
+
+                } else if (isMultiTapTriggered(3 /* taps */)) {
+                    onTripleTap(/* up */ event);
+
+                } else if (
+                    // Possible to be false on: 3tap&drag -> scale -> PTR_UP -> UP
+                        isFingerDown()
+                                //TODO long tap should never happen here
+                                && ((timeBetween(mLastDown, mLastUp) >= mLongTapMinDelay)
+                                || (distance(mLastDown, mLastUp) >= mSwipeMinDistance))
+                                // If it is a two-finger but not reach 3 tap, do not
+                                // transition to the delegating state to ensure the
+                                // reachability of the triple tap
+                                && mCompletedTapCount == 0) {
+                    transitionToDelegatingStateAndClear();
+                }
+                // LINT.ThenChange(:action_up)
+            }
+
+            private boolean isMultiFingerMultiTapTriggered(int targetTapCount, MotionEvent event) {
+                if (event.getActionMasked() == ACTION_UP && mIsTwoFingerCountReached) {
+                    mCompletedTapCount++;
+                    mIsTwoFingerCountReached = false;
+                }
+
+                if (mDetectTwoFingerTripleTap
+                        && mCompletedTapCount > TWO_FINGER_GESTURE_MAX_TAPS - 1) {
+                    final boolean enabled = !isActivated();
+                    mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled);
+                }
+                return mDetectTwoFingerTripleTap && mCompletedTapCount == targetTapCount;
+            }
+
+            private boolean shouldLogTwoFingerDoubleTap() {
+                return mCompletedTapCount
+                        == TwoFingerDoubleTapHandler.TWO_FINGER_GESTURE_MAX_TAPS - 1;
+            }
+        }
     }
 
     private void zoomInTemporary(float centerX, float centerY, boolean shortcutTriggered) {
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index 2db5443..1be352e 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -137,11 +137,6 @@
                     | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH
                     | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS;
 
-    private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS_PRE_VIC =
-            DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
-                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT
-                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
-
     private static final String PERSISTENT_ID_PREFIX_CDM_ASSOCIATION = "companion:";
 
     /**
@@ -373,9 +368,6 @@
         }
 
         int flags = DEFAULT_VIRTUAL_DISPLAY_FLAGS;
-        if (!Flags.consistentDisplayFlags()) {
-            flags |= DEFAULT_VIRTUAL_DISPLAY_FLAGS_PRE_VIC;
-        }
         if (mParams.getLockState() == VirtualDeviceParams.LOCK_STATE_ALWAYS_UNLOCKED) {
             flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
         }
@@ -1254,10 +1246,6 @@
     // as the virtual display doesn't have any focused windows. Hence, call this for
     // associating any input device to the source display if the input device emits any key events.
     private int getTargetDisplayIdForInput(int displayId) {
-        if (!Flags.interactiveScreenMirror()) {
-            return displayId;
-        }
-
         DisplayManagerInternal displayManager = LocalServices.getService(
                 DisplayManagerInternal.class);
         int mirroredDisplayId = displayManager.getDisplayIdToMirror(displayId);
@@ -1313,9 +1301,9 @@
         int displayId;
         displayId = mDisplayManagerInternal.createVirtualDisplay(virtualDisplayConfig, callback,
                 this, gwpc, packageName);
-        gwpc.setDisplayId(displayId, /* isMirrorDisplay= */ Flags.interactiveScreenMirror()
-                && mDisplayManagerInternal.getDisplayIdToMirror(displayId)
-                != Display.INVALID_DISPLAY);
+        boolean isMirrorDisplay =
+                mDisplayManagerInternal.getDisplayIdToMirror(displayId) != Display.INVALID_DISPLAY;
+        gwpc.setDisplayId(displayId, isMirrorDisplay);
 
         boolean showPointer;
         synchronized (mVirtualDeviceLock) {
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 0815384..e84250d 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -309,13 +309,14 @@
      */
     public void registerHealthObserver(PackageHealthObserver observer) {
         synchronized (mLock) {
-            ObserverInternal internalObserver = mAllObservers.get(observer.getName());
+            ObserverInternal internalObserver = mAllObservers.get(observer.getUniqueIdentifier());
             if (internalObserver != null) {
                 internalObserver.registeredObserver = observer;
             } else {
-                internalObserver = new ObserverInternal(observer.getName(), new ArrayList<>());
+                internalObserver = new ObserverInternal(observer.getUniqueIdentifier(),
+                        new ArrayList<>());
                 internalObserver.registeredObserver = observer;
-                mAllObservers.put(observer.getName(), internalObserver);
+                mAllObservers.put(observer.getUniqueIdentifier(), internalObserver);
                 syncState("added new observer");
             }
         }
@@ -342,12 +343,12 @@
     public void startObservingHealth(PackageHealthObserver observer, List<String> packageNames,
             long durationMs) {
         if (packageNames.isEmpty()) {
-            Slog.wtf(TAG, "No packages to observe, " + observer.getName());
+            Slog.wtf(TAG, "No packages to observe, " + observer.getUniqueIdentifier());
             return;
         }
         if (durationMs < 1) {
             Slog.wtf(TAG, "Invalid duration " + durationMs + "ms for observer "
-                    + observer.getName() + ". Not observing packages " + packageNames);
+                    + observer.getUniqueIdentifier() + ". Not observing packages " + packageNames);
             durationMs = DEFAULT_OBSERVING_DURATION_MS;
         }
 
@@ -374,14 +375,14 @@
             syncState("observing new packages");
 
             synchronized (mLock) {
-                ObserverInternal oldObserver = mAllObservers.get(observer.getName());
+                ObserverInternal oldObserver = mAllObservers.get(observer.getUniqueIdentifier());
                 if (oldObserver == null) {
-                    Slog.d(TAG, observer.getName() + " started monitoring health "
+                    Slog.d(TAG, observer.getUniqueIdentifier() + " started monitoring health "
                             + "of packages " + packageNames);
-                    mAllObservers.put(observer.getName(),
-                            new ObserverInternal(observer.getName(), packages));
+                    mAllObservers.put(observer.getUniqueIdentifier(),
+                            new ObserverInternal(observer.getUniqueIdentifier(), packages));
                 } else {
-                    Slog.d(TAG, observer.getName() + " added the following "
+                    Slog.d(TAG, observer.getUniqueIdentifier() + " added the following "
                             + "packages to monitor " + packageNames);
                     oldObserver.updatePackagesLocked(packages);
                 }
@@ -405,9 +406,9 @@
     public void unregisterHealthObserver(PackageHealthObserver observer) {
         mLongTaskHandler.post(() -> {
             synchronized (mLock) {
-                mAllObservers.remove(observer.getName());
+                mAllObservers.remove(observer.getUniqueIdentifier());
             }
-            syncState("unregistering observer: " + observer.getName());
+            syncState("unregistering observer: " + observer.getUniqueIdentifier());
         });
     }
 
@@ -781,7 +782,7 @@
          * Identifier for the observer, should not change across device updates otherwise the
          * watchdog may drop observing packages with the old name.
          */
-        String getName();
+        String getUniqueIdentifier();
 
         /**
          * An observer will not be pruned if this is set, even if the observer is not explicitly
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index c2cb5e9..bba97fa 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -917,7 +917,7 @@
         }
 
         @Override
-        public String getName() {
+        public String getUniqueIdentifier() {
             return NAME;
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 91b549c9..68d9221 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15312,12 +15312,17 @@
         final int cookie = traceBroadcastIntentBegin(intent, resultTo, ordered, sticky,
                 callingUid, realCallingUid, userId);
         try {
+            final BroadcastSentEventRecord broadcastSentEventRecord =
+                    new BroadcastSentEventRecord();
             final int res = broadcastIntentLockedTraced(callerApp, callerPackage, callerFeatureId,
                     intent, resolvedType, resultToApp, resultTo, resultCode, resultData,
                     resultExtras, requiredPermissions, excludedPermissions, excludedPackages,
                     appOp, BroadcastOptions.fromBundleNullable(bOptions), ordered, sticky,
                     callingPid, callingUid, realCallingUid, realCallingPid, userId,
-                    backgroundStartPrivileges, broadcastAllowList, filterExtrasForReceiver);
+                    backgroundStartPrivileges, broadcastAllowList, filterExtrasForReceiver,
+                    broadcastSentEventRecord);
+            broadcastSentEventRecord.setResult(res);
+            broadcastSentEventRecord.logToStatsd();
             return res;
         } finally {
             traceBroadcastIntentEnd(cookie);
@@ -15365,7 +15370,8 @@
             int callingUid, int realCallingUid, int realCallingPid, int userId,
             BackgroundStartPrivileges backgroundStartPrivileges,
             @Nullable int[] broadcastAllowList,
-            @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) {
+            @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
+            @NonNull BroadcastSentEventRecord broadcastSentEventRecord) {
         // Ensure all internal loopers are registered for idle checks
         BroadcastLoopers.addMyLooper();
 
@@ -15398,6 +15404,17 @@
         }
 
         intent = new Intent(intent);
+        broadcastSentEventRecord.setIntent(intent);
+        broadcastSentEventRecord.setOriginalIntentFlags(intent.getFlags());
+        broadcastSentEventRecord.setSenderUid(callingUid);
+        broadcastSentEventRecord.setRealSenderUid(realCallingUid);
+        broadcastSentEventRecord.setSticky(sticky);
+        broadcastSentEventRecord.setOrdered(ordered);
+        broadcastSentEventRecord.setResultRequested(resultTo != null);
+        final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid);
+        broadcastSentEventRecord.setSenderProcState(callerAppProcessState);
+        broadcastSentEventRecord.setSenderUidState(getRealUidStateLocked(callerApp,
+                realCallingPid));
 
         final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
         // Instant Apps cannot use FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS
@@ -15891,7 +15908,6 @@
             }
         }
 
-        final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid);
         // Add to the sticky list if requested.
         if (sticky) {
             if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
@@ -16131,6 +16147,7 @@
                     ordered, sticky, false, userId,
                     backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
                     callerAppProcessState);
+            broadcastSentEventRecord.setBroadcastRecord(r);
 
             if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);
             queue.enqueueBroadcastLocked(r);
@@ -16187,6 +16204,22 @@
         return PROCESS_STATE_NONEXISTENT;
     }
 
+    @GuardedBy("this")
+    private int getRealUidStateLocked(ProcessRecord app, int pid) {
+        if (app == null) {
+            synchronized (mPidsSelfLocked) {
+                app = mPidsSelfLocked.get(pid);
+            }
+        }
+        if (app != null && app.getThread() != null && !app.isKilled()) {
+            final UidRecord uidRecord = app.getUidRecord();
+            if (uidRecord != null) {
+                return uidRecord.getCurProcState();
+            }
+        }
+        return PROCESS_STATE_NONEXISTENT;
+    }
+
     @VisibleForTesting
     ArrayList<StickyBroadcast> getStickyBroadcastsForTest(String action, int userId) {
         synchronized (mStickyBroadcasts) {
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index edb04c5..f908c67 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -53,6 +53,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.ArrayMap;
+import android.util.IntArray;
 import android.util.PrintWriterPrinter;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
@@ -940,6 +941,46 @@
         return type;
     }
 
+    int[] calculateTypesForLogging() {
+        final IntArray types = new IntArray();
+        if (isForeground()) {
+            types.add(BROADCAST_TYPE_FOREGROUND);
+        } else {
+            types.add(BROADCAST_TYPE_BACKGROUND);
+        }
+        if (alarm) {
+            types.add(BROADCAST_TYPE_ALARM);
+        }
+        if (interactive) {
+            types.add(BROADCAST_TYPE_INTERACTIVE);
+        }
+        if (ordered) {
+            types.add(BROADCAST_TYPE_ORDERED);
+        }
+        if (prioritized) {
+            types.add(BROADCAST_TYPE_PRIORITIZED);
+        }
+        if (resultTo != null) {
+            types.add(BROADCAST_TYPE_RESULT_TO);
+        }
+        if (deferUntilActive) {
+            types.add(BROADCAST_TYPE_DEFERRABLE_UNTIL_ACTIVE);
+        }
+        if (pushMessage) {
+            types.add(BROADCAST_TYPE_PUSH_MESSAGE);
+        }
+        if (pushMessageOverQuota) {
+            types.add(BROADCAST_TYPE_PUSH_MESSAGE_OVER_QUOTA);
+        }
+        if (sticky) {
+            types.add(BROADCAST_TYPE_STICKY);
+        }
+        if (initialSticky) {
+            types.add(BROADCAST_TYPE_INITIAL_STICKY);
+        }
+        return types.toArray();
+    }
+
     public BroadcastRecord maybeStripForHistory() {
         if (!intent.canStripForHistory()) {
             return this;
diff --git a/services/core/java/com/android/server/am/BroadcastSentEventRecord.java b/services/core/java/com/android/server/am/BroadcastSentEventRecord.java
new file mode 100644
index 0000000..f2ac6d5
--- /dev/null
+++ b/services/core/java/com/android/server/am/BroadcastSentEventRecord.java
@@ -0,0 +1,134 @@
+/*
+ * 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.server.am;
+
+import static android.app.AppProtoEnums.BROADCAST_TYPE_ORDERED;
+import static android.app.AppProtoEnums.BROADCAST_TYPE_RESULT_TO;
+import static android.app.AppProtoEnums.BROADCAST_TYPE_STICKY;
+
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__FAILED_STICKY_CANT_HAVE_PERMISSION;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__FAILED_USER_STOPPED;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__SUCCESS;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_SENT__RESULT__UNKNOWN;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.content.Intent;
+import android.util.IntArray;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+final class BroadcastSentEventRecord {
+    @NonNull private Intent mIntent;
+    private int mOriginalIntentFlags;
+    private int mSenderUid;
+    private int mRealSenderUid;
+    private boolean mSticky;
+    private boolean mOrdered;
+    private boolean mResultRequested;
+    private int mSenderProcState;
+    private int mSenderUidState;
+    @Nullable private BroadcastRecord mBroadcastRecord;
+    private int mResult;
+
+    public void setIntent(@NonNull Intent intent) {
+        mIntent = intent;
+    }
+
+    public void setSenderUid(int uid) {
+        mSenderUid = uid;
+    }
+
+    public void setRealSenderUid(int uid) {
+        mRealSenderUid = uid;
+    }
+
+    public void setOriginalIntentFlags(int flags) {
+        mOriginalIntentFlags = flags;
+    }
+
+    public void setSticky(boolean sticky) {
+        mSticky = sticky;
+    }
+
+    public void setOrdered(boolean ordered) {
+        mOrdered = ordered;
+    }
+
+    public void setResultRequested(boolean resultRequested) {
+        mResultRequested = resultRequested;
+    }
+
+    public void setSenderProcState(int procState) {
+        mSenderProcState = procState;
+    }
+
+    public void setSenderUidState(int procState) {
+        mSenderUidState = procState;
+    }
+
+    public void setBroadcastRecord(@NonNull BroadcastRecord record) {
+        mBroadcastRecord = record;
+    }
+
+    public void setResult(int result) {
+        mResult = result;
+    }
+
+    public void logToStatsd() {
+        if (Flags.logBroadcastSentEvent()) {
+            int loggingResult = switch (mResult) {
+                case ActivityManager.BROADCAST_SUCCESS ->
+                        BROADCAST_SENT__RESULT__SUCCESS;
+                case ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION ->
+                        BROADCAST_SENT__RESULT__FAILED_STICKY_CANT_HAVE_PERMISSION;
+                case ActivityManager.BROADCAST_FAILED_USER_STOPPED ->
+                        BROADCAST_SENT__RESULT__FAILED_USER_STOPPED;
+                default -> BROADCAST_SENT__RESULT__UNKNOWN;
+            };
+            int[] types = calculateTypesForLogging();
+            FrameworkStatsLog.write(BROADCAST_SENT, mIntent.getAction(), mIntent.getFlags(),
+                    mOriginalIntentFlags, mSenderUid, mRealSenderUid, mIntent.getPackage() != null,
+                    mIntent.getComponent() != null,
+                    mBroadcastRecord != null ? mBroadcastRecord.receivers.size() : 0,
+                    loggingResult,
+                    mBroadcastRecord != null ? mBroadcastRecord.getDeliveryGroupPolicy() : 0,
+                    ActivityManager.processStateAmToProto(mSenderProcState),
+                    ActivityManager.processStateAmToProto(mSenderUidState), types);
+        }
+    }
+
+    private int[] calculateTypesForLogging() {
+        if (mBroadcastRecord != null) {
+            return mBroadcastRecord.calculateTypesForLogging();
+        } else {
+            final IntArray types = new IntArray();
+            if (mSticky) {
+                types.add(BROADCAST_TYPE_STICKY);
+            }
+            if (mOrdered) {
+                types.add(BROADCAST_TYPE_ORDERED);
+            }
+            if (mResultRequested) {
+                types.add(BROADCAST_TYPE_RESULT_TO);
+            }
+            return types.toArray();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index 5315167..3334393 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -184,3 +184,14 @@
     description: "Defer submitting binder calls to paused processes."
     bug: "327038797"
 }
+
+flag {
+    name: "log_broadcast_sent_event"
+    namespace: "backstage_power"
+    description: "Log the broadcast send event to Statsd"
+    bug: "355261986"
+    is_fixed_read_only: true
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java
index f31b2e1..2c52e3d 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java
@@ -241,6 +241,14 @@
                 -1 /* sensorId */);
     }
 
+    /** {@see FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED}. */
+    public void reportFingerprintsLoe(int statsModality) {
+        FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
+                statsModality,
+                BiometricsProtoEnums.ISSUE_FINGERPRINTS_LOE,
+                -1 /* sensorId */);
+    }
+
     /** {@see FrameworkStatsLog.BIOMETRIC_FRR_NOTIFICATION}. */
     public void logFrameworkNotification(int action, int modality) {
         FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_FRR_NOTIFICATION,
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
index ff1e5d5..9351bc0 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
@@ -296,6 +296,15 @@
         mSink.reportUnknownTemplateEnrolledFramework(mStatsModality);
     }
 
+    /** Report unknown enrollment in framework settings */
+    public void logFingerprintsLoe() {
+        if (shouldSkipLogging()) {
+            return;
+        }
+
+        mSink.reportFingerprintsLoe(mStatsModality);
+    }
+
     /**
      * Get a callback to start/stop ALS capture when the client runs. Do not create
      * multiple callbacks since there is at most one light sensor (they will all share
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
index 77e27ba..7bd905b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
@@ -161,6 +161,11 @@
 
         getLogger().logUnknownEnrollmentInHal();
 
+        if (mBiometricUtils.hasValidBiometricUserState(getContext(), getTargetUserId())
+                && Flags.notifyFingerprintsLoe()) {
+            getLogger().logFingerprintsLoe();
+        }
+
         mCurrentTask.start(mRemoveCallback);
     }
 
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 9e905ab..55a6ce7 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -64,7 +64,6 @@
 import android.app.compat.CompatChanges;
 import android.companion.virtual.IVirtualDevice;
 import android.companion.virtual.VirtualDeviceManager;
-import android.companion.virtual.flags.Flags;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
 import android.content.BroadcastReceiver;
@@ -1633,8 +1632,7 @@
                 && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
             // Only a valid media projection or a virtual device can create a mirror virtual
             // display.
-            if (!canProjectVideo(projection)
-                    && !isMirroringSupportedByVirtualDevice(virtualDevice)) {
+            if (!canProjectVideo(projection) && virtualDevice == null) {
                 throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
                         + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
                         + "MediaProjection token in order to create a screen sharing virtual "
@@ -1896,10 +1894,6 @@
         return -1;
     }
 
-    private static boolean isMirroringSupportedByVirtualDevice(IVirtualDevice virtualDevice) {
-        return Flags.interactiveScreenMirror() && virtualDevice != null;
-    }
-
     private void resizeVirtualDisplayInternal(IBinder appToken,
             int width, int height, int densityDpi) {
         synchronized (mSyncRoot) {
diff --git a/services/core/java/com/android/server/display/ExternalDisplayPolicy.java b/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
index 44c8d1c..28a0b28 100644
--- a/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
+++ b/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
@@ -231,7 +231,7 @@
         if (!isExternalDisplayAllowed()) {
             Slog.w(TAG, "handleExternalDisplayConnectedLocked: External display can not be used"
                                 + " because it is currently not allowed.");
-            mDisplayNotificationManager.onHighTemperatureExternalDisplayNotAllowed();
+            mHandler.post(mDisplayNotificationManager::onHighTemperatureExternalDisplayNotAllowed);
             return;
         }
 
@@ -329,7 +329,7 @@
 
         if (!isExternalDisplayAllowed()) {
             Slog.w(TAG, "External display is currently not allowed and is getting disabled.");
-            mDisplayNotificationManager.onHighTemperatureExternalDisplayNotAllowed();
+            mHandler.post(mDisplayNotificationManager::onHighTemperatureExternalDisplayNotAllowed);
         }
 
         mLogicalDisplayMapper.setDisplayEnabledLocked(logicalDisplay, /*enabled=*/ false);
diff --git a/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java b/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java
index 280a7e1..8a8440b 100644
--- a/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java
+++ b/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java
@@ -26,6 +26,7 @@
 import android.app.NotificationManager;
 import android.content.Context;
 import android.content.res.Resources;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.internal.R;
@@ -197,7 +198,8 @@
             return;
         }
 
-        mNotificationManager.cancel(DISPLAY_NOTIFICATION_TAG, DISPLAY_NOTIFICATION_ID);
+        mNotificationManager.cancelAsUser(DISPLAY_NOTIFICATION_TAG, DISPLAY_NOTIFICATION_ID,
+                UserHandle.CURRENT);
     }
 
     /**
@@ -210,8 +212,8 @@
             return;
         }
 
-        mNotificationManager.notify(DISPLAY_NOTIFICATION_TAG, DISPLAY_NOTIFICATION_ID,
-                notification);
+        mNotificationManager.notifyAsUser(DISPLAY_NOTIFICATION_TAG, DISPLAY_NOTIFICATION_ID,
+                notification, UserHandle.CURRENT);
     }
 
     /**
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 154710f..81c30dd 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1225,11 +1225,15 @@
         boolean avrSystemAudioMode = HdmiUtils.parseCommandParamSystemAudioStatus(message);
         // Set System Audio Mode according to TV's settings.
         // Handle <System Audio Mode Status> here only when
-        // SystemAudioAutoInitiationAction timeout
+        // SystemAudioAutoInitiationAction timeout.
+        // If AVR reports SAM on and it is in standby, the action SystemAudioActionFromTv
+        // triggers a <SAM Request> that will wake-up the AVR.
         HdmiDeviceInfo avr = getAvrDeviceInfo();
         if (avr == null) {
             setSystemAudioMode(false);
-        } else if (avrSystemAudioMode != tvSystemAudioMode) {
+        } else if (avrSystemAudioMode != tvSystemAudioMode
+                    || (avrSystemAudioMode && avr.getDevicePowerStatus()
+                        == HdmiControlManager.POWER_STATUS_STANDBY)) {
             addAndStartAction(new SystemAudioActionFromTv(this, avr.getLogicalAddress(),
                     tvSystemAudioMode, null));
         } else {
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
index 56e538b..028637b 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
@@ -16,7 +16,9 @@
 
 package com.android.server.hdmi;
 
+import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
@@ -89,8 +91,13 @@
 
         // If System Audio Control feature is enabled, turn on system audio mode when new AVR is
         // detected. Otherwise, turn off system audio mode.
+        // If AVR reports SAM on and it is in standby, the action SystemAudioActionFromTv
+        // triggers a <SAM Request> that will wake-up the AVR.
         boolean targetSystemAudioMode = tv().isSystemAudioControlFeatureEnabled();
-        if (currentSystemAudioMode != targetSystemAudioMode) {
+        if (currentSystemAudioMode != targetSystemAudioMode
+                || (currentSystemAudioMode && tv().getAvrDeviceInfo() != null
+                && tv().getAvrDeviceInfo().getDevicePowerStatus()
+                == HdmiControlManager.POWER_STATUS_STANDBY)) {
             // Start System Audio Control feature actions only if necessary.
             addAndStartAction(
                     new SystemAudioActionFromTv(tv(), mAvrAddress, targetSystemAudioMode, null));
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 1070f2f..e1b8e9f 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -1364,14 +1364,14 @@
             if (manager == null || manager.mLastSessionCreationRequest == null) {
                 Slog.w(TAG, "requestCreateSessionWithRouter2Locked: "
                         + "Ignoring unknown request.");
-                userHandler.notifySessionCreationFailedToRouter(routerRecord, requestId);
+                routerRecord.notifySessionCreationFailed(requestId);
                 return;
             }
             if (!TextUtils.equals(manager.mLastSessionCreationRequest.mOldSession.getId(),
                     oldSession.getId())) {
                 Slog.w(TAG, "requestCreateSessionWithRouter2Locked: "
                         + "Ignoring unmatched routing session.");
-                userHandler.notifySessionCreationFailedToRouter(routerRecord, requestId);
+                routerRecord.notifySessionCreationFailed(requestId);
                 return;
             }
             if (!TextUtils.equals(manager.mLastSessionCreationRequest.mRoute.getId(),
@@ -1384,7 +1384,7 @@
                 } else {
                     Slog.w(TAG, "requestCreateSessionWithRouter2Locked: "
                             + "Ignoring unmatched route.");
-                    userHandler.notifySessionCreationFailedToRouter(routerRecord, requestId);
+                    routerRecord.notifySessionCreationFailed(requestId);
                     return;
                 }
             }
@@ -1396,7 +1396,7 @@
                     && !TextUtils.equals(route.getId(), defaultRouteId)) {
                 Slog.w(TAG, "MODIFY_AUDIO_ROUTING permission is required to transfer to"
                         + route);
-                userHandler.notifySessionCreationFailedToRouter(routerRecord, requestId);
+                routerRecord.notifySessionCreationFailed(requestId);
                 return;
             }
         }
@@ -1484,8 +1484,7 @@
                 && !TextUtils.equals(route.getId(), defaultRouteId)) {
             userHandler.sendMessage(
                     obtainMessage(
-                            UserHandler::notifySessionCreationFailedToRouter,
-                            userHandler,
+                            RouterRecord::notifySessionCreationFailed,
                             routerRecord,
                             toOriginalRequestId(DUMMY_REQUEST_ID)));
         } else {
@@ -1762,12 +1761,7 @@
         if (routerRecord == null) {
             Slog.w(TAG, "requestCreateSessionWithManagerLocked: Ignoring session creation for "
                     + "unknown router.");
-            try {
-                managerRecord.mManager.notifyRequestFailed(requestId, REASON_UNKNOWN_ERROR);
-            } catch (RemoteException ex) {
-                Slog.w(TAG, "requestCreateSessionWithManagerLocked: Failed to notify failure. "
-                        + "Manager probably died.");
-            }
+            managerRecord.notifyRequestFailed(requestId, REASON_UNKNOWN_ERROR);
             return;
         }
 
@@ -1780,10 +1774,8 @@
                             "requestCreateSessionWithManagerLocked: Notifying failure for pending"
                                 + " session creation request - oldSession: %s, route: %s",
                             lastRequest.mOldSession, lastRequest.mRoute));
-            managerRecord.mUserRecord.mHandler.notifyRequestFailedToManager(
-                    managerRecord.mManager,
-                    toOriginalRequestId(lastRequest.mManagerRequestId),
-                    REASON_UNKNOWN_ERROR);
+            managerRecord.notifyRequestFailed(
+                    toOriginalRequestId(lastRequest.mManagerRequestId), REASON_UNKNOWN_ERROR);
         }
         managerRecord.mLastSessionCreationRequest = new SessionCreationRequest(routerRecord,
                 MediaRoute2ProviderService.REQUEST_ID_NONE, uniqueRequestId,
@@ -1793,15 +1785,12 @@
         // As a return, media router will request to create a session.
         routerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(
-                        UserHandler::requestRouterCreateSessionOnHandler,
-                        routerRecord.mUserRecord.mHandler,
-                        uniqueRequestId,
+                        RouterRecord::requestCreateSessionByManager,
                         routerRecord,
                         managerRecord,
+                        uniqueRequestId,
                         oldSession,
-                        route,
-                        transferInitiatorUserHandle,
-                        transferInitiatorPackageName));
+                        route));
     }
 
     @GuardedBy("mLock")
@@ -2256,6 +2245,71 @@
         }
 
         /**
+         * Notifies the corresponding router of a request failure.
+         *
+         * @param requestId The id of the request that failed.
+         */
+        public void notifySessionCreationFailed(int requestId) {
+            try {
+                mRouter.notifySessionCreated(requestId, /* sessionInfo= */ null);
+            } catch (RemoteException ex) {
+                Slog.w(
+                        TAG,
+                        "Failed to notify router of the session creation failure."
+                                + " Router probably died.",
+                        ex);
+            }
+        }
+
+        /**
+         * Notifies the corresponding router of the release of the given {@link RoutingSessionInfo}.
+         */
+        public void notifySessionReleased(RoutingSessionInfo sessionInfo) {
+            try {
+                mRouter.notifySessionReleased(sessionInfo);
+            } catch (RemoteException ex) {
+                Slog.w(
+                        TAG,
+                        "Failed to notify router of the session release. Router probably died.",
+                        ex);
+            }
+        }
+
+        /**
+         * Sends the corresponding router a {@link RoutingSessionInfo session} creation request,
+         * with the given {@link MediaRoute2Info} as the initial member.
+         *
+         * <p>Must be called on the thread of the corresponding {@link UserHandler}.
+         *
+         * @param managerRecord The record of the manager that made the request.
+         * @param uniqueRequestId The id of the request.
+         * @param oldSession The session from which the transfer originated.
+         * @param route The initial route member of the session to create.
+         */
+        public void requestCreateSessionByManager(
+                ManagerRecord managerRecord,
+                long uniqueRequestId,
+                RoutingSessionInfo oldSession,
+                MediaRoute2Info route) {
+            try {
+                if (route.isSystemRoute() && !hasSystemRoutingPermission()) {
+                    // The router lacks permission to modify system routing, so we hide system
+                    // route info from them.
+                    route = mUserRecord.mHandler.mSystemProvider.getDefaultRoute();
+                }
+                mRouter.requestCreateSessionByManager(uniqueRequestId, oldSession, route);
+            } catch (RemoteException ex) {
+                Slog.w(
+                        TAG,
+                        "getSessionHintsForCreatingSessionOnHandler: "
+                                + "Failed to request. Router probably died.",
+                        ex);
+                managerRecord.notifyRequestFailed(
+                        toOriginalRequestId(uniqueRequestId), REASON_UNKNOWN_ERROR);
+            }
+        }
+
+        /**
          * Sends the corresponding router an update for the given session.
          *
          * <p>Note: These updates are not directly visible to the app.
@@ -2360,6 +2414,25 @@
             }
         }
 
+        /**
+         * Notifies the corresponding manager of a request failure.
+         *
+         * <p>Must be called on the thread of the corresponding {@link UserHandler}.
+         *
+         * @param requestId The id of the request that failed.
+         * @param reason The reason of the failure. One of
+         */
+        public void notifyRequestFailed(int requestId, int reason) {
+            try {
+                mManager.notifyRequestFailed(requestId, reason);
+            } catch (RemoteException ex) {
+                Slog.w(
+                        TAG,
+                        "Failed to notify manager of the request failure. Manager probably died.",
+                        ex);
+            }
+        }
+
         private void updateScanningState(@ScanningState int scanningState) {
             if (mScanningState == scanningState) {
                 return;
@@ -2738,30 +2811,6 @@
             return -1;
         }
 
-        private void requestRouterCreateSessionOnHandler(
-                long uniqueRequestId,
-                @NonNull RouterRecord routerRecord,
-                @NonNull ManagerRecord managerRecord,
-                @NonNull RoutingSessionInfo oldSession,
-                @NonNull MediaRoute2Info route,
-                @NonNull UserHandle transferInitiatorUserHandle,
-                @NonNull String transferInitiatorPackageName) {
-            try {
-                if (route.isSystemRoute() && !routerRecord.hasSystemRoutingPermission()) {
-                    // The router lacks permission to modify system routing, so we hide system
-                    // route info from them.
-                    route = mSystemProvider.getDefaultRoute();
-                }
-                routerRecord.mRouter.requestCreateSessionByManager(
-                        uniqueRequestId, oldSession, route);
-            } catch (RemoteException ex) {
-                Slog.w(TAG, "getSessionHintsForCreatingSessionOnHandler: "
-                        + "Failed to request. Router probably died.", ex);
-                notifyRequestFailedToManager(managerRecord.mManager,
-                        toOriginalRequestId(uniqueRequestId), REASON_UNKNOWN_ERROR);
-            }
-        }
-
         private void requestCreateSessionWithRouter2OnHandler(
                 long uniqueRequestId,
                 long managerRequestId,
@@ -2774,8 +2823,7 @@
             if (provider == null) {
                 Slog.w(TAG, "requestCreateSessionWithRouter2OnHandler: Ignoring session "
                         + "creation request since no provider found for given route=" + route);
-                notifySessionCreationFailedToRouter(routerRecord,
-                        toOriginalRequestId(uniqueRequestId));
+                routerRecord.notifySessionCreationFailed(toOriginalRequestId(uniqueRequestId));
                 return;
             }
 
@@ -3054,7 +3102,7 @@
                         + sessionInfo);
                 return;
             }
-            notifySessionReleasedToRouter(routerRecord, sessionInfo);
+            routerRecord.notifySessionReleased(sessionInfo);
         }
 
         private void onRequestFailedOnHandler(@NonNull MediaRoute2Provider provider,
@@ -3073,8 +3121,7 @@
             final int requesterId = toRequesterId(uniqueRequestId);
             ManagerRecord manager = findManagerWithId(requesterId);
             if (manager != null) {
-                notifyRequestFailedToManager(
-                        manager.mManager, toOriginalRequestId(uniqueRequestId), reason);
+                manager.notifyRequestFailed(toOriginalRequestId(uniqueRequestId), reason);
             }
 
             // Currently, only manager records can get notified of failures.
@@ -3109,40 +3156,19 @@
             // Notify the requester about the failure.
             // The call should be made by either MediaRouter2 or MediaRouter2Manager.
             if (matchingRequest.mManagerRequestId == MediaRouter2Manager.REQUEST_ID_NONE) {
-                notifySessionCreationFailedToRouter(
-                        matchingRequest.mRouterRecord, toOriginalRequestId(uniqueRequestId));
+                matchingRequest.mRouterRecord.notifySessionCreationFailed(
+                        toOriginalRequestId(uniqueRequestId));
             } else {
                 final int requesterId = toRequesterId(matchingRequest.mManagerRequestId);
                 ManagerRecord manager = findManagerWithId(requesterId);
                 if (manager != null) {
-                    notifyRequestFailedToManager(manager.mManager,
+                    manager.notifyRequestFailed(
                             toOriginalRequestId(matchingRequest.mManagerRequestId), reason);
                 }
             }
             return true;
         }
 
-        private void notifySessionCreationFailedToRouter(@NonNull RouterRecord routerRecord,
-                int requestId) {
-            try {
-                routerRecord.mRouter.notifySessionCreated(requestId,
-                        /* sessionInfo= */ null);
-            } catch (RemoteException ex) {
-                Slog.w(TAG, "Failed to notify router of the session creation failure."
-                        + " Router probably died.", ex);
-            }
-        }
-
-        private void notifySessionReleasedToRouter(@NonNull RouterRecord routerRecord,
-                @NonNull RoutingSessionInfo sessionInfo) {
-            try {
-                routerRecord.mRouter.notifySessionReleased(sessionInfo);
-            } catch (RemoteException ex) {
-                Slog.w(TAG, "Failed to notify router of the session release."
-                        + " Router probably died.", ex);
-            }
-        }
-
         private List<IMediaRouter2Manager> getManagers() {
             final List<IMediaRouter2Manager> managers = new ArrayList<>();
             MediaRouter2ServiceImpl service = mServiceRef.get();
@@ -3379,16 +3405,6 @@
             //    need to update routers other than the one making the update.
         }
 
-        private void notifyRequestFailedToManager(@NonNull IMediaRouter2Manager manager,
-                int requestId, int reason) {
-            try {
-                manager.notifyRequestFailed(requestId, reason);
-            } catch (RemoteException ex) {
-                Slog.w(TAG, "Failed to notify manager of the request failure."
-                        + " Manager probably died.", ex);
-            }
-        }
-
         private void updateDiscoveryPreferenceOnHandler() {
             MediaRouter2ServiceImpl service = mServiceRef.get();
             if (service == null) {
diff --git a/services/core/java/com/android/server/notification/GroupHelper.java b/services/core/java/com/android/server/notification/GroupHelper.java
index 1cdab44..008746c 100644
--- a/services/core/java/com/android/server/notification/GroupHelper.java
+++ b/services/core/java/com/android/server/notification/GroupHelper.java
@@ -118,11 +118,32 @@
     private final ArrayMap<FullyQualifiedGroupKey, ArrayMap<String, NotificationAttributes>>
             mAggregatedNotifications = new ArrayMap<>();
 
-    private static final List<NotificationSectioner> NOTIFICATION_SHADE_SECTIONS = List.of(
-        new NotificationSectioner("AlertingSection", 0, (record) ->
-            record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT),
-        new NotificationSectioner("SilentSection", 1, (record) ->
-            record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT));
+    private static List<NotificationSectioner> NOTIFICATION_SHADE_SECTIONS =
+            getNotificationShadeSections();
+
+    private static List<NotificationSectioner> getNotificationShadeSections() {
+        if (android.service.notification.Flags.notificationClassification()) {
+            return List.of(
+                new NotificationSectioner("PromotionsSection", 0, (record) ->
+                    NotificationChannel.PROMOTIONS_ID.equals(record.getChannel().getId())),
+                new NotificationSectioner("SocialSection", 0, (record) ->
+                    NotificationChannel.SOCIAL_MEDIA_ID.equals(record.getChannel().getId())),
+                new NotificationSectioner("NewsSection", 0, (record) ->
+                    NotificationChannel.NEWS_ID.equals(record.getChannel().getId())),
+                new NotificationSectioner("RecsSection", 0, (record) ->
+                    NotificationChannel.RECS_ID.equals(record.getChannel().getId())),
+                new NotificationSectioner("AlertingSection", 0, (record) ->
+                    record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT),
+                new NotificationSectioner("SilentSection", 1, (record) ->
+                    record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT));
+        } else {
+            return List.of(
+                new NotificationSectioner("AlertingSection", 0, (record) ->
+                    record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT),
+                new NotificationSectioner("SilentSection", 1, (record) ->
+                    record.getImportance() < NotificationManager.IMPORTANCE_DEFAULT));
+        }
+    }
 
     public GroupHelper(Context context, PackageManager packageManager, int autoGroupAtCount,
             int autoGroupSparseGroupsAtCount, Callback callback) {
@@ -131,6 +152,7 @@
         mContext = context;
         mPackageManager = packageManager;
         mAutogroupSparseGroupsAtCount = autoGroupSparseGroupsAtCount;
+        NOTIFICATION_SHADE_SECTIONS = getNotificationShadeSections();
     }
 
     private String generatePackageKey(int userId, String pkg) {
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index aaa38a3..6c78b3c 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -887,7 +887,7 @@
             grantPermissionsToSystemPackage(pm,
                     getDefaultSystemHandlerActivityPackage(pm,
                             SearchManager.INTENT_ACTION_GLOBAL_SEARCH, userId),
-                    userId, PHONE_PERMISSIONS, CALENDAR_PERMISSIONS);
+                    userId, PHONE_PERMISSIONS, CALENDAR_PERMISSIONS, NEARBY_DEVICES_PERMISSIONS);
         }
 
         // Print Spooler
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 9b9d1cc..934feb3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3352,6 +3352,12 @@
             mConsumedKeysForDevice.put(deviceId, consumedKeys);
         }
 
+        // TODO(b/358569822) Remove below once we have nicer API for listening to shortcuts
+        if ((event.isMetaPressed() || KeyEvent.isMetaKey(keyCode))
+                && shouldInterceptShortcuts(focusedToken)) {
+            return keyNotConsumed;
+        }
+
         if (interceptSystemKeysAndShortcuts(focusedToken, event)
                 && event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
             consumedKeys.add(keyCode);
@@ -3842,6 +3848,15 @@
         return (metaState & KeyEvent.META_META_ON) != 0;
     }
 
+    private boolean shouldInterceptShortcuts(IBinder focusedToken) {
+        KeyInterceptionInfo info =
+                mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken);
+        boolean hasInterceptWindowFlag = (info.layoutParamsPrivateFlags
+                & WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS) != 0;
+        return hasInterceptWindowFlag && mButtonOverridePermissionChecker.canAppOverrideSystemKey(
+                mContext, info.windowOwnerUid);
+    }
+
     /**
      * In this function, we check whether a system key should be sent to the application. We also
      * detect the key gesture on this key, even if the key will be sent to the app. The gesture
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 4f28e02..e91097c 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -16,6 +16,8 @@
 
 package com.android.server.rollback;
 
+import static android.content.pm.Flags.provideInfoOfApkInApex;
+
 import android.annotation.AnyThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -23,6 +25,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.VersionedPackage;
 import android.content.rollback.PackageRollbackInfo;
@@ -230,7 +233,7 @@
 
 
     @Override
-    public String getName() {
+    public String getUniqueIdentifier() {
         return NAME;
     }
 
@@ -486,19 +489,40 @@
      */
     @AnyThread
     private boolean isModule(String packageName) {
-        // Check if the package is an APK inside an APEX. If it is, use the parent APEX package when
-        // querying PackageManager.
-        String apexPackageName = mApexManager.getActiveApexPackageNameContainingPackage(
-                packageName);
-        if (apexPackageName != null) {
-            packageName = apexPackageName;
-        }
-
         PackageManager pm = mContext.getPackageManager();
-        try {
-            return pm.getModuleInfo(packageName, 0) != null;
-        } catch (PackageManager.NameNotFoundException ignore) {
-            return false;
+
+        if (Flags.refactorCrashrecovery() && provideInfoOfApkInApex()) {
+            // Check if the package is listed among the system modules.
+            boolean isApex = false;
+            try {
+                isApex = (pm.getModuleInfo(packageName, 0 /* flags */) != null);
+            } catch (PackageManager.NameNotFoundException e) {
+                //pass
+            }
+
+            // Check if the package is an APK inside an APEX.
+            boolean isApkInApex = false;
+            try {
+                final PackageInfo pkg = pm.getPackageInfo(packageName, 0 /* flags */);
+                isApkInApex = (pkg.getApexPackageName() != null);
+            } catch (PackageManager.NameNotFoundException e) {
+                // pass
+            }
+            return isApex || isApkInApex;
+        } else {
+            // Check if the package is an APK inside an APEX. If it is, use the parent APEX package
+            // when querying PackageManager.
+            String apexPackageName = mApexManager.getActiveApexPackageNameContainingPackage(
+                    packageName);
+            if (apexPackageName != null) {
+                packageName = apexPackageName;
+            }
+
+            try {
+                return pm.getModuleInfo(packageName, 0) != null;
+            } catch (PackageManager.NameNotFoundException ignore) {
+                return false;
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 6721893..c543b6d 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -19,6 +19,7 @@
 import static android.media.AudioManager.DEVICE_NONE;
 import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED;
 import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY;
+import static android.media.tv.flags.Flags.kidsModeTvdbSharing;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -805,6 +806,19 @@
         }
     }
 
+    private boolean isServiceSingleUser(ComponentName component) {
+        try {
+            ServiceInfo serviceInfo = getContext().getPackageManager()
+                    .getServiceInfo(component, 0);
+            // Check if the single-user flag is present
+            return (serviceInfo.flags & ServiceInfo.FLAG_SINGLE_USER) != 0;
+        } catch (PackageManager.NameNotFoundException e) {
+            // Handle the case where the service is not found
+            Slog.e(TAG, "Service not found: " + component, e);
+            return false;
+        }
+    }
+
     @GuardedBy("mLock")
     private void abortPendingCreateSessionRequestsLocked(ServiceState serviceState,
             String inputId, int userId) {
@@ -2840,6 +2854,26 @@
         }
 
         @Override
+        public int getClientUserId(String sessionId) {
+            ensureTunerResourceAccessPermission();
+            int clientUserId = TvInputManager.UNKNOWN_CLIENT_USER_ID;
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        clientUserId = getClientUserIdLocked(sessionId);
+                    } catch (ClientUserIdNotFoundException e) {
+                        Slog.e(TAG, "error in getClientUserId", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+            return clientUserId;
+        }
+
+        @Override
         public int getClientPriority(int useCase, String sessionId) {
             ensureTunerResourceAccessPermission();
             final int callingPid = Binder.getCallingPid();
@@ -2924,6 +2958,16 @@
             return mSessionIdToSessionStateMap.get(sessionId).callingPid;
         }
 
+        @GuardedBy("mLock")
+        private int getClientUserIdLocked(String sessionId) throws ClientUserIdNotFoundException {
+            SessionState sessionState = mSessionIdToSessionStateMap.get(sessionId);
+            if (sessionState == null) {
+                throw new ClientUserIdNotFoundException(
+                        "Client UserId not found with sessionId " + sessionId);
+            }
+            return sessionState.userId;
+        }
+
         private void ensureTunerResourceAccessPermission() {
             if (mContext.checkCallingPermission(
                     android.Manifest.permission.TUNER_RESOURCE_ACCESS)
@@ -3495,11 +3539,15 @@
                     "bindServiceAsUser(service=" + serviceState.component + ", userId=" + userId
                             + ")");
         }
+        int bindUserId = userId;
+        if (kidsModeTvdbSharing() && isServiceSingleUser(serviceState.component)) {
+            bindUserId = UserHandle.USER_SYSTEM;
+        }
         Intent i =
                 new Intent(TvInputService.SERVICE_INTERFACE).setComponent(serviceState.component);
         serviceState.bound = mContext.bindServiceAsUser(i, serviceState.connection,
                 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
-                new UserHandle(userId));
+                new UserHandle(bindUserId));
         if (!serviceState.bound) {
             Slog.e(TAG, "failed to bind " + serviceState.component + " for userId " + userId);
             mContext.unbindService(serviceState.connection);
@@ -4700,4 +4748,10 @@
             super(name);
         }
     }
+
+    private static class ClientUserIdNotFoundException extends IllegalArgumentException {
+        ClientUserIdNotFoundException(String name) {
+            super(name);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 3d58082..5e03066 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4626,7 +4626,12 @@
         return kept;
     }
 
-    /** Update default (global) configuration and notify listeners about changes. */
+    /**
+     * Updates default (global) configuration and notifies listeners about changes.
+     *
+     * @param values The new configuration. It must always be a new instance from the caller, and
+     *               it won't be modified after calling this method.
+     */
     int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,
             boolean persistent, int userId) {
 
@@ -4640,24 +4645,6 @@
         ProtoLog.i(WM_DEBUG_CONFIGURATION, "Updating global configuration "
                 + "to: %s", values);
         writeConfigurationChanged(changes);
-        FrameworkStatsLog.write(FrameworkStatsLog.RESOURCE_CONFIGURATION_CHANGED,
-                values.colorMode,
-                values.densityDpi,
-                values.fontScale,
-                values.hardKeyboardHidden,
-                values.keyboard,
-                values.keyboardHidden,
-                values.mcc,
-                values.mnc,
-                values.navigation,
-                values.navigationHidden,
-                values.orientation,
-                values.screenHeightDp,
-                values.screenLayout,
-                values.screenWidthDp,
-                values.smallestScreenWidthDp,
-                values.touchscreen,
-                values.uiMode);
 
         // Note: certain tests currently run as platform_app which is not allowed
         // to set debug system properties. To ensure that system properties are set
@@ -4705,13 +4692,6 @@
         // resources have that config before following boot code is executed.
         mSystemThread.applyConfigurationToResources(mTempConfig);
 
-        if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
-            final Message msg = PooledLambda.obtainMessage(
-                    ActivityTaskManagerService::sendPutConfigurationForUserMsg,
-                    this, userId, new Configuration(mTempConfig));
-            mH.sendMessage(msg);
-        }
-
         SparseArray<WindowProcessController> pidMap = mProcessMap.getPidMap();
         for (int i = pidMap.size() - 1; i >= 0; i--) {
             final int pid = pidMap.keyAt(i);
@@ -4721,19 +4701,32 @@
             app.onConfigurationChanged(mTempConfig);
         }
 
-        final Message msg = PooledLambda.obtainMessage(
-                ActivityManagerInternal::broadcastGlobalConfigurationChanged,
-                mAmInternal, changes, initLocale);
-        mH.sendMessage(msg);
+        final Configuration configurationForSettings =
+                persistent && Settings.System.hasInterestingConfigurationChanges(changes)
+                        ? new Configuration(mTempConfig) : null;
+        mH.post(() -> {
+            FrameworkStatsLog.write(FrameworkStatsLog.RESOURCE_CONFIGURATION_CHANGED,
+                    values.colorMode, values.densityDpi, values.fontScale,
+                    values.hardKeyboardHidden, values.keyboard, values.keyboardHidden,
+                    values.mcc, values.mnc, values.navigation, values.navigationHidden,
+                    values.orientation, values.screenHeightDp, values.screenLayout,
+                    values.screenWidthDp, values.smallestScreenWidthDp, values.touchscreen,
+                    values.uiMode);
+            if ((changes & ActivityInfo.CONFIG_ORIENTATION) != 0) {
+                FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_ORIENTATION_CHANGED,
+                        values.orientation);
+            }
+            if (configurationForSettings != null) {
+                Settings.System.putConfigurationForUser(mContext.getContentResolver(),
+                        configurationForSettings, userId);
+            }
+            mAmInternal.broadcastGlobalConfigurationChanged(changes, initLocale);
+        });
 
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "RootConfigChange");
         // Update stored global config and notify everyone about the change.
         mRootWindowContainer.onConfigurationChanged(mTempConfig);
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-        if ((changes & ActivityInfo.CONFIG_ORIENTATION) != 0) {
-            FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_ORIENTATION_CHANGED,
-                    values.orientation);
-        }
 
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         return changes;
@@ -4883,11 +4876,6 @@
         mWindowManager.setEventDispatching(booted && !mShuttingDown);
     }
 
-    private void sendPutConfigurationForUserMsg(int userId, Configuration config) {
-        final ContentResolver resolver = mContext.getContentResolver();
-        Settings.System.putConfigurationForUser(resolver, config, userId);
-    }
-
     boolean isActivityStartsLoggingEnabled() {
         return mAmInternal.isActivityStartsLoggingEnabled();
     }
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 767effd..87867f6 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -283,8 +283,10 @@
                     // keyguard locked and activities are unable to show when locked.
                     backType = BackNavigationInfo.TYPE_CALLBACK;
                 }
-            } else if (currentTask.mAtmService.getLockTaskController().isTaskLocked(currentTask)) {
+            } else if (currentTask.mAtmService.getLockTaskController().isTaskLocked(currentTask)
+                    || currentTask.getWindowConfiguration().tasksAreFloating()) {
                 // Do not predict if current task is in task locked.
+                // Also, it is unable to play cross task animation for floating task.
                 backType = BackNavigationInfo.TYPE_CALLBACK;
             } else {
                 // Check back-to-home or cross-task
diff --git a/services/core/java/com/android/server/wm/DimmerAnimationHelper.java b/services/core/java/com/android/server/wm/DimmerAnimationHelper.java
index 37e4449..3dba57f 100644
--- a/services/core/java/com/android/server/wm/DimmerAnimationHelper.java
+++ b/services/core/java/com/android/server/wm/DimmerAnimationHelper.java
@@ -55,11 +55,10 @@
 
         Change() {}
 
-        void copyFrom(@NonNull Change other) {
+        Change(@NonNull Change other) {
             mAlpha = other.mAlpha;
             mBlurRadius = other.mBlurRadius;
             mDimmingContainer = other.mDimmingContainer;
-            mGeometryParent = other.mGeometryParent;
             mRelativeLayer = other.mRelativeLayer;
         }
 
@@ -84,8 +83,8 @@
         }
     }
 
-    private final Change mCurrentProperties = new Change();
-    private final Change mRequestedProperties = new Change();
+    private Change mCurrentProperties = new Change();
+    private Change mRequestedProperties = new Change();
     private AnimationSpec mAlphaAnimationSpec;
 
     private final AnimationAdapterFactory mAnimationAdapterFactory;
@@ -129,7 +128,7 @@
                     + "call adjustRelativeLayer?");
             return;
         }
-        if (mRequestedProperties.mDimmingContainer.getSurfaceControl() == null) {
+        if (mRequestedProperties.mDimmingContainer.mSurfaceControl == null) {
             Log.w(TAG, "container " + mRequestedProperties.mDimmingContainer
                     + "does not have a surface");
             dim.remove(t);
@@ -155,35 +154,35 @@
                         "%s skipping animation and directly setting alpha=%f, blur=%d",
                         dim, mRequestedProperties.mAlpha,
                         mRequestedProperties.mBlurRadius);
-                mCurrentProperties.copyFrom(mRequestedProperties);
-                setCurrentAlphaBlur(dim.mDimSurface, t);
+                setAlphaBlur(dim.mDimSurface, mRequestedProperties.mAlpha,
+                        mRequestedProperties.mBlurRadius, t);
                 dim.mSkipAnimation = false;
             } else {
-                Change startProperties = mCurrentProperties;
-                mCurrentProperties.copyFrom(mRequestedProperties);
-                startAnimation(t, dim, startProperties, mRequestedProperties);
+                startAnimation(t, dim);
             }
+
         } else if (!dim.isDimming()) {
             // We are not dimming, so we tried the exit animation but the alpha is already 0,
             // therefore, let's just remove this surface
             dim.remove(t);
         }
+        mCurrentProperties = new Change(mRequestedProperties);
     }
 
     private void startAnimation(
-            @NonNull SurfaceControl.Transaction t, @NonNull Dimmer.DimState dim,
-            @NonNull Change from, @NonNull Change to) {
+            @NonNull SurfaceControl.Transaction t, @NonNull Dimmer.DimState dim) {
         ProtoLog.v(WM_DEBUG_DIMMER, "Starting animation on %s", dim);
-        mAlphaAnimationSpec = getRequestedAnimationSpec(from, to);
+        mAlphaAnimationSpec = getRequestedAnimationSpec();
         mLocalAnimationAdapter = mAnimationAdapterFactory.get(mAlphaAnimationSpec,
                 dim.mHostContainer.mWmService.mSurfaceAnimationRunner);
 
-        float targetAlpha = to.mAlpha;
+        float targetAlpha = mRequestedProperties.mAlpha;
+        int targetBlur = mRequestedProperties.mBlurRadius;
 
         mLocalAnimationAdapter.startAnimation(dim.mDimSurface, t,
                 ANIMATION_TYPE_DIMMER, /* finishCallback */ (type, animator) -> {
                     synchronized (dim.mHostContainer.mWmService.mGlobalLock) {
-                        setCurrentAlphaBlur(dim.mDimSurface, t);
+                        setAlphaBlur(dim.mDimSurface, targetAlpha, targetBlur, t);
                         if (targetAlpha == 0f && !dim.isDimming()) {
                             dim.remove(t);
                         }
@@ -208,15 +207,15 @@
     }
 
     @NonNull
-    private static AnimationSpec getRequestedAnimationSpec(Change from, Change to) {
-        final float startAlpha = Math.max(from.mAlpha, 0f);
-        final int startBlur = Math.max(from.mBlurRadius, 0);
-        long duration = (long) (getDimDuration(to.mDimmingContainer)
-                * Math.abs(to.mAlpha - startAlpha));
+    private AnimationSpec getRequestedAnimationSpec() {
+        final float startAlpha = Math.max(mCurrentProperties.mAlpha, 0f);
+        final int startBlur = Math.max(mCurrentProperties.mBlurRadius, 0);
+        long duration = (long) (getDimDuration(mRequestedProperties.mDimmingContainer)
+                * Math.abs(mRequestedProperties.mAlpha - startAlpha));
 
         final AnimationSpec spec =  new AnimationSpec(
-                new AnimationSpec.AnimationExtremes<>(startAlpha, to.mAlpha),
-                new AnimationSpec.AnimationExtremes<>(startBlur, to.mBlurRadius),
+                new AnimationSpec.AnimationExtremes<>(startAlpha, mRequestedProperties.mAlpha),
+                new AnimationSpec.AnimationExtremes<>(startBlur, mRequestedProperties.mBlurRadius),
                 duration
         );
         ProtoLog.v(WM_DEBUG_DIMMER, "Dim animation requested: %s", spec);
@@ -226,7 +225,7 @@
     /**
      * Change the geometry and relative parent of this dim layer
      */
-    static void reparent(@NonNull SurfaceControl dimLayer,
+    void reparent(@NonNull SurfaceControl dimLayer,
                   @Nullable SurfaceControl newGeometryParent,
                   @NonNull SurfaceControl relativeParent,
                   int relativePosition,
@@ -241,16 +240,17 @@
         }
     }
 
-    void setCurrentAlphaBlur(@NonNull SurfaceControl sc, @NonNull SurfaceControl.Transaction t) {
+    void setAlphaBlur(@NonNull SurfaceControl sc, float alpha, int blur,
+                      @NonNull SurfaceControl.Transaction t) {
         try {
-            t.setAlpha(sc, mCurrentProperties.mAlpha);
-            t.setBackgroundBlurRadius(sc, mCurrentProperties.mBlurRadius);
+            t.setAlpha(sc, alpha);
+            t.setBackgroundBlurRadius(sc, blur);
         } catch (NullPointerException e) {
             Log.w(TAG , "Tried to change look of dim " + sc + " after remove",  e);
         }
     }
 
-    private static long getDimDuration(@NonNull WindowContainer<?> container) {
+    private long getDimDuration(@NonNull WindowContainer<?> container) {
         // Use the same duration as the animation on the WindowContainer
         AnimationAdapter animationAdapter = container.mSurfaceAnimator.getAnimation();
         final float durationScale = container.mWmService.getTransitionAnimationScaleLocked();
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 648f6bd..86285fb 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3496,10 +3496,7 @@
      */
     void collectDisplayChange(@NonNull Transition transition) {
         if (!mLastHasContent) return;
-        if (!transition.isCollecting()) {
-            throw new IllegalArgumentException("Can only collect display change if transition"
-                    + " is collecting");
-        }
+        if (!transition.isCollecting()) return;
         if (!transition.mParticipants.contains(this)) {
             transition.collect(this);
             startAsyncRotationIfNeeded();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b528e20..4ca4730 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1002,6 +1002,7 @@
                 // complete configuration.
                 continue;
             }
+            win.updateSurfacePositionIfNeeded();
             win.reportResized();
             mWmService.mResizingWindows.remove(i);
         }
@@ -3427,26 +3428,30 @@
 
     boolean allResumedActivitiesIdle() {
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
-            // TODO(b/117135575): Check resumed activities on all visible root tasks.
             final DisplayContent display = getChildAt(displayNdx);
             if (display.isSleeping()) {
                 // No resumed activities while display is sleeping.
                 continue;
             }
 
-            // If the focused root task is not null or not empty, there should have some activities
-            // resuming or resumed. Make sure these activities are idle.
-            final Task rootTask = display.getFocusedRootTask();
-            if (rootTask == null || !rootTask.hasActivity()) {
-                continue;
-            }
-            final ActivityRecord resumedActivity = rootTask.getTopResumedActivity();
-            if (resumedActivity == null || !resumedActivity.idle) {
-                ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: rootTask=%d %s "
-                        + "not idle", rootTask.getRootTaskId(), resumedActivity);
+            final boolean foundNotIdle = display.forAllLeafTaskFragments(tf -> {
+                if (!tf.isVisibleRequested()) {
+                    return false;
+                }
+                // Note that only activities that will be resumed can report idle.
+                final ActivityRecord r = tf.topRunningActivity();
+                if (r != null && !r.idle && (r.isState(RESUMED)
+                        // Its process is not attached yet and it may resume later.
+                        || (r.app == null && r.isFocusable()))) {
+                    ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: %s not idle", r);
+                    return true;
+                }
+                return false;
+            });
+            if (foundNotIdle) {
                 return false;
             }
-            if (mTransitionController.isTransientLaunch(resumedActivity)) {
+            if (mTransitionController.hasTransientLaunch(display)) {
                 // Not idle if the transient transition animation is running.
                 return false;
             }
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index ef25eda..1d2b693 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -408,6 +408,10 @@
      */
     @Nullable
     Transition getCollectingTransition() {
+        if (mCollectingTransition != null && !mCollectingTransition.isCollecting()) {
+            Slog.wtfStack(TAG, "Collecting Transition (#" + mCollectingTransition.getSyncId()
+                    + ") is not collecting. state=" + mCollectingTransition.getState());
+        }
         return mCollectingTransition;
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index bdb1d43..87c0084 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -32,6 +32,7 @@
 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
 import static android.app.StatusBarManager.DISABLE_MASK;
 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
 import static android.content.pm.PackageManager.FEATURE_PC;
@@ -9024,14 +9025,7 @@
         }
         clearPointerDownOutsideFocusRunnable();
 
-        // For embedded activity that is showing side-by-side with another activity, delay
-        // handling the touch-outside event to prevent focus rapid changes back-n-forth.
-        // Otherwise, handle the touch-outside event directly.
-        final WindowState w = t.getWindowState();
-        final ActivityRecord activity = w != null ? w.getActivityRecord() : null;
-        if (mFocusedInputTarget != t && mFocusedInputTarget != null
-                && activity != null && activity.isEmbedded()
-                && activity.getTaskFragment().getAdjacentTaskFragment() != null) {
+        if (shouldDelayTouchOutside(t)) {
             mPointerDownOutsideFocusRunnable = () -> handlePointerDownOutsideFocus(t);
             mH.postDelayed(mPointerDownOutsideFocusRunnable, POINTER_DOWN_OUTSIDE_FOCUS_TIMEOUT_MS);
         } else if (!fromHandler) {
@@ -9044,6 +9038,33 @@
         }
     }
 
+    private boolean shouldDelayTouchOutside(InputTarget t) {
+        final WindowState w = t.getWindowState();
+        final ActivityRecord activity = w != null ? w.getActivityRecord() : null;
+        final Task task = w != null ? w.getRootTask() : null;
+
+        final boolean isInputTargetNotFocused =
+                mFocusedInputTarget != t && mFocusedInputTarget != null;
+        if (!isInputTargetNotFocused) {
+            return false;
+        }
+
+        // For embedded activity that is showing side-by-side with another activity, delay
+        // handling the touch-outside event to prevent focus rapid changes back-n-forth.
+        final boolean shouldDelayTouchForEmbeddedActivity = activity != null
+                && activity.isEmbedded()
+                && activity.getTaskFragment().getAdjacentTaskFragment() != null;
+
+        // For cases when there are multiple freeform windows where non-top windows are blocking
+        // the gesture zones, delay handling the touch-outside event to prevent refocusing the
+        // the non-top windows during the gesture.
+        final boolean shouldDelayTouchForFreeform =
+                task != null && task.getWindowingMode() == WINDOWING_MODE_FREEFORM;
+
+        // If non of the above cases are true, handle the touch-outside event directly.
+        return shouldDelayTouchForEmbeddedActivity || shouldDelayTouchForFreeform;
+    }
+
     private void handlePointerDownOutsideFocus(InputTarget t) {
         synchronized (mGlobalLock) {
             if (mPointerDownOutsideFocusRunnable != null
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 923ad4b..4568f2e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5333,6 +5333,14 @@
         super.prepareSurfaces();
     }
 
+    void updateSurfacePositionIfNeeded() {
+        if (mWindowFrames.mRelFrame.top == mWindowFrames.mLastRelFrame.top
+                && mWindowFrames.mRelFrame.left == mWindowFrames.mLastRelFrame.left) {
+            return;
+        }
+        updateSurfacePosition(getSyncTransaction());
+    }
+
     @Override
     @VisibleForTesting
     void updateSurfacePosition(Transaction t) {
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index dab3978..8332b8b 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -46,12 +46,12 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.art.ArtManagerLocal;
+import com.android.server.profcollect.Utils;
 import com.android.server.wm.ActivityMetricsLaunchObserver;
 import com.android.server.wm.ActivityMetricsLaunchObserverRegistry;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
 import java.util.Arrays;
-import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -280,11 +280,7 @@
             return;
         }
 
-        // Sample for a fraction of app launches.
-        int traceFrequency = DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
-                "applaunch_trace_freq", 2);
-        int randomNum = ThreadLocalRandom.current().nextInt(100);
-        if (randomNum < traceFrequency) {
+        if (Utils.withFrequency("applaunch_trace_freq", 2)) {
             BackgroundThread.get().getThreadHandler().post(() -> {
                 try {
                     mIProfcollect.trace_system("applaunch");
@@ -318,12 +314,7 @@
         if (mIProfcollect == null) {
             return;
         }
-        // Sample for a fraction of dex2oat runs.
-        final int traceFrequency =
-            DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
-                "dex2oat_trace_freq", 25);
-        int randomNum = ThreadLocalRandom.current().nextInt(100);
-        if (randomNum < traceFrequency) {
+        if (Utils.withFrequency("dex2oat_trace_freq", 25)) {
             // Dex2oat could take a while before it starts. Add a short delay before start tracing.
             BackgroundThread.get().getThreadHandler().postDelayed(() -> {
                 try {
@@ -393,27 +384,22 @@
                 if (Arrays.asList(cameraSkipPackages).contains(packageId)) {
                     return;
                 }
-                // Sample for a fraction of camera events.
-                final int traceFrequency =
-                        DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
-                        "camera_trace_freq", 10);
-                int randomNum = ThreadLocalRandom.current().nextInt(100);
-                if (randomNum >= traceFrequency) {
-                    return;
-                }
-                final int traceDuration = 5000;
-                final String traceTag = "camera";
-                BackgroundThread.get().getThreadHandler().post(() -> {
-                    if (mIProfcollect == null) {
-                        return;
-                    }
-                    try {
-                        mIProfcollect.trace_process(traceTag, "android.hardware.camera.provider",
+                if (Utils.withFrequency("camera_trace_freq", 10)) {
+                    final int traceDuration = 5000;
+                    final String traceTag = "camera";
+                    BackgroundThread.get().getThreadHandler().post(() -> {
+                        if (mIProfcollect == null) {
+                            return;
+                        }
+                        try {
+                            mIProfcollect.trace_process(traceTag,
+                                "android.hardware.camera.provider",
                                 traceDuration);
-                    } catch (RemoteException e) {
-                        Log.e(LOG_TAG, "Failed to initiate trace: " + e.getMessage());
-                    }
-                });
+                        } catch (RemoteException e) {
+                            Log.e(LOG_TAG, "Failed to initiate trace: " + e.getMessage());
+                        }
+                    });
+                }
             }
         }, null);
     }
diff --git a/services/profcollect/src/com/android/server/profcollect/Utils.java b/services/profcollect/src/com/android/server/profcollect/Utils.java
new file mode 100644
index 0000000..d5ef14c
--- /dev/null
+++ b/services/profcollect/src/com/android/server/profcollect/Utils.java
@@ -0,0 +1,32 @@
+/**
+ * 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.server.profcollect;
+
+import android.provider.DeviceConfig;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+public final class Utils {
+
+  public static boolean withFrequency(String configName, int defaultFrequency) {
+        int threshold = DeviceConfig.getInt(
+                DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT, configName, defaultFrequency);
+        int randomNum = ThreadLocalRandom.current().nextInt(100);
+        return randomNum < threshold;
+    }
+
+}
\ No newline at end of file
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 2b03dc4..bbf2ecb 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -69,7 +69,6 @@
 import android.companion.virtual.IVirtualDevice;
 import android.companion.virtual.IVirtualDeviceManager;
 import android.companion.virtual.VirtualDeviceManager;
-import android.companion.virtual.flags.Flags;
 import android.compat.testing.PlatformCompatChangeRule;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -374,7 +373,6 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(false);
-        mSetFlagsRule.disableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
 
         mLocalServiceKeeperRule.overrideLocalService(
                 InputManagerInternal.class, mMockInputManagerInternal);
@@ -1298,44 +1296,11 @@
     }
 
     /**
-     * Tests that it's not allowed to create an auto-mirror virtual display when display mirroring
-     * is not supported in a virtual device.
-     */
-    @Test
-    public void createAutoMirrorDisplay_virtualDeviceDoesntSupportMirroring_throwsException()
-            throws Exception {
-        mSetFlagsRule.disableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
-        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
-        DisplayManagerInternal localService = displayManager.new LocalService();
-        registerDefaultDisplays(displayManager);
-        when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
-        when(mContext.checkCallingPermission(CAPTURE_VIDEO_OUTPUT)).thenReturn(
-                PackageManager.PERMISSION_DENIED);
-        IVirtualDevice virtualDevice = mock(IVirtualDevice.class);
-        when(virtualDevice.getDeviceId()).thenReturn(1);
-        when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true);
-
-        final VirtualDisplayConfig.Builder builder =
-                new VirtualDisplayConfig.Builder(VIRTUAL_DISPLAY_NAME, 600, 800, 320)
-                        .setFlags(VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR)
-                        .setUniqueId("uniqueId --- mirror display");
-        assertThrows(SecurityException.class, () -> {
-            localService.createVirtualDisplay(
-                    builder.build(),
-                    mMockAppToken /* callback */,
-                    virtualDevice /* virtualDeviceToken */,
-                    mock(DisplayWindowPolicyController.class),
-                    PACKAGE_NAME);
-        });
-    }
-
-    /**
      * Tests that the virtual display is added to the default display group when created with
      * VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR using a virtual device.
      */
     @Test
     public void createAutoMirrorVirtualDisplay_addsDisplayToDefaultDisplayGroup() throws Exception {
-        mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
         DisplayManagerInternal localService = displayManager.new LocalService();
         registerDefaultDisplays(displayManager);
@@ -1368,7 +1333,6 @@
      */
     @Test
     public void createAutoMirrorVirtualDisplay_mirrorsDefaultDisplay() throws Exception {
-        mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
         DisplayManagerInternal localService = displayManager.new LocalService();
         registerDefaultDisplays(displayManager);
@@ -1400,7 +1364,6 @@
      */
     @Test
     public void createOwnContentOnlyVirtualDisplay_doesNotMirrorAnyDisplay() throws Exception {
-        mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
         DisplayManagerInternal localService = displayManager.new LocalService();
         registerDefaultDisplays(displayManager);
@@ -1436,7 +1399,6 @@
      */
     @Test
     public void createAutoMirrorVirtualDisplay_flagAlwaysUnlockedNotSet() throws Exception {
-        mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
         DisplayManagerInternal localService = displayManager.new LocalService();
         registerDefaultDisplays(displayManager);
@@ -1472,7 +1434,6 @@
      */
     @Test
     public void createAutoMirrorVirtualDisplay_flagPresentationNotSet() throws Exception {
-        mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
         DisplayManagerInternal localService = displayManager.new LocalService();
         registerDefaultDisplays(displayManager);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java b/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
index 82acaf8..f728168 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
@@ -258,6 +258,7 @@
 
         when(mMockedLogicalDisplay.isEnabledLocked()).thenReturn(false);
         mExternalDisplayPolicy.handleExternalDisplayConnectedLocked(mMockedLogicalDisplay);
+        mHandler.flush();
         verify(mMockedInjector, never()).sendExternalDisplayEventLocked(any(), anyInt());
         verify(mMockedDisplayNotificationManager, times(2))
                 .onHighTemperatureExternalDisplayNotAllowed();
diff --git a/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java b/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java
index d6c8ceb..97c12bb 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java
@@ -30,6 +30,7 @@
 
 import android.app.Notification;
 import android.app.NotificationManager;
+import android.os.UserHandle;
 
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.filters.SmallTest;
@@ -70,6 +71,8 @@
     private ArgumentCaptor<Integer> mNotifyNoteIdCaptor;
     @Captor
     private ArgumentCaptor<Notification> mNotifyAsUserNotificationCaptor;
+    @Captor
+    private ArgumentCaptor<UserHandle> mNotifyAsUserCaptor;
 
     /** Setup tests. */
     @Before
@@ -127,7 +130,8 @@
         dnm.onDisplayPortLinkTrainingFailure();
         dnm.onCableNotCapableDisplayPort();
         dnm.onHighTemperatureExternalDisplayNotAllowed();
-        verify(mMockedNotificationManager, never()).notify(anyString(), anyInt(), any());
+        verify(mMockedNotificationManager, never()).notifyAsUser(anyString(), anyInt(), any(),
+                any());
     }
 
     @Test
@@ -175,10 +179,11 @@
     }
 
     private void assertExpectedNotification() {
-        verify(mMockedNotificationManager).notify(
+        verify(mMockedNotificationManager).notifyAsUser(
                 mNotifyTagCaptor.capture(),
                 mNotifyNoteIdCaptor.capture(),
-                mNotifyAsUserNotificationCaptor.capture());
+                mNotifyAsUserNotificationCaptor.capture(),
+                mNotifyAsUserCaptor.capture());
         assertThat(mNotifyTagCaptor.getValue()).isEqualTo("DisplayNotificationManager");
         assertThat((int) mNotifyNoteIdCaptor.getValue()).isEqualTo(1);
         final var notification = mNotifyAsUserNotificationCaptor.getValue();
@@ -188,5 +193,7 @@
         assertThat(notification.flags & FLAG_ONGOING_EVENT).isEqualTo(0);
         assertThat(notification.when).isEqualTo(0);
         assertThat(notification.getTimeoutAfter()).isEqualTo(30000L);
+        final var user = mNotifyAsUserCaptor.getValue();
+        assertThat(user).isEqualTo(UserHandle.CURRENT);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
index 238a928..8f23ab9 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
@@ -236,6 +236,13 @@
     }
 
     @Test
+    public void testFingerprintsLoe() {
+        mLogger = createLogger();
+        mLogger.logFingerprintsLoe();
+        verify(mSink).reportFingerprintsLoe(eq(DEFAULT_MODALITY));
+    }
+
+    @Test
     public void testALSCallback() {
         mLogger = createLogger();
         final CallbackWithProbe<Probe> callback =
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
index 242880c..7dcf841 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
@@ -182,13 +182,22 @@
     public void invalidBiometricUserState() throws Exception {
         mClient =  createClient();
 
+        final List<Fingerprint> templates = List.of(
+                new Fingerprint("one", 1, 1),
+                new Fingerprint("two", 2, 1),
+                new Fingerprint("three", 3, 1)
+        );
+
         final List<Fingerprint> list = new ArrayList<>();
         doReturn(true).when(mFingerprintUtils)
                 .hasValidBiometricUserState(mContext, 2);
         doReturn(list).when(mFingerprintUtils).getBiometricsForUser(mContext, 2);
 
         mClient.start(mCallback);
-        mClient.onEnumerationResult(null, 0);
+        for (int i = templates.size() - 1; i >= 0; i--) {
+            mClient.getCurrentEnumerateClient().onEnumerationResult(templates.get(i), i);
+        }
+        verify(mLogger).logFingerprintsLoe();
         verify(mFingerprintUtils).deleteStateForUser(2);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index c288212..4d067f6 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -62,7 +62,6 @@
 import android.companion.virtual.VirtualDeviceParams;
 import android.companion.virtual.audio.IAudioConfigChangedCallback;
 import android.companion.virtual.audio.IAudioRoutingCallback;
-import android.companion.virtual.flags.Flags;
 import android.companion.virtual.sensor.VirtualSensor;
 import android.companion.virtual.sensor.VirtualSensorCallback;
 import android.companion.virtual.sensor.VirtualSensorConfig;
@@ -1686,7 +1685,6 @@
 
     @Test
     public void openNonBlockedAppOnMirrorDisplay_flagEnabled_cannotBeLaunched() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
         when(mDisplayManagerInternalMock.getDisplayIdToMirror(anyInt()))
                 .thenReturn(Display.DEFAULT_DISPLAY);
         addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
@@ -1711,31 +1709,6 @@
     }
 
     @Test
-    public void openNonBlockedAppOnMirrorDisplay_flagDisabled_launchesActivity() {
-        mSetFlagsRule.disableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
-        when(mDisplayManagerInternalMock.getDisplayIdToMirror(anyInt()))
-                .thenReturn(Display.DEFAULT_DISPLAY);
-        addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
-        GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
-                DISPLAY_ID_1);
-        doNothing().when(mContext).startActivityAsUser(any(), any(), any());
-
-        ActivityInfo activityInfo = getActivityInfo(
-                NONBLOCKED_APP_PACKAGE_NAME,
-                NONBLOCKED_APP_PACKAGE_NAME,
-                /* displayOnRemoteDevices */ true,
-                /* targetDisplayCategory */ null);
-        assertThat(gwpc.canActivityBeLaunched(activityInfo, null,
-                WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /* isNewTask= */ false,
-                /* isResultExpected = */ false, /* intentSender= */ null))
-                .isTrue();
-        Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
-                activityInfo, mAssociationInfo.getDisplayName());
-        verify(mContext, never()).startActivityAsUser(argThat(intent ->
-                intent.filterEquals(blockedAppIntent)), any(), any());
-    }
-
-    @Test
     public void registerRunningAppsChangedListener_onRunningAppsChanged_listenersNotified() {
         ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2));
         addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index 2b93ccb..a7e8a00 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -2148,6 +2148,40 @@
                 .hasSize(1);
     }
 
+
+    @Test
+    public void handleReportAudioStatus_SamOnAvrStandby_startSystemAudioActionFromTv() {
+        mHdmiControlService.getHdmiCecConfig().setIntValue(
+                HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL,
+                HdmiControlManager.SYSTEM_AUDIO_CONTROL_ENABLED);
+        // Emulate Audio device on port 0x1000 (does not support ARC)
+        mNativeWrapper.setPortConnectionStatus(1, true);
+        HdmiCecMessage reportPhysicalAddress =
+                HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+                        ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
+        HdmiCecMessage reportPowerStatus =
+                HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_AUDIO_SYSTEM, ADDR_TV,
+                        HdmiControlManager.POWER_STATUS_STANDBY);
+        mNativeWrapper.onCecMessage(reportPhysicalAddress);
+        mNativeWrapper.onCecMessage(reportPowerStatus);
+        mTestLooper.dispatchAll();
+        assertThat(mHdmiCecLocalDeviceTv.getActions(SystemAudioActionFromTv.class)).hasSize(0);
+
+        HdmiCecFeatureAction systemAudioAutoInitiationAction =
+                new SystemAudioAutoInitiationAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM);
+        mHdmiCecLocalDeviceTv.addAndStartAction(systemAudioAutoInitiationAction);
+        HdmiCecMessage reportSystemAudioMode =
+                HdmiCecMessageBuilder.buildReportSystemAudioMode(
+                        ADDR_AUDIO_SYSTEM,
+                        mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+                        true);
+        mHdmiControlService.handleCecCommand(reportSystemAudioMode);
+        mTestLooper.dispatchAll();
+
+        // SAM must be on; ARC must be off
+        assertThat(mHdmiCecLocalDeviceTv.getActions(SystemAudioActionFromTv.class)).hasSize(1);
+    }
+
     protected static class MockTvDevice extends HdmiCecLocalDeviceTv {
         MockTvDevice(HdmiControlService service) {
             super(service);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
index 225c1dc..51f64ba 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java
@@ -31,10 +31,11 @@
 import static android.app.Notification.VISIBILITY_SECRET;
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION;
 import static android.service.notification.Flags.FLAG_NOTIFICATION_FORCE_GROUPING;
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
 import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
 
-import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
 import static com.android.server.notification.GroupHelper.AGGREGATE_GROUP_KEY;
 import static com.android.server.notification.GroupHelper.AUTOGROUP_KEY;
 import static com.android.server.notification.GroupHelper.BASE_FLAGS;
@@ -2518,17 +2519,7 @@
         assertThat(cachedSummary).isNull();
     }
 
-    @Test
-    @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
-    public void testGroupSectioners() {
-        final NotificationRecord notification_alerting = getNotificationRecord(mPkg, 0, "", mUser,
-            "", false, IMPORTANCE_DEFAULT);
-        assertThat(GroupHelper.getSection(notification_alerting).mName).isEqualTo("AlertingSection");
-
-        final NotificationRecord notification_silent = getNotificationRecord(mPkg, 0, "", mUser,
-            "", false, IMPORTANCE_LOW);
-        assertThat(GroupHelper.getSection(notification_silent).mName).isEqualTo("SilentSection");
-
+    private void checkNonGroupableNotifications() {
         NotificationRecord notification_conversation = mock(NotificationRecord.class);
         when(notification_conversation.isConversation()).thenReturn(true);
         assertThat(GroupHelper.getSection(notification_conversation)).isNull();
@@ -2545,7 +2536,7 @@
         assertThat(GroupHelper.getSection(notification_call)).isNull();
 
         NotificationRecord notification_colorFg = spy(getNotificationRecord(mPkg, 0, "", mUser,
-            "", false, IMPORTANCE_LOW));
+                "", false, IMPORTANCE_LOW));
         sbn = spy(getSbn("package", 0, "0", UserHandle.SYSTEM));
         n = mock(Notification.class);
         when(notification_colorFg.isConversation()).thenReturn(false);
@@ -2558,4 +2549,97 @@
         assertThat(GroupHelper.getSection(notification_colorFg)).isNull();
     }
 
+    @Test
+    @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
+    @DisableFlags(FLAG_NOTIFICATION_CLASSIFICATION)
+    public void testGroupSectioners() {
+        final NotificationRecord notification_alerting = getNotificationRecord(mPkg, 0, "", mUser,
+                "", false, IMPORTANCE_DEFAULT);
+        assertThat(GroupHelper.getSection(notification_alerting).mName).isEqualTo(
+                "AlertingSection");
+
+        final NotificationRecord notification_silent = getNotificationRecord(mPkg, 0, "", mUser,
+                "", false, IMPORTANCE_LOW);
+        assertThat(GroupHelper.getSection(notification_silent).mName).isEqualTo("SilentSection");
+
+        // Check that special categories are grouped by their importance
+        final NotificationChannel promoChannel = new NotificationChannel(
+                NotificationChannel.PROMOTIONS_ID, NotificationChannel.PROMOTIONS_ID,
+                IMPORTANCE_DEFAULT);
+        final NotificationRecord notification_promotion = getNotificationRecord(mPkg, 0, "", mUser,
+                "", false, promoChannel);
+        assertThat(GroupHelper.getSection(notification_promotion).mName).isEqualTo(
+                "AlertingSection");
+
+        final NotificationChannel newsChannel = new NotificationChannel(NotificationChannel.NEWS_ID,
+                NotificationChannel.NEWS_ID, IMPORTANCE_DEFAULT);
+        final NotificationRecord notification_news = getNotificationRecord(mPkg, 0, "", mUser,
+                "", false, newsChannel);
+        assertThat(GroupHelper.getSection(notification_news).mName).isEqualTo(
+                "AlertingSection");
+
+        final NotificationChannel socialChannel = new NotificationChannel(
+                NotificationChannel.SOCIAL_MEDIA_ID, NotificationChannel.SOCIAL_MEDIA_ID,
+                IMPORTANCE_DEFAULT);
+        final NotificationRecord notification_social = getNotificationRecord(mPkg, 0, "", mUser,
+                "", false, socialChannel);
+        assertThat(GroupHelper.getSection(notification_social).mName).isEqualTo(
+                "AlertingSection");
+
+        final NotificationChannel recsChannel = new NotificationChannel(NotificationChannel.RECS_ID,
+                NotificationChannel.RECS_ID, IMPORTANCE_DEFAULT);
+        final NotificationRecord notification_recs = getNotificationRecord(mPkg, 0, "", mUser,
+                "", false, recsChannel);
+        assertThat(GroupHelper.getSection(notification_recs).mName).isEqualTo(
+                "AlertingSection");
+
+        checkNonGroupableNotifications();
+    }
+
+    @Test
+    @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING, FLAG_NOTIFICATION_CLASSIFICATION})
+    public void testGroupSectioners_withClassificationSections() {
+        final NotificationRecord notification_alerting = getNotificationRecord(mPkg, 0, "", mUser,
+                "", false, IMPORTANCE_DEFAULT);
+        assertThat(GroupHelper.getSection(notification_alerting).mName).isEqualTo(
+                "AlertingSection");
+
+        final NotificationRecord notification_silent = getNotificationRecord(mPkg, 0, "", mUser,
+                "", false, IMPORTANCE_LOW);
+        assertThat(GroupHelper.getSection(notification_silent).mName).isEqualTo("SilentSection");
+
+        // Check that special categories are grouped in their own sections
+        final NotificationChannel promoChannel = new NotificationChannel(
+                NotificationChannel.PROMOTIONS_ID, NotificationChannel.PROMOTIONS_ID,
+                IMPORTANCE_DEFAULT);
+        final NotificationRecord notification_promotion = getNotificationRecord(mPkg, 0, "", mUser,
+                "", false, promoChannel);
+        assertThat(GroupHelper.getSection(notification_promotion).mName).isEqualTo(
+                "PromotionsSection");
+
+        final NotificationChannel newsChannel = new NotificationChannel(NotificationChannel.NEWS_ID,
+                NotificationChannel.NEWS_ID, IMPORTANCE_DEFAULT);
+        final NotificationRecord notification_news = getNotificationRecord(mPkg, 0, "", mUser,
+                "", false, newsChannel);
+        assertThat(GroupHelper.getSection(notification_news).mName).isEqualTo(
+                "NewsSection");
+
+        final NotificationChannel socialChannel = new NotificationChannel(
+                NotificationChannel.SOCIAL_MEDIA_ID, NotificationChannel.SOCIAL_MEDIA_ID,
+                IMPORTANCE_DEFAULT);
+        final NotificationRecord notification_social = getNotificationRecord(mPkg, 0, "", mUser,
+                "", false, socialChannel);
+        assertThat(GroupHelper.getSection(notification_social).mName).isEqualTo(
+                "SocialSection");
+
+        final NotificationChannel recsChannel = new NotificationChannel(NotificationChannel.RECS_ID,
+                NotificationChannel.RECS_ID, IMPORTANCE_DEFAULT);
+        final NotificationRecord notification_recs = getNotificationRecord(mPkg, 0, "", mUser,
+                "", false, recsChannel);
+        assertThat(GroupHelper.getSection(notification_recs).mName).isEqualTo(
+                "RecsSection");
+
+        checkNonGroupableNotifications();
+    }
+
 }
diff --git a/services/tests/wmtests/src/com/android/server/policy/MetaKeyEventsInterceptionTests.java b/services/tests/wmtests/src/com/android/server/policy/MetaKeyEventsInterceptionTests.java
new file mode 100644
index 0000000..b979335
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/policy/MetaKeyEventsInterceptionTests.java
@@ -0,0 +1,96 @@
+/*
+ * 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.server.policy;
+
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.view.KeyEvent;
+import android.view.WindowManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.policy.KeyInterceptionInfo;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Testing {@link PhoneWindowManager} functionality of letting app intercepting key events
+ * containing META.
+ */
+@SmallTest
+public class MetaKeyEventsInterceptionTests extends ShortcutKeyTestBase {
+
+    private static final List<KeyEvent> META_KEY_EVENTS = Arrays.asList(
+            new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_META_LEFT),
+            new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_META_RIGHT),
+            new KeyEvent(/* downTime= */ 0, /* eventTime= */
+                    0, /* action= */ 0, /* code= */ 0, /* repeat= */ 0,
+                    /* metaState= */ KeyEvent.META_META_ON));
+
+    @Before
+    public void setUp() {
+        setUpPhoneWindowManager();
+    }
+
+    @Test
+    public void doesntInterceptMetaKeyEvents_whenWindowAskedForIt() {
+        mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(/* granted= */ true);
+        setWindowKeyInterceptionWithPrivateFlags(PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS);
+
+        META_KEY_EVENTS.forEach(keyEvent -> {
+            assertKeyInterceptionResult(keyEvent, /* intercepted= */ false);
+        });
+    }
+
+    @Test
+    public void interceptsMetaKeyEvents_whenWindowDoesntHaveFlagSet() {
+        mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(/* granted= */ true);
+        setWindowKeyInterceptionWithPrivateFlags(0);
+
+        META_KEY_EVENTS.forEach(keyEvent -> {
+            assertKeyInterceptionResult(keyEvent, /* intercepted= */ true);
+        });
+    }
+
+    @Test
+    public void interceptsMetaKeyEvents_whenWindowDoesntHavePermission() {
+        mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(/* granted= */ false);
+        setWindowKeyInterceptionWithPrivateFlags(PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS);
+
+        META_KEY_EVENTS.forEach(keyEvent -> {
+            assertKeyInterceptionResult(keyEvent, /* intercepted= */ true);
+        });
+    }
+
+    private void setWindowKeyInterceptionWithPrivateFlags(int privateFlags) {
+        KeyInterceptionInfo info = new KeyInterceptionInfo(
+                WindowManager.LayoutParams.TYPE_APPLICATION, privateFlags, "title", 0);
+        mPhoneWindowManager.overrideWindowKeyInterceptionInfo(info);
+    }
+
+    private void assertKeyInterceptionResult(KeyEvent keyEvent, boolean intercepted) {
+        long result = mPhoneWindowManager.interceptKeyBeforeDispatching(keyEvent);
+        int expected = intercepted ? -1 : 0;
+        assertThat(result).isEqualTo(expected);
+    }
+}
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index 43b065d..79c7ac1 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -52,6 +52,7 @@
 import static org.mockito.Mockito.description;
 import static org.mockito.Mockito.mockingDetails;
 import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.withSettings;
 
 import android.app.ActivityManagerInternal;
@@ -613,6 +614,10 @@
                 .when(mButtonOverridePermissionChecker).canAppOverrideSystemKey(any(), anyInt());
     }
 
+    void overrideWindowKeyInterceptionInfo(KeyInterceptionInfo info) {
+        when(mWindowManagerInternal.getKeyInterceptionInfoFromToken(any())).thenReturn(info);
+    }
+
     void overrideKeyEventPolicyFlags(int flags) {
         mKeyEventPolicyFlags = flags;
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 84c2c32..4ab2fcf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -205,6 +205,28 @@
     }
 
     @Test
+    public void testAllResumedActivitiesIdle() {
+        final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        final WindowProcessController proc2 = activity2.app;
+        activity1.setState(RESUMED, "test");
+        activity2.detachFromProcess();
+        assertThat(mWm.mRoot.allResumedActivitiesIdle()).isFalse();
+
+        activity1.idle = true;
+        assertThat(mWm.mRoot.allResumedActivitiesIdle()).isFalse();
+
+        activity2.setProcess(proc2);
+        activity2.setState(RESUMED, "test");
+        activity2.idle = true;
+        assertThat(mWm.mRoot.allResumedActivitiesIdle()).isTrue();
+
+        activity1.idle = false;
+        activity1.setVisibleRequested(false);
+        assertThat(mWm.mRoot.allResumedActivitiesIdle()).isTrue();
+    }
+
+    @Test
     public void testTaskLayerRank() {
         final Task rootTask = new TaskBuilder(mSupervisor).build();
         final Task task1 = new TaskBuilder(mSupervisor).setParentTask(rootTask).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 49e349c..56fca31 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1550,10 +1550,6 @@
 
         // An active transient launch overrides idle state to avoid clearing power mode before the
         // transition is finished.
-        spyOn(mRootWindowContainer.mTransitionController);
-        doAnswer(invocation -> controller.isTransientLaunch(invocation.getArgument(0))).when(
-                mRootWindowContainer.mTransitionController).isTransientLaunch(any());
-        activity2.getTask().setResumedActivity(activity2, "test");
         activity2.idle = true;
         assertFalse(mRootWindowContainer.allResumedActivitiesIdle());
 
diff --git a/telephony/java/android/telephony/satellite/SatelliteModemEnableRequestAttributes.java b/telephony/java/android/telephony/satellite/SatelliteModemEnableRequestAttributes.java
new file mode 100644
index 0000000..5e56f84
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/SatelliteModemEnableRequestAttributes.java
@@ -0,0 +1,132 @@
+/*
+ * 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 android.telephony.satellite;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * SatelliteModemEnableRequestAttributes is used to pack info needed by modem to allow carrier to
+ * roam to satellite.
+ *
+ * @hide
+ */
+public final class SatelliteModemEnableRequestAttributes implements Parcelable {
+
+    /** {@code true} to enable satellite and {@code false} to disable satellite */
+    private final boolean mIsEnabled;
+    /**
+     * {@code true} to enable demo mode and {@code false} to disable. When disabling satellite,
+     * {@code mIsDemoMode} is always considered as {@code false} by Telephony.
+     */
+    private final boolean mIsDemoMode;
+    /**
+     * {@code true} means satellite is enabled for emergency mode, {@code false} otherwise. When
+     * disabling satellite, {@code isEmergencyMode} is always considered as {@code false} by
+     * Telephony.
+     */
+    private final boolean mIsEmergencyMode;
+
+    /** The subscription related info */
+    @NonNull private final SatelliteSubscriptionInfo mSatelliteSubscriptionInfo;
+
+    public SatelliteModemEnableRequestAttributes(boolean isEnabled, boolean isDemoMode,
+            boolean isEmergencyMode, @NonNull SatelliteSubscriptionInfo satelliteSubscriptionInfo) {
+        mIsEnabled = isEnabled;
+        mIsDemoMode = isDemoMode;
+        mIsEmergencyMode = isEmergencyMode;
+        mSatelliteSubscriptionInfo = satelliteSubscriptionInfo;
+    }
+
+    private SatelliteModemEnableRequestAttributes(Parcel in) {
+        mIsEnabled = in.readBoolean();
+        mIsDemoMode = in.readBoolean();
+        mIsEmergencyMode = in.readBoolean();
+        mSatelliteSubscriptionInfo = in.readParcelable(
+                SatelliteSubscriptionInfo.class.getClassLoader(), SatelliteSubscriptionInfo.class);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeBoolean(mIsEnabled);
+        dest.writeBoolean(mIsDemoMode);
+        dest.writeBoolean(mIsEmergencyMode);
+        mSatelliteSubscriptionInfo.writeToParcel(dest, flags);
+    }
+
+    public static final Creator<SatelliteModemEnableRequestAttributes> CREATOR = new Creator<>() {
+        @Override
+        public SatelliteModemEnableRequestAttributes createFromParcel(Parcel in) {
+            return new SatelliteModemEnableRequestAttributes(in);
+        }
+
+        @Override
+        public SatelliteModemEnableRequestAttributes[] newArray(int size) {
+            return new SatelliteModemEnableRequestAttributes[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return (new StringBuilder()).append("SatelliteModemEnableRequestAttributes{")
+                .append(", mIsEnabled=").append(mIsEnabled)
+                .append(", mIsDemoMode=").append(mIsDemoMode)
+                .append(", mIsDemoMode=").append(mIsDemoMode)
+                .append("mSatelliteSubscriptionInfo=").append(mSatelliteSubscriptionInfo)
+                .append("}")
+                .toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        SatelliteModemEnableRequestAttributes that = (SatelliteModemEnableRequestAttributes) o;
+        return mIsEnabled == that.mIsEnabled && mIsDemoMode == that.mIsDemoMode
+                && mIsEmergencyMode == that.mIsEmergencyMode && mSatelliteSubscriptionInfo.equals(
+                that.mSatelliteSubscriptionInfo);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIsEnabled, mIsDemoMode, mIsEmergencyMode, mSatelliteSubscriptionInfo);
+    }
+
+    public boolean isEnabled() {
+        return mIsEnabled;
+    }
+
+    public boolean isDemoMode() {
+        return mIsDemoMode;
+    }
+
+    public boolean isEmergencyMode() {
+        return mIsEmergencyMode;
+    }
+
+    @NonNull public SatelliteSubscriptionInfo getSatelliteSubscriptionInfo() {
+        return mSatelliteSubscriptionInfo;
+    }
+}
diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java b/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java
index 50ed627..dbe5ddd 100644
--- a/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java
+++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java
@@ -268,7 +268,7 @@
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
-        if (!(o instanceof SatelliteSubscriberProvisionStatus)) return false;
+        if (!(o instanceof SatelliteSubscriberInfo)) return false;
         SatelliteSubscriberInfo that = (SatelliteSubscriberInfo) o;
         return Objects.equals(mSubscriberId, that.mSubscriberId) && mCarrierId == that.mCarrierId
                 && Objects.equals(mNiddApn, that.mNiddApn) && mSubId == that.mSubId
diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java
index e3d619e..08ef3f2 100644
--- a/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java
+++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberProvisionStatus.java
@@ -90,7 +90,7 @@
     @Override
     @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
     public void writeToParcel(@NonNull Parcel out, int flags) {
-        mSubscriberInfo.writeToParcel(out, flags);
+        out.writeParcelable(mSubscriberInfo, flags);
         out.writeBoolean(mProvisionStatus);
     }
 
diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriptionInfo.java b/telephony/java/android/telephony/satellite/SatelliteSubscriptionInfo.java
new file mode 100644
index 0000000..2ef19f8
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/SatelliteSubscriptionInfo.java
@@ -0,0 +1,106 @@
+/*
+ * 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 android.telephony.satellite;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * SatelliteSubscriptionInfo is used to pack subscription related info needed by modem to allow
+ * carrier to roam to satellite.
+ *
+ * @hide
+ */
+public final class SatelliteSubscriptionInfo implements Parcelable {
+    /**
+     * The ICC ID used for satellite attachment.
+     */
+    @NonNull private final String mIccId;
+
+    /**
+     * The NIDD(Non IP Data) APN to be used for carrier roaming to satellite attachment.
+     */
+    @NonNull private final String mNiddApn;
+
+    public SatelliteSubscriptionInfo(@NonNull String iccId, @NonNull String niddApn) {
+        mIccId = iccId;
+        mNiddApn = niddApn;
+    }
+
+    private SatelliteSubscriptionInfo(Parcel in) {
+        mIccId = in.readString8();
+        mNiddApn = in.readString8();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString8(mIccId);
+        dest.writeString8(mNiddApn);
+    }
+
+    @NonNull public static final Creator<SatelliteSubscriptionInfo> CREATOR = new Creator<>() {
+        @Override
+        public SatelliteSubscriptionInfo createFromParcel(Parcel in) {
+            return new SatelliteSubscriptionInfo(in);
+        }
+
+        @Override
+        public SatelliteSubscriptionInfo[] newArray(int size) {
+            return new SatelliteSubscriptionInfo[size];
+        }
+    };
+
+    @Override
+    @NonNull public String toString() {
+        return (new StringBuilder()).append("SatelliteSubscriptionInfo{")
+                .append("IccId=").append(mIccId)
+                .append(", NiddApn=").append(mNiddApn)
+                .append("}")
+                .toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        SatelliteSubscriptionInfo that = (SatelliteSubscriptionInfo) o;
+        return mIccId.equals(that.getIccId()) && mNiddApn.equals(that.getNiddApn());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getIccId(), getNiddApn());
+    }
+
+    @NonNull
+    public String getIccId() {
+        return mIccId;
+    }
+
+    @NonNull
+    public String getNiddApn() {
+        return mNiddApn;
+    }
+}
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteModemEnableRequestAttributes.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteModemEnableRequestAttributes.aidl
new file mode 100644
index 0000000..0a40e15
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteModemEnableRequestAttributes.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.satellite.stub;
+
+import android.telephony.satellite.stub.SatelliteSubscriptionInfo;
+
+/**
+ * {@hide}
+ */
+ parcelable SatelliteModemEnableRequestAttributes {
+    /**
+     * {@code true} to enable satellite and {@code false} to disable.
+     */
+    boolean isEnabled;
+    /**
+     * {@code true} to enable demo mode and {@code false} to disable.
+     */
+    boolean isDemoMode;
+    /**
+     * {@code true} to enable emergency modeand {@code false} to disable.
+     */
+    boolean isEmergencyMode;
+    /**
+     * The subscription related info.
+     */
+    SatelliteSubscriptionInfo satelliteSubscriptionInfo;
+ }
\ No newline at end of file
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteSubscriptionInfo.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteSubscriptionInfo.aidl
new file mode 100644
index 0000000..f664dda
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteSubscriptionInfo.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.satellite.stub;
+
+/**
+ * {@hide}
+ */
+ parcelable SatelliteSubscriptionInfo {
+    /**
+     * The ICC ID used for satellite attachment.
+     */
+    String iccId;
+    /**
+     * The NIDD(Non IP Data) APN to be used for carrier roaming to satellite attachment.
+     */
+    String niddApn;
+ }
\ No newline at end of file
diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
index 4b745b2..4826f42 100644
--- a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
@@ -43,7 +43,6 @@
 import android.tracing.perfetto.DataSource;
 import android.util.proto.ProtoInputStream;
 
-import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.internal.protolog.common.IProtoLogGroup;
@@ -73,7 +72,6 @@
  * Test class for {@link ProtoLogImpl}.
  */
 @SuppressWarnings("ConstantConditions")
-@SmallTest
 @Presubmit
 @RunWith(JUnit4.class)
 public class PerfettoProtoLogImplTest {
@@ -166,8 +164,7 @@
         mReader = Mockito.spy(new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider));
         mProtoLog = new PerfettoProtoLogImpl(
                 viewerConfigInputStreamProvider, mReader,
-                () -> mCacheUpdater.run());
-        mProtoLog.registerGroups(TestProtoLogGroup.values());
+                () -> mCacheUpdater.run(), TestProtoLogGroup.values());
     }
 
     @After
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index ab406ef..5b17825 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -1867,7 +1867,7 @@
             return true;
         }
 
-        public String getName() {
+        public String getUniqueIdentifier() {
             return mName;
         }
 
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
index 910bf59..f59e143 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
@@ -15,6 +15,8 @@
  */
 package com.android.hoststubgen
 
+import java.io.File
+
 /**
  * We will not print the stack trace for exceptions implementing it.
  */
@@ -49,4 +51,22 @@
 /**
  * We use this for general "user" errors.
  */
-class HostStubGenUserErrorException(message: String) : Exception(message), UserErrorException
+class GeneralUserErrorException(message: String) : Exception(message), UserErrorException
+
+/** Base exception class for invalid command line arguments. */
+open class ArgumentsException(message: String?) : Exception(message), UserErrorException
+
+/** Thrown when the same annotation is used with different annotation arguments. */
+class DuplicateAnnotationException(annotationName: String?) :
+    ArgumentsException("Duplicate annotation specified: '$annotationName'")
+
+/** Thrown when an input file does not exist. */
+class InputFileNotFoundException(filename: String) :
+    ArgumentsException("File '$filename' not found")
+
+fun String.ensureFileExists(): String {
+    if (!File(this).exists()) {
+        throw InputFileNotFoundException(this)
+    }
+    return this
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
index 6b01d48..a218c55 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
@@ -19,6 +19,6 @@
     open fun onErrorFound(message: String) {
         // TODO: For now, we just throw as soon as any error is found, but eventually we should keep
         // all errors and print them at the end.
-        throw HostStubGenUserErrorException(message)
+        throw GeneralUserErrorException(message)
     }
 }
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
index fcdf824..4bcee40 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
@@ -89,6 +89,8 @@
         addPrinter(StreamPrinter(level, PrintWriter(BufferedOutputStream(
             FileOutputStream(logFilename)))))
 
+        log.i("Log file set: $logFilename for $level")
+
         return this
     }
 
@@ -122,6 +124,9 @@
     }
 
     fun println(level: LogLevel, message: String) {
+        if (message.isEmpty()) {
+            return // Don't print an empty message.
+        }
         printers.forEach {
             if (it.logLevel.ordinal >= level.ordinal) {
                 it.println(level, indent, message)
@@ -185,31 +190,45 @@
         println(LogLevel.Debug, format, *args)
     }
 
-    inline fun <T> logTime(level: LogLevel, message: String, block: () -> T): T {
+    inline fun <T> logTime(level: LogLevel, message: String, block: () -> T): Double {
+        var ret: Double = -1.0
         val start = System.currentTimeMillis()
         try {
-            return block()
+            block()
         } finally {
             val end = System.currentTimeMillis()
+            ret = (end - start) / 1000.0
             if (isEnabled(level)) {
                 println(level,
                     String.format("%s: took %.1f second(s).", message, (end - start) / 1000.0))
             }
         }
+        return ret
     }
 
-    inline fun <T> iTime(message: String, block: () -> T): T {
+    /** Do an "i" log with how long it took. */
+    inline fun <T> iTime(message: String, block: () -> T): Double {
         return logTime(LogLevel.Info, message, block)
     }
 
-    inline fun <T> vTime(message: String, block: () -> T): T {
+    /** Do a "v" log with how long it took. */
+    inline fun <T> vTime(message: String, block: () -> T): Double {
         return logTime(LogLevel.Verbose, message, block)
     }
 
-    inline fun <T> dTime(message: String, block: () -> T): T {
+    /** Do a "d" log with how long it took. */
+    inline fun <T> dTime(message: String, block: () -> T): Double {
         return logTime(LogLevel.Debug, message, block)
     }
 
+    /**
+     * Similar to the other "xTime" methods, but the message is not supposed to be printed.
+     * It's only used to measure the duration with the same interface as other log methods.
+     */
+    inline fun <T> nTime(block: () -> T): Double {
+        return logTime(LogLevel.Debug, "", block)
+    }
+
     inline fun forVerbose(block: () -> Unit) {
         if (isEnabled(LogLevel.Verbose)) {
             block()
@@ -253,6 +272,21 @@
             }
         }
     }
+
+    /**
+     * Handle log-related command line arguments.
+     */
+    fun maybeHandleCommandLineArg(currentArg: String, nextArgProvider: () -> String): Boolean {
+        when (currentArg) {
+            "-v", "--verbose" -> setConsoleLogLevel(LogLevel.Verbose)
+            "-d", "--debug" -> setConsoleLogLevel(LogLevel.Debug)
+            "-q", "--quiet" -> setConsoleLogLevel(LogLevel.None)
+            "--verbose-log" -> addFilePrinter(LogLevel.Verbose, nextArgProvider())
+            "--debug-log" -> addFilePrinter(LogLevel.Debug, nextArgProvider())
+            else -> return false
+        }
+        return true
+    }
 }
 
 private interface LogPrinter {
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenMain.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenMain.kt
index 45e7e30..8506466 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenMain.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenMain.kt
@@ -24,20 +24,32 @@
  */
 fun main(args: Array<String>) {
     executableName = "HostStubGen"
+    runMainWithBoilerplate {
+        // Parse the command line arguments.
+        var clanupOnError = false
+        try {
+            val options = HostStubGenOptions.parseArgs(args)
+            clanupOnError = options.cleanUpOnError.get
 
+            log.v("$executableName started")
+            log.v("Options: $options")
+
+            // Run.
+            HostStubGen(options).run()
+        } catch (e: Throwable) {
+            if (clanupOnError) {
+                TODO("Remove output jars here")
+            }
+            throw e
+        }
+    }
+}
+
+inline fun runMainWithBoilerplate(realMain: () -> Unit) {
     var success = false
-    var clanupOnError = false
 
     try {
-        // Parse the command line arguments.
-        val options = HostStubGenOptions.parseArgs(args)
-        clanupOnError = options.cleanUpOnError.get
-
-        log.v("$executableName started")
-        log.v("Options: $options")
-
-        // Run.
-        HostStubGen(options).run()
+        realMain()
 
         success = true
     } catch (e: Throwable) {
@@ -45,9 +57,6 @@
         if (e !is UserErrorException) {
             e.printStackTrace(PrintWriter(log.getWriter(LogLevel.Error)))
         }
-        if (clanupOnError) {
-            TODO("Remove output jars here")
-        }
     } finally {
         log.i("$executableName finished")
         log.flush()
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
index 2f833a8..f88b107 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -17,20 +17,17 @@
 
 import com.android.hoststubgen.filters.FilterPolicy
 import java.io.BufferedReader
-import java.io.File
 import java.io.FileReader
 
 /**
  * A single value that can only set once.
  */
-class SetOnce<T>(
-        private var value: T,
-) {
+open class SetOnce<T>(private var value: T) {
     class SetMoreThanOnceException : Exception()
 
     private var set = false
 
-    fun set(v: T) {
+    fun set(v: T): T {
         if (set) {
             throw SetMoreThanOnceException()
         }
@@ -39,6 +36,7 @@
         }
         set = true
         value = v
+        return v
     }
 
     val get: T
@@ -59,6 +57,16 @@
     }
 }
 
+class IntSetOnce(value: Int) : SetOnce<Int>(value) {
+    fun set(v: String): Int {
+        try {
+            return this.set(v.toInt())
+        } catch (e: NumberFormatException) {
+            throw ArgumentsException("Invalid integer $v")
+        }
+    }
+}
+
 /**
  * Options that can be set from command line arguments.
  */
@@ -113,18 +121,11 @@
 
         var apiListFile: SetOnce<String?> = SetOnce(null),
 
-        var numShards: SetOnce<Int> = SetOnce(1),
-        var shard: SetOnce<Int> = SetOnce(0),
+        var numShards: IntSetOnce = IntSetOnce(1),
+        var shard: IntSetOnce = IntSetOnce(0),
 ) {
     companion object {
 
-        private fun String.ensureFileExists(): String {
-            if (!File(this).exists()) {
-                throw InputFileNotFoundException(this)
-            }
-            return this
-        }
-
         private fun parsePackageRedirect(fromColonTo: String): Pair<String, String> {
             val colon = fromColonTo.indexOf(':')
             if ((colon < 1) || (colon + 1 >= fromColonTo.length)) {
@@ -137,7 +138,7 @@
         fun parseArgs(args: Array<String>): HostStubGenOptions {
             val ret = HostStubGenOptions()
 
-            val ai = ArgIterator(expandAtFiles(args))
+            val ai = ArgIterator.withAtFiles(args)
 
             var allAnnotations = mutableSetOf<String>()
 
@@ -148,11 +149,6 @@
                 return name
             }
 
-            fun setLogFile(level: LogLevel, filename: String) {
-                log.addFilePrinter(level, filename)
-                log.i("$level log file: $filename")
-            }
-
             while (true) {
                 val arg = ai.nextArgOptional()
                 if (arg == null) {
@@ -161,33 +157,23 @@
 
                 // Define some shorthands...
                 fun nextArg(): String = ai.nextArgRequired(arg)
-                fun SetOnce<String>.setNextStringArg(): String = nextArg().also { this.set(it) }
-                fun SetOnce<String?>.setNextStringArg(): String = nextArg().also { this.set(it) }
                 fun MutableSet<String>.addUniqueAnnotationArg(): String =
                         nextArg().also { this += ensureUniqueAnnotation(it) }
-                fun SetOnce<Int>.setNextIntArg(): String = nextArg().also {
-                    try {
-                        this.set(it.toInt())
-                    } catch (e: NumberFormatException) {
-                        throw ArgumentsException("Invalid integer for $arg: $it")
-                    }
-                }
 
+                if (log.maybeHandleCommandLineArg(arg) { nextArg() }) {
+                    continue
+                }
                 try {
                     when (arg) {
                         // TODO: Write help
                         "-h", "--help" -> TODO("Help is not implemented yet")
 
-                        "-v", "--verbose" -> log.setConsoleLogLevel(LogLevel.Verbose)
-                        "-d", "--debug" -> log.setConsoleLogLevel(LogLevel.Debug)
-                        "-q", "--quiet" -> log.setConsoleLogLevel(LogLevel.None)
-
-                        "--in-jar" -> ret.inJar.setNextStringArg().ensureFileExists()
-                        "--out-stub-jar" -> ret.outStubJar.setNextStringArg()
-                        "--out-impl-jar" -> ret.outImplJar.setNextStringArg()
+                        "--in-jar" -> ret.inJar.set(nextArg()).ensureFileExists()
+                        "--out-stub-jar" -> ret.outStubJar.set(nextArg())
+                        "--out-impl-jar" -> ret.outImplJar.set(nextArg())
 
                         "--policy-override-file" ->
-                            ret.policyOverrideFile.setNextStringArg().ensureFileExists()
+                            ret.policyOverrideFile.set(nextArg())!!.ensureFileExists()
 
                         "--clean-up-on-error" -> ret.cleanUpOnError.set(true)
                         "--no-clean-up-on-error" -> ret.cleanUpOnError.set(false)
@@ -231,19 +217,19 @@
                             ret.packageRedirects += parsePackageRedirect(nextArg())
 
                         "--annotation-allowed-classes-file" ->
-                            ret.annotationAllowedClassesFile.setNextStringArg()
+                            ret.annotationAllowedClassesFile.set(nextArg())
 
                         "--default-class-load-hook" ->
-                            ret.defaultClassLoadHook.setNextStringArg()
+                            ret.defaultClassLoadHook.set(nextArg())
 
                         "--default-method-call-hook" ->
-                            ret.defaultMethodCallHook.setNextStringArg()
+                            ret.defaultMethodCallHook.set(nextArg())
 
                         "--intersect-stub-jar" ->
                             ret.intersectStubJars += nextArg().ensureFileExists()
 
                         "--gen-keep-all-file" ->
-                            ret.inputJarAsKeepAllFile.setNextStringArg()
+                            ret.inputJarAsKeepAllFile.set(nextArg())
 
                         // Following options are for debugging.
                         "--enable-class-checker" -> ret.enableClassChecker.set(true)
@@ -261,16 +247,21 @@
                         "--no-non-stub-method-check" ->
                             ret.enableNonStubMethodCallDetection.set(false)
 
-                        "--gen-input-dump-file" -> ret.inputJarDumpFile.setNextStringArg()
+                        "--gen-input-dump-file" -> ret.inputJarDumpFile.set(nextArg())
 
-                        "--verbose-log" -> setLogFile(LogLevel.Verbose, nextArg())
-                        "--debug-log" -> setLogFile(LogLevel.Debug, nextArg())
+                        "--stats-file" -> ret.statsFile.set(nextArg())
+                        "--supported-api-list-file" -> ret.apiListFile.set(nextArg())
 
-                        "--stats-file" -> ret.statsFile.setNextStringArg()
-                        "--supported-api-list-file" -> ret.apiListFile.setNextStringArg()
-
-                        "--num-shards" -> ret.numShards.setNextIntArg()
-                        "--shard-index" -> ret.shard.setNextIntArg()
+                        "--num-shards" -> ret.numShards.set(nextArg()).also {
+                            if (it < 1) {
+                                throw ArgumentsException("$arg must be positive integer")
+                            }
+                        }
+                        "--shard-index" -> ret.shard.set(nextArg()).also {
+                            if (it < 0) {
+                                throw ArgumentsException("$arg must be positive integer or zero")
+                            }
+                        }
 
                         else -> throw ArgumentsException("Unknown option: $arg")
                     }
@@ -286,6 +277,15 @@
                 log.w("Neither --out-stub-jar nor --out-impl-jar is set." +
                         " $executableName will not generate jar files.")
             }
+            if (ret.numShards.isSet != ret.shard.isSet) {
+                throw ArgumentsException("--num-shards and --shard-index must be used together")
+            }
+
+            if (ret.numShards.isSet) {
+                if (ret.shard.get >= ret.numShards.get) {
+                    throw ArgumentsException("--shard-index must be smaller than --num-shards")
+                }
+            }
 
             if (ret.enableNonStubMethodCallDetection.get) {
                 log.w("--enable-non-stub-method-check is not fully implemented yet." +
@@ -294,87 +294,6 @@
 
             return ret
         }
-
-        /**
-         * Scan the arguments, and if any of them starts with an `@`, then load from the file
-         * and use its content as arguments.
-         *
-         * In this file, each line is treated as a single argument.
-         *
-         * The file can contain '#' as comments.
-         */
-        private fun expandAtFiles(args: Array<String>): List<String> {
-            val ret = mutableListOf<String>()
-
-            args.forEach { arg ->
-                if (!arg.startsWith('@')) {
-                    ret += arg
-                    return@forEach
-                }
-                // Read from the file, and add each line to the result.
-                val filename = arg.substring(1).ensureFileExists()
-
-                log.v("Expanding options file $filename")
-
-                BufferedReader(FileReader(filename)).use { reader ->
-                    while (true) {
-                        var line = reader.readLine()
-                        if (line == null) {
-                            break // EOF
-                        }
-
-                        line = normalizeTextLine(line)
-                        if (line.isNotEmpty()) {
-                            ret += line
-                        }
-                    }
-                }
-            }
-            return ret
-        }
-    }
-
-    open class ArgumentsException(message: String?) : Exception(message), UserErrorException
-
-    /** Thrown when the same annotation is used with different annotation arguments. */
-    class DuplicateAnnotationException(annotationName: String?) :
-            ArgumentsException("Duplicate annotation specified: '$annotationName'")
-
-    /** Thrown when an input file does not exist. */
-    class InputFileNotFoundException(filename: String) :
-            ArgumentsException("File '$filename' not found")
-
-    private class ArgIterator(
-            private val args: List<String>,
-            private var currentIndex: Int = -1
-    ) {
-        val current: String
-            get() = args.get(currentIndex)
-
-        /**
-         * Get the next argument, or [null] if there's no more arguments.
-         */
-        fun nextArgOptional(): String? {
-            if ((currentIndex + 1) >= args.size) {
-                return null
-            }
-            return args.get(++currentIndex)
-        }
-
-        /**
-         * Get the next argument, or throw if
-         */
-        fun nextArgRequired(argName: String): String {
-            nextArgOptional().let {
-                if (it == null) {
-                    throw ArgumentsException("Missing parameter for option $argName")
-                }
-                if (it.isEmpty()) {
-                    throw ArgumentsException("Parameter can't be empty for option $argName")
-                }
-                return it
-            }
-        }
     }
 
     override fun toString(): String {
@@ -415,3 +334,80 @@
             """.trimIndent()
     }
 }
+
+class ArgIterator(
+    private val args: List<String>,
+    private var currentIndex: Int = -1
+) {
+    val current: String
+        get() = args.get(currentIndex)
+
+    /**
+     * Get the next argument, or [null] if there's no more arguments.
+     */
+    fun nextArgOptional(): String? {
+        if ((currentIndex + 1) >= args.size) {
+            return null
+        }
+        return args.get(++currentIndex)
+    }
+
+    /**
+     * Get the next argument, or throw if
+     */
+    fun nextArgRequired(argName: String): String {
+        nextArgOptional().let {
+            if (it == null) {
+                throw ArgumentsException("Missing parameter for option $argName")
+            }
+            if (it.isEmpty()) {
+                throw ArgumentsException("Parameter can't be empty for option $argName")
+            }
+            return it
+        }
+    }
+
+    companion object {
+        fun withAtFiles(args: Array<String>): ArgIterator {
+            return ArgIterator(expandAtFiles(args))
+        }
+    }
+}
+
+/**
+ * Scan the arguments, and if any of them starts with an `@`, then load from the file
+ * and use its content as arguments.
+ *
+ * In this file, each line is treated as a single argument.
+ *
+ * The file can contain '#' as comments.
+ */
+private fun expandAtFiles(args: Array<String>): List<String> {
+    val ret = mutableListOf<String>()
+
+    args.forEach { arg ->
+        if (!arg.startsWith('@')) {
+            ret += arg
+            return@forEach
+        }
+        // Read from the file, and add each line to the result.
+        val filename = arg.substring(1).ensureFileExists()
+
+        log.v("Expanding options file $filename")
+
+        BufferedReader(FileReader(filename)).use { reader ->
+            while (true) {
+                var line = reader.readLine()
+                if (line == null) {
+                    break // EOF
+                }
+
+                line = normalizeTextLine(line)
+                if (line.isNotEmpty()) {
+                    ret += line
+                }
+            }
+        }
+    }
+    return ret
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
index f219dac..6cf2143 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -58,7 +58,24 @@
     return null
 }
 
-fun findAnnotationValueAsString(an: AnnotationNode, propertyName: String): String? {
+fun ClassNode.findAnyAnnotation(set: Set<String>): AnnotationNode? {
+    return findAnyAnnotation(set, this.visibleAnnotations, this.invisibleAnnotations)
+}
+
+fun MethodNode.findAnyAnnotation(set: Set<String>): AnnotationNode? {
+    return findAnyAnnotation(set, this.visibleAnnotations, this.invisibleAnnotations)
+}
+
+fun FieldNode.findAnyAnnotation(set: Set<String>): AnnotationNode? {
+    return findAnyAnnotation(set, this.visibleAnnotations, this.invisibleAnnotations)
+}
+
+fun <T> findAnnotationValueAsObject(
+    an: AnnotationNode,
+    propertyName: String,
+    expectedTypeHumanReadableName: String,
+    converter: (Any?) -> T?,
+): T? {
     for (i in 0..(an.values?.size ?: 0) - 2 step 2) {
         val name = an.values[i]
 
@@ -66,16 +83,30 @@
             continue
         }
         val value = an.values[i + 1]
-        if (value is String) {
-            return value
+        if (value == null) {
+            return null
         }
-        throw ClassParseException(
-                "The type of '$name' in annotation \"${an.desc}\" must be String" +
-                        ", but is ${value?.javaClass?.canonicalName}")
+
+        try {
+            return converter(value)
+        } catch (e: ClassCastException) {
+            throw ClassParseException(
+                "The type of '$propertyName' in annotation @${an.desc} must be " +
+                        "$expectedTypeHumanReadableName, but is ${value?.javaClass?.canonicalName}")
+        }
     }
     return null
 }
 
+fun findAnnotationValueAsString(an: AnnotationNode, propertyName: String): String? {
+    return findAnnotationValueAsObject(an, propertyName, "String", {it as String})
+}
+
+fun findAnnotationValueAsType(an: AnnotationNode, propertyName: String): Type? {
+    return findAnnotationValueAsObject(an, propertyName, "Class", {it as Type})
+}
+
+
 val periodOrSlash = charArrayOf('.', '/')
 
 fun getPackageNameFromFullClassName(fullClassName: String): String {
@@ -125,6 +156,24 @@
     return Pair(name.substring(0, pos), name.substring(pos + 1))
 }
 
+fun String.startsWithAny(vararg prefixes: String): Boolean {
+    prefixes.forEach {
+        if (this.startsWith(it)) {
+            return true
+        }
+    }
+    return false
+}
+
+fun String.endsWithAny(vararg suffixes: String): Boolean {
+    suffixes.forEach {
+        if (this.endsWith(it)) {
+            return true
+        }
+    }
+    return false
+}
+
 fun String.toJvmClassName(): String {
     return this.replace('.', '/')
 }
@@ -137,6 +186,14 @@
     return this.replace('/', '.')
 }
 
+fun zipEntryNameToClassName(entryFilename: String): String? {
+    val suffix = ".class"
+    if (!entryFilename.endsWith(suffix)) {
+        return null
+    }
+    return entryFilename.substring(0, entryFilename.length - suffix.length)
+}
+
 private val numericalInnerClassName = """.*\$\d+$""".toRegex()
 
 fun isAnonymousInnerClass(cn: ClassNode): Boolean {
@@ -278,6 +335,14 @@
     return (this.access and Opcodes.ACC_STATIC) != 0
 }
 
+fun MethodNode.isPublic(): Boolean {
+    return (this.access and Opcodes.ACC_PUBLIC) != 0
+}
+
+fun MethodNode.isSpecial(): Boolean {
+    return CTOR_NAME == this.name || CLASS_INITIALIZER_NAME == this.name
+}
+
 fun FieldNode.isEnum(): Boolean {
     return (this.access and Opcodes.ACC_ENUM) != 0
 }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
index 2607df6..e2647eb 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
@@ -27,6 +27,11 @@
 import java.io.BufferedInputStream
 import java.io.PrintWriter
 import java.util.Arrays
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicReference
+import java.util.function.Consumer
+import java.util.zip.ZipEntry
 import java.util.zip.ZipFile
 
 /**
@@ -183,10 +188,43 @@
         /**
          * Load all the classes, without code.
          */
-        fun loadClassStructures(inJar: String): ClassNodes {
-            log.iTime("Reading class structure from $inJar") {
-                val allClasses = ClassNodes()
+        fun loadClassStructures(
+            inJar: String,
+            timeCollector: Consumer<Double>? = null,
+        ): ClassNodes {
+            val allClasses = ClassNodes()
 
+            // Load classes in parallel.
+            val executor = Executors.newFixedThreadPool(4)
+
+            // First exception defected.
+            val exception = AtomicReference<Throwable>()
+
+            // Called on a BG thread. Read a single jar entry and add it to [allClasses].
+            fun parseClass(inZip: ZipFile, entry: ZipEntry) {
+                try {
+                    inZip.getInputStream(entry).use { ins ->
+                        val cr = ClassReader(BufferedInputStream(ins))
+                        val cn = ClassNode()
+                        cr.accept(
+                            cn, ClassReader.SKIP_CODE
+                                    or ClassReader.SKIP_DEBUG
+                                    or ClassReader.SKIP_FRAMES
+                        )
+                        synchronized(allClasses) {
+                            if (!allClasses.addClass(cn)) {
+                                log.w("Duplicate class found: ${cn.name}")
+                            }
+                        }
+                    }
+                } catch (e: Throwable) {
+                    log.e("Failed to load class: $e")
+                    exception.compareAndSet(null, e)
+                }
+            }
+
+            // Actually open the jar and read it on worker threads.
+            val time = log.iTime("Reading class structure from $inJar") {
                 log.withIndent {
                     ZipFile(inJar).use { inZip ->
                         val inEntries = inZip.entries()
@@ -194,40 +232,42 @@
                         while (inEntries.hasMoreElements()) {
                             val entry = inEntries.nextElement()
 
-                            BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
-                                if (entry.name.endsWith(".class")) {
-                                    val cr = ClassReader(bis)
-                                    val cn = ClassNode()
-                                    cr.accept(
-                                        cn, ClassReader.SKIP_CODE
-                                                or ClassReader.SKIP_DEBUG
-                                                or ClassReader.SKIP_FRAMES
-                                    )
-                                    if (!allClasses.addClass(cn)) {
-                                        log.w("Duplicate class found: ${cn.name}")
-                                    }
-                                } else if (entry.name.endsWith(".dex")) {
-                                    // Seems like it's an ART jar file. We can't process it.
-                                    // It's a fatal error.
-                                    throw InvalidJarFileException(
-                                        "$inJar is not a desktop jar file."
-                                        + " It contains a *.dex file."
-                                    )
-                                } else {
-                                    // Unknown file type. Skip.
-                                    while (bis.available() > 0) {
-                                        bis.skip((1024 * 1024).toLong())
-                                    }
+                            if (entry.name.endsWith(".class")) {
+                                executor.submit {
+                                    parseClass(inZip, entry)
                                 }
+                            } else if (entry.name.endsWith(".dex")) {
+                                // Seems like it's an ART jar file. We can't process it.
+                                // It's a fatal error.
+                                throw InvalidJarFileException(
+                                    "$inJar is not a desktop jar file."
+                                            + " It contains a *.dex file."
+                                )
+                            } else {
+                                // Unknown file type. Skip.
                             }
                         }
+                        // Wait for all the work to complete. (must do it before closing the zip)
+                        log.i("Waiting for all loaders to finish...")
+                        executor.shutdown()
+                        executor.awaitTermination(5, TimeUnit.MINUTES)
+                        log.i("All loaders to finished.")
                     }
                 }
+
+                // If any exception is detected, throw it.
+                exception.get()?.let {
+                    throw it
+                }
+
                 if (allClasses.size == 0) {
                     log.w("$inJar contains no *.class files.")
+                } else {
+                    log.i("Loaded ${allClasses.size} classes from $inJar.")
                 }
-                return allClasses
             }
+            timeCollector?.accept(time)
+            return allClasses
         }
     }
 }
\ No newline at end of file
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt
index 3c99e68..c3595b7 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogCallProcessorImpl.kt
@@ -120,7 +120,7 @@
 
                         logCallVisitor?.processCall(call, messageString, getLevelForMethodName(
                             call.name.toString(), call, context), groupMap.getValue(groupName))
-                    } else if (call.name.id == "initialize") {
+                    } else if (call.name.id == "init") {
                         // No processing
                     } else {
                         // Process non-log message calls