1 /* 2 * Copyright 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //! Common definitions of the Android Input Framework in rust. 18 19 use crate::ffi::RustInputDeviceIdentifier; 20 use bitflags::bitflags; 21 use inputconstants::aidl::android::os::IInputConstants; 22 use inputconstants::aidl::android::os::MotionEventFlag::MotionEventFlag; 23 use serde::{Deserialize, Serialize}; 24 use std::fmt; 25 26 /// The InputDevice ID. 27 #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 28 pub struct DeviceId(pub i32); 29 30 /// The InputDevice equivalent for Rust inputflinger 31 #[derive(Debug)] 32 pub struct InputDevice { 33 /// InputDevice ID 34 pub device_id: DeviceId, 35 /// InputDevice unique identifier 36 pub identifier: RustInputDeviceIdentifier, 37 /// InputDevice classes (equivalent to EventHub InputDeviceClass) 38 pub classes: DeviceClass, 39 } 40 41 #[repr(u32)] 42 pub enum SourceClass { 43 None = input_bindgen::AINPUT_SOURCE_CLASS_NONE, 44 Button = input_bindgen::AINPUT_SOURCE_CLASS_BUTTON, 45 Pointer = input_bindgen::AINPUT_SOURCE_CLASS_POINTER, 46 Navigation = input_bindgen::AINPUT_SOURCE_CLASS_NAVIGATION, 47 Position = input_bindgen::AINPUT_SOURCE_CLASS_POSITION, 48 Joystick = input_bindgen::AINPUT_SOURCE_CLASS_JOYSTICK, 49 } 50 51 bitflags! { 52 /// Source of the input device or input events. 53 #[derive(Clone, Copy, Debug, PartialEq)] 54 pub struct Source: u32 { 55 // Constants from SourceClass, added here for compatibility reasons 56 /// SourceClass::Button 57 const SourceClassButton = SourceClass::Button as u32; 58 /// SourceClass::Pointer 59 const SourceClassPointer = SourceClass::Pointer as u32; 60 /// SourceClass::Navigation 61 const SourceClassNavigation = SourceClass::Navigation as u32; 62 /// SourceClass::Position 63 const SourceClassPosition = SourceClass::Position as u32; 64 /// SourceClass::Joystick 65 const SourceClassJoystick = SourceClass::Joystick as u32; 66 67 /// SOURCE_UNKNOWN 68 const Unknown = input_bindgen::AINPUT_SOURCE_UNKNOWN; 69 /// SOURCE_KEYBOARD 70 const Keyboard = input_bindgen::AINPUT_SOURCE_KEYBOARD; 71 /// SOURCE_DPAD 72 const Dpad = input_bindgen::AINPUT_SOURCE_DPAD; 73 /// SOURCE_GAMEPAD 74 const Gamepad = input_bindgen::AINPUT_SOURCE_GAMEPAD; 75 /// SOURCE_TOUCHSCREEN 76 const Touchscreen = input_bindgen::AINPUT_SOURCE_TOUCHSCREEN; 77 /// SOURCE_MOUSE 78 const Mouse = input_bindgen::AINPUT_SOURCE_MOUSE; 79 /// SOURCE_STYLUS 80 const Stylus = input_bindgen::AINPUT_SOURCE_STYLUS; 81 /// SOURCE_BLUETOOTH_STYLUS 82 const BluetoothStylus = input_bindgen::AINPUT_SOURCE_BLUETOOTH_STYLUS; 83 /// SOURCE_TRACKBALL 84 const Trackball = input_bindgen::AINPUT_SOURCE_TRACKBALL; 85 /// SOURCE_MOUSE_RELATIVE 86 const MouseRelative = input_bindgen::AINPUT_SOURCE_MOUSE_RELATIVE; 87 /// SOURCE_TOUCHPAD 88 const Touchpad = input_bindgen::AINPUT_SOURCE_TOUCHPAD; 89 /// SOURCE_TOUCH_NAVIGATION 90 const TouchNavigation = input_bindgen::AINPUT_SOURCE_TOUCH_NAVIGATION; 91 /// SOURCE_JOYSTICK 92 const Joystick = input_bindgen::AINPUT_SOURCE_JOYSTICK; 93 /// SOURCE_HDMI 94 const HDMI = input_bindgen::AINPUT_SOURCE_HDMI; 95 /// SOURCE_SENSOR 96 const Sensor = input_bindgen::AINPUT_SOURCE_SENSOR; 97 /// SOURCE_ROTARY_ENCODER 98 const RotaryEncoder = input_bindgen::AINPUT_SOURCE_ROTARY_ENCODER; 99 } 100 } 101 102 /// A rust enum representation of a MotionEvent action. 103 #[repr(u32)] 104 #[derive(Clone, Copy, Eq, PartialEq)] 105 pub enum MotionAction { 106 /// ACTION_DOWN 107 Down = input_bindgen::AMOTION_EVENT_ACTION_DOWN, 108 /// ACTION_UP 109 Up = input_bindgen::AMOTION_EVENT_ACTION_UP, 110 /// ACTION_MOVE 111 Move = input_bindgen::AMOTION_EVENT_ACTION_MOVE, 112 /// ACTION_CANCEL 113 Cancel = input_bindgen::AMOTION_EVENT_ACTION_CANCEL, 114 /// ACTION_OUTSIDE 115 Outside = input_bindgen::AMOTION_EVENT_ACTION_OUTSIDE, 116 /// ACTION_POINTER_DOWN 117 PointerDown { 118 /// The index of the affected pointer. 119 action_index: usize, 120 } = input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN, 121 /// ACTION_POINTER_UP 122 PointerUp { 123 /// The index of the affected pointer. 124 action_index: usize, 125 } = input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP, 126 /// ACTION_HOVER_ENTER 127 HoverEnter = input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER, 128 /// ACTION_HOVER_MOVE 129 HoverMove = input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE, 130 /// ACTION_HOVER_EXIT 131 HoverExit = input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT, 132 /// ACTION_SCROLL 133 Scroll = input_bindgen::AMOTION_EVENT_ACTION_SCROLL, 134 /// ACTION_BUTTON_PRESS 135 ButtonPress { 136 /// The button being pressed. 137 action_button: MotionButton, 138 } = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS, 139 /// ACTION_BUTTON_RELEASE 140 ButtonRelease { 141 /// The button being released. 142 action_button: MotionButton, 143 } = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE, 144 } 145 146 impl fmt::Display for MotionAction { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 148 match self { 149 MotionAction::Down => write!(f, "DOWN"), 150 MotionAction::Up => write!(f, "UP"), 151 MotionAction::Move => write!(f, "MOVE"), 152 MotionAction::Cancel => write!(f, "CANCEL"), 153 MotionAction::Outside => write!(f, "OUTSIDE"), 154 MotionAction::PointerDown { action_index } => { 155 write!(f, "POINTER_DOWN({})", action_index) 156 } 157 MotionAction::PointerUp { action_index } => write!(f, "POINTER_UP({})", action_index), 158 MotionAction::HoverMove => write!(f, "HOVER_MOVE"), 159 MotionAction::Scroll => write!(f, "SCROLL"), 160 MotionAction::HoverEnter => write!(f, "HOVER_ENTER"), 161 MotionAction::HoverExit => write!(f, "HOVER_EXIT"), 162 MotionAction::ButtonPress { action_button } => { 163 write!(f, "BUTTON_PRESS({action_button:?})") 164 } 165 MotionAction::ButtonRelease { action_button } => { 166 write!(f, "BUTTON_RELEASE({action_button:?})") 167 } 168 } 169 } 170 } 171 172 impl MotionAction { 173 /// Creates a [`MotionAction`] from an `AMOTION_EVENT_ACTION_…` constant and an action button 174 /// (which should be empty for all actions except `BUTTON_PRESS` and `…_RELEASE`). from_code(action: u32, action_button: MotionButton) -> Self175 pub fn from_code(action: u32, action_button: MotionButton) -> Self { 176 let (action_masked, action_index) = MotionAction::breakdown_action(action); 177 match action_masked { 178 input_bindgen::AMOTION_EVENT_ACTION_DOWN => MotionAction::Down, 179 input_bindgen::AMOTION_EVENT_ACTION_UP => MotionAction::Up, 180 input_bindgen::AMOTION_EVENT_ACTION_MOVE => MotionAction::Move, 181 input_bindgen::AMOTION_EVENT_ACTION_CANCEL => MotionAction::Cancel, 182 input_bindgen::AMOTION_EVENT_ACTION_OUTSIDE => MotionAction::Outside, 183 input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN => { 184 MotionAction::PointerDown { action_index } 185 } 186 input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP => { 187 MotionAction::PointerUp { action_index } 188 } 189 input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER => MotionAction::HoverEnter, 190 input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE => MotionAction::HoverMove, 191 input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT => MotionAction::HoverExit, 192 input_bindgen::AMOTION_EVENT_ACTION_SCROLL => MotionAction::Scroll, 193 input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS => { 194 MotionAction::ButtonPress { action_button } 195 } 196 input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE => { 197 MotionAction::ButtonRelease { action_button } 198 } 199 _ => panic!("Unknown action: {}", action), 200 } 201 } 202 breakdown_action(action: u32) -> (u32, usize)203 fn breakdown_action(action: u32) -> (u32, usize) { 204 let action_masked = action & input_bindgen::AMOTION_EVENT_ACTION_MASK; 205 let index = (action & input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) 206 >> input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; 207 (action_masked, index.try_into().unwrap()) 208 } 209 } 210 211 bitflags! { 212 /// MotionEvent buttons. 213 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] 214 pub struct MotionButton: u32 { 215 /// Primary button (e.g. the left mouse button) 216 const Primary = input_bindgen::AMOTION_EVENT_BUTTON_PRIMARY; 217 /// Secondary button (e.g. the right mouse button) 218 const Secondary = input_bindgen::AMOTION_EVENT_BUTTON_SECONDARY; 219 /// Tertiary button (e.g. the middle mouse button) 220 const Tertiary = input_bindgen::AMOTION_EVENT_BUTTON_TERTIARY; 221 /// Back button 222 const Back = input_bindgen::AMOTION_EVENT_BUTTON_BACK; 223 /// Forward button 224 const Forward = input_bindgen::AMOTION_EVENT_BUTTON_FORWARD; 225 /// Primary stylus button 226 const StylusPrimary = input_bindgen::AMOTION_EVENT_BUTTON_STYLUS_PRIMARY; 227 /// Secondary stylus button 228 const StylusSecondary = input_bindgen::AMOTION_EVENT_BUTTON_STYLUS_SECONDARY; 229 } 230 } 231 232 bitflags! { 233 /// MotionEvent flags. 234 /// The source of truth for the flag definitions are the MotionEventFlag AIDL enum. 235 /// The flag values are redefined here as a bitflags API. 236 #[derive(Clone, Copy, Debug)] 237 pub struct MotionFlags: u32 { 238 /// FLAG_WINDOW_IS_OBSCURED 239 const WINDOW_IS_OBSCURED = MotionEventFlag::WINDOW_IS_OBSCURED.0 as u32; 240 /// FLAG_WINDOW_IS_PARTIALLY_OBSCURED 241 const WINDOW_IS_PARTIALLY_OBSCURED = MotionEventFlag::WINDOW_IS_PARTIALLY_OBSCURED.0 as u32; 242 /// FLAG_HOVER_EXIT_PENDING 243 const HOVER_EXIT_PENDING = MotionEventFlag::HOVER_EXIT_PENDING.0 as u32; 244 /// FLAG_IS_GENERATED_GESTURE 245 const IS_GENERATED_GESTURE = MotionEventFlag::IS_GENERATED_GESTURE.0 as u32; 246 /// FLAG_CANCELED 247 const CANCELED = MotionEventFlag::CANCELED.0 as u32; 248 /// FLAG_NO_FOCUS_CHANGE 249 const NO_FOCUS_CHANGE = MotionEventFlag::NO_FOCUS_CHANGE.0 as u32; 250 /// PRIVATE_FLAG_SUPPORTS_ORIENTATION 251 const PRIVATE_FLAG_SUPPORTS_ORIENTATION = 252 MotionEventFlag::PRIVATE_FLAG_SUPPORTS_ORIENTATION.0 as u32; 253 /// PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION 254 const PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION = 255 MotionEventFlag::PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION.0 as u32; 256 /// FLAG_IS_ACCESSIBILITY_EVENT 257 const IS_ACCESSIBILITY_EVENT = MotionEventFlag::IS_ACCESSIBILITY_EVENT.0 as u32; 258 /// FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL 259 const INJECTED_FROM_ACCESSIBILITY_TOOL = 260 MotionEventFlag::INJECTED_FROM_ACCESSIBILITY_TOOL.0 as u32; 261 /// FLAG_TAINTED 262 const TAINTED = MotionEventFlag::TAINTED.0 as u32; 263 /// FLAG_TARGET_ACCESSIBILITY_FOCUS 264 const TARGET_ACCESSIBILITY_FOCUS = MotionEventFlag::TARGET_ACCESSIBILITY_FOCUS.0 as u32; 265 } 266 } 267 268 impl Source { 269 /// Return true if this source is from the provided class is_from_class(&self, source_class: SourceClass) -> bool270 pub fn is_from_class(&self, source_class: SourceClass) -> bool { 271 let class_bits = source_class as u32; 272 self.bits() & class_bits == class_bits 273 } 274 } 275 276 bitflags! { 277 /// Device class of the input device. These are duplicated from Eventhub.h 278 /// We need to make sure the two version remain in sync when adding new classes. 279 #[derive(Debug, PartialEq)] 280 pub struct DeviceClass: u32 { 281 /// The input device is a keyboard or has buttons 282 const Keyboard = IInputConstants::DEVICE_CLASS_KEYBOARD as u32; 283 /// The input device is an alpha-numeric keyboard (not just a dial pad) 284 const AlphabeticKey = IInputConstants::DEVICE_CLASS_ALPHAKEY as u32; 285 /// The input device is a touchscreen or a touchpad (either single-touch or multi-touch) 286 const Touch = IInputConstants::DEVICE_CLASS_TOUCH as u32; 287 /// The input device is a cursor device such as a trackball or mouse. 288 const Cursor = IInputConstants::DEVICE_CLASS_CURSOR as u32; 289 /// The input device is a multi-touch touchscreen or touchpad. 290 const MultiTouch = IInputConstants::DEVICE_CLASS_TOUCH_MT as u32; 291 /// The input device is a directional pad (implies keyboard, has DPAD keys). 292 const Dpad = IInputConstants::DEVICE_CLASS_DPAD as u32; 293 /// The input device is a gamepad (implies keyboard, has BUTTON keys). 294 const Gamepad = IInputConstants::DEVICE_CLASS_GAMEPAD as u32; 295 /// The input device has switches. 296 const Switch = IInputConstants::DEVICE_CLASS_SWITCH as u32; 297 /// The input device is a joystick (implies gamepad, has joystick absolute axes). 298 const Joystick = IInputConstants::DEVICE_CLASS_JOYSTICK as u32; 299 /// The input device has a vibrator (supports FF_RUMBLE). 300 const Vibrator = IInputConstants::DEVICE_CLASS_VIBRATOR as u32; 301 /// The input device has a microphone. 302 const Mic = IInputConstants::DEVICE_CLASS_MIC as u32; 303 /// The input device is an external stylus (has data we want to fuse with touch data). 304 const ExternalStylus = IInputConstants::DEVICE_CLASS_EXTERNAL_STYLUS as u32; 305 /// The input device has a rotary encoder 306 const RotaryEncoder = IInputConstants::DEVICE_CLASS_ROTARY_ENCODER as u32; 307 /// The input device has a sensor like accelerometer, gyro, etc 308 const Sensor = IInputConstants::DEVICE_CLASS_SENSOR as u32; 309 /// The input device has a battery 310 const Battery = IInputConstants::DEVICE_CLASS_BATTERY as u32; 311 /// The input device has sysfs controllable lights 312 const Light = IInputConstants::DEVICE_CLASS_LIGHT as u32; 313 /// The input device is a touchpad, requiring an on-screen cursor. 314 const Touchpad = IInputConstants::DEVICE_CLASS_TOUCHPAD as u32; 315 /// The input device is virtual (not a real device, not part of UI configuration). 316 const Virtual = IInputConstants::DEVICE_CLASS_VIRTUAL as u32; 317 /// The input device is external (not built-in). 318 const External = IInputConstants::DEVICE_CLASS_EXTERNAL as u32; 319 } 320 } 321 322 bitflags! { 323 /// Modifier state flags 324 #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] 325 pub struct ModifierState: u32 { 326 /// No meta keys are pressed 327 const None = input_bindgen::AMETA_NONE; 328 /// This mask is used to check whether one of the ALT meta keys is pressed 329 const AltOn = input_bindgen::AMETA_ALT_ON; 330 /// This mask is used to check whether the left ALT meta key is pressed 331 const AltLeftOn = input_bindgen::AMETA_ALT_LEFT_ON; 332 /// This mask is used to check whether the right ALT meta key is pressed 333 const AltRightOn = input_bindgen::AMETA_ALT_RIGHT_ON; 334 /// This mask is used to check whether one of the SHIFT meta keys is pressed 335 const ShiftOn = input_bindgen::AMETA_SHIFT_ON; 336 /// This mask is used to check whether the left SHIFT meta key is pressed 337 const ShiftLeftOn = input_bindgen::AMETA_SHIFT_LEFT_ON; 338 /// This mask is used to check whether the right SHIFT meta key is pressed 339 const ShiftRightOn = input_bindgen::AMETA_SHIFT_RIGHT_ON; 340 /// This mask is used to check whether the SYM meta key is pressed 341 const SymOn = input_bindgen::AMETA_SYM_ON; 342 /// This mask is used to check whether the FUNCTION meta key is pressed 343 const FunctionOn = input_bindgen::AMETA_FUNCTION_ON; 344 /// This mask is used to check whether one of the CTRL meta keys is pressed 345 const CtrlOn = input_bindgen::AMETA_CTRL_ON; 346 /// This mask is used to check whether the left CTRL meta key is pressed 347 const CtrlLeftOn = input_bindgen::AMETA_CTRL_LEFT_ON; 348 /// This mask is used to check whether the right CTRL meta key is pressed 349 const CtrlRightOn = input_bindgen::AMETA_CTRL_RIGHT_ON; 350 /// This mask is used to check whether one of the META meta keys is pressed 351 const MetaOn = input_bindgen::AMETA_META_ON; 352 /// This mask is used to check whether the left META meta key is pressed 353 const MetaLeftOn = input_bindgen::AMETA_META_LEFT_ON; 354 /// This mask is used to check whether the right META meta key is pressed 355 const MetaRightOn = input_bindgen::AMETA_META_RIGHT_ON; 356 /// This mask is used to check whether the CAPS LOCK meta key is on 357 const CapsLockOn = input_bindgen::AMETA_CAPS_LOCK_ON; 358 /// This mask is used to check whether the NUM LOCK meta key is on 359 const NumLockOn = input_bindgen::AMETA_NUM_LOCK_ON; 360 /// This mask is used to check whether the SCROLL LOCK meta key is on 361 const ScrollLockOn = input_bindgen::AMETA_SCROLL_LOCK_ON; 362 } 363 } 364 365 /// A rust enum representation of a Keyboard type. 366 #[repr(u32)] 367 #[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)] 368 #[serde(tag = "type")] 369 pub enum KeyboardType { 370 /// KEYBOARD_TYPE_NONE 371 #[default] 372 None = input_bindgen::AINPUT_KEYBOARD_TYPE_NONE, 373 /// KEYBOARD_TYPE_NON_ALPHABETIC 374 NonAlphabetic = input_bindgen::AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, 375 /// KEYBOARD_TYPE_ALPHABETIC 376 Alphabetic = input_bindgen::AINPUT_KEYBOARD_TYPE_ALPHABETIC, 377 } 378 379 #[cfg(test)] 380 mod tests { 381 use crate::input::SourceClass; 382 use crate::MotionFlags; 383 use crate::Source; 384 use inputconstants::aidl::android::os::MotionEventFlag::MotionEventFlag; 385 386 #[test] convert_source_class_pointer()387 fn convert_source_class_pointer() { 388 let source = Source::from_bits(input_bindgen::AINPUT_SOURCE_CLASS_POINTER).unwrap(); 389 assert!(source.is_from_class(SourceClass::Pointer)); 390 } 391 392 /// Ensure all MotionEventFlag constants are re-defined in rust. 393 #[test] all_motion_event_flags_defined()394 fn all_motion_event_flags_defined() { 395 for flag in MotionEventFlag::enum_values() { 396 assert!( 397 MotionFlags::from_bits(flag.0 as u32).is_some(), 398 "MotionEventFlag value {flag:?} is not redefined as a rust MotionFlags" 399 ); 400 } 401 } 402 } 403