Skip to content

Commit 983e76b

Browse files
author
Vaibhav Devmurari
committed
Support bounce and slow keys for internal Alphabetic keyboards
Test: atest --host libinputflinger_rs_test Bug: 294546335 Flag: EXEMPT bugfix Change-Id: I590e9494f1bab562ac2b3c085781f05f2c250314
1 parent faff77d commit 983e76b

7 files changed

Lines changed: 243 additions & 26 deletions

File tree

libs/input/rust/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ mod keyboard_classifier;
2424

2525
pub use data_store::{DataStore, DefaultFileReaderWriter};
2626
pub use input::{
27-
DeviceClass, DeviceId, InputDevice, ModifierState, MotionAction, MotionFlags, Source,
27+
DeviceClass, DeviceId, InputDevice, KeyboardType, ModifierState, MotionAction, MotionFlags,
28+
Source,
2829
};
2930
pub use input_verifier::InputVerifier;
3031
pub use keyboard_classifier::KeyboardClassifier;

services/inputflinger/InputFilter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ void InputFilter::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs&
6060
AidlDeviceInfo& aidlInfo = mDeviceInfos.emplace_back();
6161
aidlInfo.deviceId = info.getId();
6262
aidlInfo.external = info.isExternal();
63+
aidlInfo.keyboardType = info.getKeyboardType();
6364
}
6465
if (isFilterEnabled()) {
6566
LOG_ALWAYS_FATAL_IF(!mInputFilterRust->notifyInputDevicesChanged(mDeviceInfos).isOk());

services/inputflinger/aidl/com/android/server/inputflinger/DeviceInfo.aidl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ package com.android.server.inputflinger;
2323
parcelable DeviceInfo {
2424
int deviceId;
2525
boolean external;
26+
int keyboardType;
2627
}

services/inputflinger/rust/bounce_keys_filter.rs

Lines changed: 138 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717
//! Bounce keys input filter implementation.
1818
//! Bounce keys is an accessibility feature to aid users who have physical disabilities, that
1919
//! allows the user to configure the device to ignore rapid, repeated key presses of the same key.
20-
use crate::input_filter::Filter;
20+
use crate::input_filter::{Filter, VIRTUAL_KEYBOARD_DEVICE_ID};
2121

2222
use android_hardware_input_common::aidl::android::hardware::input::common::Source::Source;
2323
use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
2424
DeviceInfo::DeviceInfo, KeyEvent::KeyEvent, KeyEventAction::KeyEventAction,
2525
};
26+
use input::KeyboardType;
2627
use log::debug;
2728
use std::collections::{HashMap, HashSet};
2829

@@ -42,7 +43,7 @@ pub struct BounceKeysFilter {
4243
next: Box<dyn Filter + Send + Sync>,
4344
key_event_map: HashMap<i32, LastUpKeyEvent>,
4445
blocked_events: Vec<BlockedEvent>,
45-
external_devices: HashSet<i32>,
46+
supported_devices: HashSet<i32>,
4647
bounce_key_threshold_ns: i64,
4748
}
4849

@@ -56,15 +57,15 @@ impl BounceKeysFilter {
5657
next,
5758
key_event_map: HashMap::new(),
5859
blocked_events: Vec::new(),
59-
external_devices: HashSet::new(),
60+
supported_devices: HashSet::new(),
6061
bounce_key_threshold_ns,
6162
}
6263
}
6364
}
6465

6566
impl Filter for BounceKeysFilter {
6667
fn notify_key(&mut self, event: &KeyEvent) {
67-
if !(self.external_devices.contains(&event.deviceId) && event.source == Source::KEYBOARD) {
68+
if !(self.supported_devices.contains(&event.deviceId) && event.source == Source::KEYBOARD) {
6869
self.next.notify_key(event);
6970
return;
7071
}
@@ -110,10 +111,17 @@ impl Filter for BounceKeysFilter {
110111
self.blocked_events.retain(|blocked_event| {
111112
device_infos.iter().any(|x| blocked_event.device_id == x.deviceId)
112113
});
113-
self.external_devices.clear();
114+
self.supported_devices.clear();
114115
for device_info in device_infos {
115-
if device_info.external {
116-
self.external_devices.insert(device_info.deviceId);
116+
if device_info.deviceId == VIRTUAL_KEYBOARD_DEVICE_ID {
117+
continue;
118+
}
119+
if device_info.keyboardType == KeyboardType::None as i32 {
120+
continue;
121+
}
122+
// Support Alphabetic keyboards and Non-alphabetic external keyboards
123+
if device_info.external || device_info.keyboardType == KeyboardType::Alphabetic as i32 {
124+
self.supported_devices.insert(device_info.deviceId);
117125
}
118126
}
119127
self.next.notify_devices_changed(device_infos);
@@ -127,11 +135,12 @@ impl Filter for BounceKeysFilter {
127135
#[cfg(test)]
128136
mod tests {
129137
use crate::bounce_keys_filter::BounceKeysFilter;
130-
use crate::input_filter::{test_filter::TestFilter, Filter};
138+
use crate::input_filter::{test_filter::TestFilter, Filter, VIRTUAL_KEYBOARD_DEVICE_ID};
131139
use android_hardware_input_common::aidl::android::hardware::input::common::Source::Source;
132140
use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
133141
DeviceInfo::DeviceInfo, KeyEvent::KeyEvent, KeyEventAction::KeyEventAction,
134142
};
143+
use input::KeyboardType;
135144

136145
static BASE_KEY_EVENT: KeyEvent = KeyEvent {
137146
id: 1,
@@ -156,6 +165,7 @@ mod tests {
156165
Box::new(next.clone()),
157166
1, /* device_id */
158167
100, /* threshold */
168+
KeyboardType::Alphabetic,
159169
);
160170

161171
let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
@@ -181,12 +191,68 @@ mod tests {
181191
}
182192

183193
#[test]
184-
fn test_is_notify_key_doesnt_block_for_internal_keyboard() {
194+
fn test_is_notify_key_blocks_for_internal_keyboard() {
195+
let mut next = TestFilter::new();
196+
let mut filter = setup_filter_with_internal_device(
197+
Box::new(next.clone()),
198+
1, /* device_id */
199+
100, /* threshold */
200+
KeyboardType::Alphabetic,
201+
);
202+
203+
let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
204+
filter.notify_key(&event);
205+
assert_eq!(next.last_event().unwrap(), event);
206+
207+
let event = KeyEvent { action: KeyEventAction::UP, ..BASE_KEY_EVENT };
208+
filter.notify_key(&event);
209+
assert_eq!(next.last_event().unwrap(), event);
210+
211+
next.clear();
212+
let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
213+
filter.notify_key(&event);
214+
assert!(next.last_event().is_none());
215+
216+
let event = KeyEvent { eventTime: 100, action: KeyEventAction::UP, ..BASE_KEY_EVENT };
217+
filter.notify_key(&event);
218+
assert!(next.last_event().is_none());
219+
220+
let event = KeyEvent { eventTime: 200, action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
221+
filter.notify_key(&event);
222+
assert_eq!(next.last_event().unwrap(), event);
223+
}
224+
225+
#[test]
226+
fn test_is_notify_key_doesnt_block_for_internal_non_alphabetic_keyboard() {
185227
let next = TestFilter::new();
186228
let mut filter = setup_filter_with_internal_device(
187229
Box::new(next.clone()),
188230
1, /* device_id */
189231
100, /* threshold */
232+
KeyboardType::NonAlphabetic,
233+
);
234+
235+
let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
236+
filter.notify_key(&event);
237+
assert_eq!(next.last_event().unwrap(), event);
238+
239+
let event = KeyEvent { action: KeyEventAction::UP, ..BASE_KEY_EVENT };
240+
filter.notify_key(&event);
241+
assert_eq!(next.last_event().unwrap(), event);
242+
243+
let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
244+
filter.notify_key(&event);
245+
assert_eq!(next.last_event().unwrap(), event);
246+
}
247+
248+
#[test]
249+
fn test_is_notify_key_doesnt_block_for_virtual_keyboard() {
250+
let next = TestFilter::new();
251+
let mut filter = setup_filter_with_internal_device(
252+
Box::new(next.clone()),
253+
VIRTUAL_KEYBOARD_DEVICE_ID, /* device_id */
254+
100, /* threshold */
255+
KeyboardType::Alphabetic,
190256
);
191257

192258
let event = KeyEvent { action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
@@ -209,6 +275,7 @@ mod tests {
209275
Box::new(next.clone()),
210276
1, /* device_id */
211277
100, /* threshold */
278+
KeyboardType::NonAlphabetic,
212279
);
213280

214281
let event =
@@ -233,12 +300,60 @@ mod tests {
233300
let mut filter = setup_filter_with_devices(
234301
Box::new(next.clone()),
235302
&[
236-
DeviceInfo { deviceId: 1, external: true },
237-
DeviceInfo { deviceId: 2, external: true },
303+
DeviceInfo {
304+
deviceId: 1,
305+
external: true,
306+
keyboardType: KeyboardType::Alphabetic as i32,
307+
},
308+
DeviceInfo {
309+
deviceId: 2,
310+
external: true,
311+
keyboardType: KeyboardType::Alphabetic as i32,
312+
},
313+
],
314+
100, /* threshold */
315+
);
316+
317+
// Bounce key scenario on the external keyboard
318+
let event = KeyEvent { deviceId: 1, action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
319+
filter.notify_key(&event);
320+
assert_eq!(next.last_event().unwrap(), event);
321+
322+
let event = KeyEvent { deviceId: 1, action: KeyEventAction::UP, ..BASE_KEY_EVENT };
323+
filter.notify_key(&event);
324+
assert_eq!(next.last_event().unwrap(), event);
325+
326+
next.clear();
327+
let event = KeyEvent { deviceId: 1, action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
328+
filter.notify_key(&event);
329+
assert!(next.last_event().is_none());
330+
331+
let event = KeyEvent { deviceId: 2, action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
332+
filter.notify_key(&event);
333+
assert_eq!(next.last_event().unwrap(), event);
334+
}
335+
336+
#[test]
337+
fn test_is_notify_key_for_external_and_internal_alphabetic_keyboards() {
338+
let mut next = TestFilter::new();
339+
let mut filter = setup_filter_with_devices(
340+
Box::new(next.clone()),
341+
&[
342+
DeviceInfo {
343+
deviceId: 1,
344+
external: false,
345+
keyboardType: KeyboardType::Alphabetic as i32,
346+
},
347+
DeviceInfo {
348+
deviceId: 2,
349+
external: true,
350+
keyboardType: KeyboardType::Alphabetic as i32,
351+
},
238352
],
239353
100, /* threshold */
240354
);
241355

356+
// Bounce key scenario on the internal keyboard
242357
let event = KeyEvent { deviceId: 1, action: KeyEventAction::DOWN, ..BASE_KEY_EVENT };
243358
filter.notify_key(&event);
244359
assert_eq!(next.last_event().unwrap(), event);
@@ -261,10 +376,15 @@ mod tests {
261376
next: Box<dyn Filter + Send + Sync>,
262377
device_id: i32,
263378
threshold: i64,
379+
keyboard_type: KeyboardType,
264380
) -> BounceKeysFilter {
265381
setup_filter_with_devices(
266382
next,
267-
&[DeviceInfo { deviceId: device_id, external: true }],
383+
&[DeviceInfo {
384+
deviceId: device_id,
385+
external: true,
386+
keyboardType: keyboard_type as i32,
387+
}],
268388
threshold,
269389
)
270390
}
@@ -273,10 +393,15 @@ mod tests {
273393
next: Box<dyn Filter + Send + Sync>,
274394
device_id: i32,
275395
threshold: i64,
396+
keyboard_type: KeyboardType,
276397
) -> BounceKeysFilter {
277398
setup_filter_with_devices(
278399
next,
279-
&[DeviceInfo { deviceId: device_id, external: false }],
400+
&[DeviceInfo {
401+
deviceId: device_id,
402+
external: false,
403+
keyboardType: keyboard_type as i32,
404+
}],
280405
threshold,
281406
)
282407
}

services/inputflinger/rust/input_filter.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ use input::ModifierState;
3535
use log::{error, info};
3636
use std::sync::{Arc, Mutex, RwLock};
3737

38+
/// Virtual keyboard device ID
39+
pub const VIRTUAL_KEYBOARD_DEVICE_ID: i32 = -1;
40+
3841
/// Interface for all the sub input filters
3942
pub trait Filter {
4043
fn notify_key(&mut self, event: &KeyEvent);
@@ -214,6 +217,7 @@ mod tests {
214217
InputFilterConfiguration::InputFilterConfiguration, KeyEvent::KeyEvent,
215218
KeyEventAction::KeyEventAction,
216219
};
220+
use input::KeyboardType;
217221
use std::sync::{Arc, RwLock};
218222

219223
#[test]
@@ -256,7 +260,11 @@ mod tests {
256260
Arc::new(RwLock::new(Strong::new(Box::new(test_callbacks)))),
257261
);
258262
assert!(input_filter
259-
.notifyInputDevicesChanged(&[DeviceInfo { deviceId: 0, external: true }])
263+
.notifyInputDevicesChanged(&[DeviceInfo {
264+
deviceId: 0,
265+
external: true,
266+
keyboardType: KeyboardType::None as i32
267+
}])
260268
.is_ok());
261269
assert!(test_filter.is_device_changed_called());
262270
}

0 commit comments

Comments
 (0)