input_verifier: add isolated MotionEvent checks
Previously, we were checking the consistency of MotionEvents inside
input_verifier in one large 'match' statement.
However, the verifier should only be used to check whether a given
MotionEvent makes sense in relation to all of the preceding motions.
To improve the situation, in this CL some checks are moved into a
separate function. Those checks allow us to test whether the event
itself makes sense. If the event is bad, then no need to do the
remaining checks in input_verifier.
This CL makes the rust code a bit closer to the current checks
implemented in the InputDispatcher.
Bug: 211379801
Test: TEST=inputflinger_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST
Change-Id: I60437797980f4f8f050023419a03d80e4ee4e1f1
diff --git a/libs/input/rust/input_verifier.rs b/libs/input/rust/input_verifier.rs
index 2d94e70..bbc6d98 100644
--- a/libs/input/rust/input_verifier.rs
+++ b/libs/input/rust/input_verifier.rs
@@ -22,6 +22,49 @@
use std::collections::HashMap;
use std::collections::HashSet;
+fn verify_event(
+ action: MotionAction,
+ pointer_properties: &[RustPointerProperties],
+ flags: &MotionFlags,
+) -> Result<(), String> {
+ let pointer_count = pointer_properties.len();
+ if pointer_count < 1 {
+ return Err(format!("Invalid {} event: no pointers", action));
+ }
+ match action {
+ MotionAction::Down
+ | MotionAction::HoverEnter
+ | MotionAction::HoverExit
+ | MotionAction::HoverMove
+ | MotionAction::Up => {
+ if pointer_count != 1 {
+ return Err(format!(
+ "Invalid {} event: there are {} pointers in the event",
+ action, pointer_count
+ ));
+ }
+ }
+
+ MotionAction::Cancel => {
+ if !flags.contains(MotionFlags::CANCELED) {
+ return Err(format!(
+ "For ACTION_CANCEL, must set FLAG_CANCELED. Received flags: {:#?}",
+ flags
+ ));
+ }
+ }
+
+ MotionAction::PointerDown { action_index } | MotionAction::PointerUp { action_index } => {
+ if action_index >= pointer_count {
+ return Err(format!("Got {}, but event has {} pointer(s)", action, pointer_count));
+ }
+ }
+
+ _ => {}
+ }
+ Ok(())
+}
+
/// The InputVerifier is used to validate a stream of input events.
pub struct InputVerifier {
name: String,
@@ -71,15 +114,10 @@
);
}
+ verify_event(action.into(), pointer_properties, &flags)?;
+
match action.into() {
MotionAction::Down => {
- if pointer_properties.len() != 1 {
- return Err(format!(
- "{}: Invalid DOWN event: there are {} pointers in the event",
- self.name,
- pointer_properties.len()
- ));
- }
let it = self
.touching_pointer_ids_by_device
.entry(device_id)
@@ -140,13 +178,6 @@
it.remove(&pointer_id);
}
MotionAction::Up => {
- if pointer_properties.len() != 1 {
- return Err(format!(
- "{}: Invalid UP event: there are {} pointers in the event",
- self.name,
- pointer_properties.len()
- ));
- }
if !self.touching_pointer_ids_by_device.contains_key(&device_id) {
return Err(format!(
"{} Received ACTION_UP but no pointers are currently down for device {:?}",
@@ -171,12 +202,6 @@
self.touching_pointer_ids_by_device.remove(&device_id);
}
MotionAction::Cancel => {
- if !flags.contains(MotionFlags::CANCELED) {
- return Err(format!(
- "{}: For ACTION_CANCEL, must set FLAG_CANCELED",
- self.name
- ));
- }
if !self.ensure_touching_pointers_match(device_id, pointer_properties) {
return Err(format!(
"{}: Got ACTION_CANCEL, but the pointers don't match. \
@@ -274,6 +299,26 @@
use crate::MotionFlags;
use crate::RustPointerProperties;
use crate::Source;
+
+ #[test]
+ /**
+ * Send a DOWN event with 2 pointers and ensure that it's marked as invalid.
+ */
+ fn bad_down_event() {
+ let mut verifier = InputVerifier::new("Test", /*should_log*/ true);
+ let pointer_properties =
+ Vec::from([RustPointerProperties { id: 0 }, RustPointerProperties { id: 1 }]);
+ assert!(verifier
+ .process_movement(
+ DeviceId(1),
+ Source::Touchscreen,
+ input_bindgen::AMOTION_EVENT_ACTION_DOWN,
+ &pointer_properties,
+ MotionFlags::empty(),
+ )
+ .is_err());
+ }
+
#[test]
fn single_pointer_stream() {
let mut verifier = InputVerifier::new("Test", /*should_log*/ false);