summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/input/InputVerifier.h2
-rw-r--r--libs/input/Android.bp22
-rw-r--r--libs/input/InputTransport.cpp4
-rw-r--r--libs/input/InputVerifier.cpp6
-rw-r--r--libs/input/rust/input.rs56
-rw-r--r--libs/input/rust/input_verifier.rs76
-rw-r--r--libs/input/rust/lib.rs5
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp6
8 files changed, 161 insertions, 16 deletions
diff --git a/include/input/InputVerifier.h b/include/input/InputVerifier.h
index b8574829f3..14dd463425 100644
--- a/include/input/InputVerifier.h
+++ b/include/input/InputVerifier.h
@@ -46,7 +46,7 @@ class InputVerifier {
public:
InputVerifier(const std::string& name);
- android::base::Result<void> processMovement(int32_t deviceId, int32_t action,
+ android::base::Result<void> processMovement(int32_t deviceId, int32_t source, int32_t action,
uint32_t pointerCount,
const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords, int32_t flags);
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 36a01d37a5..ab4af1a7b6 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -90,6 +90,28 @@ rust_bindgen {
"--allowlist-var=AMOTION_EVENT_ACTION_DOWN",
"--allowlist-var=AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT",
"--allowlist-var=MAX_POINTER_ID",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_NONE",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_BUTTON",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_POINTER",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_NAVIGATION",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_POSITION",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_JOYSTICK",
+ "--allowlist-var=AINPUT_SOURCE_UNKNOWN",
+ "--allowlist-var=AINPUT_SOURCE_KEYBOARD",
+ "--allowlist-var=AINPUT_SOURCE_DPAD",
+ "--allowlist-var=AINPUT_SOURCE_GAMEPAD",
+ "--allowlist-var=AINPUT_SOURCE_TOUCHSCREEN",
+ "--allowlist-var=AINPUT_SOURCE_MOUSE",
+ "--allowlist-var=AINPUT_SOURCE_STYLUS",
+ "--allowlist-var=AINPUT_SOURCE_BLUETOOTH_STYLUS",
+ "--allowlist-var=AINPUT_SOURCE_TRACKBALL",
+ "--allowlist-var=AINPUT_SOURCE_MOUSE_RELATIVE",
+ "--allowlist-var=AINPUT_SOURCE_TOUCHPAD",
+ "--allowlist-var=AINPUT_SOURCE_TOUCH_NAVIGATION",
+ "--allowlist-var=AINPUT_SOURCE_JOYSTICK",
+ "--allowlist-var=AINPUT_SOURCE_HDMI",
+ "--allowlist-var=AINPUT_SOURCE_SENSOR",
+ "--allowlist-var=AINPUT_SOURCE_ROTARY_ENCODER",
],
static_libs: [
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 16000139f7..b5a823d76a 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -632,8 +632,8 @@ status_t InputPublisher::publishMotionEvent(
MotionEvent::actionToString(action).c_str()));
if (verifyEvents()) {
Result<void> result =
- mInputVerifier.processMovement(deviceId, action, pointerCount, pointerProperties,
- pointerCoords, flags);
+ mInputVerifier.processMovement(deviceId, source, action, pointerCount,
+ pointerProperties, pointerCoords, flags);
if (!result.ok()) {
LOG(FATAL) << "Bad stream: " << result.error();
}
diff --git a/libs/input/InputVerifier.cpp b/libs/input/InputVerifier.cpp
index 6c602e031d..cec244539e 100644
--- a/libs/input/InputVerifier.cpp
+++ b/libs/input/InputVerifier.cpp
@@ -33,7 +33,7 @@ namespace android {
InputVerifier::InputVerifier(const std::string& name)
: mVerifier(android::input::verifier::create(rust::String::lossy(name))){};
-Result<void> InputVerifier::processMovement(DeviceId deviceId, int32_t action,
+Result<void> InputVerifier::processMovement(DeviceId deviceId, int32_t source, int32_t action,
uint32_t pointerCount,
const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords, int32_t flags) {
@@ -43,8 +43,8 @@ Result<void> InputVerifier::processMovement(DeviceId deviceId, int32_t action,
}
rust::Slice<const RustPointerProperties> properties{rpp.data(), rpp.size()};
rust::String errorMessage =
- android::input::verifier::process_movement(*mVerifier, deviceId, action, properties,
- static_cast<uint32_t>(flags));
+ android::input::verifier::process_movement(*mVerifier, deviceId, source, action,
+ properties, static_cast<uint32_t>(flags));
if (errorMessage.empty()) {
return {};
} else {
diff --git a/libs/input/rust/input.rs b/libs/input/rust/input.rs
index 9d3b38693a..9725b00212 100644
--- a/libs/input/rust/input.rs
+++ b/libs/input/rust/input.rs
@@ -23,6 +23,54 @@ use std::fmt;
#[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 @@ bitflags! {
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 64c0466687..2d94e70309 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 @@ impl InputVerifier {
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 @@ impl InputVerifier {
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 @@ impl InputVerifier {
));
}
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 @@ impl InputVerifier {
}
}
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 @@ impl InputVerifier {
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 @@ mod tests {
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 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
&pointer_properties,
MotionFlags::empty(),
@@ -261,6 +290,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_MOVE,
&pointer_properties,
MotionFlags::empty(),
@@ -269,6 +299,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_UP,
&pointer_properties,
MotionFlags::empty(),
@@ -283,6 +314,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
&pointer_properties,
MotionFlags::empty(),
@@ -291,6 +323,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_MOVE,
&pointer_properties,
MotionFlags::empty(),
@@ -299,6 +332,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(2),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
&pointer_properties,
MotionFlags::empty(),
@@ -307,6 +341,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(2),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_MOVE,
&pointer_properties,
MotionFlags::empty(),
@@ -315,6 +350,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_UP,
&pointer_properties,
MotionFlags::empty(),
@@ -329,6 +365,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
&pointer_properties,
MotionFlags::empty(),
@@ -337,6 +374,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_CANCEL,
&pointer_properties,
MotionFlags::CANCELED,
@@ -351,6 +389,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
&pointer_properties,
MotionFlags::empty(),
@@ -359,6 +398,7 @@ mod tests {
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 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_UP,
&pointer_properties,
MotionFlags::empty(),
@@ -387,6 +428,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
&pointer_properties,
MotionFlags::empty(),
@@ -396,6 +438,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE,
&pointer_properties,
MotionFlags::empty(),
@@ -405,6 +448,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT,
&pointer_properties,
MotionFlags::empty(),
@@ -414,6 +458,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
&pointer_properties,
MotionFlags::empty(),
@@ -428,6 +473,7 @@ mod tests {
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
&pointer_properties,
MotionFlags::empty(),
@@ -437,10 +483,28 @@ mod tests {
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 1d3c434f76..01d959942c 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 @@ mod ffi {
fn process_movement(
verifier: &mut InputVerifier,
device_id: i32,
+ source: u32,
action: u32,
pointer_properties: &[RustPointerProperties],
flags: u32,
@@ -73,12 +74,14 @@ fn create(name: String) -> Box<InputVerifier> {
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(),
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 9cd1e0903d..4657c011f6 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4324,9 +4324,9 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) {
mVerifiersByDisplay.try_emplace(args.displayId,
StringPrintf("display %" PRId32, args.displayId));
Result<void> result =
- it->second.processMovement(args.deviceId, args.action, args.getPointerCount(),
- args.pointerProperties.data(), args.pointerCoords.data(),
- args.flags);
+ it->second.processMovement(args.deviceId, args.source, args.action,
+ args.getPointerCount(), args.pointerProperties.data(),
+ args.pointerCoords.data(), args.flags);
if (!result.ok()) {
LOG(FATAL) << "Bad stream: " << result.error() << " caused by " << args.dump();
}