• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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