Merge "Move datasource tests" into main
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index caf6992..72a68f8 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1797,18 +1797,20 @@
 
   public class InputSettings {
     method @FlaggedApi("com.android.hardware.input.keyboard_a11y_bounce_keys_flag") public static int getAccessibilityBounceKeysThreshold(@NonNull android.content.Context);
-    method @FlaggedApi("com.android.hardware.input.keyboard_repeat_keys") public static int getAccessibilityRepeatKeysDelay(@NonNull android.content.Context);
-    method @FlaggedApi("com.android.hardware.input.keyboard_repeat_keys") public static int getAccessibilityRepeatKeysTimeout(@NonNull android.content.Context);
     method @FlaggedApi("com.android.hardware.input.keyboard_a11y_slow_keys_flag") public static int getAccessibilitySlowKeysThreshold(@NonNull android.content.Context);
+    method @FlaggedApi("com.android.input.flags.keyboard_repeat_keys") public static int getRepeatKeysDelay(@NonNull android.content.Context);
+    method @FlaggedApi("com.android.input.flags.keyboard_repeat_keys") public static int getRepeatKeysTimeout(@NonNull android.content.Context);
     method @FlaggedApi("com.android.hardware.input.keyboard_a11y_mouse_keys") public static boolean isAccessibilityMouseKeysEnabled(@NonNull android.content.Context);
     method @FlaggedApi("com.android.hardware.input.keyboard_a11y_sticky_keys_flag") public static boolean isAccessibilityStickyKeysEnabled(@NonNull android.content.Context);
+    method @FlaggedApi("com.android.input.flags.keyboard_repeat_keys") public static boolean isRepeatKeysEnabled(@NonNull android.content.Context);
     method @FlaggedApi("com.android.hardware.input.keyboard_a11y_bounce_keys_flag") @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void setAccessibilityBounceKeysThreshold(@NonNull android.content.Context, int);
     method @FlaggedApi("com.android.hardware.input.keyboard_a11y_mouse_keys") @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void setAccessibilityMouseKeysEnabled(@NonNull android.content.Context, boolean);
-    method @FlaggedApi("com.android.hardware.input.keyboard_repeat_keys") @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void setAccessibilityRepeatKeysDelay(@NonNull android.content.Context, int);
-    method @FlaggedApi("com.android.hardware.input.keyboard_repeat_keys") @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void setAccessibilityRepeatKeysTimeout(@NonNull android.content.Context, int);
     method @FlaggedApi("com.android.hardware.input.keyboard_a11y_slow_keys_flag") @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void setAccessibilitySlowKeysThreshold(@NonNull android.content.Context, int);
     method @FlaggedApi("com.android.hardware.input.keyboard_a11y_sticky_keys_flag") @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void setAccessibilityStickyKeysEnabled(@NonNull android.content.Context, boolean);
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void setMaximumObscuringOpacityForTouch(@NonNull android.content.Context, @FloatRange(from=0, to=1) float);
+    method @FlaggedApi("com.android.input.flags.keyboard_repeat_keys") @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void setRepeatKeysDelay(@NonNull android.content.Context, int);
+    method @FlaggedApi("com.android.input.flags.keyboard_repeat_keys") @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void setRepeatKeysEnabled(@NonNull android.content.Context, boolean);
+    method @FlaggedApi("com.android.input.flags.keyboard_repeat_keys") @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void setRepeatKeysTimeout(@NonNull android.content.Context, int);
     field public static final int DEFAULT_POINTER_SPEED = 0; // 0x0
   }
 
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index 8592ded..177ee6f 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -20,15 +20,15 @@
 import static com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_MOUSE_KEYS;
 import static com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SLOW_KEYS_FLAG;
 import static com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_STICKY_KEYS_FLAG;
-import static com.android.hardware.input.Flags.FLAG_KEYBOARD_REPEAT_KEYS;
 import static com.android.hardware.input.Flags.keyboardA11yBounceKeysFlag;
 import static com.android.hardware.input.Flags.keyboardA11ySlowKeysFlag;
 import static com.android.hardware.input.Flags.keyboardA11yStickyKeysFlag;
 import static com.android.hardware.input.Flags.keyboardA11yMouseKeys;
-import static com.android.hardware.input.Flags.keyboardRepeatKeys;
 import static com.android.hardware.input.Flags.touchpadTapDragging;
 import static com.android.hardware.input.Flags.touchpadVisualizer;
 import static com.android.input.flags.Flags.enableInputFilterRustImpl;
+import static com.android.input.flags.Flags.FLAG_KEYBOARD_REPEAT_KEYS;
+import static com.android.input.flags.Flags.keyboardRepeatKeys;
 
 import android.Manifest;
 import android.annotation.FlaggedApi;
@@ -800,7 +800,7 @@
      *
      * <p>
      * ‘Repeat keys’ is a feature which allows users to generate key repeats when a particular
-     * key on the physical keyboard is held down. This accessibility feature allows the user
+     * key on the physical keyboard is held down. This feature allows the user
      * to configure the timeout before the key repeats begin as well as the delay
      * between successive key repeats.
      * </p>
@@ -812,7 +812,31 @@
     }
 
     /**
-     * Get Accessibility repeat keys timeout duration in milliseconds.
+     * Whether "Repeat keys" feature is enabled.
+     * Repeat keys is ON by default.
+     * The repeat keys timeout and delay would have the default values in the default ON case.
+     *
+     * <p>
+     * 'Repeat keys’ is a feature which allows users to generate key repeats when a particular
+     * key on the physical keyboard is held down. This feature allows the user
+     * to configure the timeout before the key repeats begin as well as the delay
+     * between successive key repeats.
+     * </p>
+     *
+     * @hide
+     */
+    @TestApi
+    @FlaggedApi(FLAG_KEYBOARD_REPEAT_KEYS)
+    public static boolean isRepeatKeysEnabled(@NonNull Context context) {
+        if (!isRepeatKeysFeatureFlagEnabled()) {
+            return true;
+        }
+        return Settings.Secure.getIntForUser(context.getContentResolver(),
+                Settings.Secure.KEY_REPEAT_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
+    }
+
+    /**
+     * Get repeat keys timeout duration in milliseconds.
      * The default key repeat timeout is {@link ViewConfiguration#DEFAULT_KEY_REPEAT_TIMEOUT_MS}.
      *
      * @param context The application context
@@ -823,7 +847,7 @@
      *
      * <p>
      * ‘Repeat keys’ is a feature which allows users to generate key repeats when a particular
-     * key on the physical keyboard is held down. This accessibility feature allows the user
+     * key on the physical keyboard is held down. This feature allows the user
      * to configure the timeout before the key repeats begin as well as the delay
      * between successive key repeats.
      * </p>
@@ -832,14 +856,17 @@
      */
     @TestApi
     @FlaggedApi(FLAG_KEYBOARD_REPEAT_KEYS)
-    public static int getAccessibilityRepeatKeysTimeout(@NonNull Context context) {
+    public static int getRepeatKeysTimeout(@NonNull Context context) {
+        if (!isRepeatKeysFeatureFlagEnabled()) {
+            return ViewConfiguration.getKeyRepeatTimeout();
+        }
         return Settings.Secure.getIntForUser(context.getContentResolver(),
                 Settings.Secure.KEY_REPEAT_TIMEOUT_MS, ViewConfiguration.getKeyRepeatTimeout(),
                 UserHandle.USER_CURRENT);
     }
 
     /**
-     * Get Accessibility repeat keys delay rate in milliseconds.
+     * Get repeat keys delay rate in milliseconds.
      * The default key repeat delay is {@link ViewConfiguration#DEFAULT_KEY_REPEAT_DELAY_MS}.
      *
      * @param context The application context
@@ -850,7 +877,7 @@
      *
      * <p>
      * ‘Repeat keys’ is a feature which allows users to generate key repeats when a particular
-     * key on the physical keyboard is held down. This accessibility feature allows the user
+     * key on the physical keyboard is held down. This feature allows the user
      * to configure the timeout before the key repeats begin as well as the delay
      * between successive key repeats.
      * </p>
@@ -859,14 +886,41 @@
      */
     @TestApi
     @FlaggedApi(FLAG_KEYBOARD_REPEAT_KEYS)
-    public static int getAccessibilityRepeatKeysDelay(@NonNull Context context) {
+    public static int getRepeatKeysDelay(@NonNull Context context) {
+        if (!isRepeatKeysFeatureFlagEnabled()) {
+            return ViewConfiguration.getKeyRepeatDelay();
+        }
         return Settings.Secure.getIntForUser(context.getContentResolver(),
                 Settings.Secure.KEY_REPEAT_DELAY_MS, ViewConfiguration.getKeyRepeatDelay(),
                 UserHandle.USER_CURRENT);
     }
 
     /**
-     * Set Accessibility repeat keys timeout duration in milliseconds.
+     * Set repeat keys feature enabled/disabled.
+     *
+     * <p>
+     * 'Repeat keys’ is a feature which allows users to generate key repeats when a particular
+     * key on the physical keyboard is held down. This feature allows the user
+     * to configure the timeout before the key repeats begin as well as the delay
+     * between successive key repeats.
+     * </p>
+     *
+     * @hide
+     */
+    @TestApi
+    @FlaggedApi(FLAG_KEYBOARD_REPEAT_KEYS)
+    @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
+    public static void setRepeatKeysEnabled(@NonNull Context context,
+            boolean enabled) {
+        if (!isRepeatKeysFeatureFlagEnabled()) {
+            return;
+        }
+        Settings.Secure.putIntForUser(context.getContentResolver(),
+                Settings.Secure.KEY_REPEAT_ENABLED, enabled ? 1 : 0, UserHandle.USER_CURRENT);
+    }
+
+    /**
+     * Set repeat keys timeout duration in milliseconds.
      *
      * @param timeoutTimeMillis time duration for which a key should be pressed after which the
      *                          pressed key will be repeated. The timeout must be between
@@ -875,7 +929,7 @@
      *
      *  <p>
      * ‘Repeat keys’ is a feature which allows users to generate key repeats when a particular
-     * key on the physical keyboard is held down. This accessibility feature allows the user
+     * key on the physical keyboard is held down. This feature allows the user
      * to configure the timeout before the key repeats begin as well as the delay
      *  between successive key repeats.
      * </p>
@@ -885,8 +939,12 @@
     @TestApi
     @FlaggedApi(FLAG_KEYBOARD_REPEAT_KEYS)
     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
-    public static void setAccessibilityRepeatKeysTimeout(@NonNull Context context,
+    public static void setRepeatKeysTimeout(@NonNull Context context,
             int timeoutTimeMillis) {
+        if (!isRepeatKeysFeatureFlagEnabled()
+                && !isRepeatKeysEnabled(context)) {
+            return;
+        }
         if (timeoutTimeMillis < MIN_KEY_REPEAT_TIMEOUT_MILLIS
                 || timeoutTimeMillis > MAX_KEY_REPEAT_TIMEOUT_MILLIS) {
             throw new IllegalArgumentException(
@@ -900,7 +958,7 @@
     }
 
     /**
-     * Set Accessibility repeat key delay duration in milliseconds.
+     * Set repeat key delay duration in milliseconds.
      *
      * @param delayTimeMillis Time duration between successive key repeats when a key is
      *                        pressed down. The delay duration must be between
@@ -908,7 +966,7 @@
      *                        {@link #MAX_KEY_REPEAT_DELAY_MILLIS}
      * <p>
      * ‘Repeat keys’ is a feature which allows users to generate key repeats when a particular
-     * key on the physical keyboard is held down. This accessibility feature allows the user
+     * key on the physical keyboard is held down. This feature allows the user
      * to configure the timeout before the key repeats begin as well as the delay
      * between successive key repeats.
      * </p>
@@ -918,8 +976,12 @@
     @TestApi
     @FlaggedApi(FLAG_KEYBOARD_REPEAT_KEYS)
     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
-    public static void setAccessibilityRepeatKeysDelay(@NonNull Context context,
+    public static void setRepeatKeysDelay(@NonNull Context context,
             int delayTimeMillis) {
+        if (!isRepeatKeysFeatureFlagEnabled()
+                && !isRepeatKeysEnabled(context)) {
+            return;
+        }
         if (delayTimeMillis < MIN_KEY_REPEAT_DELAY_MILLIS
                 || delayTimeMillis > MAX_KEY_REPEAT_DELAY_MILLIS) {
             throw new IllegalArgumentException(
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0ada993..b8a8be1 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9158,15 +9158,27 @@
         public static final String MULTI_PRESS_TIMEOUT = "multi_press_timeout";
 
         /**
+         * Whether to enable key repeats for Physical Keyboard.
+         *
+         * If set to false, continuous key presses on
+         * physical keyboard will not cause the pressed key to repeated.
+         * @hide
+         */
+        @Readable
+        public static final String KEY_REPEAT_ENABLED = "key_repeat_enabled";
+
+        /**
          * The duration before a key repeat begins in milliseconds.
          * @hide
          */
+        @Readable
         public static final String KEY_REPEAT_TIMEOUT_MS = "key_repeat_timeout";
 
         /**
          * The duration between successive key repeats in milliseconds.
          * @hide
          */
+        @Readable
         public static final String KEY_REPEAT_DELAY_MS = "key_repeat_delay";
 
         /**
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index cb7c226..606e829 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -401,6 +401,7 @@
     optional SettingProto long_press_timeout = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto key_press_timeout_ms = 96 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto key_press_delay_ms = 97 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto key_repeat_enabled = 102 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
     message ManagedProfile {
         option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -735,5 +736,5 @@
 
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 102;
+    // Next tag = 103;
 }
diff --git a/location/java/android/location/flags/location.aconfig b/location/java/android/location/flags/location.aconfig
index cddc337..c3cb492 100644
--- a/location/java/android/location/flags/location.aconfig
+++ b/location/java/android/location/flags/location.aconfig
@@ -94,6 +94,16 @@
 }
 
 flag {
+    name: "use_legacy_ntp_time"
+    namespace: "location"
+    description: "Flag for switching to legacy NtpNetworkTimeHelper"
+    bug: "368034558"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
     name: "subscriptions_changed_listener_thread"
     namespace: "location"
     description: "Flag for running onSubscriptionsChangedListener on FgThread"
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InputMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InputMediaDevice.java
index 766cd43..9dd2dbb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InputMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InputMediaDevice.java
@@ -80,6 +80,10 @@
                 context, id, audioDeviceInfoType, maxVolume, currentVolume, isVolumeFixed);
     }
 
+    public @AudioDeviceType int getAudioDeviceInfoType() {
+        return mAudioDeviceInfoType;
+    }
+
     public static boolean isSupportedInputDevice(@AudioDeviceType int audioDeviceInfoType) {
         return switch (audioDeviceInfoType) {
             case TYPE_BUILTIN_MIC,
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java
index 874e030..0c50166 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java
@@ -15,13 +15,20 @@
  */
 package com.android.settingslib.media;
 
+import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_SELECTED;
+
 import android.content.Context;
+import android.media.AudioAttributes;
+import android.media.AudioDeviceAttributes;
 import android.media.AudioDeviceCallback;
 import android.media.AudioDeviceInfo;
 import android.media.AudioManager;
+import android.media.MediaRecorder;
 import android.os.Handler;
+import android.util.Slog;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -35,12 +42,18 @@
 
     private static final String TAG = "InputRouteManager";
 
+    @VisibleForTesting
+    static final AudioAttributes INPUT_ATTRIBUTES =
+            new AudioAttributes.Builder().setCapturePreset(MediaRecorder.AudioSource.MIC).build();
+
     private final Context mContext;
 
     private final AudioManager mAudioManager;
 
     @VisibleForTesting final List<MediaDevice> mInputMediaDevices = new CopyOnWriteArrayList<>();
 
+    private MediaDevice mSelectedInputDevice;
+
     private final Collection<InputDeviceCallback> mCallbacks = new CopyOnWriteArrayList<>();
 
     @VisibleForTesting
@@ -76,8 +89,27 @@
         mCallbacks.remove(callback);
     }
 
+    public @Nullable MediaDevice getSelectedInputDevice() {
+        return mSelectedInputDevice;
+    }
+
     private void dispatchInputDeviceListUpdate() {
-        // TODO (b/360175574): Get selected input device.
+        // Get selected input device.
+        List<AudioDeviceAttributes> attributesOfSelectedInputDevices =
+                mAudioManager.getDevicesForAttributes(INPUT_ATTRIBUTES);
+        int selectedInputDeviceAttributesType;
+        if (attributesOfSelectedInputDevices.isEmpty()) {
+            Slog.e(TAG, "Unexpected empty list of input devices. Using built-in mic.");
+            selectedInputDeviceAttributesType = AudioDeviceInfo.TYPE_BUILTIN_MIC;
+        } else {
+            if (attributesOfSelectedInputDevices.size() > 1) {
+                Slog.w(
+                        TAG,
+                        "AudioManager.getDevicesForAttributes returned more than one element."
+                                + " Using the first one.");
+            }
+            selectedInputDeviceAttributesType = attributesOfSelectedInputDevices.get(0).getType();
+        }
 
         // Get all input devices.
         AudioDeviceInfo[] audioDeviceInfos =
@@ -93,6 +125,10 @@
                             getCurrentInputGain(),
                             isInputGainFixed());
             if (mediaDevice != null) {
+                if (info.getType() == selectedInputDeviceAttributesType) {
+                    mediaDevice.setState(STATE_SELECTED);
+                    mSelectedInputDevice = mediaDevice;
+                }
                 mInputMediaDevices.add(mediaDevice);
             }
         }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java
index 2501ae6..8a18d07 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settingslib.media;
 
+import static com.android.settingslib.media.InputRouteManager.INPUT_ATTRIBUTES;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.mock;
@@ -23,6 +25,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.media.AudioDeviceAttributes;
 import android.media.AudioDeviceInfo;
 import android.media.AudioManager;
 
@@ -36,6 +39,10 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {ShadowRouter2Manager.class})
 public class InputRouteManagerTest {
@@ -124,6 +131,97 @@
     }
 
     @Test
+    public void getSelectedInputDevice_returnOneFromAudioManager() {
+        final AudioDeviceInfo info1 = mock(AudioDeviceInfo.class);
+        when(info1.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET);
+        when(info1.getId()).thenReturn(INPUT_WIRED_HEADSET_ID);
+
+        final AudioDeviceInfo info2 = mock(AudioDeviceInfo.class);
+        when(info2.getType()).thenReturn(AudioDeviceInfo.TYPE_BUILTIN_MIC);
+        when(info2.getId()).thenReturn(BUILTIN_MIC_ID);
+
+        final AudioManager audioManager = mock(AudioManager.class);
+        AudioDeviceInfo[] devices = {info1, info2};
+        when(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn(devices);
+
+        // Mock audioManager.getDevicesForAttributes returns exactly one audioDeviceAttributes.
+        AudioDeviceAttributes audioDeviceAttributes = new AudioDeviceAttributes(info1);
+        when(audioManager.getDevicesForAttributes(INPUT_ATTRIBUTES))
+                .thenReturn(Collections.singletonList(audioDeviceAttributes));
+
+        InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager);
+        inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices);
+
+        // The selected input device has the same type as the one returned from AudioManager.
+        InputMediaDevice selectedInputDevice =
+                (InputMediaDevice) inputRouteManager.getSelectedInputDevice();
+        assertThat(selectedInputDevice.getAudioDeviceInfoType())
+                .isEqualTo(AudioDeviceInfo.TYPE_WIRED_HEADSET);
+    }
+
+    @Test
+    public void getSelectedInputDevice_returnMoreThanOneFromAudioManager() {
+        final AudioDeviceInfo info1 = mock(AudioDeviceInfo.class);
+        when(info1.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET);
+        when(info1.getId()).thenReturn(INPUT_WIRED_HEADSET_ID);
+
+        final AudioDeviceInfo info2 = mock(AudioDeviceInfo.class);
+        when(info2.getType()).thenReturn(AudioDeviceInfo.TYPE_BUILTIN_MIC);
+        when(info2.getId()).thenReturn(BUILTIN_MIC_ID);
+
+        final AudioManager audioManager = mock(AudioManager.class);
+        AudioDeviceInfo[] devices = {info1, info2};
+        when(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn(devices);
+
+        // Mock audioManager.getDevicesForAttributes returns more than one audioDeviceAttributes.
+        AudioDeviceAttributes audioDeviceAttributes1 = new AudioDeviceAttributes(info1);
+        AudioDeviceAttributes audioDeviceAttributes2 = new AudioDeviceAttributes(info2);
+        List<AudioDeviceAttributes> attributesOfSelectedInputDevices = new ArrayList<>();
+        attributesOfSelectedInputDevices.add(audioDeviceAttributes1);
+        attributesOfSelectedInputDevices.add(audioDeviceAttributes2);
+        when(audioManager.getDevicesForAttributes(INPUT_ATTRIBUTES))
+                .thenReturn(attributesOfSelectedInputDevices);
+
+        InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager);
+        inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices);
+
+        // The selected input device has the same type as the first one returned from AudioManager.
+        InputMediaDevice selectedInputDevice =
+                (InputMediaDevice) inputRouteManager.getSelectedInputDevice();
+        assertThat(selectedInputDevice.getAudioDeviceInfoType())
+                .isEqualTo(AudioDeviceInfo.TYPE_WIRED_HEADSET);
+    }
+
+    @Test
+    public void getSelectedInputDevice_returnEmptyFromAudioManager() {
+        final AudioDeviceInfo info1 = mock(AudioDeviceInfo.class);
+        when(info1.getType()).thenReturn(AudioDeviceInfo.TYPE_WIRED_HEADSET);
+        when(info1.getId()).thenReturn(INPUT_WIRED_HEADSET_ID);
+
+        final AudioDeviceInfo info2 = mock(AudioDeviceInfo.class);
+        when(info2.getType()).thenReturn(AudioDeviceInfo.TYPE_BUILTIN_MIC);
+        when(info2.getId()).thenReturn(BUILTIN_MIC_ID);
+
+        final AudioManager audioManager = mock(AudioManager.class);
+        AudioDeviceInfo[] devices = {info1, info2};
+        when(audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn(devices);
+
+        // Mock audioManager.getDevicesForAttributes returns empty list of audioDeviceAttributes.
+        List<AudioDeviceAttributes> attributesOfSelectedInputDevices = new ArrayList<>();
+        when(audioManager.getDevicesForAttributes(INPUT_ATTRIBUTES))
+                .thenReturn(attributesOfSelectedInputDevices);
+
+        InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager);
+        inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices);
+
+        // The selected input device has default type AudioDeviceInfo.TYPE_BUILTIN_MIC.
+        InputMediaDevice selectedInputDevice =
+                (InputMediaDevice) inputRouteManager.getSelectedInputDevice();
+        assertThat(selectedInputDevice.getAudioDeviceInfoType())
+                .isEqualTo(AudioDeviceInfo.TYPE_BUILTIN_MIC);
+    }
+
+    @Test
     public void getMaxInputGain_returnMaxInputGain() {
         assertThat(mInputRouteManager.getMaxInputGain()).isEqualTo(15);
     }
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 40a8199..d710939 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -86,6 +86,7 @@
         Settings.Secure.DOUBLE_TAP_TO_WAKE,
         Settings.Secure.WAKE_GESTURE_ENABLED,
         Settings.Secure.LONG_PRESS_TIMEOUT,
+        Settings.Secure.KEY_REPEAT_ENABLED,
         Settings.Secure.KEY_REPEAT_TIMEOUT_MS,
         Settings.Secure.KEY_REPEAT_DELAY_MS,
         Settings.Secure.CAMERA_GESTURE_DISABLED,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 3b9c683..fa16a44 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -133,6 +133,7 @@
         VALIDATORS.put(Secure.DOUBLE_TAP_TO_WAKE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.WAKE_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.LONG_PRESS_TIMEOUT, NON_NEGATIVE_INTEGER_VALIDATOR);
+        VALIDATORS.put(Secure.KEY_REPEAT_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.KEY_REPEAT_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR);
         VALIDATORS.put(Secure.KEY_REPEAT_DELAY_MS, NON_NEGATIVE_INTEGER_VALIDATOR);
         VALIDATORS.put(Secure.CAMERA_GESTURE_DISABLED, BOOLEAN_VALIDATOR);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSwitchingController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSwitchingController.java
index 2cbc7575..f7b7353 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSwitchingController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSwitchingController.java
@@ -157,7 +157,7 @@
     @VisibleForTesting
     boolean mNeedRefresh = false;
     private MediaController mMediaController;
-    private InputRouteManager mInputRouteManager;
+    @VisibleForTesting InputRouteManager mInputRouteManager;
     @VisibleForTesting
     Callback mCallback;
     @VisibleForTesting
@@ -927,7 +927,18 @@
     }
 
     public List<MediaDevice> getSelectedMediaDevice() {
-        return mLocalMediaManager.getSelectedMediaDevice();
+        if (!enableInputRouting()) {
+            return mLocalMediaManager.getSelectedMediaDevice();
+        }
+
+        // Add selected input device if input routing is supported.
+        List<MediaDevice> selectedDevices =
+                new ArrayList<>(mLocalMediaManager.getSelectedMediaDevice());
+        MediaDevice selectedInputDevice = mInputRouteManager.getSelectedInputDevice();
+        if (selectedInputDevice != null) {
+            selectedDevices.add(selectedInputDevice);
+        }
+        return selectedDevices;
     }
 
     List<MediaDevice> getDeselectableMediaDevice() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaSwitchingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaSwitchingControllerTest.java
index d3e20c6..53f0800 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaSwitchingControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaSwitchingControllerTest.java
@@ -73,6 +73,7 @@
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.media.InputMediaDevice;
+import com.android.settingslib.media.InputRouteManager;
 import com.android.settingslib.media.LocalMediaManager;
 import com.android.settingslib.media.MediaDevice;
 import com.android.systemui.SysuiTestCase;
@@ -100,6 +101,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 @SmallTest
@@ -115,6 +117,10 @@
     private static final String TEST_SONG = "test_song";
     private static final String TEST_SESSION_ID = "test_session_id";
     private static final String TEST_SESSION_NAME = "test_session_name";
+    private static final int MAX_VOLUME = 1;
+    private static final int CURRENT_VOLUME = 0;
+    private static final boolean VOLUME_FIXED_TRUE = true;
+
     @Mock
     private DialogTransitionAnimator mDialogTransitionAnimator;
     @Mock
@@ -181,6 +187,7 @@
     private String mPackageName = null;
     private MediaSwitchingController mMediaSwitchingController;
     private LocalMediaManager mLocalMediaManager;
+    private InputRouteManager mInputRouteManager;
     private List<MediaController> mMediaControllers = new ArrayList<>();
     private List<MediaDevice> mMediaDevices = new ArrayList<>();
     private List<NearbyDevice> mNearbyDevices = new ArrayList<>();
@@ -228,6 +235,10 @@
         mLocalMediaManager = spy(mMediaSwitchingController.mLocalMediaManager);
         when(mLocalMediaManager.isPreferenceRouteListingExist()).thenReturn(false);
         mMediaSwitchingController.mLocalMediaManager = mLocalMediaManager;
+        mMediaSwitchingController.mInputRouteManager =
+                new InputRouteManager(mContext, mAudioManager);
+        mInputRouteManager = spy(mMediaSwitchingController.mInputRouteManager);
+        mMediaSwitchingController.mInputRouteManager = mInputRouteManager;
         MediaDescription.Builder builder = new MediaDescription.Builder();
         builder.setTitle(TEST_SONG);
         builder.setSubtitle(TEST_ARTIST);
@@ -545,9 +556,6 @@
         // Output devices have changed.
         mMediaSwitchingController.onDeviceListUpdate(mMediaDevices);
 
-        final int MAX_VOLUME = 1;
-        final int CURRENT_VOLUME = 0;
-        final boolean IS_VOLUME_FIXED = true;
         final MediaDevice mediaDevice3 =
                 InputMediaDevice.create(
                         mContext,
@@ -555,7 +563,7 @@
                         AudioDeviceInfo.TYPE_BUILTIN_MIC,
                         MAX_VOLUME,
                         CURRENT_VOLUME,
-                        IS_VOLUME_FIXED);
+                        VOLUME_FIXED_TRUE);
         final MediaDevice mediaDevice4 =
                 InputMediaDevice.create(
                         mContext,
@@ -563,7 +571,7 @@
                         AudioDeviceInfo.TYPE_WIRED_HEADSET,
                         MAX_VOLUME,
                         CURRENT_VOLUME,
-                        IS_VOLUME_FIXED);
+                        VOLUME_FIXED_TRUE);
         final List<MediaDevice> inputDevices = new ArrayList<>();
         inputDevices.add(mediaDevice3);
         inputDevices.add(mediaDevice4);
@@ -1312,4 +1320,23 @@
 
         verify(mCallback).dismissDialog();
     }
+
+    @EnableFlags(Flags.FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL)
+    @Test
+    public void getSelectedMediaDevice() {
+        // Mock MediaDevice since none of the output media device constructor is publicly available
+        // outside of SettingsLib package.
+        final MediaDevice selectedOutputMediaDevice = mock(MediaDevice.class);
+        doReturn(Collections.singletonList(selectedOutputMediaDevice))
+                .when(mLocalMediaManager)
+                .getSelectedMediaDevice();
+
+        // Mock selected input media device.
+        final MediaDevice selectedInputMediaDevice = mock(MediaDevice.class);
+        doReturn(selectedInputMediaDevice).when(mInputRouteManager).getSelectedInputDevice();
+
+        List<MediaDevice> selectedMediaDevices = mMediaSwitchingController.getSelectedMediaDevice();
+        assertThat(selectedMediaDevices)
+                .containsExactly(selectedOutputMediaDevice, selectedInputMediaDevice);
+    }
 }
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 6bb56c9..e885c14 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -79,6 +79,7 @@
         sSecureSettingToTypeMap.put(Settings.Secure.MULTI_PRESS_TIMEOUT, int.class);
         sSecureSettingToTypeMap.put(Settings.Secure.KEY_REPEAT_TIMEOUT_MS, int.class);
         sSecureSettingToTypeMap.put(Settings.Secure.KEY_REPEAT_DELAY_MS, int.class);
+        sSecureSettingToTypeMap.put(Settings.Secure.KEY_REPEAT_ENABLED, int.class);
         sSecureSettingToTypeMap.put(Settings.Secure.STYLUS_POINTER_ICON_ENABLED, int.class);
         // add other secure settings here...
 
diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java
index 835fb72..d70bd8b 100644
--- a/services/core/java/com/android/server/input/InputSettingsObserver.java
+++ b/services/core/java/com/android/server/input/InputSettingsObserver.java
@@ -94,6 +94,8 @@
                         (reason) -> updateKeyRepeatInfo()),
                 Map.entry(Settings.Secure.getUriFor(Settings.Secure.KEY_REPEAT_DELAY_MS),
                         (reason) -> updateKeyRepeatInfo()),
+                Map.entry(Settings.Secure.getUriFor(Settings.Secure.KEY_REPEAT_ENABLED),
+                        (reason) -> updateKeyRepeatInfo()),
                 Map.entry(Settings.System.getUriFor(Settings.System.SHOW_ROTARY_INPUT),
                         (reason) -> updateShowRotaryInput()),
                 Map.entry(Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS),
@@ -230,6 +232,11 @@
     }
 
     private void updateKeyRepeatInfo() {
+        // Key repeat is enabled by default
+        final boolean keyRepeatEnabled = Settings.Secure.getIntForUser(
+                mContext.getContentResolver(), Settings.Secure.KEY_REPEAT_ENABLED, 1,
+                UserHandle.USER_CURRENT) != 0;
+
         // Use ViewConfiguration getters only as fallbacks because they may return stale values.
         final int timeoutMs = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                 Settings.Secure.KEY_REPEAT_TIMEOUT_MS, ViewConfiguration.getKeyRepeatTimeout(),
@@ -237,7 +244,7 @@
         final int delayMs = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                 Settings.Secure.KEY_REPEAT_DELAY_MS, ViewConfiguration.getKeyRepeatDelay(),
                 UserHandle.USER_CURRENT);
-        mNative.setKeyRepeatConfiguration(timeoutMs, delayMs);
+        mNative.setKeyRepeatConfiguration(timeoutMs, delayMs, keyRepeatEnabled);
     }
 
     private void updateMaximumObscuringOpacityForTouch() {
diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java
index 1e7c97f9..5dd461d 100644
--- a/services/core/java/com/android/server/input/NativeInputManagerService.java
+++ b/services/core/java/com/android/server/input/NativeInputManagerService.java
@@ -212,7 +212,7 @@
 
     void setMotionClassifierEnabled(boolean enabled);
 
-    void setKeyRepeatConfiguration(int timeoutMs, int delayMs);
+    void setKeyRepeatConfiguration(int timeoutMs, int delayMs, boolean keyRepeatEnabled);
 
     InputSensorInfo[] getSensorList(int deviceId);
 
@@ -509,7 +509,8 @@
         public native void setMotionClassifierEnabled(boolean enabled);
 
         @Override
-        public native void setKeyRepeatConfiguration(int timeoutMs, int delayMs);
+        public native void setKeyRepeatConfiguration(int timeoutMs, int delayMs,
+                boolean keyRepeatEnabled);
 
         @Override
         public native InputSensorInfo[] getSensorList(int deviceId);
diff --git a/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java b/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java
index 01c108b..494ea77 100644
--- a/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java
+++ b/services/core/java/com/android/server/location/gnss/NetworkTimeHelper.java
@@ -19,6 +19,7 @@
 import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
 import android.content.Context;
+import android.location.flags.Flags;
 import android.os.Looper;
 
 import java.io.PrintWriter;
@@ -55,7 +56,7 @@
     static NetworkTimeHelper create(
             @NonNull Context context, @NonNull Looper looper,
             @NonNull InjectTimeCallback injectTimeCallback) {
-        if (USE_TIME_DETECTOR_IMPL) {
+        if (!Flags.useLegacyNtpTime()) {
             TimeDetectorNetworkTimeHelper.Environment environment =
                     new TimeDetectorNetworkTimeHelper.EnvironmentImpl(looper);
             return new TimeDetectorNetworkTimeHelper(environment, injectTimeCallback);
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 155e73c..d2493c5 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -2725,12 +2725,13 @@
 }
 
 static void nativeSetKeyRepeatConfiguration(JNIEnv* env, jobject nativeImplObj, jint timeoutMs,
-                                            jint delayMs) {
+                                            jint delayMs, jboolean keyRepeatEnabled) {
     NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
     im->getInputManager()->getDispatcher().setKeyRepeatConfiguration(std::chrono::milliseconds(
                                                                              timeoutMs),
                                                                      std::chrono::milliseconds(
-                                                                             delayMs));
+                                                                             delayMs),
+                                                                     keyRepeatEnabled);
 }
 
 static jobject createInputSensorInfo(JNIEnv* env, jstring name, jstring vendor, jint version,
@@ -3029,7 +3030,7 @@
         {"setDisplayEligibilityForPointerCapture", "(IZ)V",
          (void*)nativeSetDisplayEligibilityForPointerCapture},
         {"setMotionClassifierEnabled", "(Z)V", (void*)nativeSetMotionClassifierEnabled},
-        {"setKeyRepeatConfiguration", "(II)V", (void*)nativeSetKeyRepeatConfiguration},
+        {"setKeyRepeatConfiguration", "(IIZ)V", (void*)nativeSetKeyRepeatConfiguration},
         {"getSensorList", "(I)[Landroid/hardware/input/InputSensorInfo;",
          (void*)nativeGetSensorList},
         {"getTouchpadHardwareProperties",
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 96ddf80..b8f9767 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2815,7 +2815,8 @@
     }
 
     @Test
-    @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
+    @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING,
+            android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST})
     public void testOnlyForceGroupIfNeeded_newNotification_notAutogrouped() {
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
         when(mGroupHelper.onNotificationPosted(any(), anyBoolean())).thenReturn(false);
@@ -2834,7 +2835,8 @@
     }
 
     @Test
-    @EnableFlags(FLAG_NOTIFICATION_FORCE_GROUPING)
+    @EnableFlags({FLAG_NOTIFICATION_FORCE_GROUPING,
+            android.app.Flags.FLAG_CHECK_AUTOGROUP_BEFORE_POST})
     public void testOnlyForceGroupIfNeeded_newNotification_wasAutogrouped() {
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false);
         when(mGroupHelper.onNotificationPosted(any(), anyBoolean())).thenReturn(true);
diff --git a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
index 2a82d5f..351ec463 100644
--- a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
+++ b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
@@ -212,9 +212,10 @@
         verify(native).setMotionClassifierEnabled(anyBoolean())
         verify(native).setMaximumObscuringOpacityForTouch(anyFloat())
         verify(native).setStylusPointerIconEnabled(anyBoolean())
-        // Called twice at boot, since there are individual callbacks to update the
-        // key repeat timeout and the key repeat delay.
-        verify(native, times(2)).setKeyRepeatConfiguration(anyInt(), anyInt())
+        // Called thrice at boot, since there are individual callbacks to update the
+        // key repeat timeout, the key repeat delay and whether key repeat enabled.
+        verify(native, times(3)).setKeyRepeatConfiguration(anyInt(), anyInt(),
+            anyBoolean())
     }
 
     @Test