Support bounce and slow keys for internal Alphabetic keyboards

Test: atest --host libinputflinger_rs_test
Bug: 294546335
Flag: EXEMPT bugfix
Change-Id: I590e9494f1bab562ac2b3c085781f05f2c250314
diff --git a/libs/input/rust/lib.rs b/libs/input/rust/lib.rs
index 008f675..9b6fe3c 100644
--- a/libs/input/rust/lib.rs
+++ b/libs/input/rust/lib.rs
@@ -24,7 +24,8 @@
 
 pub use data_store::{DataStore, DefaultFileReaderWriter};
 pub use input::{
-    DeviceClass, DeviceId, InputDevice, ModifierState, MotionAction, MotionFlags, Source,
+    DeviceClass, DeviceId, InputDevice, KeyboardType, ModifierState, MotionAction, MotionFlags,
+    Source,
 };
 pub use input_verifier::InputVerifier;
 pub use keyboard_classifier::KeyboardClassifier;
diff --git a/services/inputflinger/InputFilter.cpp b/services/inputflinger/InputFilter.cpp
index e4d73fc..2d5803b 100644
--- a/services/inputflinger/InputFilter.cpp
+++ b/services/inputflinger/InputFilter.cpp
@@ -60,6 +60,7 @@
         AidlDeviceInfo& aidlInfo = mDeviceInfos.emplace_back();
         aidlInfo.deviceId = info.getId();
         aidlInfo.external = info.isExternal();
+        aidlInfo.keyboardType = info.getKeyboardType();
     }
     if (isFilterEnabled()) {
         LOG_ALWAYS_FATAL_IF(!mInputFilterRust->notifyInputDevicesChanged(mDeviceInfos).isOk());
diff --git a/services/inputflinger/aidl/com/android/server/inputflinger/DeviceInfo.aidl b/services/inputflinger/aidl/com/android/server/inputflinger/DeviceInfo.aidl
index b9e6a03..5b0b9ac 100644
--- a/services/inputflinger/aidl/com/android/server/inputflinger/DeviceInfo.aidl
+++ b/services/inputflinger/aidl/com/android/server/inputflinger/DeviceInfo.aidl
@@ -23,4 +23,5 @@
 parcelable DeviceInfo {
     int deviceId;
     boolean external;
+    int keyboardType;
 }
\ No newline at end of file
diff --git a/services/inputflinger/rust/bounce_keys_filter.rs b/services/inputflinger/rust/bounce_keys_filter.rs
index 2d5039a..dc4f1df 100644
--- a/services/inputflinger/rust/bounce_keys_filter.rs
+++ b/services/inputflinger/rust/bounce_keys_filter.rs
@@ -17,12 +17,13 @@
 //! Bounce keys input filter implementation.
 //! Bounce keys is an accessibility feature to aid users who have physical disabilities, that
 //! allows the user to configure the device to ignore rapid, repeated key presses of the same key.
-use crate::input_filter::Filter;
+use crate::input_filter::{Filter, VIRTUAL_KEYBOARD_DEVICE_ID};
 
 use android_hardware_input_common::aidl::android::hardware::input::common::Source::Source;
 use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
     DeviceInfo::DeviceInfo, KeyEvent::KeyEvent, KeyEventAction::KeyEventAction,
 };
+use input::KeyboardType;
 use log::debug;
 use std::collections::{HashMap, HashSet};
 
@@ -42,7 +43,7 @@
     next: Box<dyn Filter + Send + Sync>,
     key_event_map: HashMap<i32, LastUpKeyEvent>,
     blocked_events: Vec<BlockedEvent>,
-    external_devices: HashSet<i32>,
+    supported_devices: HashSet<i32>,
     bounce_key_threshold_ns: i64,
 }
 
@@ -56,7 +57,7 @@
             next,
             key_event_map: HashMap::new(),
             blocked_events: Vec::new(),
-            external_devices: HashSet::new(),
+            supported_devices: HashSet::new(),
             bounce_key_threshold_ns,
         }
     }
@@ -64,7 +65,7 @@
 
 impl Filter for BounceKeysFilter {
     fn notify_key(&mut self, event: &KeyEvent) {
-        if !(self.external_devices.contains(&event.deviceId) && event.source == Source::KEYBOARD) {
+        if !(self.supported_devices.contains(&event.deviceId) && event.source == Source::KEYBOARD) {
             self.next.notify_key(event);
             return;
         }
@@ -110,10 +111,17 @@
         self.blocked_events.retain(|blocked_event| {
             device_infos.iter().any(|x| blocked_event.device_id == x.deviceId)
         });
-        self.external_devices.clear();
+        self.supported_devices.clear();
         for device_info in device_infos {
-            if device_info.external {
-                self.external_devices.insert(device_info.deviceId);
+            if device_info.deviceId == VIRTUAL_KEYBOARD_DEVICE_ID {
+                continue;
+            }
+            if device_info.keyboardType == KeyboardType::None as i32 {
+                continue;
+            }
+            // Support Alphabetic keyboards and Non-alphabetic external keyboards
+            if device_info.external || device_info.keyboardType == KeyboardType::Alphabetic as i32 {
+                self.supported_devices.insert(device_info.deviceId);
             }
         }
         self.next.notify_devices_changed(device_infos);
@@ -127,11 +135,12 @@
 #[cfg(test)]
 mod tests {
     use crate::bounce_keys_filter::BounceKeysFilter;
-    use crate::input_filter::{test_filter::TestFilter, Filter};
+    use crate::input_filter::{test_filter::TestFilter, Filter, VIRTUAL_KEYBOARD_DEVICE_ID};
     use android_hardware_input_common::aidl::android::hardware::input::common::Source::Source;
     use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
         DeviceInfo::DeviceInfo, KeyEvent::KeyEvent, KeyEventAction::KeyEventAction,
     };
+    use input::KeyboardType;
 
     static BASE_KEY_EVENT: KeyEvent = KeyEvent {
         id: 1,
@@ -156,6 +165,7 @@
             Box::new(next.clone()),
             1,   /* device_id */
             100, /* threshold */
+            KeyboardType::Alphabetic,
         );
 
         let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
@@ -181,12 +191,68 @@
     }
 
     #[test]
-    fn test_is_notify_key_doesnt_block_for_internal_keyboard() {
+    fn test_is_notify_key_blocks_for_internal_keyboard() {
+        let mut next = TestFilter::new();
+        let mut filter = setup_filter_with_internal_device(
+            Box::new(next.clone()),
+            1,   /* device_id */
+            100, /* threshold */
+            KeyboardType::Alphabetic,
+        );
+
+        let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
+        filter.notify_key(&event);
+        assert_eq!(next.last_event().unwrap(), event);
+
+        let event = KeyEvent { action: KeyEventAction::UP, ..BASE_KEY_EVENT };
+        filter.notify_key(&event);
+        assert_eq!(next.last_event().unwrap(), event);
+
+        next.clear();
+        let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
+        filter.notify_key(&event);
+        assert!(next.last_event().is_none());
+
+        let event = KeyEvent { eventTime: 100, action: KeyEventAction::UP, ..BASE_KEY_EVENT };
+        filter.notify_key(&event);
+        assert!(next.last_event().is_none());
+
+        let event = KeyEvent { eventTime: 200, action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
+        filter.notify_key(&event);
+        assert_eq!(next.last_event().unwrap(), event);
+    }
+
+    #[test]
+    fn test_is_notify_key_doesnt_block_for_internal_non_alphabetic_keyboard() {
         let next = TestFilter::new();
         let mut filter = setup_filter_with_internal_device(
             Box::new(next.clone()),
             1,   /* device_id */
             100, /* threshold */
+            KeyboardType::NonAlphabetic,
+        );
+
+        let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
+        filter.notify_key(&event);
+        assert_eq!(next.last_event().unwrap(), event);
+
+        let event = KeyEvent { action: KeyEventAction::UP, ..BASE_KEY_EVENT };
+        filter.notify_key(&event);
+        assert_eq!(next.last_event().unwrap(), event);
+
+        let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
+        filter.notify_key(&event);
+        assert_eq!(next.last_event().unwrap(), event);
+    }
+
+    #[test]
+    fn test_is_notify_key_doesnt_block_for_virtual_keyboard() {
+        let next = TestFilter::new();
+        let mut filter = setup_filter_with_internal_device(
+            Box::new(next.clone()),
+            VIRTUAL_KEYBOARD_DEVICE_ID, /* device_id */
+            100,                        /* threshold */
+            KeyboardType::Alphabetic,
         );
 
         let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
@@ -209,6 +275,7 @@
             Box::new(next.clone()),
             1,   /* device_id */
             100, /* threshold */
+            KeyboardType::NonAlphabetic,
         );
 
         let event =
@@ -233,12 +300,60 @@
         let mut filter = setup_filter_with_devices(
             Box::new(next.clone()),
             &[
-                DeviceInfo { deviceId: 1, external: true },
-                DeviceInfo { deviceId: 2, external: true },
+                DeviceInfo {
+                    deviceId: 1,
+                    external: true,
+                    keyboardType: KeyboardType::Alphabetic as i32,
+                },
+                DeviceInfo {
+                    deviceId: 2,
+                    external: true,
+                    keyboardType: KeyboardType::Alphabetic as i32,
+                },
             ],
             100, /* threshold */
         );
 
+        // Bounce key scenario on the external keyboard
+        let event = KeyEvent { deviceId: 1, action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
+        filter.notify_key(&event);
+        assert_eq!(next.last_event().unwrap(), event);
+
+        let event = KeyEvent { deviceId: 1, action: KeyEventAction::UP, ..BASE_KEY_EVENT };
+        filter.notify_key(&event);
+        assert_eq!(next.last_event().unwrap(), event);
+
+        next.clear();
+        let event = KeyEvent { deviceId: 1, action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
+        filter.notify_key(&event);
+        assert!(next.last_event().is_none());
+
+        let event = KeyEvent { deviceId: 2, action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
+        filter.notify_key(&event);
+        assert_eq!(next.last_event().unwrap(), event);
+    }
+
+    #[test]
+    fn test_is_notify_key_for_external_and_internal_alphabetic_keyboards() {
+        let mut next = TestFilter::new();
+        let mut filter = setup_filter_with_devices(
+            Box::new(next.clone()),
+            &[
+                DeviceInfo {
+                    deviceId: 1,
+                    external: false,
+                    keyboardType: KeyboardType::Alphabetic as i32,
+                },
+                DeviceInfo {
+                    deviceId: 2,
+                    external: true,
+                    keyboardType: KeyboardType::Alphabetic as i32,
+                },
+            ],
+            100, /* threshold */
+        );
+
+        // Bounce key scenario on the internal keyboard
         let event = KeyEvent { deviceId: 1, action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
         filter.notify_key(&event);
         assert_eq!(next.last_event().unwrap(), event);
@@ -261,10 +376,15 @@
         next: Box<dyn Filter + Send + Sync>,
         device_id: i32,
         threshold: i64,
+        keyboard_type: KeyboardType,
     ) -> BounceKeysFilter {
         setup_filter_with_devices(
             next,
-            &[DeviceInfo { deviceId: device_id, external: true }],
+            &[DeviceInfo {
+                deviceId: device_id,
+                external: true,
+                keyboardType: keyboard_type as i32,
+            }],
             threshold,
         )
     }
@@ -273,10 +393,15 @@
         next: Box<dyn Filter + Send + Sync>,
         device_id: i32,
         threshold: i64,
+        keyboard_type: KeyboardType,
     ) -> BounceKeysFilter {
         setup_filter_with_devices(
             next,
-            &[DeviceInfo { deviceId: device_id, external: false }],
+            &[DeviceInfo {
+                deviceId: device_id,
+                external: false,
+                keyboardType: keyboard_type as i32,
+            }],
             threshold,
         )
     }
diff --git a/services/inputflinger/rust/input_filter.rs b/services/inputflinger/rust/input_filter.rs
index 8b44af3..f166723 100644
--- a/services/inputflinger/rust/input_filter.rs
+++ b/services/inputflinger/rust/input_filter.rs
@@ -35,6 +35,9 @@
 use log::{error, info};
 use std::sync::{Arc, Mutex, RwLock};
 
+/// Virtual keyboard device ID
+pub const VIRTUAL_KEYBOARD_DEVICE_ID: i32 = -1;
+
 /// Interface for all the sub input filters
 pub trait Filter {
     fn notify_key(&mut self, event: &KeyEvent);
@@ -214,6 +217,7 @@
         InputFilterConfiguration::InputFilterConfiguration, KeyEvent::KeyEvent,
         KeyEventAction::KeyEventAction,
     };
+    use input::KeyboardType;
     use std::sync::{Arc, RwLock};
 
     #[test]
@@ -256,7 +260,11 @@
             Arc::new(RwLock::new(Strong::new(Box::new(test_callbacks)))),
         );
         assert!(input_filter
-            .notifyInputDevicesChanged(&[DeviceInfo { deviceId: 0, external: true }])
+            .notifyInputDevicesChanged(&[DeviceInfo {
+                deviceId: 0,
+                external: true,
+                keyboardType: KeyboardType::None as i32
+            }])
             .is_ok());
         assert!(test_filter.is_device_changed_called());
     }
diff --git a/services/inputflinger/rust/slow_keys_filter.rs b/services/inputflinger/rust/slow_keys_filter.rs
index 0f18a2f..3e242d8 100644
--- a/services/inputflinger/rust/slow_keys_filter.rs
+++ b/services/inputflinger/rust/slow_keys_filter.rs
@@ -18,12 +18,13 @@
 //! Slow keys is an accessibility feature to aid users who have physical disabilities, that allows
 //! the user to specify the duration for which one must press-and-hold a key before the system
 //! accepts the keypress.
-use crate::input_filter::Filter;
+use crate::input_filter::{Filter, VIRTUAL_KEYBOARD_DEVICE_ID};
 use crate::input_filter_thread::{InputFilterThread, ThreadCallback};
 use android_hardware_input_common::aidl::android::hardware::input::common::Source::Source;
 use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
     DeviceInfo::DeviceInfo, KeyEvent::KeyEvent, KeyEventAction::KeyEventAction,
 };
+use input::KeyboardType;
 use log::debug;
 use std::collections::HashSet;
 use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
@@ -41,7 +42,7 @@
 struct SlowKeysFilterInner {
     next: Box<dyn Filter + Send + Sync>,
     slow_key_threshold_ns: i64,
-    external_devices: HashSet<i32>,
+    supported_devices: HashSet<i32>,
     // This tracks KeyEvents that are blocked by Slow keys filter and will be passed through if the
     // press duration exceeds the slow keys threshold.
     pending_down_events: Vec<KeyEvent>,
@@ -65,7 +66,7 @@
         let filter = Self(Arc::new(RwLock::new(SlowKeysFilterInner {
             next,
             slow_key_threshold_ns,
-            external_devices: HashSet::new(),
+            supported_devices: HashSet::new(),
             pending_down_events: Vec::new(),
             ongoing_down_events: Vec::new(),
             input_filter_thread: input_filter_thread.clone(),
@@ -98,7 +99,7 @@
         {
             // acquire write lock
             let mut slow_filter = self.write_inner();
-            if !(slow_filter.external_devices.contains(&event.deviceId)
+            if !(slow_filter.supported_devices.contains(&event.deviceId)
                 && event.source == Source::KEYBOARD)
             {
                 slow_filter.next.notify_key(event);
@@ -164,10 +165,17 @@
         slow_filter
             .ongoing_down_events
             .retain(|event| device_infos.iter().any(|x| event.device_id == x.deviceId));
-        slow_filter.external_devices.clear();
+        slow_filter.supported_devices.clear();
         for device_info in device_infos {
-            if device_info.external {
-                slow_filter.external_devices.insert(device_info.deviceId);
+            if device_info.deviceId == VIRTUAL_KEYBOARD_DEVICE_ID {
+                continue;
+            }
+            if device_info.keyboardType == KeyboardType::None as i32 {
+                continue;
+            }
+            // Support Alphabetic keyboards and Non-alphabetic external keyboards
+            if device_info.external || device_info.keyboardType == KeyboardType::Alphabetic as i32 {
+                slow_filter.supported_devices.insert(device_info.deviceId);
             }
         }
         slow_filter.next.notify_devices_changed(device_infos);
@@ -217,6 +225,7 @@
     use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
         DeviceInfo::DeviceInfo, KeyEvent::KeyEvent, KeyEventAction::KeyEventAction,
     };
+    use input::KeyboardType;
     use nix::{sys::time::TimeValLike, time::clock_gettime, time::ClockId};
     use std::sync::{Arc, RwLock};
     use std::time::Duration;
@@ -240,7 +249,7 @@
     static SLOW_KEYS_THRESHOLD_NS: i64 = 100 * 1000000; // 100 ms
 
     #[test]
-    fn test_is_notify_key_for_internal_keyboard_not_blocked() {
+    fn test_is_notify_key_for_internal_non_alphabetic_keyboard_not_blocked() {
         let test_callbacks = TestCallbacks::new();
         let test_thread = get_thread(test_callbacks.clone());
         let next = TestFilter::new();
@@ -249,6 +258,7 @@
             test_thread.clone(),
             1, /* device_id */
             SLOW_KEYS_THRESHOLD_NS,
+            KeyboardType::NonAlphabetic,
         );
 
         let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
@@ -266,6 +276,7 @@
             test_thread.clone(),
             1, /* device_id */
             SLOW_KEYS_THRESHOLD_NS,
+            KeyboardType::NonAlphabetic,
         );
 
         let event =
@@ -275,6 +286,58 @@
     }
 
     #[test]
+    fn test_notify_key_for_internal_alphabetic_keyboard_when_key_pressed_for_threshold_time() {
+        let test_callbacks = TestCallbacks::new();
+        let test_thread = get_thread(test_callbacks.clone());
+        let next = TestFilter::new();
+        let mut filter = setup_filter_with_internal_device(
+            Box::new(next.clone()),
+            test_thread.clone(),
+            1, /* device_id */
+            SLOW_KEYS_THRESHOLD_NS,
+            KeyboardType::Alphabetic,
+        );
+        let down_time = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap().num_nanoseconds();
+        filter.notify_key(&KeyEvent {
+            action: KeyEventAction::DOWN,
+            downTime: down_time,
+            eventTime: down_time,
+            ..BASE_KEY_EVENT
+        });
+        assert!(next.last_event().is_none());
+
+        std::thread::sleep(Duration::from_nanos(2 * SLOW_KEYS_THRESHOLD_NS as u64));
+        assert_eq!(
+            next.last_event().unwrap(),
+            KeyEvent {
+                action: KeyEventAction::DOWN,
+                downTime: down_time + SLOW_KEYS_THRESHOLD_NS,
+                eventTime: down_time + SLOW_KEYS_THRESHOLD_NS,
+                policyFlags: POLICY_FLAG_DISABLE_KEY_REPEAT,
+                ..BASE_KEY_EVENT
+            }
+        );
+
+        let up_time = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap().num_nanoseconds();
+        filter.notify_key(&KeyEvent {
+            action: KeyEventAction::UP,
+            downTime: down_time,
+            eventTime: up_time,
+            ..BASE_KEY_EVENT
+        });
+
+        assert_eq!(
+            next.last_event().unwrap(),
+            KeyEvent {
+                action: KeyEventAction::UP,
+                downTime: down_time + SLOW_KEYS_THRESHOLD_NS,
+                eventTime: up_time,
+                ..BASE_KEY_EVENT
+            }
+        );
+    }
+
+    #[test]
     fn test_notify_key_for_external_keyboard_when_key_pressed_for_threshold_time() {
         let test_callbacks = TestCallbacks::new();
         let test_thread = get_thread(test_callbacks.clone());
@@ -284,6 +347,7 @@
             test_thread.clone(),
             1, /* device_id */
             SLOW_KEYS_THRESHOLD_NS,
+            KeyboardType::Alphabetic,
         );
         let down_time = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap().num_nanoseconds();
         filter.notify_key(&KeyEvent {
@@ -335,6 +399,7 @@
             test_thread.clone(),
             1, /* device_id */
             SLOW_KEYS_THRESHOLD_NS,
+            KeyboardType::Alphabetic,
         );
         let mut now = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap().num_nanoseconds();
         filter.notify_key(&KeyEvent {
@@ -367,6 +432,7 @@
             test_thread.clone(),
             1, /* device_id */
             SLOW_KEYS_THRESHOLD_NS,
+            KeyboardType::Alphabetic,
         );
 
         let now = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap().num_nanoseconds();
@@ -388,11 +454,16 @@
         test_thread: InputFilterThread,
         device_id: i32,
         threshold: i64,
+        keyboard_type: KeyboardType,
     ) -> SlowKeysFilter {
         setup_filter_with_devices(
             next,
             test_thread,
-            &[DeviceInfo { deviceId: device_id, external: true }],
+            &[DeviceInfo {
+                deviceId: device_id,
+                external: true,
+                keyboardType: keyboard_type as i32,
+            }],
             threshold,
         )
     }
@@ -402,11 +473,16 @@
         test_thread: InputFilterThread,
         device_id: i32,
         threshold: i64,
+        keyboard_type: KeyboardType,
     ) -> SlowKeysFilter {
         setup_filter_with_devices(
             next,
             test_thread,
-            &[DeviceInfo { deviceId: device_id, external: false }],
+            &[DeviceInfo {
+                deviceId: device_id,
+                external: false,
+                keyboardType: keyboard_type as i32,
+            }],
             threshold,
         )
     }
diff --git a/services/inputflinger/rust/sticky_keys_filter.rs b/services/inputflinger/rust/sticky_keys_filter.rs
index 6c7c7fb..dfcea79 100644
--- a/services/inputflinger/rust/sticky_keys_filter.rs
+++ b/services/inputflinger/rust/sticky_keys_filter.rs
@@ -235,6 +235,7 @@
         DeviceInfo::DeviceInfo, IInputFilter::IInputFilterCallbacks::IInputFilterCallbacks,
         KeyEvent::KeyEvent, KeyEventAction::KeyEventAction,
     };
+    use input::KeyboardType;
     use input::ModifierState;
     use std::sync::{Arc, RwLock};
 
@@ -496,7 +497,11 @@
             ..BASE_KEY_UP
         });
 
-        sticky_keys_filter.notify_devices_changed(&[DeviceInfo { deviceId: 2, external: true }]);
+        sticky_keys_filter.notify_devices_changed(&[DeviceInfo {
+            deviceId: 2,
+            external: true,
+            keyboardType: KeyboardType::Alphabetic as i32,
+        }]);
         assert_eq!(
             test_callbacks.get_last_modifier_state(),
             ModifierState::CtrlLeftOn | ModifierState::CtrlOn