diff options
author | 2023-06-22 23:08:18 +0000 | |
---|---|---|
committer | 2023-06-23 18:57:22 +0000 | |
commit | 0762b1f7ddcdc92b4175fa858028c752a930e61a (patch) | |
tree | 7530b5253588cc8c4e24a0a6544f35f27237a821 | |
parent | 89f7119821cad623418b6091fccab72d12e9cc01 (diff) |
Re-organize and export libinput_rust as a rust library
We export some definitions from libinput_rust as the "input" crate so
they can be used directly by other rust libraries.
Bug: 278783893
Test: atest libinput_rust_test
Change-Id: Icba79b67103f710d8bb1cb8892016bbd4e3e6ff9
-rw-r--r-- | libs/input/Android.bp | 61 | ||||
-rw-r--r-- | libs/input/InputVerifier.cpp | 2 | ||||
-rw-r--r-- | libs/input/rust/Android.bp | 72 | ||||
-rw-r--r-- | libs/input/rust/input.rs | 126 | ||||
-rw-r--r-- | libs/input/rust/input_verifier.rs (renamed from libs/input/input_verifier.rs) | 208 | ||||
-rw-r--r-- | libs/input/rust/lib.rs | 88 |
6 files changed, 319 insertions, 238 deletions
diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 30e4afe27d..f9f3d47301 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -109,62 +109,6 @@ cc_library_static { ], } -genrule { - name: "libinput_cxx_bridge_code", - tools: ["cxxbridge"], - cmd: "$(location cxxbridge) $(in) >> $(out)", - srcs: ["input_verifier.rs"], - out: ["inputverifier_generated.cpp"], -} - -genrule { - name: "libinput_cxx_bridge_header", - tools: ["cxxbridge"], - cmd: "$(location cxxbridge) $(in) --header >> $(out)", - srcs: ["input_verifier.rs"], - out: ["input_verifier.rs.h"], -} - -rust_defaults { - name: "libinput_rust_defaults", - srcs: ["input_verifier.rs"], - host_supported: true, - rustlibs: [ - "libbitflags", - "libcxx", - "libinput_bindgen", - "liblogger", - "liblog_rust", - "inputconstants-rust", - ], - - shared_libs: [ - "libbase", - "liblog", - ], -} - -rust_ffi_static { - name: "libinput_rust", - crate_name: "input", - defaults: ["libinput_rust_defaults"], -} - -rust_test { - name: "libinput_rust_test", - defaults: ["libinput_rust_defaults"], - whole_static_libs: [ - "libinput_from_rust_to_cpp", - ], - test_options: { - unit_test: true, - }, - test_suites: ["device_tests"], - sanitize: { - hwaddress: true, - }, -} - cc_library { name: "libinput", cpp_std: "c++20", @@ -176,7 +120,6 @@ cc_library { "-Wno-unused-parameter", ], srcs: [ - "FromRustToCpp.cpp", "Input.cpp", "InputDevice.cpp", "InputEventLabels.cpp", @@ -208,8 +151,6 @@ cc_library { "toolbox_input_labels", ], - generated_sources: ["libinput_cxx_bridge_code"], - shared_libs: [ "libbase", "libcutils", @@ -235,7 +176,7 @@ cc_library { ], whole_static_libs: [ - "libinput_rust", + "libinput_rust_ffi", ], export_static_lib_headers: [ diff --git a/libs/input/InputVerifier.cpp b/libs/input/InputVerifier.cpp index 32b4ca0fc1..b0546a5243 100644 --- a/libs/input/InputVerifier.cpp +++ b/libs/input/InputVerifier.cpp @@ -18,7 +18,7 @@ #include <android-base/logging.h> #include <input/InputVerifier.h> -#include "input_verifier.rs.h" +#include "input_cxx_bridge.rs.h" using android::base::Error; using android::base::Result; diff --git a/libs/input/rust/Android.bp b/libs/input/rust/Android.bp new file mode 100644 index 0000000000..018d199ce2 --- /dev/null +++ b/libs/input/rust/Android.bp @@ -0,0 +1,72 @@ +// Copyright 2023 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +rust_defaults { + name: "libinput_rust_defaults", + crate_name: "input", + srcs: ["lib.rs"], + host_supported: true, + rustlibs: [ + "libbitflags", + "libcxx", + "libinput_bindgen", + "liblogger", + "liblog_rust", + "inputconstants-rust", + ], + whole_static_libs: [ + "libinput_from_rust_to_cpp", + ], + shared_libs: [ + "libbase", + ], +} + +rust_library { + name: "libinput_rust", + defaults: ["libinput_rust_defaults"], +} + +rust_ffi_static { + name: "libinput_rust_ffi", + defaults: ["libinput_rust_defaults"], +} + +rust_test { + name: "libinput_rust_test", + defaults: ["libinput_rust_defaults"], + test_options: { + unit_test: true, + }, + test_suites: ["device_tests"], + sanitize: { + hwaddress: true, + }, +} + +genrule { + name: "libinput_cxx_bridge_code", + tools: ["cxxbridge"], + cmd: "$(location cxxbridge) $(in) >> $(out)", + srcs: ["lib.rs"], + out: ["input_cxx_bridge_generated.cpp"], +} + +genrule { + name: "libinput_cxx_bridge_header", + tools: ["cxxbridge"], + cmd: "$(location cxxbridge) $(in) --header >> $(out)", + srcs: ["lib.rs"], + out: ["input_cxx_bridge.rs.h"], +} diff --git a/libs/input/rust/input.rs b/libs/input/rust/input.rs new file mode 100644 index 0000000000..a308c26b2e --- /dev/null +++ b/libs/input/rust/input.rs @@ -0,0 +1,126 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//! Common definitions of the Android Input Framework in rust. + +use bitflags::bitflags; +use std::fmt; + +/// The InputDevice ID. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct DeviceId(pub i32); + +/// A rust enum representation of a MotionEvent action. +#[repr(u32)] +pub enum MotionAction { + /// ACTION_DOWN + Down = input_bindgen::AMOTION_EVENT_ACTION_DOWN, + /// ACTION_UP + Up = input_bindgen::AMOTION_EVENT_ACTION_UP, + /// ACTION_MOVE + Move = input_bindgen::AMOTION_EVENT_ACTION_MOVE, + /// ACTION_CANCEL + Cancel = input_bindgen::AMOTION_EVENT_ACTION_CANCEL, + /// ACTION_OUTSIDE + Outside = input_bindgen::AMOTION_EVENT_ACTION_OUTSIDE, + /// ACTION_POINTER_DOWN + PointerDown { + /// The index of the affected pointer. + action_index: usize, + } = input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN, + /// ACTION_POINTER_UP + PointerUp { + /// The index of the affected pointer. + action_index: usize, + } = input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP, + /// ACTION_HOVER_ENTER + HoverEnter = input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER, + /// ACTION_HOVER_MOVE + HoverMove = input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE, + /// ACTION_HOVER_EXIT + HoverExit = input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT, + /// ACTION_SCROLL + Scroll = input_bindgen::AMOTION_EVENT_ACTION_SCROLL, + /// ACTION_BUTTON_PRESS + ButtonPress = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS, + /// ACTION_BUTTON_RELEASE + ButtonRelease = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE, +} + +impl fmt::Display for MotionAction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + MotionAction::Down => write!(f, "DOWN"), + MotionAction::Up => write!(f, "UP"), + MotionAction::Move => write!(f, "MOVE"), + MotionAction::Cancel => write!(f, "CANCEL"), + MotionAction::Outside => write!(f, "OUTSIDE"), + MotionAction::PointerDown { action_index } => { + write!(f, "POINTER_DOWN({})", action_index) + } + MotionAction::PointerUp { action_index } => write!(f, "POINTER_UP({})", action_index), + MotionAction::HoverMove => write!(f, "HOVER_MOVE"), + MotionAction::Scroll => write!(f, "SCROLL"), + MotionAction::HoverEnter => write!(f, "HOVER_ENTER"), + MotionAction::HoverExit => write!(f, "HOVER_EXIT"), + MotionAction::ButtonPress => write!(f, "BUTTON_PRESS"), + MotionAction::ButtonRelease => write!(f, "BUTTON_RELEASE"), + } + } +} + +impl From<u32> for MotionAction { + fn from(action: u32) -> Self { + let (action_masked, action_index) = MotionAction::breakdown_action(action); + match action_masked { + input_bindgen::AMOTION_EVENT_ACTION_DOWN => MotionAction::Down, + input_bindgen::AMOTION_EVENT_ACTION_UP => MotionAction::Up, + input_bindgen::AMOTION_EVENT_ACTION_MOVE => MotionAction::Move, + input_bindgen::AMOTION_EVENT_ACTION_CANCEL => MotionAction::Cancel, + input_bindgen::AMOTION_EVENT_ACTION_OUTSIDE => MotionAction::Outside, + input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN => { + MotionAction::PointerDown { action_index } + } + input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP => { + MotionAction::PointerUp { action_index } + } + input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER => MotionAction::HoverEnter, + input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE => MotionAction::HoverMove, + input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT => MotionAction::HoverExit, + input_bindgen::AMOTION_EVENT_ACTION_SCROLL => MotionAction::Scroll, + input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS => MotionAction::ButtonPress, + input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE => MotionAction::ButtonRelease, + _ => panic!("Unknown action: {}", action), + } + } +} + +impl MotionAction { + fn breakdown_action(action: u32) -> (u32, usize) { + let action_masked = action & input_bindgen::AMOTION_EVENT_ACTION_MASK; + let index = (action & input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) + >> input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + (action_masked, index.try_into().unwrap()) + } +} + +bitflags! { + /// MotionEvent flags. + pub struct MotionFlags: i32 { + /// FLAG_CANCELED + const CANCELED = input_bindgen::AMOTION_EVENT_FLAG_CANCELED; + } +} diff --git a/libs/input/input_verifier.rs b/libs/input/rust/input_verifier.rs index 2e05a63149..1cc11297b6 100644 --- a/libs/input/input_verifier.rs +++ b/libs/input/rust/input_verifier.rs @@ -14,191 +14,45 @@ * limitations under the License. */ -//! Validate the incoming motion stream. -//! This class is not thread-safe. -//! State is stored in the "InputVerifier" object -//! that can be created via the 'create' method. -//! Usage: -//! Box<InputVerifier> verifier = create("inputChannel name"); -//! result = process_movement(verifier, ...); -//! if (result) { -//! crash(result.error_message()); -//! } +//! Contains the InputVerifier, used to validate a stream of input events. +use crate::ffi::RustPointerProperties; +use crate::input::{DeviceId, MotionAction, MotionFlags}; +use log::info; use std::collections::HashMap; use std::collections::HashSet; -use bitflags::bitflags; -use log::info; - -#[cxx::bridge(namespace = "android::input")] -mod ffi { - #[namespace = "android"] - unsafe extern "C++" { - include!("ffi/FromRustToCpp.h"); - fn shouldLog(tag: &str) -> bool; - } - #[namespace = "android::input::verifier"] - extern "Rust" { - type InputVerifier; - - fn create(name: String) -> Box<InputVerifier>; - fn process_movement( - verifier: &mut InputVerifier, - device_id: i32, - action: u32, - pointer_properties: &[RustPointerProperties], - flags: i32, - ) -> String; - } - - pub struct RustPointerProperties { - id: i32, - } -} - -use crate::ffi::shouldLog; -use crate::ffi::RustPointerProperties; - -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -struct DeviceId(i32); - -fn process_movement( - verifier: &mut InputVerifier, - device_id: i32, - action: u32, - pointer_properties: &[RustPointerProperties], - flags: i32, -) -> String { - let result = verifier.process_movement( - DeviceId(device_id), - action, - pointer_properties, - Flags::from_bits(flags).unwrap(), - ); - match result { - Ok(()) => "".to_string(), - Err(e) => e, - } -} - -fn create(name: String) -> Box<InputVerifier> { - Box::new(InputVerifier::new(&name)) -} - -#[repr(u32)] -enum MotionAction { - Down = input_bindgen::AMOTION_EVENT_ACTION_DOWN, - Up = input_bindgen::AMOTION_EVENT_ACTION_UP, - Move = input_bindgen::AMOTION_EVENT_ACTION_MOVE, - Cancel = input_bindgen::AMOTION_EVENT_ACTION_CANCEL, - Outside = input_bindgen::AMOTION_EVENT_ACTION_OUTSIDE, - PointerDown { action_index: usize } = input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN, - PointerUp { action_index: usize } = input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP, - HoverEnter = input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER, - HoverMove = input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE, - HoverExit = input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT, - Scroll = input_bindgen::AMOTION_EVENT_ACTION_SCROLL, - ButtonPress = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS, - ButtonRelease = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE, -} - -fn get_action_index(action: u32) -> usize { - let index = (action & input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) - >> input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; - index.try_into().unwrap() -} - -impl From<u32> for MotionAction { - fn from(action: u32) -> Self { - let action_masked = action & input_bindgen::AMOTION_EVENT_ACTION_MASK; - let action_index = get_action_index(action); - match action_masked { - input_bindgen::AMOTION_EVENT_ACTION_DOWN => MotionAction::Down, - input_bindgen::AMOTION_EVENT_ACTION_UP => MotionAction::Up, - input_bindgen::AMOTION_EVENT_ACTION_MOVE => MotionAction::Move, - input_bindgen::AMOTION_EVENT_ACTION_CANCEL => MotionAction::Cancel, - input_bindgen::AMOTION_EVENT_ACTION_OUTSIDE => MotionAction::Outside, - input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN => { - MotionAction::PointerDown { action_index } - } - input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP => { - MotionAction::PointerUp { action_index } - } - input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER => MotionAction::HoverEnter, - input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE => MotionAction::HoverMove, - input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT => MotionAction::HoverExit, - input_bindgen::AMOTION_EVENT_ACTION_SCROLL => MotionAction::Scroll, - input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS => MotionAction::ButtonPress, - input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE => MotionAction::ButtonRelease, - _ => panic!("Unknown action: {}", action), - } - } -} - -bitflags! { - struct Flags: i32 { - const CANCELED = input_bindgen::AMOTION_EVENT_FLAG_CANCELED; - } -} - -fn motion_action_to_string(action: u32) -> String { - match action.into() { - MotionAction::Down => "DOWN".to_string(), - MotionAction::Up => "UP".to_string(), - MotionAction::Move => "MOVE".to_string(), - MotionAction::Cancel => "CANCEL".to_string(), - MotionAction::Outside => "OUTSIDE".to_string(), - MotionAction::PointerDown { action_index } => { - format!("POINTER_DOWN({})", action_index) - } - MotionAction::PointerUp { action_index } => { - format!("POINTER_UP({})", action_index) - } - MotionAction::HoverMove => "HOVER_MOVE".to_string(), - MotionAction::Scroll => "SCROLL".to_string(), - MotionAction::HoverEnter => "HOVER_ENTER".to_string(), - MotionAction::HoverExit => "HOVER_EXIT".to_string(), - MotionAction::ButtonPress => "BUTTON_PRESS".to_string(), - MotionAction::ButtonRelease => "BUTTON_RELEASE".to_string(), - } -} - -/** - * Log all of the movements that are sent to this verifier. Helps to identify the streams that lead - * to inconsistent events. - * Enable this via "adb shell setprop log.tag.InputVerifierLogEvents DEBUG" - */ -fn log_events() -> bool { - shouldLog("InputVerifierLogEvents") -} - -struct InputVerifier { +/// The InputVerifier is used to validate a stream of input events. +pub struct InputVerifier { name: String, + should_log: bool, touching_pointer_ids_by_device: HashMap<DeviceId, HashSet<i32>>, } impl InputVerifier { - fn new(name: &str) -> Self { + /// Create a new InputVerifier. + pub fn new(name: &str, should_log: bool) -> Self { logger::init( logger::Config::default() .with_tag_on_device("InputVerifier") .with_min_level(log::Level::Trace), ); - Self { name: name.to_owned(), touching_pointer_ids_by_device: HashMap::new() } + Self { name: name.to_owned(), should_log, touching_pointer_ids_by_device: HashMap::new() } } - fn process_movement( + /// Process a pointer movement event from an InputDevice. + /// If the event is not valid, we return an error string that describes the issue. + pub fn process_movement( &mut self, device_id: DeviceId, action: u32, pointer_properties: &[RustPointerProperties], - flags: Flags, + flags: MotionFlags, ) -> Result<(), String> { - if log_events() { + if self.should_log { info!( "Processing {} for device {:?} ({} pointer{}) on {}", - motion_action_to_string(action), + MotionAction::from(action).to_string(), device_id, pointer_properties.len(), if pointer_properties.len() == 1 { "" } else { "s" }, @@ -284,7 +138,7 @@ impl InputVerifier { it.clear(); } MotionAction::Cancel => { - if flags.contains(Flags::CANCELED) { + if flags.contains(MotionFlags::CANCELED) { return Err(format!( "{}: For ACTION_CANCEL, must set FLAG_CANCELED", self.name @@ -325,20 +179,20 @@ impl InputVerifier { #[cfg(test)] mod tests { + use crate::input_verifier::InputVerifier; use crate::DeviceId; - use crate::Flags; - use crate::InputVerifier; + use crate::MotionFlags; use crate::RustPointerProperties; #[test] fn single_pointer_stream() { - let mut verifier = InputVerifier::new("Test"); + 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_DOWN, &pointer_properties, - Flags::empty(), + MotionFlags::empty(), ) .is_ok()); assert!(verifier @@ -346,7 +200,7 @@ mod tests { DeviceId(1), input_bindgen::AMOTION_EVENT_ACTION_MOVE, &pointer_properties, - Flags::empty(), + MotionFlags::empty(), ) .is_ok()); assert!(verifier @@ -354,21 +208,21 @@ mod tests { DeviceId(1), input_bindgen::AMOTION_EVENT_ACTION_UP, &pointer_properties, - Flags::empty(), + MotionFlags::empty(), ) .is_ok()); } #[test] fn multi_device_stream() { - let mut verifier = InputVerifier::new("Test"); + 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_DOWN, &pointer_properties, - Flags::empty(), + MotionFlags::empty(), ) .is_ok()); assert!(verifier @@ -376,7 +230,7 @@ mod tests { DeviceId(1), input_bindgen::AMOTION_EVENT_ACTION_MOVE, &pointer_properties, - Flags::empty(), + MotionFlags::empty(), ) .is_ok()); assert!(verifier @@ -384,7 +238,7 @@ mod tests { DeviceId(2), input_bindgen::AMOTION_EVENT_ACTION_DOWN, &pointer_properties, - Flags::empty(), + MotionFlags::empty(), ) .is_ok()); assert!(verifier @@ -392,7 +246,7 @@ mod tests { DeviceId(2), input_bindgen::AMOTION_EVENT_ACTION_MOVE, &pointer_properties, - Flags::empty(), + MotionFlags::empty(), ) .is_ok()); assert!(verifier @@ -400,21 +254,21 @@ mod tests { DeviceId(1), input_bindgen::AMOTION_EVENT_ACTION_UP, &pointer_properties, - Flags::empty(), + MotionFlags::empty(), ) .is_ok()); } #[test] fn test_invalid_up() { - let mut verifier = InputVerifier::new("Test"); + 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_UP, &pointer_properties, - Flags::empty(), + MotionFlags::empty(), ) .is_err()); } diff --git a/libs/input/rust/lib.rs b/libs/input/rust/lib.rs new file mode 100644 index 0000000000..25b2ecbcda --- /dev/null +++ b/libs/input/rust/lib.rs @@ -0,0 +1,88 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//! The rust component of libinput. + +mod input; +mod input_verifier; + +pub use input::{DeviceId, MotionAction, MotionFlags}; +pub use input_verifier::InputVerifier; + +#[cxx::bridge(namespace = "android::input")] +mod ffi { + #[namespace = "android"] + unsafe extern "C++" { + include!("ffi/FromRustToCpp.h"); + fn shouldLog(tag: &str) -> bool; + } + + #[namespace = "android::input::verifier"] + extern "Rust" { + /// Used to validate the incoming motion stream. + /// This class is not thread-safe. + /// State is stored in the "InputVerifier" object + /// that can be created via the 'create' method. + /// Usage: + /// + /// ```ignore + /// Box<InputVerifier> verifier = create("inputChannel name"); + /// result = process_movement(verifier, ...); + /// if (result) { + /// crash(result.error_message()); + /// } + /// ``` + type InputVerifier; + fn create(name: String) -> Box<InputVerifier>; + fn process_movement( + verifier: &mut InputVerifier, + device_id: i32, + action: u32, + pointer_properties: &[RustPointerProperties], + flags: i32, + ) -> String; + } + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] + pub struct RustPointerProperties { + pub id: i32, + } +} + +use crate::ffi::RustPointerProperties; + +fn process_movement( + verifier: &mut InputVerifier, + device_id: i32, + action: u32, + pointer_properties: &[RustPointerProperties], + flags: i32, +) -> String { + let result = verifier.process_movement( + DeviceId(device_id), + action, + pointer_properties, + MotionFlags::from_bits(flags).unwrap(), + ); + match result { + Ok(()) => "".to_string(), + Err(e) => e, + } +} + +fn create(name: String) -> Box<InputVerifier> { + Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents"))) +} |