Merge "Reset IME visible types only when losing control" into main
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 80578e4..ac67909 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1765,15 +1765,12 @@
   public final class InputManager {
     method public void addUniqueIdAssociation(@NonNull String, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.REMAP_MODIFIER_KEYS) public void clearAllModifierKeyRemappings();
-    method @Nullable public String getCurrentKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier);
-    method @NonNull public java.util.List<java.lang.String> getKeyboardLayoutDescriptorsForInputDevice(@NonNull android.view.InputDevice);
+    method @NonNull public java.util.List<java.lang.String> getKeyboardLayoutDescriptors();
     method @NonNull public String getKeyboardLayoutTypeForLayoutDescriptor(@NonNull String);
     method @NonNull @RequiresPermission(android.Manifest.permission.REMAP_MODIFIER_KEYS) public java.util.Map<java.lang.Integer,java.lang.Integer> getModifierKeyRemapping();
     method public int getMousePointerSpeed();
     method @RequiresPermission(android.Manifest.permission.REMAP_MODIFIER_KEYS) public void remapModifierKey(int, int);
-    method @RequiresPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT) public void removeKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier, @NonNull String);
     method public void removeUniqueIdAssociation(@NonNull String);
-    method @RequiresPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT) public void setCurrentKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier, @NonNull String);
     field public static final long BLOCK_UNTRUSTED_TOUCHES = 158002302L; // 0x96aec7eL
   }
 
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 2816f77..1c37aa2 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -94,33 +94,8 @@
     // Keyboard layouts configuration.
     KeyboardLayout[] getKeyboardLayouts();
 
-    KeyboardLayout[] getKeyboardLayoutsForInputDevice(in InputDeviceIdentifier identifier);
-
     KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor);
 
-    String getCurrentKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier);
-
-    @EnforcePermission("SET_KEYBOARD_LAYOUT")
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
-            + "android.Manifest.permission.SET_KEYBOARD_LAYOUT)")
-    void setCurrentKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor);
-
-    String[] getEnabledKeyboardLayoutsForInputDevice(in InputDeviceIdentifier identifier);
-
-    @EnforcePermission("SET_KEYBOARD_LAYOUT")
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
-            + "android.Manifest.permission.SET_KEYBOARD_LAYOUT)")
-    void addKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor);
-
-    @EnforcePermission("SET_KEYBOARD_LAYOUT")
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
-            + "android.Manifest.permission.SET_KEYBOARD_LAYOUT)")
-    void removeKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor);
-
-    // New Keyboard layout config APIs
     KeyboardLayoutSelectionResult getKeyboardLayoutForInputDevice(
             in InputDeviceIdentifier identifier, int userId, in InputMethodInfo imeInfo,
             in InputMethodSubtype imeSubtype);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index a1242fb..f949158 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -473,22 +473,21 @@
     }
 
     /**
-     * Returns the descriptors of all supported keyboard layouts appropriate for the specified
-     * input device.
+     * Returns the descriptors of all supported keyboard layouts.
      * <p>
      * The input manager consults the built-in keyboard layouts as well as all keyboard layouts
      * advertised by applications using a {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
      * </p>
      *
-     * @param device The input device to query.
      * @return The ids of all keyboard layouts which are supported by the specified input device.
      *
      * @hide
      */
     @TestApi
     @NonNull
-    public List<String> getKeyboardLayoutDescriptorsForInputDevice(@NonNull InputDevice device) {
-        KeyboardLayout[] layouts = getKeyboardLayoutsForInputDevice(device.getIdentifier());
+    @SuppressLint("UnflaggedApi")
+    public List<String> getKeyboardLayoutDescriptors() {
+        KeyboardLayout[] layouts = getKeyboardLayouts();
         List<String> res = new ArrayList<>();
         for (KeyboardLayout kl : layouts) {
             res.add(kl.getDescriptor());
@@ -511,33 +510,18 @@
     @TestApi
     @NonNull
     public String getKeyboardLayoutTypeForLayoutDescriptor(@NonNull String layoutDescriptor) {
-        KeyboardLayout[] layouts = getKeyboardLayouts();
-        for (KeyboardLayout kl : layouts) {
-            if (layoutDescriptor.equals(kl.getDescriptor())) {
-                return kl.getLayoutType();
-            }
-        }
-        return "";
+        KeyboardLayout layout = getKeyboardLayout(layoutDescriptor);
+        return layout == null ? "" : layout.getLayoutType();
     }
 
     /**
-     * Gets information about all supported keyboard layouts appropriate
-     * for a specific input device.
-     * <p>
-     * The input manager consults the built-in keyboard layouts as well
-     * as all keyboard layouts advertised by applications using a
-     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
-     * </p>
-     *
-     * @return A list of all supported keyboard layouts for a specific
-     * input device.
-     *
+     * TODO(b/330517633): Cleanup the unsupported API
      * @hide
      */
     @NonNull
     public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
             @NonNull InputDeviceIdentifier identifier) {
-        return mGlobal.getKeyboardLayoutsForInputDevice(identifier);
+        return new KeyboardLayout[0];
     }
 
     /**
@@ -549,6 +533,7 @@
      *
      * @hide
      */
+    @Nullable
     public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
         if (keyboardLayoutDescriptor == null) {
             throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
@@ -562,121 +547,45 @@
     }
 
     /**
-     * Gets the current keyboard layout descriptor for the specified input device.
-     *
-     * @param identifier Identifier for the input device
-     * @return The keyboard layout descriptor, or null if no keyboard layout has been set.
-     *
+     * TODO(b/330517633): Cleanup the unsupported API
      * @hide
      */
-    @TestApi
     @Nullable
     public String getCurrentKeyboardLayoutForInputDevice(
             @NonNull InputDeviceIdentifier identifier) {
-        try {
-            return mIm.getCurrentKeyboardLayoutForInputDevice(identifier);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
+        return null;
     }
 
     /**
-     * Sets the current keyboard layout descriptor for the specified input device.
-     * <p>
-     * This method may have the side-effect of causing the input device in question to be
-     * reconfigured.
-     * </p>
-     *
-     * @param identifier The identifier for the input device.
-     * @param keyboardLayoutDescriptor The keyboard layout descriptor to use, must not be null.
-     *
+     * TODO(b/330517633): Cleanup the unsupported API
      * @hide
      */
-    @TestApi
-    @RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
     public void setCurrentKeyboardLayoutForInputDevice(@NonNull InputDeviceIdentifier identifier,
-            @NonNull String keyboardLayoutDescriptor) {
-        mGlobal.setCurrentKeyboardLayoutForInputDevice(identifier,
-                keyboardLayoutDescriptor);
-    }
+            @NonNull String keyboardLayoutDescriptor) {}
 
     /**
-     * Gets all keyboard layout descriptors that are enabled for the specified input device.
-     *
-     * @param identifier The identifier for the input device.
-     * @return The keyboard layout descriptors.
-     *
+     * TODO(b/330517633): Cleanup the unsupported API
      * @hide
      */
     public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
-        if (identifier == null) {
-            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
-        }
-
-        try {
-            return mIm.getEnabledKeyboardLayoutsForInputDevice(identifier);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
+        return new String[0];
     }
 
     /**
-     * Adds the keyboard layout descriptor for the specified input device.
-     * <p>
-     * This method may have the side-effect of causing the input device in question to be
-     * reconfigured.
-     * </p>
-     *
-     * @param identifier The identifier for the input device.
-     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to add.
-     *
+     * TODO(b/330517633): Cleanup the unsupported API
      * @hide
      */
-    @RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
     public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
             String keyboardLayoutDescriptor) {
-        if (identifier == null) {
-            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
-        }
-        if (keyboardLayoutDescriptor == null) {
-            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
-        }
-
-        try {
-            mIm.addKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
     }
 
     /**
-     * Removes the keyboard layout descriptor for the specified input device.
-     * <p>
-     * This method may have the side-effect of causing the input device in question to be
-     * reconfigured.
-     * </p>
-     *
-     * @param identifier The identifier for the input device.
-     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to remove.
-     *
+     * TODO(b/330517633): Cleanup the unsupported API
      * @hide
      */
-    @TestApi
     @RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
     public void removeKeyboardLayoutForInputDevice(@NonNull InputDeviceIdentifier identifier,
             @NonNull String keyboardLayoutDescriptor) {
-        if (identifier == null) {
-            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
-        }
-        if (keyboardLayoutDescriptor == null) {
-            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
-        }
-
-        try {
-            mIm.removeKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
     }
 
     /**
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
index 7c104a0..7b29666 100644
--- a/core/java/android/hardware/input/InputManagerGlobal.java
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -1068,36 +1068,21 @@
     }
 
     /**
-     * @see InputManager#getKeyboardLayoutsForInputDevice(InputDeviceIdentifier)
+     * TODO(b/330517633): Cleanup the unsupported API
      */
     @NonNull
     public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
             @NonNull InputDeviceIdentifier identifier) {
-        try {
-            return mIm.getKeyboardLayoutsForInputDevice(identifier);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
+        return new KeyboardLayout[0];
     }
 
     /**
-     * @see InputManager#setCurrentKeyboardLayoutForInputDevice
-     * (InputDeviceIdentifier, String)
+     * TODO(b/330517633): Cleanup the unsupported API
      */
-    @RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
     public void setCurrentKeyboardLayoutForInputDevice(
             @NonNull InputDeviceIdentifier identifier,
-            @NonNull String keyboardLayoutDescriptor) {
-        Objects.requireNonNull(identifier, "identifier must not be null");
-        Objects.requireNonNull(keyboardLayoutDescriptor,
-                "keyboardLayoutDescriptor must not be null");
-        try {
-            mIm.setCurrentKeyboardLayoutForInputDevice(identifier,
-                    keyboardLayoutDescriptor);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
-    }
+            @NonNull String keyboardLayoutDescriptor) {}
+
 
     /**
      * @see InputDevice#getSensorManager()
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index efe31ff..616004b 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -36,3 +36,10 @@
     description: "Enables a limit on the number of Tasks shown in Desktop Mode"
     bug: "332502912"
 }
+
+flag {
+    name: "enable_windowing_edge_drag_resize"
+    namespace: "lse_desktop_experience"
+    description: "Enables edge drag resizing for all input sources"
+    bug: "323383067"
+}
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index f9347ee..e8b4104 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -424,12 +424,14 @@
 key 582   VOICE_ASSIST
 # Linux KEY_ASSISTANT
 key 583   ASSIST
+key 585   EMOJI_PICKER
 key 656   MACRO_1
 key 657   MACRO_2
 key 658   MACRO_3
 key 659   MACRO_4
 
 # Keys defined by HID usages
+key usage 0x0c0065 SCREENSHOT                FALLBACK_USAGE_MAPPING
 key usage 0x0c0067 WINDOW                    FALLBACK_USAGE_MAPPING
 key usage 0x0c006F BRIGHTNESS_UP             FALLBACK_USAGE_MAPPING
 key usage 0x0c0070 BRIGHTNESS_DOWN           FALLBACK_USAGE_MAPPING
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 207ccbe..871e9ab 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -80,4 +80,7 @@
     boolean hasCustomMediaSessionPolicyProvider(String componentName);
     int getSessionPolicies(in MediaSession.Token token);
     void setSessionPolicies(in MediaSession.Token token, int policies);
+
+    // For testing of temporarily engaged sessions.
+    void expireTempEngagedSessions();
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt
index 8b546b4..791893b 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt
@@ -23,7 +23,6 @@
 @Composable
 fun TwoTargetSwitchPreference(
     model: SwitchPreferenceModel,
-    icon: @Composable (() -> Unit)? = null,
     primaryEnabled: () -> Boolean = { true },
     primaryOnClick: (() -> Unit)?,
 ) {
@@ -33,7 +32,7 @@
             summary = model.summary,
             primaryEnabled = primaryEnabled,
             primaryOnClick = primaryOnClick,
-            icon = icon,
+            icon = model.icon,
         ) {
             SettingsSwitch(
                 checked = model.checked(),
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt
index 5c2d770..1f7122e 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt
@@ -33,11 +33,13 @@
         model = object : SwitchPreferenceModel {
             override val title = label
             override val summary = this@AppListTwoTargetSwitchItem.summary
+            override val icon = @Composable {
+                AppIcon(record.app, SettingsDimension.appIconItemSize)
+            }
             override val checked = checked
             override val changeable = changeable
             override val onCheckedChange = onCheckedChange
         },
-        icon = { AppIcon(record.app, SettingsDimension.appIconItemSize) },
         primaryOnClick = onClick,
     )
 }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceModel.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceModel.kt
index 87cd2b8..c9934ad 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceModel.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceModel.kt
@@ -52,6 +52,8 @@
         checked = model.checked,
     )
 
+    override val icon = model.icon
+
     override val checked = when (restrictedMode) {
         null -> ({ null })
         is NoRestricted -> model.checked
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedTwoTargetSwitchPreference.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedTwoTargetSwitchPreference.kt
index e100773..1bed733 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedTwoTargetSwitchPreference.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedTwoTargetSwitchPreference.kt
@@ -29,14 +29,12 @@
 @Composable
 fun RestrictedTwoTargetSwitchPreference(
     model: SwitchPreferenceModel,
-    icon: @Composable (() -> Unit)? = null,
     restrictions: Restrictions,
     primaryEnabled: () -> Boolean = { true },
     primaryOnClick: (() -> Unit)?,
 ) {
     RestrictedTwoTargetSwitchPreference(
         model = model,
-        icon = icon,
         primaryEnabled = primaryEnabled,
         primaryOnClick = primaryOnClick,
         restrictions = restrictions,
@@ -48,21 +46,19 @@
 @Composable
 internal fun RestrictedTwoTargetSwitchPreference(
     model: SwitchPreferenceModel,
-    icon: @Composable (() -> Unit)? = null,
     primaryEnabled: () -> Boolean = { true },
     primaryOnClick: (() -> Unit)?,
     restrictions: Restrictions,
     restrictionsProviderFactory: RestrictionsProviderFactory,
 ) {
     if (restrictions.isEmpty()) {
-        TwoTargetSwitchPreference(model, icon, primaryEnabled, primaryOnClick)
+        TwoTargetSwitchPreference(model, primaryEnabled, primaryOnClick)
         return
     }
     val restrictedMode = restrictionsProviderFactory.rememberRestrictedMode(restrictions).value
     RestrictedSwitchWrapper(model, restrictedMode) { restrictedModel ->
         TwoTargetSwitchPreference(
             model = restrictedModel,
-            icon = icon,
             primaryEnabled = restrictedMode.restrictEnabled(primaryEnabled),
             primaryOnClick = restrictedMode.restrictOnClick(primaryOnClick),
         )
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/BottomComponentButtonSurface.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/BottomComponentButtonSurface.kt
new file mode 100644
index 0000000..167eb65
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/BottomComponentButtonSurface.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.
+ */
+
+package com.android.systemui.volume.panel.component.button.ui.composable
+
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+
+/**
+ * Container to create a rim around the button. Both `Expandable` and `OutlinedIconToggleButton`
+ * have antialiasing problem when used with [androidx.compose.foundation.BorderStroke] and some
+ * contrast container color.
+ */
+// TODO(b/331584069): Remove this once antialiasing bug is fixed
+@Composable
+fun BottomComponentButtonSurface(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
+    Surface(
+        modifier = modifier.height(64.dp),
+        shape = RoundedCornerShape(28.dp),
+        color = MaterialTheme.colorScheme.surface,
+        content = content,
+    )
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ButtonComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ButtonComponent.kt
index 8f187cc..fc511e1 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ButtonComponent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ButtonComponent.kt
@@ -16,14 +16,12 @@
 
 package com.android.systemui.volume.panel.component.button.ui.composable
 
-import androidx.compose.foundation.BorderStroke
 import androidx.compose.foundation.basicMarquee
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material3.MaterialTheme
@@ -64,20 +62,21 @@
             verticalArrangement = Arrangement.spacedBy(12.dp),
             horizontalAlignment = Alignment.CenterHorizontally,
         ) {
-            Expandable(
-                modifier =
-                    Modifier.height(64.dp).fillMaxWidth().semantics {
-                        role = Role.Button
-                        contentDescription = label
-                    },
-                color = MaterialTheme.colorScheme.primaryContainer,
-                shape = RoundedCornerShape(28.dp),
-                contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
-                borderStroke = BorderStroke(8.dp, MaterialTheme.colorScheme.surface),
-                onClick = onClick,
-            ) {
-                Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
-                    Icon(modifier = Modifier.size(24.dp), icon = viewModel.icon)
+            BottomComponentButtonSurface {
+                Expandable(
+                    modifier =
+                        Modifier.fillMaxSize().padding(8.dp).semantics {
+                            role = Role.Button
+                            contentDescription = label
+                        },
+                    color = MaterialTheme.colorScheme.primaryContainer,
+                    shape = RoundedCornerShape(28.dp),
+                    contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
+                    onClick = onClick,
+                ) {
+                    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
+                        Icon(modifier = Modifier.size(24.dp), icon = viewModel.icon)
+                    }
                 }
             }
             Text(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt
index 51ec63b..780e3f2 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/button/ui/composable/ToggleButtonComponent.kt
@@ -16,23 +16,23 @@
 
 package com.android.systemui.volume.panel.component.button.ui.composable
 
-import androidx.compose.foundation.BorderStroke
 import androidx.compose.foundation.basicMarquee
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.IconButtonDefaults
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.OutlinedIconToggleButton
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.semantics.clearAndSetSemantics
 import androidx.compose.ui.semantics.contentDescription
@@ -62,26 +62,33 @@
             verticalArrangement = Arrangement.spacedBy(12.dp),
             horizontalAlignment = Alignment.CenterHorizontally,
         ) {
-            OutlinedIconToggleButton(
-                modifier =
-                    Modifier.height(64.dp).fillMaxWidth().semantics {
-                        role = Role.Switch
-                        contentDescription = label
-                    },
-                checked = viewModel.isChecked,
-                onCheckedChange = onCheckedChange,
-                shape = RoundedCornerShape(28.dp),
-                colors =
-                    IconButtonDefaults.outlinedIconToggleButtonColors(
-                        containerColor = MaterialTheme.colorScheme.surface,
-                        contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
-                        checkedContainerColor = MaterialTheme.colorScheme.primaryContainer,
-                        checkedContentColor = MaterialTheme.colorScheme.onPrimaryContainer,
-                    ),
-                border = BorderStroke(8.dp, MaterialTheme.colorScheme.surface),
-            ) {
-                Icon(modifier = Modifier.size(24.dp), icon = viewModel.icon)
+            BottomComponentButtonSurface {
+                val colors =
+                    if (viewModel.isChecked) {
+                        ButtonDefaults.buttonColors(
+                            containerColor = MaterialTheme.colorScheme.primaryContainer,
+                            contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
+                        )
+                    } else {
+                        ButtonDefaults.buttonColors(
+                            containerColor = Color.Transparent,
+                            contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
+                        )
+                    }
+                Button(
+                    modifier =
+                        Modifier.fillMaxSize().padding(8.dp).semantics {
+                            role = Role.Switch
+                            contentDescription = label
+                        },
+                    onClick = { onCheckedChange(!viewModel.isChecked) },
+                    shape = RoundedCornerShape(28.dp),
+                    colors = colors
+                ) {
+                    Icon(modifier = Modifier.size(24.dp), icon = viewModel.icon)
+                }
             }
+
             Text(
                 modifier = Modifier.clearAndSetSemantics {}.basicMarquee(),
                 text = label,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt
index e2d7d11..c743314 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/selector/ui/composable/VolumePanelRadioButtons.kt
@@ -46,6 +46,12 @@
 import androidx.compose.ui.layout.Placeable
 import androidx.compose.ui.layout.layoutId
 import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.clearAndSetSemantics
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.role
+import androidx.compose.ui.semantics.selected
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntOffset
@@ -112,10 +118,16 @@
                 horizontalArrangement = Arrangement.spacedBy(spacing)
             ) {
                 for (itemIndex in items.indices) {
+                    val item = items[itemIndex]
                     Row(
                         modifier =
                             Modifier.height(48.dp)
                                 .weight(1f)
+                                .semantics {
+                                    item.contentDescription?.let { contentDescription = it }
+                                    role = Role.Switch
+                                    selected = itemIndex == scope.selectedIndex
+                                }
                                 .clickable(
                                     interactionSource = null,
                                     indication = null,
@@ -124,7 +136,6 @@
                         horizontalArrangement = Arrangement.Center,
                         verticalAlignment = Alignment.CenterVertically,
                     ) {
-                        val item = items[itemIndex]
                         if (item.icon !== Empty) {
                             with(items[itemIndex]) { icon() }
                         }
@@ -138,7 +149,8 @@
                             start = indicatorBackgroundPadding,
                             top = labelIndicatorBackgroundSpacing,
                             end = indicatorBackgroundPadding
-                        ),
+                        )
+                        .clearAndSetSemantics {},
                 horizontalArrangement = Arrangement.spacedBy(spacing),
             ) {
                 for (itemIndex in items.indices) {
@@ -296,6 +308,7 @@
         onItemSelected: () -> Unit,
         icon: @Composable RowScope.() -> Unit = Empty,
         label: @Composable RowScope.() -> Unit = Empty,
+        contentDescription: String? = null,
     )
 }
 
@@ -317,6 +330,7 @@
         onItemSelected: () -> Unit,
         icon: @Composable RowScope.() -> Unit,
         label: @Composable RowScope.() -> Unit,
+        contentDescription: String?,
     ) {
         require(!isSelected || !hasSelectedItem) { "Only one item should be selected at a time" }
         if (isSelected) {
@@ -327,6 +341,7 @@
                 onItemSelected = onItemSelected,
                 icon = icon,
                 label = label,
+                contentDescription = contentDescription,
             )
         )
     }
@@ -340,6 +355,7 @@
     val onItemSelected: () -> Unit,
     val icon: @Composable RowScope.() -> Unit,
     val label: @Composable RowScope.() -> Unit,
+    val contentDescription: String?,
 )
 
 private const val UNSET_OFFSET = -1
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt
index 6673afd..eed54da 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/spatialaudio/ui/composable/SpatialAudioPopup.kt
@@ -74,9 +74,11 @@
         }
         VolumePanelRadioButtonBar {
             for (buttonViewModel in enabledModelStates) {
+                val label = buttonViewModel.button.label.toString()
                 item(
                     isSelected = buttonViewModel.button.isChecked,
                     onItemSelected = { viewModel.setEnabled(buttonViewModel.model) },
+                    contentDescription = label,
                     icon = {
                         Icon(
                             icon = buttonViewModel.button.icon,
@@ -86,7 +88,7 @@
                     label = {
                         Text(
                             modifier = Modifier.basicMarquee(),
-                            text = buttonViewModel.button.label.toString(),
+                            text = label,
                             style = MaterialTheme.typography.labelMedium,
                             color = buttonViewModel.labelColor.toColor(),
                             textAlign = TextAlign.Center,
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 77119d5..f32c11d 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -1197,54 +1197,11 @@
     }
 
     @Override // Binder call
-    public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
-            final InputDeviceIdentifier identifier) {
-        return mKeyboardLayoutManager.getKeyboardLayoutsForInputDevice(identifier);
-    }
-
-    @Override // Binder call
     public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
         return mKeyboardLayoutManager.getKeyboardLayout(keyboardLayoutDescriptor);
     }
 
     @Override // Binder call
-    public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
-        return mKeyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(identifier);
-    }
-
-    @EnforcePermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
-    @Override // Binder call
-    public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor) {
-        super.setCurrentKeyboardLayoutForInputDevice_enforcePermission();
-        mKeyboardLayoutManager.setCurrentKeyboardLayoutForInputDevice(identifier,
-                keyboardLayoutDescriptor);
-    }
-
-    @Override // Binder call
-    public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
-        return mKeyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(identifier);
-    }
-
-    @EnforcePermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
-    @Override // Binder call
-    public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor) {
-        super.addKeyboardLayoutForInputDevice_enforcePermission();
-        mKeyboardLayoutManager.addKeyboardLayoutForInputDevice(identifier,
-                keyboardLayoutDescriptor);
-    }
-
-    @EnforcePermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
-    @Override // Binder call
-    public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor) {
-        super.removeKeyboardLayoutForInputDevice_enforcePermission();
-        mKeyboardLayoutManager.removeKeyboardLayoutForInputDevice(identifier,
-                keyboardLayoutDescriptor);
-    }
-
-    @Override // Binder call
     public KeyboardLayoutSelectionResult getKeyboardLayoutForInputDevice(
             InputDeviceIdentifier identifier, @UserIdInt int userId,
             @NonNull InputMethodInfo imeInfo, @Nullable InputMethodSubtype imeSubtype) {
@@ -1270,11 +1227,6 @@
                 imeInfo, imeSubtype);
     }
 
-
-    public void switchKeyboardLayout(int deviceId, int direction) {
-        mKeyboardLayoutManager.switchKeyboardLayout(deviceId, direction);
-    }
-
     public void setFocusedApplication(int displayId, InputApplicationHandle application) {
         mNative.setFocusedApplication(displayId, application);
     }
diff --git a/services/core/java/com/android/server/input/KeyboardLayoutManager.java b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
index 6610081..9ba647f 100644
--- a/services/core/java/com/android/server/input/KeyboardLayoutManager.java
+++ b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
@@ -60,7 +60,6 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.ArrayMap;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -69,7 +68,6 @@
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
-import android.widget.Toast;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -96,7 +94,6 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
-import java.util.stream.Stream;
 
 /**
  * A component of {@link InputManagerService} responsible for managing Physical Keyboard layouts.
@@ -112,9 +109,8 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final int MSG_UPDATE_EXISTING_DEVICES = 1;
-    private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2;
-    private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3;
-    private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
+    private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 2;
+    private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 3;
 
     private final Context mContext;
     private final NativeInputManagerService mNative;
@@ -126,13 +122,14 @@
     // Connected keyboards with associated keyboard layouts (either auto-detected or manually
     // selected layout).
     private final SparseArray<KeyboardConfiguration> mConfiguredKeyboards = new SparseArray<>();
-    private Toast mSwitchedKeyboardLayoutToast;
 
     // This cache stores "best-matched" layouts so that we don't need to run the matching
     // algorithm repeatedly.
     @GuardedBy("mKeyboardLayoutCache")
     private final Map<String, KeyboardLayoutSelectionResult> mKeyboardLayoutCache =
             new ArrayMap<>();
+
+    private HashSet<String> mAvailableLayouts = new HashSet<>();
     private final Object mImeInfoLock = new Object();
     @Nullable
     @GuardedBy("mImeInfoLock")
@@ -206,68 +203,51 @@
         }
 
         boolean needToShowNotification = false;
-        if (!useNewSettingsUi()) {
-            synchronized (mDataStore) {
-                String layout = getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
-                if (layout == null) {
-                    layout = getDefaultKeyboardLayout(inputDevice);
-                    if (layout != null) {
-                        setCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier(), layout);
-                    }
-                }
-                if (layout == null) {
-                    // In old settings show notification always until user manually selects a
-                    // layout in the settings.
+        Set<String> selectedLayouts = new HashSet<>();
+        List<ImeInfo> imeInfoList = getImeInfoListForLayoutMapping();
+        List<KeyboardLayoutSelectionResult> resultList = new ArrayList<>();
+        boolean hasMissingLayout = false;
+        for (ImeInfo imeInfo : imeInfoList) {
+            // Check if the layout has been previously configured
+            KeyboardLayoutSelectionResult result = getKeyboardLayoutForInputDeviceInternal(
+                    keyboardIdentifier, imeInfo);
+            if (result.getLayoutDescriptor() != null) {
+                selectedLayouts.add(result.getLayoutDescriptor());
+            } else {
+                hasMissingLayout = true;
+            }
+            resultList.add(result);
+        }
+
+        if (DEBUG) {
+            Slog.d(TAG,
+                    "Layouts selected for input device: " + keyboardIdentifier
+                            + " -> selectedLayouts: " + selectedLayouts);
+        }
+
+        // If even one layout not configured properly, we need to ask user to configure
+        // the keyboard properly from the Settings.
+        if (hasMissingLayout) {
+            selectedLayouts.clear();
+        }
+
+        config.setConfiguredLayouts(selectedLayouts);
+
+        synchronized (mDataStore) {
+            try {
+                final String key = keyboardIdentifier.toString();
+                if (mDataStore.setSelectedKeyboardLayouts(key, selectedLayouts)) {
+                    // Need to show the notification only if layout selection changed
+                    // from the previous configuration
                     needToShowNotification = true;
                 }
-            }
-        } else {
-            Set<String> selectedLayouts = new HashSet<>();
-            List<ImeInfo> imeInfoList = getImeInfoListForLayoutMapping();
-            List<KeyboardLayoutSelectionResult> resultList = new ArrayList<>();
-            boolean hasMissingLayout = false;
-            for (ImeInfo imeInfo : imeInfoList) {
-                // Check if the layout has been previously configured
-                KeyboardLayoutSelectionResult result = getKeyboardLayoutForInputDeviceInternal(
-                        keyboardIdentifier, imeInfo);
-                boolean noLayoutFound = result.getLayoutDescriptor() == null;
-                if (!noLayoutFound) {
-                    selectedLayouts.add(result.getLayoutDescriptor());
+
+                if (shouldLogConfiguration) {
+                    logKeyboardConfigurationEvent(inputDevice, imeInfoList, resultList,
+                            !mDataStore.hasInputDeviceEntry(key));
                 }
-                resultList.add(result);
-                hasMissingLayout |= noLayoutFound;
-            }
-
-            if (DEBUG) {
-                Slog.d(TAG,
-                        "Layouts selected for input device: " + keyboardIdentifier
-                                + " -> selectedLayouts: " + selectedLayouts);
-            }
-
-            // If even one layout not configured properly, we need to ask user to configure
-            // the keyboard properly from the Settings.
-            if (hasMissingLayout) {
-                selectedLayouts.clear();
-            }
-
-            config.setConfiguredLayouts(selectedLayouts);
-
-            synchronized (mDataStore) {
-                try {
-                    final String key = keyboardIdentifier.toString();
-                    if (mDataStore.setSelectedKeyboardLayouts(key, selectedLayouts)) {
-                        // Need to show the notification only if layout selection changed
-                        // from the previous configuration
-                        needToShowNotification = true;
-                    }
-
-                    if (shouldLogConfiguration) {
-                        logKeyboardConfigurationEvent(inputDevice, imeInfoList, resultList,
-                                !mDataStore.hasInputDeviceEntry(key));
-                    }
-                } finally {
-                    mDataStore.saveIfNeeded();
-                }
+            } finally {
+                mDataStore.saveIfNeeded();
             }
         }
         if (needToShowNotification) {
@@ -275,63 +255,6 @@
         }
     }
 
-    private String getDefaultKeyboardLayout(final InputDevice inputDevice) {
-        final Locale systemLocale = mContext.getResources().getConfiguration().locale;
-        // If our locale doesn't have a language for some reason, then we don't really have a
-        // reasonable default.
-        if (TextUtils.isEmpty(systemLocale.getLanguage())) {
-            return null;
-        }
-        final List<KeyboardLayout> layouts = new ArrayList<>();
-        visitAllKeyboardLayouts((resources, keyboardLayoutResId, layout) -> {
-            // Only select a default when we know the layout is appropriate. For now, this
-            // means it's a custom layout for a specific keyboard.
-            if (layout.getVendorId() != inputDevice.getVendorId()
-                    || layout.getProductId() != inputDevice.getProductId()) {
-                return;
-            }
-            final LocaleList locales = layout.getLocales();
-            for (int localeIndex = 0; localeIndex < locales.size(); ++localeIndex) {
-                final Locale locale = locales.get(localeIndex);
-                if (locale != null && isCompatibleLocale(systemLocale, locale)) {
-                    layouts.add(layout);
-                    break;
-                }
-            }
-        });
-
-        if (layouts.isEmpty()) {
-            return null;
-        }
-
-        // First sort so that ones with higher priority are listed at the top
-        Collections.sort(layouts);
-        // Next we want to try to find an exact match of language, country and variant.
-        for (KeyboardLayout layout : layouts) {
-            final LocaleList locales = layout.getLocales();
-            for (int localeIndex = 0; localeIndex < locales.size(); ++localeIndex) {
-                final Locale locale = locales.get(localeIndex);
-                if (locale != null && locale.getCountry().equals(systemLocale.getCountry())
-                        && locale.getVariant().equals(systemLocale.getVariant())) {
-                    return layout.getDescriptor();
-                }
-            }
-        }
-        // Then try an exact match of language and country
-        for (KeyboardLayout layout : layouts) {
-            final LocaleList locales = layout.getLocales();
-            for (int localeIndex = 0; localeIndex < locales.size(); ++localeIndex) {
-                final Locale locale = locales.get(localeIndex);
-                if (locale != null && locale.getCountry().equals(systemLocale.getCountry())) {
-                    return layout.getDescriptor();
-                }
-            }
-        }
-
-        // Give up and just use the highest priority layout with matching language
-        return layouts.get(0).getDescriptor();
-    }
-
     private static boolean isCompatibleLocale(Locale systemLocale, Locale keyboardLocale) {
         // Different languages are never compatible
         if (!systemLocale.getLanguage().equals(keyboardLocale.getLanguage())) {
@@ -343,11 +266,19 @@
                 || systemLocale.getCountry().equals(keyboardLocale.getCountry());
     }
 
+    @MainThread
     private void updateKeyboardLayouts() {
         // Scan all input devices state for keyboard layouts that have been uninstalled.
-        final HashSet<String> availableKeyboardLayouts = new HashSet<String>();
+        final HashSet<String> availableKeyboardLayouts = new HashSet<>();
         visitAllKeyboardLayouts((resources, keyboardLayoutResId, layout) ->
                 availableKeyboardLayouts.add(layout.getDescriptor()));
+
+        // If available layouts don't change, there is no need to reload layouts.
+        if (mAvailableLayouts.equals(availableKeyboardLayouts)) {
+            return;
+        }
+        mAvailableLayouts = availableKeyboardLayouts;
+
         synchronized (mDataStore) {
             try {
                 mDataStore.removeUninstalledKeyboardLayouts(availableKeyboardLayouts);
@@ -374,53 +305,6 @@
     }
 
     @AnyThread
-    public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
-            final InputDeviceIdentifier identifier) {
-        if (useNewSettingsUi()) {
-            // Provide all supported keyboard layouts since Ime info is not provided
-            return getKeyboardLayouts();
-        }
-        final String[] enabledLayoutDescriptors =
-                getEnabledKeyboardLayoutsForInputDevice(identifier);
-        final ArrayList<KeyboardLayout> enabledLayouts =
-                new ArrayList<>(enabledLayoutDescriptors.length);
-        final ArrayList<KeyboardLayout> potentialLayouts = new ArrayList<>();
-        visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
-            boolean mHasSeenDeviceSpecificLayout;
-
-            @Override
-            public void visitKeyboardLayout(Resources resources,
-                    int keyboardLayoutResId, KeyboardLayout layout) {
-                // First check if it's enabled. If the keyboard layout is enabled then we always
-                // want to return it as a possible layout for the device.
-                for (String s : enabledLayoutDescriptors) {
-                    if (s != null && s.equals(layout.getDescriptor())) {
-                        enabledLayouts.add(layout);
-                        return;
-                    }
-                }
-                // Next find any potential layouts that aren't yet enabled for the device. For
-                // devices that have special layouts we assume there's a reason that the generic
-                // layouts don't work for them so we don't want to return them since it's likely
-                // to result in a poor user experience.
-                if (layout.getVendorId() == identifier.getVendorId()
-                        && layout.getProductId() == identifier.getProductId()) {
-                    if (!mHasSeenDeviceSpecificLayout) {
-                        mHasSeenDeviceSpecificLayout = true;
-                        potentialLayouts.clear();
-                    }
-                    potentialLayouts.add(layout);
-                } else if (layout.getVendorId() == -1 && layout.getProductId() == -1
-                        && !mHasSeenDeviceSpecificLayout) {
-                    potentialLayouts.add(layout);
-                }
-            }
-        });
-        return Stream.concat(enabledLayouts.stream(), potentialLayouts.stream()).toArray(
-                KeyboardLayout[]::new);
-    }
-
-    @AnyThread
     @Nullable
     public KeyboardLayout getKeyboardLayout(@NonNull String keyboardLayoutDescriptor) {
         Objects.requireNonNull(keyboardLayoutDescriptor,
@@ -580,195 +464,16 @@
         return LocaleList.forLanguageTags(languageTags.replace('|', ','));
     }
 
-    @AnyThread
-    @Nullable
-    public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
-        if (useNewSettingsUi()) {
-            Slog.e(TAG, "getCurrentKeyboardLayoutForInputDevice API not supported");
-            return null;
-        }
-        String key = new KeyboardIdentifier(identifier).toString();
-        synchronized (mDataStore) {
-            String layout;
-            // try loading it using the layout descriptor if we have it
-            layout = mDataStore.getCurrentKeyboardLayout(key);
-            if (layout == null && !key.equals(identifier.getDescriptor())) {
-                // if it doesn't exist fall back to the device descriptor
-                layout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
-            }
-            if (DEBUG) {
-                Slog.d(TAG, "getCurrentKeyboardLayoutForInputDevice() "
-                        + identifier.toString() + ": " + layout);
-            }
-            return layout;
-        }
-    }
-
-    @AnyThread
-    public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor) {
-        if (useNewSettingsUi()) {
-            Slog.e(TAG, "setCurrentKeyboardLayoutForInputDevice API not supported");
-            return;
-        }
-
-        Objects.requireNonNull(keyboardLayoutDescriptor,
-                "keyboardLayoutDescriptor must not be null");
-        String key = new KeyboardIdentifier(identifier).toString();
-        synchronized (mDataStore) {
-            try {
-                if (mDataStore.setCurrentKeyboardLayout(key, keyboardLayoutDescriptor)) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "setCurrentKeyboardLayoutForInputDevice() " + identifier
-                                + " key: " + key
-                                + " keyboardLayoutDescriptor: " + keyboardLayoutDescriptor);
-                    }
-                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
-                }
-            } finally {
-                mDataStore.saveIfNeeded();
-            }
-        }
-    }
-
-    @AnyThread
-    public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
-        if (useNewSettingsUi()) {
-            Slog.e(TAG, "getEnabledKeyboardLayoutsForInputDevice API not supported");
-            return new String[0];
-        }
-        String key = new KeyboardIdentifier(identifier).toString();
-        synchronized (mDataStore) {
-            String[] layouts = mDataStore.getKeyboardLayouts(key);
-            if ((layouts == null || layouts.length == 0)
-                    && !key.equals(identifier.getDescriptor())) {
-                layouts = mDataStore.getKeyboardLayouts(identifier.getDescriptor());
-            }
-            return layouts;
-        }
-    }
-
-    @AnyThread
-    public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor) {
-        if (useNewSettingsUi()) {
-            Slog.e(TAG, "addKeyboardLayoutForInputDevice API not supported");
-            return;
-        }
-        Objects.requireNonNull(keyboardLayoutDescriptor,
-                "keyboardLayoutDescriptor must not be null");
-
-        String key = new KeyboardIdentifier(identifier).toString();
-        synchronized (mDataStore) {
-            try {
-                String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
-                if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
-                    oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
-                }
-                if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
-                        && !Objects.equals(oldLayout,
-                        mDataStore.getCurrentKeyboardLayout(key))) {
-                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
-                }
-            } finally {
-                mDataStore.saveIfNeeded();
-            }
-        }
-    }
-
-    @AnyThread
-    public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
-            String keyboardLayoutDescriptor) {
-        if (useNewSettingsUi()) {
-            Slog.e(TAG, "removeKeyboardLayoutForInputDevice API not supported");
-            return;
-        }
-        Objects.requireNonNull(keyboardLayoutDescriptor,
-                "keyboardLayoutDescriptor must not be null");
-
-        String key = new KeyboardIdentifier(identifier).toString();
-        synchronized (mDataStore) {
-            try {
-                String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
-                if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
-                    oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
-                }
-                boolean removed = mDataStore.removeKeyboardLayout(key, keyboardLayoutDescriptor);
-                if (!key.equals(identifier.getDescriptor())) {
-                    // We need to remove from both places to ensure it is gone
-                    removed |= mDataStore.removeKeyboardLayout(identifier.getDescriptor(),
-                            keyboardLayoutDescriptor);
-                }
-                if (removed && !Objects.equals(oldLayout,
-                        mDataStore.getCurrentKeyboardLayout(key))) {
-                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
-                }
-            } finally {
-                mDataStore.saveIfNeeded();
-            }
-        }
-    }
-
-    @AnyThread
-    public void switchKeyboardLayout(int deviceId, int direction) {
-        if (useNewSettingsUi()) {
-            Slog.e(TAG, "switchKeyboardLayout API not supported");
-            return;
-        }
-        mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
-    }
-
-    @MainThread
-    private void handleSwitchKeyboardLayout(int deviceId, int direction) {
-        final InputDevice device = getInputDevice(deviceId);
-        if (device != null) {
-            final boolean changed;
-            final String keyboardLayoutDescriptor;
-
-            String key = new KeyboardIdentifier(device.getIdentifier()).toString();
-            synchronized (mDataStore) {
-                try {
-                    changed = mDataStore.switchKeyboardLayout(key, direction);
-                    keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout(
-                            key);
-                } finally {
-                    mDataStore.saveIfNeeded();
-                }
-            }
-
-            if (changed) {
-                if (mSwitchedKeyboardLayoutToast != null) {
-                    mSwitchedKeyboardLayoutToast.cancel();
-                    mSwitchedKeyboardLayoutToast = null;
-                }
-                if (keyboardLayoutDescriptor != null) {
-                    KeyboardLayout keyboardLayout = getKeyboardLayout(keyboardLayoutDescriptor);
-                    if (keyboardLayout != null) {
-                        mSwitchedKeyboardLayoutToast = Toast.makeText(
-                                mContext, keyboardLayout.getLabel(), Toast.LENGTH_SHORT);
-                        mSwitchedKeyboardLayoutToast.show();
-                    }
-                }
-
-                reloadKeyboardLayouts();
-            }
-        }
-    }
-
     @Nullable
     @AnyThread
     public String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier, String languageTag,
             String layoutType) {
         String keyboardLayoutDescriptor;
-        if (useNewSettingsUi()) {
-            synchronized (mImeInfoLock) {
-                KeyboardLayoutSelectionResult result = getKeyboardLayoutForInputDeviceInternal(
-                        new KeyboardIdentifier(identifier, languageTag, layoutType),
-                        mCurrentImeInfo);
-                keyboardLayoutDescriptor = result.getLayoutDescriptor();
-            }
-        } else {
-            keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
+        synchronized (mImeInfoLock) {
+            KeyboardLayoutSelectionResult result = getKeyboardLayoutForInputDeviceInternal(
+                    new KeyboardIdentifier(identifier, languageTag, layoutType),
+                    mCurrentImeInfo);
+            keyboardLayoutDescriptor = result.getLayoutDescriptor();
         }
         if (keyboardLayoutDescriptor == null) {
             return null;
@@ -797,10 +502,6 @@
     public KeyboardLayoutSelectionResult getKeyboardLayoutForInputDevice(
             InputDeviceIdentifier identifier, @UserIdInt int userId,
             @NonNull InputMethodInfo imeInfo, @Nullable InputMethodSubtype imeSubtype) {
-        if (!useNewSettingsUi()) {
-            Slog.e(TAG, "getKeyboardLayoutForInputDevice() API not supported");
-            return FAILED;
-        }
         InputDevice inputDevice = getInputDevice(identifier);
         if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
             return FAILED;
@@ -820,10 +521,6 @@
             @UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
             @Nullable InputMethodSubtype imeSubtype,
             String keyboardLayoutDescriptor) {
-        if (!useNewSettingsUi()) {
-            Slog.e(TAG, "setKeyboardLayoutForInputDevice() API not supported");
-            return;
-        }
         Objects.requireNonNull(keyboardLayoutDescriptor,
                 "keyboardLayoutDescriptor must not be null");
         InputDevice inputDevice = getInputDevice(identifier);
@@ -854,10 +551,6 @@
     public KeyboardLayout[] getKeyboardLayoutListForInputDevice(InputDeviceIdentifier identifier,
             @UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
             @Nullable InputMethodSubtype imeSubtype) {
-        if (!useNewSettingsUi()) {
-            Slog.e(TAG, "getKeyboardLayoutListForInputDevice() API not supported");
-            return new KeyboardLayout[0];
-        }
         InputDevice inputDevice = getInputDevice(identifier);
         if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
             return new KeyboardLayout[0];
@@ -923,10 +616,6 @@
     public void onInputMethodSubtypeChanged(@UserIdInt int userId,
             @Nullable InputMethodSubtypeHandle subtypeHandle,
             @Nullable InputMethodSubtype subtype) {
-        if (!useNewSettingsUi()) {
-            Slog.e(TAG, "onInputMethodSubtypeChanged() API not supported");
-            return;
-        }
         if (subtypeHandle == null) {
             if (DEBUG) {
                 Slog.d(TAG, "No InputMethod is running, ignoring change");
@@ -1289,9 +978,6 @@
                     onInputDeviceAdded(deviceId);
                 }
                 return true;
-            case MSG_SWITCH_KEYBOARD_LAYOUT:
-                handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
-                return true;
             case MSG_RELOAD_KEYBOARD_LAYOUTS:
                 reloadKeyboardLayouts();
                 return true;
@@ -1303,10 +989,6 @@
         }
     }
 
-    private boolean useNewSettingsUi() {
-        return FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI);
-    }
-
     @Nullable
     private InputDevice getInputDevice(int deviceId) {
         InputManager inputManager = mContext.getSystemService(InputManager.class);
diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java
index 31083fd..7859253 100644
--- a/services/core/java/com/android/server/input/PersistentDataStore.java
+++ b/services/core/java/com/android/server/input/PersistentDataStore.java
@@ -27,7 +27,6 @@
 import android.view.Surface;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
@@ -42,7 +41,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -74,7 +72,7 @@
             new HashMap<String, InputDeviceState>();
 
     // The interface for methods which should be replaced by the test harness.
-    private Injector mInjector;
+    private final Injector mInjector;
 
     // True if the data has been loaded.
     private boolean mLoaded;
@@ -83,7 +81,7 @@
     private boolean mDirty;
 
     // Storing key remapping
-    private Map<Integer, Integer> mKeyRemapping = new HashMap<>();
+    private final Map<Integer, Integer> mKeyRemapping = new HashMap<>();
 
     public PersistentDataStore() {
         this(new Injector());
@@ -130,22 +128,6 @@
     }
 
     @Nullable
-    public String getCurrentKeyboardLayout(String inputDeviceDescriptor) {
-        InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
-        return state != null ? state.getCurrentKeyboardLayout() : null;
-    }
-
-    public boolean setCurrentKeyboardLayout(String inputDeviceDescriptor,
-            String keyboardLayoutDescriptor) {
-        InputDeviceState state = getOrCreateInputDeviceState(inputDeviceDescriptor);
-        if (state.setCurrentKeyboardLayout(keyboardLayoutDescriptor)) {
-            setDirty();
-            return true;
-        }
-        return false;
-    }
-
-    @Nullable
     public String getKeyboardLayout(String inputDeviceDescriptor, String key) {
         InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
         return state != null ? state.getKeyboardLayout(key) : null;
@@ -171,43 +153,6 @@
         return false;
     }
 
-    public String[] getKeyboardLayouts(String inputDeviceDescriptor) {
-        InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
-        if (state == null) {
-            return (String[])ArrayUtils.emptyArray(String.class);
-        }
-        return state.getKeyboardLayouts();
-    }
-
-    public boolean addKeyboardLayout(String inputDeviceDescriptor,
-            String keyboardLayoutDescriptor) {
-        InputDeviceState state = getOrCreateInputDeviceState(inputDeviceDescriptor);
-        if (state.addKeyboardLayout(keyboardLayoutDescriptor)) {
-            setDirty();
-            return true;
-        }
-        return false;
-    }
-
-    public boolean removeKeyboardLayout(String inputDeviceDescriptor,
-            String keyboardLayoutDescriptor) {
-        InputDeviceState state = getOrCreateInputDeviceState(inputDeviceDescriptor);
-        if (state.removeKeyboardLayout(keyboardLayoutDescriptor)) {
-            setDirty();
-            return true;
-        }
-        return false;
-    }
-
-    public boolean switchKeyboardLayout(String inputDeviceDescriptor, int direction) {
-        InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
-        if (state != null && state.switchKeyboardLayout(direction)) {
-            setDirty();
-            return true;
-        }
-        return false;
-    }
-
     public boolean setKeyboardBacklightBrightness(String inputDeviceDescriptor, int lightId,
             int brightness) {
         InputDeviceState state = getOrCreateInputDeviceState(inputDeviceDescriptor);
@@ -417,9 +362,6 @@
                 "x_ymix", "x_offset", "y_xmix", "y_scale", "y_offset" };
 
         private final TouchCalibration[] mTouchCalibration = new TouchCalibration[4];
-        @Nullable
-        private String mCurrentKeyboardLayout;
-        private final ArrayList<String> mKeyboardLayouts = new ArrayList<String>();
         private final SparseIntArray mKeyboardBacklightBrightnessMap = new SparseIntArray();
 
         private final Map<String, String> mKeyboardLayoutMap = new ArrayMap<>();
@@ -465,49 +407,6 @@
             return true;
         }
 
-        @Nullable
-        public String getCurrentKeyboardLayout() {
-            return mCurrentKeyboardLayout;
-        }
-
-        public boolean setCurrentKeyboardLayout(String keyboardLayout) {
-            if (Objects.equals(mCurrentKeyboardLayout, keyboardLayout)) {
-                return false;
-            }
-            addKeyboardLayout(keyboardLayout);
-            mCurrentKeyboardLayout = keyboardLayout;
-            return true;
-        }
-
-        public String[] getKeyboardLayouts() {
-            if (mKeyboardLayouts.isEmpty()) {
-                return (String[])ArrayUtils.emptyArray(String.class);
-            }
-            return mKeyboardLayouts.toArray(new String[mKeyboardLayouts.size()]);
-        }
-
-        public boolean addKeyboardLayout(String keyboardLayout) {
-            int index = Collections.binarySearch(mKeyboardLayouts, keyboardLayout);
-            if (index >= 0) {
-                return false;
-            }
-            mKeyboardLayouts.add(-index - 1, keyboardLayout);
-            if (mCurrentKeyboardLayout == null) {
-                mCurrentKeyboardLayout = keyboardLayout;
-            }
-            return true;
-        }
-
-        public boolean removeKeyboardLayout(String keyboardLayout) {
-            int index = Collections.binarySearch(mKeyboardLayouts, keyboardLayout);
-            if (index < 0) {
-                return false;
-            }
-            mKeyboardLayouts.remove(index);
-            updateCurrentKeyboardLayoutIfRemoved(keyboardLayout, index);
-            return true;
-        }
-
         public boolean setKeyboardBacklightBrightness(int lightId, int brightness) {
             if (mKeyboardBacklightBrightnessMap.get(lightId, INVALID_VALUE) == brightness) {
                 return false;
@@ -521,48 +420,8 @@
             return brightness == INVALID_VALUE ? OptionalInt.empty() : OptionalInt.of(brightness);
         }
 
-        private void updateCurrentKeyboardLayoutIfRemoved(
-                String removedKeyboardLayout, int removedIndex) {
-            if (Objects.equals(mCurrentKeyboardLayout, removedKeyboardLayout)) {
-                if (!mKeyboardLayouts.isEmpty()) {
-                    int index = removedIndex;
-                    if (index == mKeyboardLayouts.size()) {
-                        index = 0;
-                    }
-                    mCurrentKeyboardLayout = mKeyboardLayouts.get(index);
-                } else {
-                    mCurrentKeyboardLayout = null;
-                }
-            }
-        }
-
-        public boolean switchKeyboardLayout(int direction) {
-            final int size = mKeyboardLayouts.size();
-            if (size < 2) {
-                return false;
-            }
-            int index = Collections.binarySearch(mKeyboardLayouts, mCurrentKeyboardLayout);
-            assert index >= 0;
-            if (direction > 0) {
-                index = (index + 1) % size;
-            } else {
-                index = (index + size - 1) % size;
-            }
-            mCurrentKeyboardLayout = mKeyboardLayouts.get(index);
-            return true;
-        }
-
         public boolean removeUninstalledKeyboardLayouts(Set<String> availableKeyboardLayouts) {
             boolean changed = false;
-            for (int i = mKeyboardLayouts.size(); i-- > 0; ) {
-                String keyboardLayout = mKeyboardLayouts.get(i);
-                if (!availableKeyboardLayouts.contains(keyboardLayout)) {
-                    Slog.i(TAG, "Removing uninstalled keyboard layout " + keyboardLayout);
-                    mKeyboardLayouts.remove(i);
-                    updateCurrentKeyboardLayoutIfRemoved(keyboardLayout, i);
-                    changed = true;
-                }
-            }
             List<String> removedEntries = new ArrayList<>();
             for (String key : mKeyboardLayoutMap.keySet()) {
                 if (!availableKeyboardLayouts.contains(mKeyboardLayoutMap.get(key))) {
@@ -582,27 +441,7 @@
                 throws IOException, XmlPullParserException {
             final int outerDepth = parser.getDepth();
             while (XmlUtils.nextElementWithin(parser, outerDepth)) {
-                if (parser.getName().equals("keyboard-layout")) {
-                    String descriptor = parser.getAttributeValue(null, "descriptor");
-                    if (descriptor == null) {
-                        throw new XmlPullParserException(
-                                "Missing descriptor attribute on keyboard-layout.");
-                    }
-                    String current = parser.getAttributeValue(null, "current");
-                    if (mKeyboardLayouts.contains(descriptor)) {
-                        throw new XmlPullParserException(
-                                "Found duplicate keyboard layout.");
-                    }
-
-                    mKeyboardLayouts.add(descriptor);
-                    if (current != null && current.equals("true")) {
-                        if (mCurrentKeyboardLayout != null) {
-                            throw new XmlPullParserException(
-                                    "Found multiple current keyboard layouts.");
-                        }
-                        mCurrentKeyboardLayout = descriptor;
-                    }
-                } else if (parser.getName().equals("keyed-keyboard-layout")) {
+                if (parser.getName().equals("keyed-keyboard-layout")) {
                     String key = parser.getAttributeValue(null, "key");
                     if (key == null) {
                         throw new XmlPullParserException(
@@ -676,27 +515,9 @@
                     }
                 }
             }
-
-            // Maintain invariant that layouts are sorted.
-            Collections.sort(mKeyboardLayouts);
-
-            // Maintain invariant that there is always a current keyboard layout unless
-            // there are none installed.
-            if (mCurrentKeyboardLayout == null && !mKeyboardLayouts.isEmpty()) {
-                mCurrentKeyboardLayout = mKeyboardLayouts.get(0);
-            }
         }
 
         public void saveToXml(TypedXmlSerializer serializer) throws IOException {
-            for (String layout : mKeyboardLayouts) {
-                serializer.startTag(null, "keyboard-layout");
-                serializer.attribute(null, "descriptor", layout);
-                if (layout.equals(mCurrentKeyboardLayout)) {
-                    serializer.attributeBoolean(null, "current", true);
-                }
-                serializer.endTag(null, "keyboard-layout");
-            }
-
             for (String key : mKeyboardLayoutMap.keySet()) {
                 serializer.startTag(null, "keyed-keyboard-layout");
                 serializer.attribute(null, "key", key);
diff --git a/services/core/java/com/android/server/media/MediaSession2Record.java b/services/core/java/com/android/server/media/MediaSession2Record.java
index 0cd7654..dfb2b0a 100644
--- a/services/core/java/com/android/server/media/MediaSession2Record.java
+++ b/services/core/java/com/android/server/media/MediaSession2Record.java
@@ -157,6 +157,11 @@
     }
 
     @Override
+    public void expireTempEngaged() {
+        // NA as MediaSession2 doesn't support UserEngagementStates for FGS.
+    }
+
+    @Override
     public boolean sendMediaButton(String packageName, int pid, int uid, boolean asSystemService,
             KeyEvent ke, int sequenceId, ResultReceiver cb) {
         // TODO(jaewan): Implement.
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index eb4e6e4..8f164d3 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -24,6 +24,7 @@
 import static android.media.session.MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -85,6 +86,8 @@
 import com.android.server.uri.UriGrantsManagerInternal;
 
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -225,6 +228,49 @@
 
     private int mPolicies;
 
+    private @UserEngagementState int mUserEngagementState = USER_DISENGAGED;
+
+    @IntDef({USER_PERMANENTLY_ENGAGED, USER_TEMPORARY_ENGAGED, USER_DISENGAGED})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface UserEngagementState {}
+
+    /**
+     * Indicates that the session is active and in one of the user engaged states.
+     *
+     * @see #updateUserEngagedStateIfNeededLocked(boolean) ()
+     */
+    private static final int USER_PERMANENTLY_ENGAGED = 0;
+
+    /**
+     * Indicates that the session is active and in {@link PlaybackState#STATE_PAUSED} state.
+     *
+     * @see #updateUserEngagedStateIfNeededLocked(boolean) ()
+     */
+    private static final int USER_TEMPORARY_ENGAGED = 1;
+
+    /**
+     * Indicates that the session is either not active or in one of the user disengaged states
+     *
+     * @see #updateUserEngagedStateIfNeededLocked(boolean) ()
+     */
+    private static final int USER_DISENGAGED = 2;
+
+    /**
+     * Indicates the duration of the temporary engaged states.
+     *
+     * <p>Some {@link MediaSession} states like {@link PlaybackState#STATE_PAUSED} are temporarily
+     * engaged, meaning the corresponding session is only considered in an engaged state for the
+     * duration of this timeout, and only if coming from an engaged state.
+     *
+     * <p>For example, if a session is transitioning from a user-engaged state {@link
+     * PlaybackState#STATE_PLAYING} to a temporary user-engaged state {@link
+     * PlaybackState#STATE_PAUSED}, then the session will be considered in a user-engaged state for
+     * the duration of this timeout, starting at the transition instant. However, a temporary
+     * user-engaged state is not considered user-engaged when transitioning from a non-user engaged
+     * state {@link PlaybackState#STATE_STOPPED}.
+     */
+    private static final int TEMP_USER_ENGAGED_TIMEOUT = 600000;
+
     public MediaSessionRecord(
             int ownerPid,
             int ownerUid,
@@ -548,6 +594,7 @@
             mSessionCb.mCb.asBinder().unlinkToDeath(this, 0);
             mDestroyed = true;
             mPlaybackState = null;
+            updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ true);
             mHandler.post(MessageHandler.MSG_DESTROYED);
         }
     }
@@ -559,6 +606,12 @@
         }
     }
 
+    @Override
+    public void expireTempEngaged() {
+        mHandler.removeCallbacks(mHandleTempEngagedSessionTimeout);
+        updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ true);
+    }
+
     /**
      * Sends media button.
      *
@@ -849,7 +902,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -876,7 +929,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -911,7 +964,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -938,7 +991,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -965,7 +1018,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -992,7 +1045,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -1017,7 +1070,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -1042,7 +1095,7 @@
             }
         }
         // After notifying clear all listeners
-        mControllerCallbackHolders.clear();
+        removeControllerHoldersSafely(null);
     }
 
     private PlaybackState getStateWithUpdatedPosition() {
@@ -1090,6 +1143,17 @@
         return -1;
     }
 
+    private void removeControllerHoldersSafely(
+            Collection<ISessionControllerCallbackHolder> holders) {
+        synchronized (mLock) {
+            if (holders == null) {
+                mControllerCallbackHolders.clear();
+            } else {
+                mControllerCallbackHolders.removeAll(holders);
+            }
+        }
+    }
+
     private PlaybackInfo getVolumeAttributes() {
         int volumeType;
         AudioAttributes attributes;
@@ -1118,6 +1182,11 @@
                 }
             };
 
+    private final Runnable mHandleTempEngagedSessionTimeout =
+            () -> {
+                updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ true);
+            };
+
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
     private static boolean componentNameExists(
             @NonNull ComponentName componentName, @NonNull Context context, int userId) {
@@ -1134,6 +1203,40 @@
         return !resolveInfos.isEmpty();
     }
 
+    private void updateUserEngagedStateIfNeededLocked(boolean isTimeoutExpired) {
+        int oldUserEngagedState = mUserEngagementState;
+        int newUserEngagedState;
+        if (!isActive() || mPlaybackState == null) {
+            newUserEngagedState = USER_DISENGAGED;
+        } else if (isActive() && mPlaybackState.isActive()) {
+            newUserEngagedState = USER_PERMANENTLY_ENGAGED;
+        } else if (mPlaybackState.getState() == PlaybackState.STATE_PAUSED) {
+            newUserEngagedState =
+                    oldUserEngagedState == USER_PERMANENTLY_ENGAGED || !isTimeoutExpired
+                            ? USER_TEMPORARY_ENGAGED
+                            : USER_DISENGAGED;
+        } else {
+            newUserEngagedState = USER_DISENGAGED;
+        }
+        if (oldUserEngagedState == newUserEngagedState) {
+            return;
+        }
+
+        if (newUserEngagedState == USER_TEMPORARY_ENGAGED) {
+            mHandler.postDelayed(mHandleTempEngagedSessionTimeout, TEMP_USER_ENGAGED_TIMEOUT);
+        } else if (oldUserEngagedState == USER_TEMPORARY_ENGAGED) {
+            mHandler.removeCallbacks(mHandleTempEngagedSessionTimeout);
+        }
+
+        boolean wasUserEngaged = oldUserEngagedState != USER_DISENGAGED;
+        boolean isNowUserEngaged = newUserEngagedState != USER_DISENGAGED;
+        mUserEngagementState = newUserEngagedState;
+        if (wasUserEngaged != isNowUserEngaged) {
+            mService.onSessionUserEngagementStateChange(
+                    /* mediaSessionRecord= */ this, /* isUserEngaged= */ isNowUserEngaged);
+        }
+    }
+
     private final class SessionStub extends ISession.Stub {
         @Override
         public void destroySession() throws RemoteException {
@@ -1171,8 +1274,10 @@
                         .logFgsApiEnd(ActivityManager.FOREGROUND_SERVICE_API_TYPE_MEDIA_PLAYBACK,
                                 callingUid, callingPid);
             }
-
-            mIsActive = active;
+            synchronized (mLock) {
+                mIsActive = active;
+                updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ false);
+            }
             long token = Binder.clearCallingIdentity();
             try {
                 mService.onSessionActiveStateChanged(MediaSessionRecord.this, mPlaybackState);
@@ -1330,6 +1435,7 @@
                     && TRANSITION_PRIORITY_STATES.contains(newState));
             synchronized (mLock) {
                 mPlaybackState = state;
+                updateUserEngagedStateIfNeededLocked(/* isTimeoutExpired= */ false);
             }
             final long token = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
index 0999199..b57b148 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
@@ -196,6 +196,12 @@
      */
     public abstract boolean isClosed();
 
+    /**
+     * Note: This method is only used for testing purposes If the session is temporary engaged, the
+     * timeout will expire and it will become disengaged.
+     */
+    public abstract void expireTempEngaged();
+
     @Override
     public final boolean equals(Object o) {
         if (this == o) return true;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 53c32cf..2ca76a5 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -367,11 +367,13 @@
             }
             boolean isUserEngaged = isUserEngaged(record, playbackState);
 
-            Log.d(TAG, "onSessionActiveStateChanged: "
-                    + "record=" + record
-                    + "playbackState=" + playbackState
-                    + "allowRunningInForeground=" + isUserEngaged);
-            setForegroundServiceAllowance(record, /* allowRunningInForeground= */ isUserEngaged);
+            Log.d(
+                    TAG,
+                    "onSessionActiveStateChanged:"
+                            + " record="
+                            + record
+                            + " playbackState="
+                            + playbackState);
             reportMediaInteractionEvent(record, isUserEngaged);
             mHandler.postSessionsChanged(record);
         }
@@ -479,11 +481,13 @@
             }
             user.mPriorityStack.onPlaybackStateChanged(record, shouldUpdatePriority);
             boolean isUserEngaged = isUserEngaged(record, playbackState);
-            Log.d(TAG, "onSessionPlaybackStateChanged: "
-                    + "record=" + record
-                    + "playbackState=" + playbackState
-                    + "allowRunningInForeground=" + isUserEngaged);
-            setForegroundServiceAllowance(record, /* allowRunningInForeground= */ isUserEngaged);
+            Log.d(
+                    TAG,
+                    "onSessionPlaybackStateChanged:"
+                            + " record="
+                            + record
+                            + " playbackState="
+                            + playbackState);
             reportMediaInteractionEvent(record, isUserEngaged);
         }
     }
@@ -650,33 +654,54 @@
         session.close();
 
         Log.d(TAG, "destroySessionLocked: record=" + session);
-        setForegroundServiceAllowance(session, /* allowRunningInForeground= */ false);
+
         reportMediaInteractionEvent(session, /* userEngaged= */ false);
         mHandler.postSessionsChanged(session);
     }
 
-    private void setForegroundServiceAllowance(
-            MediaSessionRecordImpl record, boolean allowRunningInForeground) {
-        if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
-            return;
-        }
-        ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
-                record.getForegroundServiceDelegationOptions();
-        if (foregroundServiceDelegationOptions == null) {
-            return;
-        }
-        if (allowRunningInForeground) {
-            onUserSessionEngaged(record);
+    void onSessionUserEngagementStateChange(
+            MediaSessionRecordImpl mediaSessionRecord, boolean isUserEngaged) {
+        if (isUserEngaged) {
+            addUserEngagedSession(mediaSessionRecord);
+            startFgsIfSessionIsLinkedToNotification(mediaSessionRecord);
         } else {
-            onUserDisengaged(record);
+            removeUserEngagedSession(mediaSessionRecord);
+            stopFgsIfNoSessionIsLinkedToNotification(mediaSessionRecord);
         }
     }
 
-    private void onUserSessionEngaged(MediaSessionRecordImpl mediaSessionRecord) {
+    private void addUserEngagedSession(MediaSessionRecordImpl mediaSessionRecord) {
         synchronized (mLock) {
             int uid = mediaSessionRecord.getUid();
             mUserEngagedSessionsForFgs.putIfAbsent(uid, new HashSet<>());
             mUserEngagedSessionsForFgs.get(uid).add(mediaSessionRecord);
+        }
+    }
+
+    private void removeUserEngagedSession(MediaSessionRecordImpl mediaSessionRecord) {
+        synchronized (mLock) {
+            int uid = mediaSessionRecord.getUid();
+            Set<MediaSessionRecordImpl> mUidUserEngagedSessionsForFgs =
+                    mUserEngagedSessionsForFgs.get(uid);
+            if (mUidUserEngagedSessionsForFgs == null) {
+                return;
+            }
+
+            mUidUserEngagedSessionsForFgs.remove(mediaSessionRecord);
+            if (mUidUserEngagedSessionsForFgs.isEmpty()) {
+                mUserEngagedSessionsForFgs.remove(uid);
+            }
+        }
+    }
+
+    private void startFgsIfSessionIsLinkedToNotification(
+            MediaSessionRecordImpl mediaSessionRecord) {
+        Log.d(TAG, "startFgsIfSessionIsLinkedToNotification: record=" + mediaSessionRecord);
+        if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
+            return;
+        }
+        synchronized (mLock) {
+            int uid = mediaSessionRecord.getUid();
             for (Notification mediaNotification : mMediaNotifications.getOrDefault(uid, Set.of())) {
                 if (mediaSessionRecord.isLinkedToNotification(mediaNotification)) {
                     mActivityManagerInternal.startForegroundServiceDelegate(
@@ -688,30 +713,34 @@
         }
     }
 
-    private void onUserDisengaged(MediaSessionRecordImpl mediaSessionRecord) {
+    private void stopFgsIfNoSessionIsLinkedToNotification(
+            MediaSessionRecordImpl mediaSessionRecord) {
+        Log.d(TAG, "stopFgsIfNoSessionIsLinkedToNotification: record=" + mediaSessionRecord);
+        if (!Flags.enableNotifyingActivityManagerWithMediaSessionStatusChange()) {
+            return;
+        }
         synchronized (mLock) {
             int uid = mediaSessionRecord.getUid();
-            if (mUserEngagedSessionsForFgs.containsKey(uid)) {
-                mUserEngagedSessionsForFgs.get(uid).remove(mediaSessionRecord);
-                if (mUserEngagedSessionsForFgs.get(uid).isEmpty()) {
-                    mUserEngagedSessionsForFgs.remove(uid);
-                }
+            ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
+                    mediaSessionRecord.getForegroundServiceDelegationOptions();
+            if (foregroundServiceDelegationOptions == null) {
+                return;
             }
 
-            boolean shouldStopFgs = true;
-            for (MediaSessionRecordImpl sessionRecord :
+            for (MediaSessionRecordImpl record :
                     mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
-                for (Notification mediaNotification : mMediaNotifications.getOrDefault(uid,
-                        Set.of())) {
-                    if (sessionRecord.isLinkedToNotification(mediaNotification)) {
-                        shouldStopFgs = false;
+                for (Notification mediaNotification :
+                        mMediaNotifications.getOrDefault(uid, Set.of())) {
+                    if (record.isLinkedToNotification(mediaNotification)) {
+                        // A user engaged session linked with a media notification is found.
+                        // We shouldn't call stop FGS in this case.
+                        return;
                     }
                 }
             }
-            if (shouldStopFgs) {
-                mActivityManagerInternal.stopForegroundServiceDelegate(
-                        mediaSessionRecord.getForegroundServiceDelegationOptions());
-            }
+
+            mActivityManagerInternal.stopForegroundServiceDelegate(
+                    foregroundServiceDelegationOptions);
         }
     }
 
@@ -2502,7 +2531,6 @@
             }
             MediaSessionRecord session = null;
             MediaButtonReceiverHolder mediaButtonReceiverHolder = null;
-
             if (mCustomMediaKeyDispatcher != null) {
                 MediaSession.Token token = mCustomMediaKeyDispatcher.getMediaSession(
                         keyEvent, uid, asSystemService);
@@ -2630,6 +2658,18 @@
                     && streamType <= AudioManager.STREAM_NOTIFICATION;
         }
 
+        @Override
+        public void expireTempEngagedSessions() {
+            synchronized (mLock) {
+                for (Set<MediaSessionRecordImpl> uidSessions :
+                        mUserEngagedSessionsForFgs.values()) {
+                    for (MediaSessionRecordImpl sessionRecord : uidSessions) {
+                        sessionRecord.expireTempEngaged();
+                    }
+                }
+            }
+        }
+
         private class MediaKeyListenerResultReceiver extends ResultReceiver implements Runnable {
             private final String mPackageName;
             private final int mPid;
@@ -3127,7 +3167,6 @@
             super.onNotificationPosted(sbn);
             Notification postedNotification = sbn.getNotification();
             int uid = sbn.getUid();
-
             if (!postedNotification.isMediaNotification()) {
                 return;
             }
@@ -3138,8 +3177,8 @@
                         mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
                     ForegroundServiceDelegationOptions foregroundServiceDelegationOptions =
                             mediaSessionRecord.getForegroundServiceDelegationOptions();
-                    if (mediaSessionRecord.isLinkedToNotification(postedNotification)
-                            && foregroundServiceDelegationOptions != null) {
+                    if (foregroundServiceDelegationOptions != null
+                            && mediaSessionRecord.isLinkedToNotification(postedNotification)) {
                         mActivityManagerInternal.startForegroundServiceDelegate(
                                 foregroundServiceDelegationOptions,
                                 /* connection= */ null);
@@ -3173,21 +3212,7 @@
                     return;
                 }
 
-                boolean shouldStopFgs = true;
-                for (MediaSessionRecordImpl mediaSessionRecord :
-                        mUserEngagedSessionsForFgs.getOrDefault(uid, Set.of())) {
-                    for (Notification mediaNotification :
-                            mMediaNotifications.getOrDefault(uid, Set.of())) {
-                        if (mediaSessionRecord.isLinkedToNotification(mediaNotification)) {
-                            shouldStopFgs = false;
-                        }
-                    }
-                }
-                if (shouldStopFgs
-                        && notificationRecord.getForegroundServiceDelegationOptions() != null) {
-                    mActivityManagerInternal.stopForegroundServiceDelegate(
-                            notificationRecord.getForegroundServiceDelegationOptions());
-                }
+                stopFgsIfNoSessionIsLinkedToNotification(notificationRecord);
             }
         }
 
diff --git a/services/core/java/com/android/server/media/MediaShellCommand.java b/services/core/java/com/android/server/media/MediaShellCommand.java
index a563808..a20de31 100644
--- a/services/core/java/com/android/server/media/MediaShellCommand.java
+++ b/services/core/java/com/android/server/media/MediaShellCommand.java
@@ -92,6 +92,8 @@
                 runMonitor();
             } else if (cmd.equals("volume")) {
                 runVolume();
+            } else if (cmd.equals("expire-temp-engaged-sessions")) {
+                expireTempEngagedSessions();
             } else {
                 showError("Error: unknown command '" + cmd + "'");
                 return -1;
@@ -367,4 +369,8 @@
     private void runVolume() throws Exception {
         VolumeCtrl.run(this);
     }
+
+    private void expireTempEngagedSessions() throws Exception {
+        mSessionService.expireTempEngagedSessions();
+    }
 }
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 4eb8b2b..c8fd7e4 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -184,6 +184,16 @@
                         throwInvalidBugreportFileForCallerException(
                                 bugreportFile, callingInfo.second);
                     }
+
+                    boolean keepBugreportOnRetrieval = false;
+                    if (onboardingBugreportV2Enabled()) {
+                        keepBugreportOnRetrieval = mBugreportFilesToPersist.contains(
+                                bugreportFile);
+                    }
+
+                    if (!keepBugreportOnRetrieval) {
+                        bugreportFilesForUid.remove(bugreportFile);
+                    }
                 } else {
                     ArraySet<String> bugreportFilesForCaller = mBugreportFiles.get(callingInfo);
                     if (bugreportFilesForCaller != null
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 7db83d7..b4919a4 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -174,7 +174,6 @@
 import android.service.vr.IPersistentVrStateCallbacks;
 import android.speech.RecognizerIntent;
 import android.telecom.TelecomManager;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.util.MathUtils;
 import android.util.MutableBoolean;
@@ -4121,14 +4120,10 @@
 
     private void handleSwitchKeyboardLayout(@NonNull KeyEvent event, int direction,
             IBinder focusedToken) {
-        if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)) {
-            IBinder targetWindowToken =
-                    mWindowManagerInternal.getTargetWindowTokenFromInputToken(focusedToken);
-            InputMethodManagerInternal.get().onSwitchKeyboardLayoutShortcut(direction,
-                    event.getDisplayId(), targetWindowToken);
-        } else {
-            mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
-        }
+        IBinder targetWindowToken =
+                mWindowManagerInternal.getTargetWindowTokenFromInputToken(focusedToken);
+        InputMethodManagerInternal.get().onSwitchKeyboardLayoutShortcut(direction,
+                event.getDisplayId(), targetWindowToken);
     }
 
     private boolean interceptFallback(IBinder focusedToken, KeyEvent fallbackEvent,
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 2623025..9ca4e27 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -251,12 +251,6 @@
          */
         public int getCameraLensCoverState();
 
-        /**
-         * Switch the keyboard layout for the given device.
-         * Direction should be +1 or -1 to go to the next or previous keyboard layout.
-         */
-        public void switchKeyboardLayout(int deviceId, int direction);
-
         public void shutdown(boolean confirm);
         public void reboot(boolean confirm);
         public void rebootSafeMode(boolean confirm);
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 55eeaf2..5c24eee 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -274,6 +274,12 @@
     }
 
     @Override
+    boolean isSyncFinished(BLASTSyncEngine.SyncGroup group) {
+        // TODO(b/233286785): Support sync state for wallpaper. See WindowState#prepareSync.
+        return !mVisibleRequested || !hasVisibleNotDrawnWallpaper();
+    }
+
+    @Override
     public String toString() {
         if (stringName == null) {
             StringBuilder sb = new StringBuilder();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index aeefc34..8a68afb 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3685,12 +3685,6 @@
 
     // Called by window manager policy.  Not exposed externally.
     @Override
-    public void switchKeyboardLayout(int deviceId, int direction) {
-        mInputManager.switchKeyboardLayout(deviceId, direction);
-    }
-
-    // Called by window manager policy.  Not exposed externally.
-    @Override
     public void shutdown(boolean confirm) {
         // Pass in the UI context, since ShutdownThread requires it (to show UI).
         ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
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 52df010..eac9929 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -85,7 +85,6 @@
 import android.os.test.TestLooper;
 import android.service.dreams.DreamManagerInternal;
 import android.telecom.TelecomManager;
-import android.util.FeatureFlagUtils;
 import android.view.Display;
 import android.view.InputDevice;
 import android.view.KeyEvent;
@@ -743,15 +742,8 @@
 
     void assertSwitchKeyboardLayout(int direction, int displayId) {
         mTestLooper.dispatchAll();
-        if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)) {
-            verify(mInputMethodManagerInternal).onSwitchKeyboardLayoutShortcut(eq(direction),
-                    eq(displayId), eq(mImeTargetWindowToken));
-            verify(mWindowManagerFuncsImpl, never()).switchKeyboardLayout(anyInt(), anyInt());
-        } else {
-            verify(mWindowManagerFuncsImpl).switchKeyboardLayout(anyInt(), eq(direction));
-            verify(mInputMethodManagerInternal, never())
-                    .onSwitchKeyboardLayoutShortcut(anyInt(), anyInt(), any());
-        }
+        verify(mInputMethodManagerInternal).onSwitchKeyboardLayoutShortcut(eq(direction),
+                eq(displayId), eq(mImeTargetWindowToken));
     }
 
     void assertTakeBugreport() {
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt
index 511c948..1390218 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotationTransition.kt
@@ -17,8 +17,12 @@
 package com.android.server.wm.flicker.activityembedding.rotation
 
 import android.platform.test.annotations.Presubmit
+import android.tools.Position
+import android.tools.datatypes.Rect
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.traces.Condition
+import android.tools.traces.DeviceStateDump
 import android.tools.traces.component.ComponentNameMatcher
 import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase
 import com.android.server.wm.flicker.helpers.setRotation
@@ -30,7 +34,14 @@
     override val transition: FlickerBuilder.() -> Unit = {
         setup { this.setRotation(flicker.scenario.startRotation) }
         teardown { testApp.exit(wmHelper) }
-        transitions { this.setRotation(flicker.scenario.endRotation) }
+        transitions {
+            this.setRotation(flicker.scenario.endRotation)
+            if (!flicker.scenario.isTablet) {
+                wmHelper.StateSyncBuilder()
+                    .add(navBarInPosition(flicker.scenario.isGesturalNavigation))
+                    .waitForAndVerify()
+            }
+        }
     }
 
     /** {@inheritDoc} */
@@ -76,4 +87,37 @@
         appLayerRotates_StartingPos()
         appLayerRotates_EndingPos()
     }
+
+    private fun navBarInPosition(isGesturalNavigation: Boolean): Condition<DeviceStateDump> {
+        return Condition("navBarPosition") { dump ->
+            val display =
+                dump.layerState.displays.filterNot { it.isOff }.minByOrNull { it.id }
+                    ?: error("There is no display!")
+            val displayArea = display.layerStackSpace
+            val navBarPosition = display.navBarPosition(isGesturalNavigation)
+            val navBarRegion = dump.layerState
+                .getLayerWithBuffer(ComponentNameMatcher.NAV_BAR)
+                ?.visibleRegion?.bounds ?: Rect.EMPTY
+
+            when (navBarPosition) {
+                Position.TOP ->
+                    navBarRegion.top == displayArea.top &&
+                        navBarRegion.left == displayArea.left &&
+                        navBarRegion.right == displayArea.right
+                Position.BOTTOM ->
+                    navBarRegion.bottom == displayArea.bottom &&
+                        navBarRegion.left == displayArea.left &&
+                        navBarRegion.right == displayArea.right
+                Position.LEFT ->
+                    navBarRegion.left == displayArea.left &&
+                        navBarRegion.top == displayArea.top &&
+                        navBarRegion.bottom == displayArea.bottom
+                Position.RIGHT ->
+                    navBarRegion.right == displayArea.right &&
+                        navBarRegion.top == displayArea.top &&
+                        navBarRegion.bottom == displayArea.bottom
+                else -> error("Unknown position $navBarPosition")
+            }
+        }
+    }
 }
diff --git a/tests/FlickerTests/README.md b/tests/FlickerTests/README.md
index 6b28fdf..7429250 100644
--- a/tests/FlickerTests/README.md
+++ b/tests/FlickerTests/README.md
@@ -7,82 +7,17 @@
 
 ## Adding a Test
 
-By default tests should inherit from `RotationTestBase` or `NonRotationTestBase` and must override the variable `transitionToRun` (Kotlin) or the function `getTransitionToRun()` (Java).
-Only tests that are not supported by these classes should inherit directly from the `FlickerTestBase` class.
+By default, tests should inherit from `TestBase` and override the variable `transition` (Kotlin) or the function `getTransition()` (Java).
 
-### Rotation animations and transitions
+Inheriting from this class ensures the common assertions will be executed, namely:
 
-Tests that rotate the device should inherit from `RotationTestBase`.
-Tests that inherit from the class automatically receive start and end rotation values.  
-Moreover, these tests inherit the following checks:
 * all regions on the screen are covered
 * status bar is always visible
-* status bar rotates
+* status bar is at the correct position at the start and end of the transition
 * nav bar is always visible
-* nav bar is rotates
+* nav bar is at the correct position at the start and end of the transition
 
 The default tests can be disabled by overriding the respective methods and including an `@Ignore` annotation.
 
-### Non-Rotation animations and transitions
+For more examples of how a test looks like check `ChangeAppRotationTest` within the `Rotation` subdirectory.
 
-`NonRotationTestBase` was created to make it easier to write tests that do not involve rotation (e.g., `Pip`, `split screen` or `IME`).
-Tests that inherit from the class are automatically executed twice: once in portrait and once in landscape mode and the assertions are checked independently.
-Moreover, these tests inherit the following checks:
-* all regions on the screen are covered
-* status bar is always visible
-* nav bar is always visible
-
-The default tests can be disabled by overriding the respective methods and including an `@Ignore` annotation.
-
-### Exceptional cases
-
-Tests that rotate the device should inherit from `RotationTestBase`.
-This class allows the test to be freely configured and does not provide any assertions.  
-
-
-### Example
-
-Start by defining common or error prone transitions using `TransitionRunner`.
-```kotlin
-@LargeTest
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class MyTest(
-    beginRotationName: String,
-    beginRotation: Int
-) : NonRotationTestBase(beginRotationName, beginRotation) {
-    init {
-        mTestApp = MyAppHelper(InstrumentationRegistry.getInstrumentation())
-    }
-
-    override val transitionToRun: TransitionRunner
-        get() = TransitionRunner.newBuilder()
-            .withTag("myTest")
-            .recordAllRuns()
-            .runBefore { device.pressHome() }
-            .runBefore { device.waitForIdle() }
-            .run { testApp.open() }
-            .runAfter{ testApp.exit() }
-            .repeat(2)
-            .includeJankyRuns()
-            .build()
-
-    @Test
-    fun myWMTest() {
-        checkResults {
-            WmTraceSubject.assertThat(it)
-                    .showsAppWindow(MyTestApp)
-                    .forAllEntries()
-        }
-    }
-
-    @Test
-    fun mySFTest() {
-        checkResults {
-            LayersTraceSubject.assertThat(it)
-                    .showsLayer(MyTestApp)
-                    .forAllEntries()
-        }
-    }
-}
-```
diff --git a/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt b/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
index e60764f..80282c3 100644
--- a/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
@@ -33,7 +33,6 @@
 import android.os.Bundle
 import android.os.test.TestLooper
 import android.platform.test.annotations.Presubmit
-import android.provider.Settings
 import android.util.proto.ProtoOutputStream
 import android.view.InputDevice
 import android.view.inputmethod.InputMethodInfo
@@ -47,9 +46,7 @@
 import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotEquals
-import org.junit.Assert.assertNull
 import org.junit.Assert.assertTrue
-import org.junit.Assert.assertThrows
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -234,631 +231,326 @@
     }
 
     @Test
-    fun testDefaultUi_getKeyboardLayouts() {
-        NewSettingsApiFlag(false).use {
-            val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
-            assertNotEquals(
-                "Default UI: Keyboard layout API should not return empty array",
-                0,
-                keyboardLayouts.size
-            )
-            assertTrue(
-                "Default UI: Keyboard layout API should provide English(US) layout",
-                hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
-        }
+    fun testGetKeyboardLayouts() {
+        val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
+        assertNotEquals(
+            "Keyboard layout API should not return empty array",
+            0,
+            keyboardLayouts.size
+        )
+        assertTrue(
+            "Keyboard layout API should provide English(US) layout",
+            hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+        )
     }
 
     @Test
-    fun testNewUi_getKeyboardLayouts() {
-        NewSettingsApiFlag(true).use {
-            val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
-            assertNotEquals(
-                "New UI: Keyboard layout API should not return empty array",
-                0,
-                keyboardLayouts.size
-            )
-            assertTrue(
-                "New UI: Keyboard layout API should provide English(US) layout",
-                hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
-        }
+    fun testGetKeyboardLayout() {
+        val keyboardLayout =
+            keyboardLayoutManager.getKeyboardLayout(ENGLISH_US_LAYOUT_DESCRIPTOR)
+        assertEquals("getKeyboardLayout API should return correct Layout from " +
+                "available layouts",
+            ENGLISH_US_LAYOUT_DESCRIPTOR,
+            keyboardLayout!!.descriptor
+        )
     }
 
     @Test
-    fun testDefaultUi_getKeyboardLayoutsForInputDevice() {
-        NewSettingsApiFlag(false).use {
-            val keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutsForInputDevice(keyboardDevice.identifier)
-            assertNotEquals(
-                "Default UI: getKeyboardLayoutsForInputDevice API should not return empty array",
-                0,
-                keyboardLayouts.size
-            )
-            assertTrue(
-                "Default UI: getKeyboardLayoutsForInputDevice API should provide English(US) " +
-                        "layout",
-                hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
+    fun testGetSetKeyboardLayoutForInputDevice_withImeInfo() {
+        val imeSubtype = createImeSubtype()
 
-            val vendorSpecificKeyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutsForInputDevice(
-                    vendorSpecificKeyboardDevice.identifier
-                )
-            assertEquals(
-                "Default UI: getKeyboardLayoutsForInputDevice API should return only vendor " +
-                        "specific layout",
+        keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+            keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+            ENGLISH_UK_LAYOUT_DESCRIPTOR
+        )
+        var result =
+            keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
+            )
+        assertEquals(
+            "getKeyboardLayoutForInputDevice API should return the set layout",
+            ENGLISH_UK_LAYOUT_DESCRIPTOR,
+            result.layoutDescriptor
+        )
+
+        // This should replace previously set layout
+        keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+            keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+            ENGLISH_US_LAYOUT_DESCRIPTOR
+        )
+        result =
+            keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
+            )
+        assertEquals(
+            "getKeyboardLayoutForInputDevice API should return the last set layout",
+            ENGLISH_US_LAYOUT_DESCRIPTOR,
+            result.layoutDescriptor
+        )
+    }
+
+    @Test
+    fun testGetKeyboardLayoutListForInputDevice() {
+        // Check Layouts for "hi-Latn". It should return all 'Latn' keyboard layouts
+        var keyboardLayouts =
+            keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo,
+                createImeSubtypeForLanguageTag("hi-Latn")
+            )
+        assertNotEquals(
+            "getKeyboardLayoutListForInputDevice API should return the list of " +
+                    "supported layouts with matching script code",
+            0,
+            keyboardLayouts.size
+        )
+        assertTrue("getKeyboardLayoutListForInputDevice API should return a list " +
+                "containing English(US) layout for hi-Latn",
+            containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+        )
+        assertTrue("getKeyboardLayoutListForInputDevice API should return a list " +
+                "containing English(No script code) layout for hi-Latn",
+            containsLayout(
+                keyboardLayouts,
+                createLayoutDescriptor("keyboard_layout_english_without_script_code")
+            )
+        )
+
+        // Check Layouts for "hi" which by default uses 'Deva' script.
+        keyboardLayouts =
+            keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo,
+                createImeSubtypeForLanguageTag("hi")
+            )
+        assertEquals("getKeyboardLayoutListForInputDevice API should return empty " +
+                "list if no supported layouts available",
+            0,
+            keyboardLayouts.size
+        )
+
+        // If user manually selected some layout, always provide it in the layout list
+        val imeSubtype = createImeSubtypeForLanguageTag("hi")
+        keyboardLayoutManager.setKeyboardLayoutForInputDevice(
+            keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
+            ENGLISH_US_LAYOUT_DESCRIPTOR
+        )
+        keyboardLayouts =
+            keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo,
+                imeSubtype
+            )
+        assertEquals("getKeyboardLayoutListForInputDevice API should return user " +
+                "selected layout even if the script is incompatible with IME",
                 1,
-                vendorSpecificKeyboardLayouts.size
-            )
-            assertEquals(
-                "Default UI: getKeyboardLayoutsForInputDevice API should return vendor specific " +
-                        "layout",
-                VENDOR_SPECIFIC_LAYOUT_DESCRIPTOR,
-                vendorSpecificKeyboardLayouts[0].descriptor
-            )
-        }
-    }
+            keyboardLayouts.size
+        )
 
-    @Test
-    fun testNewUi_getKeyboardLayoutsForInputDevice() {
-        NewSettingsApiFlag(true).use {
-            val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
-            assertNotEquals(
-                    "New UI: getKeyboardLayoutsForInputDevice API should not return empty array",
-                    0,
-                    keyboardLayouts.size
-            )
-            assertTrue(
-                    "New UI: getKeyboardLayoutsForInputDevice API should provide English(US) " +
-                            "layout",
-                    hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
-        }
-    }
-
-    @Test
-    fun testDefaultUi_getSetCurrentKeyboardLayoutForInputDevice() {
-        NewSettingsApiFlag(false).use {
-            assertNull(
-                "Default UI: getCurrentKeyboardLayoutForInputDevice API should return null if " +
-                        "nothing was set",
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-
-            keyboardLayoutManager.setCurrentKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier,
-                ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            val keyboardLayout =
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            assertEquals(
-                "Default UI: getCurrentKeyboardLayoutForInputDevice API should return the set " +
-                        "layout",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                keyboardLayout
-            )
-        }
-    }
-
-    @Test
-    fun testNewUi_getSetCurrentKeyboardLayoutForInputDevice() {
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.setCurrentKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier,
-                ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            assertNull(
-                "New UI: getCurrentKeyboardLayoutForInputDevice API should always return null " +
-                        "even after setCurrentKeyboardLayoutForInputDevice",
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testDefaultUi_getEnabledKeyboardLayoutsForInputDevice() {
-        NewSettingsApiFlag(false).use {
-            keyboardLayoutManager.addKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-
-            val keyboardLayouts =
-                keyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(
-                    keyboardDevice.identifier
-                )
-            assertEquals(
-                "Default UI: getEnabledKeyboardLayoutsForInputDevice API should return added " +
-                        "layout",
-                1,
-                keyboardLayouts.size
-            )
-            assertEquals(
-                "Default UI: getEnabledKeyboardLayoutsForInputDevice API should return " +
-                        "English(US) layout",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                keyboardLayouts[0]
-            )
-            assertEquals(
-                "Default UI: getCurrentKeyboardLayoutForInputDevice API should return " +
-                        "English(US) layout (Auto select the first enabled layout)",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-
-            keyboardLayoutManager.removeKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            assertEquals(
-                "Default UI: getKeyboardLayoutsForInputDevice API should return 0 layouts",
-                0,
-                keyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(
-                    keyboardDevice.identifier
-                ).size
-            )
-            assertNull(
-                "Default UI: getCurrentKeyboardLayoutForInputDevice API should return null after " +
-                        "the enabled layout is removed",
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testNewUi_getEnabledKeyboardLayoutsForInputDevice() {
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.addKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-
-            assertEquals(
-                "New UI: getEnabledKeyboardLayoutsForInputDevice API should return always return " +
-                        "an empty array",
-                0,
-                keyboardLayoutManager.getEnabledKeyboardLayoutsForInputDevice(
-                    keyboardDevice.identifier
-                ).size
-            )
-            assertNull(
-                "New UI: getCurrentKeyboardLayoutForInputDevice API should always return null",
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testDefaultUi_switchKeyboardLayout() {
-        NewSettingsApiFlag(false).use {
-            keyboardLayoutManager.addKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            keyboardLayoutManager.addKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_UK_LAYOUT_DESCRIPTOR
-            )
-            assertEquals(
-                "Default UI: getCurrentKeyboardLayoutForInputDevice API should return " +
-                        "English(US) layout",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-
-            keyboardLayoutManager.switchKeyboardLayout(DEVICE_ID, 1)
-
-            // Throws null pointer because trying to show toast using TestLooper
-            assertThrows(NullPointerException::class.java) { testLooper.dispatchAll() }
-            assertEquals("Default UI: getCurrentKeyboardLayoutForInputDevice API should return " +
-                    "English(UK) layout",
-                ENGLISH_UK_LAYOUT_DESCRIPTOR,
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testNewUi_switchKeyboardLayout() {
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.addKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            keyboardLayoutManager.addKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, ENGLISH_UK_LAYOUT_DESCRIPTOR
-            )
-
-            keyboardLayoutManager.switchKeyboardLayout(DEVICE_ID, 1)
-            testLooper.dispatchAll()
-
-            assertNull("New UI: getCurrentKeyboardLayoutForInputDevice API should always return " +
-                    "null",
-                keyboardLayoutManager.getCurrentKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testDefaultUi_getKeyboardLayout() {
-        NewSettingsApiFlag(false).use {
-            val keyboardLayout =
-                keyboardLayoutManager.getKeyboardLayout(ENGLISH_US_LAYOUT_DESCRIPTOR)
-            assertEquals("Default UI: getKeyboardLayout API should return correct Layout from " +
-                    "available layouts",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                keyboardLayout!!.descriptor
-            )
-        }
-    }
-
-    @Test
-    fun testNewUi_getKeyboardLayout() {
-        NewSettingsApiFlag(true).use {
-            val keyboardLayout =
-                keyboardLayoutManager.getKeyboardLayout(ENGLISH_US_LAYOUT_DESCRIPTOR)
-            assertEquals("New UI: getKeyboardLayout API should return correct Layout from " +
-                    "available layouts",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                keyboardLayout!!.descriptor
-            )
-        }
-    }
-
-    @Test
-    fun testDefaultUi_getSetKeyboardLayoutForInputDevice_WithImeInfo() {
-        NewSettingsApiFlag(false).use {
-            val imeSubtype = createImeSubtype()
-            keyboardLayoutManager.setKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
-                ENGLISH_UK_LAYOUT_DESCRIPTOR
-            )
-            assertEquals(
-                "Default UI: getKeyboardLayoutForInputDevice API should always return " +
-                        "KeyboardLayoutSelectionResult.FAILED",
-                KeyboardLayoutSelectionResult.FAILED,
-                keyboardLayoutManager.getKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testNewUi_getSetKeyboardLayoutForInputDevice_withImeInfo() {
-        NewSettingsApiFlag(true).use {
-            val imeSubtype = createImeSubtype()
-
-            keyboardLayoutManager.setKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
-                ENGLISH_UK_LAYOUT_DESCRIPTOR
-            )
-            var result =
-                keyboardLayoutManager.getKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
-                )
-            assertEquals(
-                "New UI: getKeyboardLayoutForInputDevice API should return the set layout",
-                ENGLISH_UK_LAYOUT_DESCRIPTOR,
-                result.layoutDescriptor
-            )
-
-            // This should replace previously set layout
-            keyboardLayoutManager.setKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
-                ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            result =
-                keyboardLayoutManager.getKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype
-                )
-            assertEquals(
-                "New UI: getKeyboardLayoutForInputDevice API should return the last set layout",
-                ENGLISH_US_LAYOUT_DESCRIPTOR,
-                result.layoutDescriptor
-            )
-        }
-    }
-
-    @Test
-    fun testDefaultUi_getKeyboardLayoutListForInputDevice() {
-        NewSettingsApiFlag(false).use {
-            val keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+        // Special case Japanese: UScript ignores provided script code for certain language tags
+        // Should manually match provided script codes and then rely on Uscript to derive
+        // script from language tags and match those.
+        keyboardLayouts =
+            keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
                     keyboardDevice.identifier, USER_ID, imeInfo,
-                    createImeSubtype()
-                )
-            assertEquals("Default UI: getKeyboardLayoutListForInputDevice API should always " +
-                    "return empty array",
-                0,
-                keyboardLayouts.size
+                    createImeSubtypeForLanguageTag("ja-Latn-JP")
             )
-        }
-    }
+        assertNotEquals(
+            "getKeyboardLayoutListForInputDevice API should return the list of " +
+                    "supported layouts with matching script code for ja-Latn-JP",
+            0,
+            keyboardLayouts.size
+        )
+        assertTrue("getKeyboardLayoutListForInputDevice API should return a list " +
+                "containing English(US) layout for ja-Latn-JP",
+            containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+        )
+        assertTrue("getKeyboardLayoutListForInputDevice API should return a list " +
+                "containing English(No script code) layout for ja-Latn-JP",
+            containsLayout(
+                keyboardLayouts,
+                createLayoutDescriptor("keyboard_layout_english_without_script_code")
+            )
+        )
 
-    @Test
-    fun testNewUi_getKeyboardLayoutListForInputDevice() {
-        NewSettingsApiFlag(true).use {
-            // Check Layouts for "hi-Latn". It should return all 'Latn' keyboard layouts
-            var keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+        // If script code not explicitly provided for Japanese should rely on Uscript to find
+        // derived script code and hence no suitable layout will be found.
+        keyboardLayouts =
+            keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
                     keyboardDevice.identifier, USER_ID, imeInfo,
-                    createImeSubtypeForLanguageTag("hi-Latn")
-                )
-            assertNotEquals(
-                "New UI: getKeyboardLayoutListForInputDevice API should return the list of " +
-                        "supported layouts with matching script code",
-                0,
-                keyboardLayouts.size
+                    createImeSubtypeForLanguageTag("ja-JP")
             )
-            assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
-                    "containing English(US) layout for hi-Latn",
-                containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
-            assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
-                    "containing English(No script code) layout for hi-Latn",
-                containsLayout(
-                    keyboardLayouts,
-                    createLayoutDescriptor("keyboard_layout_english_without_script_code")
-                )
-            )
+        assertEquals(
+            "getKeyboardLayoutListForInputDevice API should return empty list of " +
+                    "supported layouts with matching script code for ja-JP",
+            0,
+            keyboardLayouts.size
+        )
 
-            // Check Layouts for "hi" which by default uses 'Deva' script.
-            keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo,
-                    createImeSubtypeForLanguageTag("hi")
-                )
-            assertEquals("New UI: getKeyboardLayoutListForInputDevice API should return empty " +
-                    "list if no supported layouts available",
-                0,
-                keyboardLayouts.size
+        // If IME doesn't have a corresponding language tag, then should show all available
+        // layouts no matter the script code.
+        keyboardLayouts =
+            keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo, null
             )
-
-            // If user manually selected some layout, always provide it in the layout list
-            val imeSubtype = createImeSubtypeForLanguageTag("hi")
-            keyboardLayoutManager.setKeyboardLayoutForInputDevice(
-                keyboardDevice.identifier, USER_ID, imeInfo, imeSubtype,
-                ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo,
-                    imeSubtype
-                )
-            assertEquals("New UI: getKeyboardLayoutListForInputDevice API should return user " +
-                    "selected layout even if the script is incompatible with IME",
-                    1,
-                keyboardLayouts.size
-            )
-
-            // Special case Japanese: UScript ignores provided script code for certain language tags
-            // Should manually match provided script codes and then rely on Uscript to derive
-            // script from language tags and match those.
-            keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
-                        keyboardDevice.identifier, USER_ID, imeInfo,
-                        createImeSubtypeForLanguageTag("ja-Latn-JP")
-                )
-            assertNotEquals(
-                "New UI: getKeyboardLayoutListForInputDevice API should return the list of " +
-                        "supported layouts with matching script code for ja-Latn-JP",
-                0,
-                keyboardLayouts.size
-            )
-            assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
-                    "containing English(US) layout for ja-Latn-JP",
-                containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
-            assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
-                    "containing English(No script code) layout for ja-Latn-JP",
-                containsLayout(
-                    keyboardLayouts,
-                    createLayoutDescriptor("keyboard_layout_english_without_script_code")
-                )
-            )
-
-            // If script code not explicitly provided for Japanese should rely on Uscript to find
-            // derived script code and hence no suitable layout will be found.
-            keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
-                        keyboardDevice.identifier, USER_ID, imeInfo,
-                        createImeSubtypeForLanguageTag("ja-JP")
-                )
-            assertEquals(
-                "New UI: getKeyboardLayoutListForInputDevice API should return empty list of " +
-                        "supported layouts with matching script code for ja-JP",
-                0,
-                keyboardLayouts.size
-            )
-
-            // If IME doesn't have a corresponding language tag, then should show all available
-            // layouts no matter the script code.
-            keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo, null
-                )
-            assertNotEquals(
-                "New UI: getKeyboardLayoutListForInputDevice API should return all layouts if" +
-                    "language tag or subtype not provided",
-                0,
-                keyboardLayouts.size
-            )
-            assertTrue("New UI: getKeyboardLayoutListForInputDevice API should contain Latin " +
-                "layouts if language tag or subtype not provided",
-                containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
-            )
-            assertTrue("New UI: getKeyboardLayoutListForInputDevice API should contain Cyrillic " +
-                "layouts if language tag or subtype not provided",
-                containsLayout(
-                    keyboardLayouts,
-                    createLayoutDescriptor("keyboard_layout_russian")
-                )
-            )
-        }
-    }
-
-    @Test
-    fun testNewUi_getDefaultKeyboardLayoutForInputDevice_withImeLanguageTag() {
-        NewSettingsApiFlag(true).use {
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTag("en-US"),
-                ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTag("en-GB"),
-                ENGLISH_UK_LAYOUT_DESCRIPTOR
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTag("de"),
-                GERMAN_LAYOUT_DESCRIPTOR
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTag("fr-FR"),
-                createLayoutDescriptor("keyboard_layout_french")
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTag("ru"),
+        assertNotEquals(
+            "getKeyboardLayoutListForInputDevice API should return all layouts if" +
+                "language tag or subtype not provided",
+            0,
+            keyboardLayouts.size
+        )
+        assertTrue("getKeyboardLayoutListForInputDevice API should contain Latin " +
+            "layouts if language tag or subtype not provided",
+            containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+        )
+        assertTrue("getKeyboardLayoutListForInputDevice API should contain Cyrillic " +
+            "layouts if language tag or subtype not provided",
+            containsLayout(
+                keyboardLayouts,
                 createLayoutDescriptor("keyboard_layout_russian")
             )
-            assertEquals(
-                "New UI: getDefaultKeyboardLayoutForInputDevice should return " +
-                        "KeyboardLayoutSelectionResult.FAILED when no layout available",
-                KeyboardLayoutSelectionResult.FAILED,
-                keyboardLayoutManager.getKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo,
-                    createImeSubtypeForLanguageTag("it")
-                )
-            )
-            assertEquals(
-                "New UI: getDefaultKeyboardLayoutForInputDevice should return " +
-                        "KeyboardLayoutSelectionResult.FAILED when no layout for script code is" +
-                        "available",
-                KeyboardLayoutSelectionResult.FAILED,
-                keyboardLayoutManager.getKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo,
-                    createImeSubtypeForLanguageTag("en-Deva")
-                )
-            )
-        }
+        )
     }
 
     @Test
-    fun testNewUi_getDefaultKeyboardLayoutForInputDevice_withImeLanguageTagAndLayoutType() {
-        NewSettingsApiFlag(true).use {
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("en-US", "qwerty"),
-                ENGLISH_US_LAYOUT_DESCRIPTOR
+    fun testGetDefaultKeyboardLayoutForInputDevice_withImeLanguageTag() {
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTag("en-US"),
+            ENGLISH_US_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTag("en-GB"),
+            ENGLISH_UK_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTag("de"),
+            GERMAN_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTag("fr-FR"),
+            createLayoutDescriptor("keyboard_layout_french")
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTag("ru"),
+            createLayoutDescriptor("keyboard_layout_russian")
+        )
+        assertEquals(
+            "getDefaultKeyboardLayoutForInputDevice should return " +
+                    "KeyboardLayoutSelectionResult.FAILED when no layout available",
+            KeyboardLayoutSelectionResult.FAILED,
+            keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo,
+                createImeSubtypeForLanguageTag("it")
             )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("en-US", "dvorak"),
-                createLayoutDescriptor("keyboard_layout_english_us_dvorak")
-            )
-            // Try to match layout type even if country doesn't match
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("en-GB", "dvorak"),
-                createLayoutDescriptor("keyboard_layout_english_us_dvorak")
-            )
-            // Choose layout based on layout type priority, if layout type is not provided by IME
-            // (Qwerty > Dvorak > Extended)
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("en-US", ""),
-                ENGLISH_US_LAYOUT_DESCRIPTOR
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("en-GB", "qwerty"),
-                ENGLISH_UK_LAYOUT_DESCRIPTOR
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("de", "qwertz"),
-                GERMAN_LAYOUT_DESCRIPTOR
-            )
-            // Wrong layout type should match with language if provided layout type not available
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("de", "qwerty"),
-                GERMAN_LAYOUT_DESCRIPTOR
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("fr-FR", "azerty"),
-                createLayoutDescriptor("keyboard_layout_french")
-            )
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("ru", "qwerty"),
-                createLayoutDescriptor("keyboard_layout_russian_qwerty")
-            )
-            // If layout type is empty then prioritize KCM with empty layout type
-            assertCorrectLayout(
-                keyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
-                createLayoutDescriptor("keyboard_layout_russian")
-            )
-            assertEquals("New UI: getDefaultKeyboardLayoutForInputDevice should return " +
+        )
+        assertEquals(
+            "getDefaultKeyboardLayoutForInputDevice should return " +
                     "KeyboardLayoutSelectionResult.FAILED when no layout for script code is" +
                     "available",
-                KeyboardLayoutSelectionResult.FAILED,
-                keyboardLayoutManager.getKeyboardLayoutForInputDevice(
-                    keyboardDevice.identifier, USER_ID, imeInfo,
-                    createImeSubtypeForLanguageTagAndLayoutType("en-Deva-US", "")
-                )
+            KeyboardLayoutSelectionResult.FAILED,
+            keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo,
+                createImeSubtypeForLanguageTag("en-Deva")
             )
-        }
+        )
     }
 
     @Test
-    fun testNewUi_getDefaultKeyboardLayoutForInputDevice_withHwLanguageTagAndLayoutType() {
-        NewSettingsApiFlag(true).use {
-            val frenchSubtype = createImeSubtypeForLanguageTagAndLayoutType("fr", "azerty")
-            // Should return English dvorak even if IME current layout is French, since HW says the
-            // keyboard is a Dvorak keyboard
-            assertCorrectLayout(
-                englishDvorakKeyboardDevice,
-                frenchSubtype,
-                createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+    fun testGetDefaultKeyboardLayoutForInputDevice_withImeLanguageTagAndLayoutType() {
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("en-US", "qwerty"),
+            ENGLISH_US_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("en-US", "dvorak"),
+            createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+        )
+        // Try to match layout type even if country doesn't match
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("en-GB", "dvorak"),
+            createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+        )
+        // Choose layout based on layout type priority, if layout type is not provided by IME
+        // (Qwerty > Dvorak > Extended)
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("en-US", ""),
+            ENGLISH_US_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("en-GB", "qwerty"),
+            ENGLISH_UK_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("de", "qwertz"),
+            GERMAN_LAYOUT_DESCRIPTOR
+        )
+        // Wrong layout type should match with language if provided layout type not available
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("de", "qwerty"),
+            GERMAN_LAYOUT_DESCRIPTOR
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("fr-FR", "azerty"),
+            createLayoutDescriptor("keyboard_layout_french")
+        )
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("ru", "qwerty"),
+            createLayoutDescriptor("keyboard_layout_russian_qwerty")
+        )
+        // If layout type is empty then prioritize KCM with empty layout type
+        assertCorrectLayout(
+            keyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
+            createLayoutDescriptor("keyboard_layout_russian")
+        )
+        assertEquals("getDefaultKeyboardLayoutForInputDevice should return " +
+                "KeyboardLayoutSelectionResult.FAILED when no layout for script code is" +
+                "available",
+            KeyboardLayoutSelectionResult.FAILED,
+            keyboardLayoutManager.getKeyboardLayoutForInputDevice(
+                keyboardDevice.identifier, USER_ID, imeInfo,
+                createImeSubtypeForLanguageTagAndLayoutType("en-Deva-US", "")
             )
+        )
+    }
 
-            // Back to back changing HW keyboards with same product and vendor ID but different
-            // language and layout type should configure the layouts correctly.
-            assertCorrectLayout(
-                englishQwertyKeyboardDevice,
-                frenchSubtype,
-                createLayoutDescriptor("keyboard_layout_english_us")
-            )
+    @Test
+    fun testGetDefaultKeyboardLayoutForInputDevice_withHwLanguageTagAndLayoutType() {
+        val frenchSubtype = createImeSubtypeForLanguageTagAndLayoutType("fr", "azerty")
+        // Should return English dvorak even if IME current layout is French, since HW says the
+        // keyboard is a Dvorak keyboard
+        assertCorrectLayout(
+            englishDvorakKeyboardDevice,
+            frenchSubtype,
+            createLayoutDescriptor("keyboard_layout_english_us_dvorak")
+        )
 
-            // Fallback to IME information if the HW provided layout script is incompatible with the
-            // provided IME subtype
-            assertCorrectLayout(
-                englishDvorakKeyboardDevice,
-                createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
-                createLayoutDescriptor("keyboard_layout_russian")
-            )
-        }
+        // Back to back changing HW keyboards with same product and vendor ID but different
+        // language and layout type should configure the layouts correctly.
+        assertCorrectLayout(
+            englishQwertyKeyboardDevice,
+            frenchSubtype,
+            createLayoutDescriptor("keyboard_layout_english_us")
+        )
+
+        // Fallback to IME information if the HW provided layout script is incompatible with the
+        // provided IME subtype
+        assertCorrectLayout(
+            englishDvorakKeyboardDevice,
+            createImeSubtypeForLanguageTagAndLayoutType("ru", ""),
+            createLayoutDescriptor("keyboard_layout_russian")
+        )
     }
 
     @Test
@@ -867,27 +559,25 @@
                 KeyboardLayoutManager.ImeInfo(0, imeInfo,
                         createImeSubtypeForLanguageTagAndLayoutType("de-Latn", "qwertz")))
         Mockito.doReturn(imeInfos).`when`(keyboardLayoutManager).imeInfoListForLayoutMapping
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.onInputDeviceAdded(keyboardDevice.id)
-            ExtendedMockito.verify {
-                FrameworkStatsLog.write(
-                        ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
-                        ArgumentMatchers.anyBoolean(),
-                        ArgumentMatchers.eq(keyboardDevice.vendorId),
-                        ArgumentMatchers.eq(keyboardDevice.productId),
-                        ArgumentMatchers.eq(
-                            createByteArray(
-                                KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
-                                LAYOUT_TYPE_DEFAULT,
-                                GERMAN_LAYOUT_NAME,
-                                KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD,
-                                "de-Latn",
-                                LAYOUT_TYPE_QWERTZ
-                            ),
+        keyboardLayoutManager.onInputDeviceAdded(keyboardDevice.id)
+        ExtendedMockito.verify {
+            FrameworkStatsLog.write(
+                    ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
+                    ArgumentMatchers.anyBoolean(),
+                    ArgumentMatchers.eq(keyboardDevice.vendorId),
+                    ArgumentMatchers.eq(keyboardDevice.productId),
+                    ArgumentMatchers.eq(
+                        createByteArray(
+                            KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
+                            LAYOUT_TYPE_DEFAULT,
+                            GERMAN_LAYOUT_NAME,
+                            KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_VIRTUAL_KEYBOARD,
+                            "de-Latn",
+                            LAYOUT_TYPE_QWERTZ
                         ),
-                        ArgumentMatchers.eq(keyboardDevice.deviceBus),
-                )
-            }
+                    ),
+                    ArgumentMatchers.eq(keyboardDevice.deviceBus),
+            )
         }
     }
 
@@ -897,27 +587,25 @@
                 KeyboardLayoutManager.ImeInfo(0, imeInfo,
                         createImeSubtypeForLanguageTagAndLayoutType("de-Latn", "qwertz")))
         Mockito.doReturn(imeInfos).`when`(keyboardLayoutManager).imeInfoListForLayoutMapping
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.onInputDeviceAdded(englishQwertyKeyboardDevice.id)
-            ExtendedMockito.verify {
-                FrameworkStatsLog.write(
-                        ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
-                        ArgumentMatchers.anyBoolean(),
-                        ArgumentMatchers.eq(englishQwertyKeyboardDevice.vendorId),
-                        ArgumentMatchers.eq(englishQwertyKeyboardDevice.productId),
-                        ArgumentMatchers.eq(
-                            createByteArray(
-                                "en",
-                                LAYOUT_TYPE_QWERTY,
-                                ENGLISH_US_LAYOUT_NAME,
-                                KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEVICE,
-                                "de-Latn",
-                                LAYOUT_TYPE_QWERTZ
-                            )
-                        ),
-                        ArgumentMatchers.eq(keyboardDevice.deviceBus),
-                )
-            }
+        keyboardLayoutManager.onInputDeviceAdded(englishQwertyKeyboardDevice.id)
+        ExtendedMockito.verify {
+            FrameworkStatsLog.write(
+                    ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
+                    ArgumentMatchers.anyBoolean(),
+                    ArgumentMatchers.eq(englishQwertyKeyboardDevice.vendorId),
+                    ArgumentMatchers.eq(englishQwertyKeyboardDevice.productId),
+                    ArgumentMatchers.eq(
+                        createByteArray(
+                            "en",
+                            LAYOUT_TYPE_QWERTY,
+                            ENGLISH_US_LAYOUT_NAME,
+                            KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEVICE,
+                            "de-Latn",
+                            LAYOUT_TYPE_QWERTZ
+                        )
+                    ),
+                    ArgumentMatchers.eq(keyboardDevice.deviceBus),
+            )
         }
     }
 
@@ -925,27 +613,25 @@
     fun testConfigurationLogged_onInputDeviceAdded_DefaultSelection() {
         val imeInfos = listOf(KeyboardLayoutManager.ImeInfo(0, imeInfo, createImeSubtype()))
         Mockito.doReturn(imeInfos).`when`(keyboardLayoutManager).imeInfoListForLayoutMapping
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.onInputDeviceAdded(keyboardDevice.id)
-            ExtendedMockito.verify {
-                FrameworkStatsLog.write(
-                        ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
-                        ArgumentMatchers.anyBoolean(),
-                        ArgumentMatchers.eq(keyboardDevice.vendorId),
-                        ArgumentMatchers.eq(keyboardDevice.productId),
-                        ArgumentMatchers.eq(
-                            createByteArray(
-                                KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
-                                LAYOUT_TYPE_DEFAULT,
-                                "Default",
-                                KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEFAULT,
-                                KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
-                                LAYOUT_TYPE_DEFAULT
-                            ),
+        keyboardLayoutManager.onInputDeviceAdded(keyboardDevice.id)
+        ExtendedMockito.verify {
+            FrameworkStatsLog.write(
+                    ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
+                    ArgumentMatchers.anyBoolean(),
+                    ArgumentMatchers.eq(keyboardDevice.vendorId),
+                    ArgumentMatchers.eq(keyboardDevice.productId),
+                    ArgumentMatchers.eq(
+                        createByteArray(
+                            KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
+                            LAYOUT_TYPE_DEFAULT,
+                            "Default",
+                            KeyboardLayoutSelectionResult.LAYOUT_SELECTION_CRITERIA_DEFAULT,
+                            KeyboardMetricsCollector.DEFAULT_LANGUAGE_TAG,
+                            LAYOUT_TYPE_DEFAULT
                         ),
-                        ArgumentMatchers.eq(keyboardDevice.deviceBus),
-                )
-            }
+                    ),
+                    ArgumentMatchers.eq(keyboardDevice.deviceBus),
+            )
         }
     }
 
@@ -953,19 +639,17 @@
     fun testConfigurationNotLogged_onInputDeviceChanged() {
         val imeInfos = listOf(KeyboardLayoutManager.ImeInfo(0, imeInfo, createImeSubtype()))
         Mockito.doReturn(imeInfos).`when`(keyboardLayoutManager).imeInfoListForLayoutMapping
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
-            ExtendedMockito.verify({
-                FrameworkStatsLog.write(
-                        ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
-                        ArgumentMatchers.anyBoolean(),
-                        ArgumentMatchers.anyInt(),
-                        ArgumentMatchers.anyInt(),
-                        ArgumentMatchers.any(ByteArray::class.java),
-                        ArgumentMatchers.anyInt(),
-                )
-            }, Mockito.times(0))
-        }
+        keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
+        ExtendedMockito.verify({
+            FrameworkStatsLog.write(
+                    ArgumentMatchers.eq(FrameworkStatsLog.KEYBOARD_CONFIGURED),
+                    ArgumentMatchers.anyBoolean(),
+                    ArgumentMatchers.anyInt(),
+                    ArgumentMatchers.anyInt(),
+                    ArgumentMatchers.any(ByteArray::class.java),
+                    ArgumentMatchers.anyInt(),
+            )
+        }, Mockito.times(0))
     }
 
     @Test
@@ -975,18 +659,16 @@
         Mockito.doReturn(false).`when`(keyboardLayoutManager).isVirtualDevice(
             ArgumentMatchers.eq(keyboardDevice.id)
         )
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
-            ExtendedMockito.verify(
-                notificationManager,
-                Mockito.times(1)
-            ).notifyAsUser(
-                ArgumentMatchers.isNull(),
-                ArgumentMatchers.anyInt(),
-                ArgumentMatchers.any(),
-                ArgumentMatchers.any()
-            )
-        }
+        keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
+        ExtendedMockito.verify(
+            notificationManager,
+            Mockito.times(1)
+        ).notifyAsUser(
+            ArgumentMatchers.isNull(),
+            ArgumentMatchers.anyInt(),
+            ArgumentMatchers.any(),
+            ArgumentMatchers.any()
+        )
     }
 
     @Test
@@ -996,18 +678,16 @@
         Mockito.doReturn(true).`when`(keyboardLayoutManager).isVirtualDevice(
             ArgumentMatchers.eq(keyboardDevice.id)
         )
-        NewSettingsApiFlag(true).use {
-            keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
-            ExtendedMockito.verify(
-                notificationManager,
-                Mockito.never()
-            ).notifyAsUser(
-                ArgumentMatchers.isNull(),
-                ArgumentMatchers.anyInt(),
-                ArgumentMatchers.any(),
-                ArgumentMatchers.any()
-            )
-        }
+        keyboardLayoutManager.onInputDeviceChanged(keyboardDevice.id)
+        ExtendedMockito.verify(
+            notificationManager,
+            Mockito.never()
+        ).notifyAsUser(
+            ArgumentMatchers.isNull(),
+            ArgumentMatchers.anyInt(),
+            ArgumentMatchers.any(),
+            ArgumentMatchers.any()
+        )
     }
 
     private fun assertCorrectLayout(
@@ -1019,7 +699,7 @@
             device.identifier, USER_ID, imeInfo, imeSubtype
         )
         assertEquals(
-            "New UI: getDefaultKeyboardLayoutForInputDevice should return $expectedLayout",
+            "getDefaultKeyboardLayoutForInputDevice should return $expectedLayout",
             expectedLayout,
             result.layoutDescriptor
         )
@@ -1123,21 +803,4 @@
         info.serviceInfo.name = RECEIVER_NAME
         return info
     }
-
-    private inner class NewSettingsApiFlag constructor(enabled: Boolean) : AutoCloseable {
-        init {
-            Settings.Global.putString(
-                context.contentResolver,
-                "settings_new_keyboard_ui", enabled.toString()
-            )
-        }
-
-        override fun close() {
-            Settings.Global.putString(
-                context.contentResolver,
-                "settings_new_keyboard_ui",
-                ""
-            )
-        }
-    }
 }