summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Siarhei Vishniakou <svv@google.com> 2023-06-28 15:57:47 -0700
committer Siarhei Vishniakou <svv@google.com> 2023-07-04 20:39:21 +0000
commit1160ecdfa295225f9eec1a20212746e412ca5c29 (patch)
tree2ea1233163568350bf6013397f0b8bb5031581de
parent556a811bacebb21be966fd22d36d0a3c64eb5cd6 (diff)
Add hovering support to verifier
In order to allow fuzzing of dispatcher, we need to be able to avoid incorrect hover sequences sent to the listener. Add hovering support for verifier in this CL. Bug: 211379801 Test: TEST=inputflinger_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST Change-Id: If7ee8ecb62044768915acc4657029366e193c6db
-rw-r--r--include/input/InputVerifier.h2
-rw-r--r--libs/input/InputVerifier.cpp9
-rw-r--r--libs/input/rust/input_verifier.rs131
-rw-r--r--libs/input/rust/lib.rs9
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp4
5 files changed, 150 insertions, 5 deletions
diff --git a/include/input/InputVerifier.h b/include/input/InputVerifier.h
index 3715408388..b8574829f3 100644
--- a/include/input/InputVerifier.h
+++ b/include/input/InputVerifier.h
@@ -51,6 +51,8 @@ public:
const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords, int32_t flags);
+ void resetDevice(int32_t deviceId);
+
private:
rust::Box<android::input::verifier::InputVerifier> mVerifier;
};
diff --git a/libs/input/InputVerifier.cpp b/libs/input/InputVerifier.cpp
index b0546a5243..851babfb54 100644
--- a/libs/input/InputVerifier.cpp
+++ b/libs/input/InputVerifier.cpp
@@ -24,6 +24,8 @@ using android::base::Error;
using android::base::Result;
using android::input::RustPointerProperties;
+using DeviceId = int32_t;
+
namespace android {
// --- InputVerifier ---
@@ -31,7 +33,8 @@ namespace android {
InputVerifier::InputVerifier(const std::string& name)
: mVerifier(android::input::verifier::create(name)){};
-Result<void> InputVerifier::processMovement(int32_t deviceId, int32_t action, uint32_t pointerCount,
+Result<void> InputVerifier::processMovement(DeviceId deviceId, int32_t action,
+ uint32_t pointerCount,
const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords, int32_t flags) {
std::vector<RustPointerProperties> rpp;
@@ -49,4 +52,8 @@ Result<void> InputVerifier::processMovement(int32_t deviceId, int32_t action, ui
}
}
+void InputVerifier::resetDevice(DeviceId deviceId) {
+ android::input::verifier::reset_device(*mVerifier, deviceId);
+}
+
} // namespace android
diff --git a/libs/input/rust/input_verifier.rs b/libs/input/rust/input_verifier.rs
index 1cc11297b6..fdb623033b 100644
--- a/libs/input/rust/input_verifier.rs
+++ b/libs/input/rust/input_verifier.rs
@@ -27,6 +27,7 @@ pub struct InputVerifier {
name: String,
should_log: bool,
touching_pointer_ids_by_device: HashMap<DeviceId, HashSet<i32>>,
+ hovering_pointer_ids_by_device: HashMap<DeviceId, HashSet<i32>>,
}
impl InputVerifier {
@@ -37,7 +38,12 @@ impl InputVerifier {
.with_tag_on_device("InputVerifier")
.with_min_level(log::Level::Trace),
);
- Self { name: name.to_owned(), should_log, touching_pointer_ids_by_device: HashMap::new() }
+ Self {
+ name: name.to_owned(),
+ should_log,
+ touching_pointer_ids_by_device: HashMap::new(),
+ hovering_pointer_ids_by_device: HashMap::new(),
+ }
}
/// Process a pointer movement event from an InputDevice.
@@ -135,7 +141,7 @@ impl InputVerifier {
self.name, pointer_id, it, device_id
));
}
- it.clear();
+ self.touching_pointer_ids_by_device.remove(&device_id);
}
MotionAction::Cancel => {
if flags.contains(MotionFlags::CANCELED) {
@@ -153,11 +159,68 @@ impl InputVerifier {
}
self.touching_pointer_ids_by_device.remove(&device_id);
}
+ /*
+ * The hovering protocol currently supports a single pointer only, because we do not
+ * have ACTION_HOVER_POINTER_ENTER or ACTION_HOVER_POINTER_EXIT.
+ * Still, we are keeping the infrastructure here pretty general in case that is
+ * eventually supported.
+ */
+ MotionAction::HoverEnter => {
+ if self.hovering_pointer_ids_by_device.contains_key(&device_id) {
+ return Err(format!(
+ "{}: Invalid HOVER_ENTER event - pointers already hovering for device {:?}:\
+ {:?}",
+ self.name, device_id, self.hovering_pointer_ids_by_device
+ ));
+ }
+ let it = self
+ .hovering_pointer_ids_by_device
+ .entry(device_id)
+ .or_insert_with(HashSet::new);
+ it.insert(pointer_properties[0].id);
+ }
+ MotionAction::HoverMove => {
+ // For compatibility reasons, we allow HOVER_MOVE without a prior HOVER_ENTER.
+ // If there was no prior HOVER_ENTER, just start a new hovering pointer.
+ let it = self
+ .hovering_pointer_ids_by_device
+ .entry(device_id)
+ .or_insert_with(HashSet::new);
+ it.insert(pointer_properties[0].id);
+ }
+ MotionAction::HoverExit => {
+ if !self.hovering_pointer_ids_by_device.contains_key(&device_id) {
+ return Err(format!(
+ "{}: Invalid HOVER_EXIT event - no pointers are hovering for device {:?}",
+ self.name, device_id
+ ));
+ }
+ let pointer_id = pointer_properties[0].id;
+ let it = self.hovering_pointer_ids_by_device.get_mut(&device_id).unwrap();
+ it.remove(&pointer_id);
+
+ if !it.is_empty() {
+ return Err(format!(
+ "{}: Removed hovering pointer {}, but pointers are still\
+ hovering for device {:?}: {:?}",
+ self.name, pointer_id, device_id, it
+ ));
+ }
+ self.hovering_pointer_ids_by_device.remove(&device_id);
+ }
_ => return Ok(()),
}
Ok(())
}
+ /// Notify the verifier that the device has been reset, which will cause the verifier to erase
+ /// the current internal state for this device. Subsequent events from this device are expected
+ //// to start a new gesture.
+ pub fn reset_device(&mut self, device_id: DeviceId) {
+ self.touching_pointer_ids_by_device.remove(&device_id);
+ self.hovering_pointer_ids_by_device.remove(&device_id);
+ }
+
fn ensure_touching_pointers_match(
&self,
device_id: DeviceId,
@@ -272,4 +335,68 @@ mod tests {
)
.is_err());
}
+
+ #[test]
+ fn correct_hover_sequence() {
+ let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
+ let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
+ assert!(verifier
+ .process_movement(
+ DeviceId(1),
+ input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
+ &pointer_properties,
+ MotionFlags::empty(),
+ )
+ .is_ok());
+
+ assert!(verifier
+ .process_movement(
+ DeviceId(1),
+ input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE,
+ &pointer_properties,
+ MotionFlags::empty(),
+ )
+ .is_ok());
+
+ assert!(verifier
+ .process_movement(
+ DeviceId(1),
+ input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT,
+ &pointer_properties,
+ MotionFlags::empty(),
+ )
+ .is_ok());
+
+ assert!(verifier
+ .process_movement(
+ DeviceId(1),
+ input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
+ &pointer_properties,
+ MotionFlags::empty(),
+ )
+ .is_ok());
+ }
+
+ #[test]
+ fn double_hover_enter() {
+ let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
+ let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
+ assert!(verifier
+ .process_movement(
+ DeviceId(1),
+ input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
+ &pointer_properties,
+ MotionFlags::empty(),
+ )
+ .is_ok());
+
+ assert!(verifier
+ .process_movement(
+ DeviceId(1),
+ input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
+ &pointer_properties,
+ MotionFlags::empty(),
+ )
+ .is_err());
+ }
}
diff --git a/libs/input/rust/lib.rs b/libs/input/rust/lib.rs
index 25b2ecbcda..892f558da6 100644
--- a/libs/input/rust/lib.rs
+++ b/libs/input/rust/lib.rs
@@ -54,6 +54,7 @@ mod ffi {
pointer_properties: &[RustPointerProperties],
flags: i32,
) -> String;
+ fn reset_device(verifier: &mut InputVerifier, device_id: i32);
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@@ -64,6 +65,10 @@ mod ffi {
use crate::ffi::RustPointerProperties;
+fn create(name: String) -> Box<InputVerifier> {
+ Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents")))
+}
+
fn process_movement(
verifier: &mut InputVerifier,
device_id: i32,
@@ -83,6 +88,6 @@ fn process_movement(
}
}
-fn create(name: String) -> Box<InputVerifier> {
- Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents")))
+fn reset_device(verifier: &mut InputVerifier, device_id: i32) {
+ verifier.reset_device(DeviceId(device_id));
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 29c4e469ea..482e23f043 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4516,6 +4516,10 @@ void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
std::unique_ptr<DeviceResetEntry> newEntry =
std::make_unique<DeviceResetEntry>(args.id, args.eventTime, args.deviceId);
needWake = enqueueInboundEventLocked(std::move(newEntry));
+
+ for (auto& [_, verifier] : mVerifiersByDisplay) {
+ verifier.resetDevice(args.deviceId);
+ }
} // release lock
if (needWake) {