InputVerifier: only check pointer sources

Check for the source inside InputVerifier. Sources like MOUSE_RELATIVE
could send ACTION_MOVE events without a prior DOWN event. Verifying such
streams is tricky, so let's simply skip such events for now.

Also in this CL, add some verifications to the number of pointers inside
the event.

Bug: 211379801
Test: enable event verification and run native tests
Test: atest inputflinger_tests libinput_tests
Change-Id: I3703ba57af7ede77712b91b7429ac46c0624a616
diff --git a/libs/input/rust/input.rs b/libs/input/rust/input.rs
index 9d3b386..9725b00 100644
--- a/libs/input/rust/input.rs
+++ b/libs/input/rust/input.rs
@@ -23,6 +23,54 @@
 #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
 pub struct DeviceId(pub i32);
 
+#[repr(u32)]
+pub enum SourceClass {
+    None = input_bindgen::AINPUT_SOURCE_CLASS_NONE,
+    Button = input_bindgen::AINPUT_SOURCE_CLASS_BUTTON,
+    Pointer = input_bindgen::AINPUT_SOURCE_CLASS_POINTER,
+    Navigation = input_bindgen::AINPUT_SOURCE_CLASS_NAVIGATION,
+    Position = input_bindgen::AINPUT_SOURCE_CLASS_POSITION,
+    Joystick = input_bindgen::AINPUT_SOURCE_CLASS_JOYSTICK,
+}
+
+bitflags! {
+    /// Source of the input device or input events.
+    pub struct Source: u32 {
+        /// SOURCE_UNKNOWN
+        const Unknown = input_bindgen::AINPUT_SOURCE_UNKNOWN;
+        /// SOURCE_KEYBOARD
+        const Keyboard = input_bindgen::AINPUT_SOURCE_KEYBOARD;
+        /// SOURCE_DPAD
+        const Dpad = input_bindgen::AINPUT_SOURCE_DPAD;
+        /// SOURCE_GAMEPAD
+        const Gamepad = input_bindgen::AINPUT_SOURCE_GAMEPAD;
+        /// SOURCE_TOUCHSCREEN
+        const Touchscreen = input_bindgen::AINPUT_SOURCE_TOUCHSCREEN;
+        /// SOURCE_MOUSE
+        const Mouse = input_bindgen::AINPUT_SOURCE_MOUSE;
+        /// SOURCE_STYLUS
+        const Stylus = input_bindgen::AINPUT_SOURCE_STYLUS;
+        /// SOURCE_BLUETOOTH_STYLUS
+        const BluetoothStylus = input_bindgen::AINPUT_SOURCE_BLUETOOTH_STYLUS;
+        /// SOURCE_TRACKBALL
+        const Trackball = input_bindgen::AINPUT_SOURCE_TRACKBALL;
+        /// SOURCE_MOUSE_RELATIVE
+        const MouseRelative = input_bindgen::AINPUT_SOURCE_MOUSE_RELATIVE;
+        /// SOURCE_TOUCHPAD
+        const Touchpad = input_bindgen::AINPUT_SOURCE_TOUCHPAD;
+        /// SOURCE_TOUCH_NAVIGATION
+        const TouchNavigation = input_bindgen::AINPUT_SOURCE_TOUCH_NAVIGATION;
+        /// SOURCE_JOYSTICK
+        const Joystick = input_bindgen::AINPUT_SOURCE_JOYSTICK;
+        /// SOURCE_HDMI
+        const HDMI = input_bindgen::AINPUT_SOURCE_HDMI;
+        /// SOURCE_SENSOR
+        const Sensor = input_bindgen::AINPUT_SOURCE_SENSOR;
+        /// SOURCE_ROTARY_ENCODER
+        const RotaryEncoder = input_bindgen::AINPUT_SOURCE_ROTARY_ENCODER;
+    }
+}
+
 /// A rust enum representation of a MotionEvent action.
 #[repr(u32)]
 pub enum MotionAction {
@@ -134,3 +182,11 @@
         const NO_FOCUS_CHANGE = input_bindgen::AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE;
     }
 }
+
+impl Source {
+    /// Return true if this source is from the provided class
+    pub fn is_from_class(&self, source_class: SourceClass) -> bool {
+        let class_bits = source_class as u32;
+        self.bits() & class_bits == class_bits
+    }
+}
diff --git a/libs/input/rust/input_verifier.rs b/libs/input/rust/input_verifier.rs
index 64c0466..2d94e70 100644
--- a/libs/input/rust/input_verifier.rs
+++ b/libs/input/rust/input_verifier.rs
@@ -17,7 +17,7 @@
 //! Contains the InputVerifier, used to validate a stream of input events.
 
 use crate::ffi::RustPointerProperties;
-use crate::input::{DeviceId, MotionAction, MotionFlags};
+use crate::input::{DeviceId, MotionAction, MotionFlags, Source, SourceClass};
 use log::info;
 use std::collections::HashMap;
 use std::collections::HashSet;
@@ -51,10 +51,15 @@
     pub fn process_movement(
         &mut self,
         device_id: DeviceId,
+        source: Source,
         action: u32,
         pointer_properties: &[RustPointerProperties],
         flags: MotionFlags,
     ) -> Result<(), String> {
+        if !source.is_from_class(SourceClass::Pointer) {
+            // Skip non-pointer sources like MOUSE_RELATIVE for now
+            return Ok(());
+        }
         if self.should_log {
             info!(
                 "Processing {} for device {:?} ({} pointer{}) on {}",
@@ -68,6 +73,13 @@
 
         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)
@@ -90,10 +102,19 @@
                     ));
                 }
                 let it = self.touching_pointer_ids_by_device.get_mut(&device_id).unwrap();
+                if it.len() != pointer_properties.len() - 1 {
+                    return Err(format!(
+                        "{}: There are currently {} touching pointers, but the incoming \
+                         POINTER_DOWN event has {}",
+                        self.name,
+                        it.len(),
+                        pointer_properties.len()
+                    ));
+                }
                 let pointer_id = pointer_properties[action_index].id;
                 if it.contains(&pointer_id) {
                     return Err(format!(
-                        "{}: Pointer with id={} not found in the properties",
+                        "{}: Pointer with id={} already present found in the properties",
                         self.name, pointer_id
                     ));
                 }
@@ -108,11 +129,10 @@
                 }
             }
             MotionAction::PointerUp { action_index } => {
-                if !self.touching_pointer_ids_by_device.contains_key(&device_id) {
+                if !self.ensure_touching_pointers_match(device_id, pointer_properties) {
                     return Err(format!(
-                        "{}: Received POINTER_UP but no pointers are currently down for device \
-                        {:?}",
-                        self.name, device_id
+                        "{}: ACTION_POINTER_UP touching pointers don't match",
+                        self.name
                     ));
                 }
                 let it = self.touching_pointer_ids_by_device.get_mut(&device_id).unwrap();
@@ -120,6 +140,13 @@
                 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 {:?}",
@@ -246,6 +273,7 @@
     use crate::DeviceId;
     use crate::MotionFlags;
     use crate::RustPointerProperties;
+    use crate::Source;
     #[test]
     fn single_pointer_stream() {
         let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
@@ -253,6 +281,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_DOWN,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -261,6 +290,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_MOVE,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -269,6 +299,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_UP,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -283,6 +314,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_DOWN,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -291,6 +323,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_MOVE,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -299,6 +332,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(2),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_DOWN,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -307,6 +341,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(2),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_MOVE,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -315,6 +350,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_UP,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -329,6 +365,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_DOWN,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -337,6 +374,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_CANCEL,
                 &pointer_properties,
                 MotionFlags::CANCELED,
@@ -351,6 +389,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_DOWN,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -359,6 +398,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_CANCEL,
                 &pointer_properties,
                 MotionFlags::empty(), // forgot to set FLAG_CANCELED
@@ -373,6 +413,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_UP,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -387,6 +428,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -396,6 +438,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -405,6 +448,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -414,6 +458,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -428,6 +473,7 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
                 &pointer_properties,
                 MotionFlags::empty(),
@@ -437,10 +483,28 @@
         assert!(verifier
             .process_movement(
                 DeviceId(1),
+                Source::Touchscreen,
                 input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
                 &pointer_properties,
                 MotionFlags::empty(),
             )
             .is_err());
     }
+
+    // Send a MOVE without a preceding DOWN event. This is OK because it's from source
+    // MOUSE_RELATIVE, which is used during pointer capture. The verifier should allow such event.
+    #[test]
+    fn relative_mouse_move() {
+        let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
+        let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
+        assert!(verifier
+            .process_movement(
+                DeviceId(2),
+                Source::MouseRelative,
+                input_bindgen::AMOTION_EVENT_ACTION_MOVE,
+                &pointer_properties,
+                MotionFlags::empty(),
+            )
+            .is_ok());
+    }
 }
diff --git a/libs/input/rust/lib.rs b/libs/input/rust/lib.rs
index 1d3c434..01d9599 100644
--- a/libs/input/rust/lib.rs
+++ b/libs/input/rust/lib.rs
@@ -19,7 +19,7 @@
 mod input;
 mod input_verifier;
 
-pub use input::{DeviceId, MotionAction, MotionFlags};
+pub use input::{DeviceId, MotionAction, MotionFlags, Source};
 pub use input_verifier::InputVerifier;
 
 #[cxx::bridge(namespace = "android::input")]
@@ -51,6 +51,7 @@
         fn process_movement(
             verifier: &mut InputVerifier,
             device_id: i32,
+            source: u32,
             action: u32,
             pointer_properties: &[RustPointerProperties],
             flags: u32,
@@ -73,12 +74,14 @@
 fn process_movement(
     verifier: &mut InputVerifier,
     device_id: i32,
+    source: u32,
     action: u32,
     pointer_properties: &[RustPointerProperties],
     flags: u32,
 ) -> String {
     let result = verifier.process_movement(
         DeviceId(device_id),
+        Source::from_bits(source).unwrap(),
         action,
         pointer_properties,
         MotionFlags::from_bits(flags).unwrap(),