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 std::fmt;
23 
24 /// The InputDevice ID.
25 #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
26 pub struct DeviceId(pub i32);
27 
28 /// The InputDevice equivalent for Rust inputflinger
29 #[derive(Debug)]
30 pub struct InputDevice {
31     /// InputDevice ID
32     pub device_id: DeviceId,
33     /// InputDevice unique identifier
34     pub identifier: RustInputDeviceIdentifier,
35     /// InputDevice classes (equivalent to EventHub InputDeviceClass)
36     pub classes: DeviceClass,
37 }
38 
39 #[repr(u32)]
40 pub enum SourceClass {
41     None = input_bindgen::AINPUT_SOURCE_CLASS_NONE,
42     Button = input_bindgen::AINPUT_SOURCE_CLASS_BUTTON,
43     Pointer = input_bindgen::AINPUT_SOURCE_CLASS_POINTER,
44     Navigation = input_bindgen::AINPUT_SOURCE_CLASS_NAVIGATION,
45     Position = input_bindgen::AINPUT_SOURCE_CLASS_POSITION,
46     Joystick = input_bindgen::AINPUT_SOURCE_CLASS_JOYSTICK,
47 }
48 
49 bitflags! {
50     /// Source of the input device or input events.
51     #[derive(Debug, PartialEq)]
52     pub struct Source: u32 {
53         // Constants from SourceClass, added here for compatibility reasons
54         /// SourceClass::Button
55         const SourceClassButton = SourceClass::Button as u32;
56         /// SourceClass::Pointer
57         const SourceClassPointer = SourceClass::Pointer as u32;
58         /// SourceClass::Navigation
59         const SourceClassNavigation = SourceClass::Navigation as u32;
60         /// SourceClass::Position
61         const SourceClassPosition = SourceClass::Position as u32;
62         /// SourceClass::Joystick
63         const SourceClassJoystick = SourceClass::Joystick as u32;
64 
65         /// SOURCE_UNKNOWN
66         const Unknown = input_bindgen::AINPUT_SOURCE_UNKNOWN;
67         /// SOURCE_KEYBOARD
68         const Keyboard = input_bindgen::AINPUT_SOURCE_KEYBOARD;
69         /// SOURCE_DPAD
70         const Dpad = input_bindgen::AINPUT_SOURCE_DPAD;
71         /// SOURCE_GAMEPAD
72         const Gamepad = input_bindgen::AINPUT_SOURCE_GAMEPAD;
73         /// SOURCE_TOUCHSCREEN
74         const Touchscreen = input_bindgen::AINPUT_SOURCE_TOUCHSCREEN;
75         /// SOURCE_MOUSE
76         const Mouse = input_bindgen::AINPUT_SOURCE_MOUSE;
77         /// SOURCE_STYLUS
78         const Stylus = input_bindgen::AINPUT_SOURCE_STYLUS;
79         /// SOURCE_BLUETOOTH_STYLUS
80         const BluetoothStylus = input_bindgen::AINPUT_SOURCE_BLUETOOTH_STYLUS;
81         /// SOURCE_TRACKBALL
82         const Trackball = input_bindgen::AINPUT_SOURCE_TRACKBALL;
83         /// SOURCE_MOUSE_RELATIVE
84         const MouseRelative = input_bindgen::AINPUT_SOURCE_MOUSE_RELATIVE;
85         /// SOURCE_TOUCHPAD
86         const Touchpad = input_bindgen::AINPUT_SOURCE_TOUCHPAD;
87         /// SOURCE_TOUCH_NAVIGATION
88         const TouchNavigation = input_bindgen::AINPUT_SOURCE_TOUCH_NAVIGATION;
89         /// SOURCE_JOYSTICK
90         const Joystick = input_bindgen::AINPUT_SOURCE_JOYSTICK;
91         /// SOURCE_HDMI
92         const HDMI = input_bindgen::AINPUT_SOURCE_HDMI;
93         /// SOURCE_SENSOR
94         const Sensor = input_bindgen::AINPUT_SOURCE_SENSOR;
95         /// SOURCE_ROTARY_ENCODER
96         const RotaryEncoder = input_bindgen::AINPUT_SOURCE_ROTARY_ENCODER;
97     }
98 }
99 
100 /// A rust enum representation of a MotionEvent action.
101 #[repr(u32)]
102 pub enum MotionAction {
103     /// ACTION_DOWN
104     Down = input_bindgen::AMOTION_EVENT_ACTION_DOWN,
105     /// ACTION_UP
106     Up = input_bindgen::AMOTION_EVENT_ACTION_UP,
107     /// ACTION_MOVE
108     Move = input_bindgen::AMOTION_EVENT_ACTION_MOVE,
109     /// ACTION_CANCEL
110     Cancel = input_bindgen::AMOTION_EVENT_ACTION_CANCEL,
111     /// ACTION_OUTSIDE
112     Outside = input_bindgen::AMOTION_EVENT_ACTION_OUTSIDE,
113     /// ACTION_POINTER_DOWN
114     PointerDown {
115         /// The index of the affected pointer.
116         action_index: usize,
117     } = input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN,
118     /// ACTION_POINTER_UP
119     PointerUp {
120         /// The index of the affected pointer.
121         action_index: usize,
122     } = input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP,
123     /// ACTION_HOVER_ENTER
124     HoverEnter = input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
125     /// ACTION_HOVER_MOVE
126     HoverMove = input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE,
127     /// ACTION_HOVER_EXIT
128     HoverExit = input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT,
129     /// ACTION_SCROLL
130     Scroll = input_bindgen::AMOTION_EVENT_ACTION_SCROLL,
131     /// ACTION_BUTTON_PRESS
132     ButtonPress = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
133     /// ACTION_BUTTON_RELEASE
134     ButtonRelease = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE,
135 }
136 
137 impl fmt::Display for MotionAction {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result138     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139         match self {
140             MotionAction::Down => write!(f, "DOWN"),
141             MotionAction::Up => write!(f, "UP"),
142             MotionAction::Move => write!(f, "MOVE"),
143             MotionAction::Cancel => write!(f, "CANCEL"),
144             MotionAction::Outside => write!(f, "OUTSIDE"),
145             MotionAction::PointerDown { action_index } => {
146                 write!(f, "POINTER_DOWN({})", action_index)
147             }
148             MotionAction::PointerUp { action_index } => write!(f, "POINTER_UP({})", action_index),
149             MotionAction::HoverMove => write!(f, "HOVER_MOVE"),
150             MotionAction::Scroll => write!(f, "SCROLL"),
151             MotionAction::HoverEnter => write!(f, "HOVER_ENTER"),
152             MotionAction::HoverExit => write!(f, "HOVER_EXIT"),
153             MotionAction::ButtonPress => write!(f, "BUTTON_PRESS"),
154             MotionAction::ButtonRelease => write!(f, "BUTTON_RELEASE"),
155         }
156     }
157 }
158 
159 impl From<u32> for MotionAction {
from(action: u32) -> Self160     fn from(action: u32) -> Self {
161         let (action_masked, action_index) = MotionAction::breakdown_action(action);
162         match action_masked {
163             input_bindgen::AMOTION_EVENT_ACTION_DOWN => MotionAction::Down,
164             input_bindgen::AMOTION_EVENT_ACTION_UP => MotionAction::Up,
165             input_bindgen::AMOTION_EVENT_ACTION_MOVE => MotionAction::Move,
166             input_bindgen::AMOTION_EVENT_ACTION_CANCEL => MotionAction::Cancel,
167             input_bindgen::AMOTION_EVENT_ACTION_OUTSIDE => MotionAction::Outside,
168             input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN => {
169                 MotionAction::PointerDown { action_index }
170             }
171             input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP => {
172                 MotionAction::PointerUp { action_index }
173             }
174             input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER => MotionAction::HoverEnter,
175             input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE => MotionAction::HoverMove,
176             input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT => MotionAction::HoverExit,
177             input_bindgen::AMOTION_EVENT_ACTION_SCROLL => MotionAction::Scroll,
178             input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS => MotionAction::ButtonPress,
179             input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE => MotionAction::ButtonRelease,
180             _ => panic!("Unknown action: {}", action),
181         }
182     }
183 }
184 
185 impl MotionAction {
breakdown_action(action: u32) -> (u32, usize)186     fn breakdown_action(action: u32) -> (u32, usize) {
187         let action_masked = action & input_bindgen::AMOTION_EVENT_ACTION_MASK;
188         let index = (action & input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
189             >> input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
190         (action_masked, index.try_into().unwrap())
191     }
192 }
193 
194 bitflags! {
195     /// MotionEvent flags.
196     #[derive(Debug)]
197     pub struct MotionFlags: u32 {
198         /// FLAG_WINDOW_IS_OBSCURED
199         const WINDOW_IS_OBSCURED = IInputConstants::MOTION_EVENT_FLAG_WINDOW_IS_OBSCURED as u32;
200         /// FLAG_WINDOW_IS_PARTIALLY_OBSCURED
201         const WINDOW_IS_PARTIALLY_OBSCURED = IInputConstants::MOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED as u32;
202         /// FLAG_HOVER_EXIT_PENDING
203         const HOVER_EXIT_PENDING = IInputConstants::MOTION_EVENT_FLAG_HOVER_EXIT_PENDING as u32;
204         /// FLAG_IS_GENERATED_GESTURE
205         const IS_GENERATED_GESTURE = IInputConstants::MOTION_EVENT_FLAG_IS_GENERATED_GESTURE as u32;
206         /// FLAG_CANCELED
207         const CANCELED = IInputConstants::INPUT_EVENT_FLAG_CANCELED as u32;
208         /// FLAG_NO_FOCUS_CHANGE
209         const NO_FOCUS_CHANGE = IInputConstants::MOTION_EVENT_FLAG_NO_FOCUS_CHANGE as u32;
210         /// PRIVATE_FLAG_SUPPORTS_ORIENTATION
211         const PRIVATE_SUPPORTS_ORIENTATION = IInputConstants::MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION as u32;
212         /// PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION
213         const PRIVATE_SUPPORTS_DIRECTIONAL_ORIENTATION =
214                 IInputConstants::MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION as u32;
215         /// FLAG_IS_ACCESSIBILITY_EVENT
216         const IS_ACCESSIBILITY_EVENT = IInputConstants::INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT as u32;
217         /// FLAG_TAINTED
218         const TAINTED = IInputConstants::INPUT_EVENT_FLAG_TAINTED as u32;
219         /// FLAG_TARGET_ACCESSIBILITY_FOCUS
220         const TARGET_ACCESSIBILITY_FOCUS = IInputConstants::MOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS as u32;
221     }
222 }
223 
224 impl Source {
225     /// Return true if this source is from the provided class
is_from_class(&self, source_class: SourceClass) -> bool226     pub fn is_from_class(&self, source_class: SourceClass) -> bool {
227         let class_bits = source_class as u32;
228         self.bits() & class_bits == class_bits
229     }
230 }
231 
232 bitflags! {
233     /// Device class of the input device. These are duplicated from Eventhub.h
234     /// We need to make sure the two version remain in sync when adding new classes.
235     #[derive(Debug, PartialEq)]
236     pub struct DeviceClass: u32 {
237         /// The input device is a keyboard or has buttons
238         const Keyboard = IInputConstants::DEVICE_CLASS_KEYBOARD as u32;
239         /// The input device is an alpha-numeric keyboard (not just a dial pad)
240         const AlphabeticKey = IInputConstants::DEVICE_CLASS_ALPHAKEY as u32;
241         /// The input device is a touchscreen or a touchpad (either single-touch or multi-touch)
242         const Touch = IInputConstants::DEVICE_CLASS_TOUCH as u32;
243         /// The input device is a cursor device such as a trackball or mouse.
244         const Cursor = IInputConstants::DEVICE_CLASS_CURSOR as u32;
245         /// The input device is a multi-touch touchscreen or touchpad.
246         const MultiTouch = IInputConstants::DEVICE_CLASS_TOUCH_MT as u32;
247         /// The input device is a directional pad (implies keyboard, has DPAD keys).
248         const Dpad = IInputConstants::DEVICE_CLASS_DPAD as u32;
249         /// The input device is a gamepad (implies keyboard, has BUTTON keys).
250         const Gamepad = IInputConstants::DEVICE_CLASS_GAMEPAD as u32;
251         /// The input device has switches.
252         const Switch = IInputConstants::DEVICE_CLASS_SWITCH as u32;
253         /// The input device is a joystick (implies gamepad, has joystick absolute axes).
254         const Joystick = IInputConstants::DEVICE_CLASS_JOYSTICK as u32;
255         /// The input device has a vibrator (supports FF_RUMBLE).
256         const Vibrator = IInputConstants::DEVICE_CLASS_VIBRATOR as u32;
257         /// The input device has a microphone.
258         const Mic = IInputConstants::DEVICE_CLASS_MIC as u32;
259         /// The input device is an external stylus (has data we want to fuse with touch data).
260         const ExternalStylus = IInputConstants::DEVICE_CLASS_EXTERNAL_STYLUS as u32;
261         /// The input device has a rotary encoder
262         const RotaryEncoder = IInputConstants::DEVICE_CLASS_ROTARY_ENCODER as u32;
263         /// The input device has a sensor like accelerometer, gyro, etc
264         const Sensor = IInputConstants::DEVICE_CLASS_SENSOR as u32;
265         /// The input device has a battery
266         const Battery = IInputConstants::DEVICE_CLASS_BATTERY as u32;
267         /// The input device has sysfs controllable lights
268         const Light = IInputConstants::DEVICE_CLASS_LIGHT as u32;
269         /// The input device is a touchpad, requiring an on-screen cursor.
270         const Touchpad = IInputConstants::DEVICE_CLASS_TOUCHPAD as u32;
271         /// The input device is virtual (not a real device, not part of UI configuration).
272         const Virtual = IInputConstants::DEVICE_CLASS_VIRTUAL as u32;
273         /// The input device is external (not built-in).
274         const External = IInputConstants::DEVICE_CLASS_EXTERNAL as u32;
275     }
276 }
277 
278 bitflags! {
279     /// Modifier state flags
280     #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
281     pub struct ModifierState: u32 {
282         /// No meta keys are pressed
283         const None = input_bindgen::AMETA_NONE;
284         /// This mask is used to check whether one of the ALT meta keys is pressed
285         const AltOn = input_bindgen::AMETA_ALT_ON;
286         /// This mask is used to check whether the left ALT meta key is pressed
287         const AltLeftOn = input_bindgen::AMETA_ALT_LEFT_ON;
288         /// This mask is used to check whether the right ALT meta key is pressed
289         const AltRightOn = input_bindgen::AMETA_ALT_RIGHT_ON;
290         /// This mask is used to check whether one of the SHIFT meta keys is pressed
291         const ShiftOn = input_bindgen::AMETA_SHIFT_ON;
292         /// This mask is used to check whether the left SHIFT meta key is pressed
293         const ShiftLeftOn = input_bindgen::AMETA_SHIFT_LEFT_ON;
294         /// This mask is used to check whether the right SHIFT meta key is pressed
295         const ShiftRightOn = input_bindgen::AMETA_SHIFT_RIGHT_ON;
296         /// This mask is used to check whether the SYM meta key is pressed
297         const SymOn = input_bindgen::AMETA_SYM_ON;
298         /// This mask is used to check whether the FUNCTION meta key is pressed
299         const FunctionOn = input_bindgen::AMETA_FUNCTION_ON;
300         /// This mask is used to check whether one of the CTRL meta keys is pressed
301         const CtrlOn = input_bindgen::AMETA_CTRL_ON;
302         /// This mask is used to check whether the left CTRL meta key is pressed
303         const CtrlLeftOn = input_bindgen::AMETA_CTRL_LEFT_ON;
304         /// This mask is used to check whether the right CTRL meta key is pressed
305         const CtrlRightOn = input_bindgen::AMETA_CTRL_RIGHT_ON;
306         /// This mask is used to check whether one of the META meta keys is pressed
307         const MetaOn = input_bindgen::AMETA_META_ON;
308         /// This mask is used to check whether the left META meta key is pressed
309         const MetaLeftOn = input_bindgen::AMETA_META_LEFT_ON;
310         /// This mask is used to check whether the right META meta key is pressed
311         const MetaRightOn = input_bindgen::AMETA_META_RIGHT_ON;
312         /// This mask is used to check whether the CAPS LOCK meta key is on
313         const CapsLockOn = input_bindgen::AMETA_CAPS_LOCK_ON;
314         /// This mask is used to check whether the NUM LOCK meta key is on
315         const NumLockOn = input_bindgen::AMETA_NUM_LOCK_ON;
316         /// This mask is used to check whether the SCROLL LOCK meta key is on
317         const ScrollLockOn = input_bindgen::AMETA_SCROLL_LOCK_ON;
318     }
319 }
320 
321 /// A rust enum representation of a Keyboard type.
322 #[repr(u32)]
323 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
324 pub enum KeyboardType {
325     /// KEYBOARD_TYPE_NONE
326     None = input_bindgen::AINPUT_KEYBOARD_TYPE_NONE,
327     /// KEYBOARD_TYPE_NON_ALPHABETIC
328     NonAlphabetic = input_bindgen::AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC,
329     /// KEYBOARD_TYPE_ALPHABETIC
330     Alphabetic = input_bindgen::AINPUT_KEYBOARD_TYPE_ALPHABETIC,
331 }
332 
333 #[cfg(test)]
334 mod tests {
335     use crate::input::SourceClass;
336     use crate::Source;
337     #[test]
convert_source_class_pointer()338     fn convert_source_class_pointer() {
339         let source = Source::from_bits(input_bindgen::AINPUT_SOURCE_CLASS_POINTER).unwrap();
340         assert!(source.is_from_class(SourceClass::Pointer));
341     }
342 }
343