xref: /aosp_15_r20/frameworks/native/libs/input/rust/lib.rs (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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 //! The rust component of libinput.
18 
19 mod data_store;
20 mod input;
21 mod input_verifier;
22 mod keyboard_classification_config;
23 mod keyboard_classifier;
24 
25 pub use data_store::{DataStore, DefaultFileReaderWriter};
26 pub use input::{
27     DeviceClass, DeviceId, InputDevice, KeyboardType, ModifierState, MotionAction, MotionFlags,
28     Source,
29 };
30 pub use input_verifier::InputVerifier;
31 pub use keyboard_classifier::KeyboardClassifier;
32 
33 #[cxx::bridge(namespace = "android::input")]
34 #[allow(clippy::needless_maybe_sized)]
35 #[allow(unsafe_op_in_unsafe_fn)]
36 mod ffi {
37     #[namespace = "android"]
38     unsafe extern "C++" {
39         include!("ffi/FromRustToCpp.h");
shouldLog(tag: &str) -> bool40         fn shouldLog(tag: &str) -> bool;
41     }
42 
43     #[namespace = "android::input::verifier"]
44     extern "Rust" {
45         /// Used to validate the incoming motion stream.
46         /// This class is not thread-safe.
47         /// State is stored in the "InputVerifier" object
48         /// that can be created via the 'create' method.
49         /// Usage:
50         ///
51         /// ```ignore
52         /// Box<InputVerifier> verifier = create("inputChannel name");
53         /// result = process_movement(verifier, ...);
54         /// if (result) {
55         ///    crash(result.error_message());
56         /// }
57         /// ```
58         type InputVerifier;
59         #[cxx_name = create]
create_input_verifier(name: String) -> Box<InputVerifier>60         fn create_input_verifier(name: String) -> Box<InputVerifier>;
process_movement( verifier: &mut InputVerifier, device_id: i32, source: u32, action: u32, pointer_properties: &[RustPointerProperties], flags: u32, ) -> String61         fn process_movement(
62             verifier: &mut InputVerifier,
63             device_id: i32,
64             source: u32,
65             action: u32,
66             pointer_properties: &[RustPointerProperties],
67             flags: u32,
68         ) -> String;
reset_device(verifier: &mut InputVerifier, device_id: i32)69         fn reset_device(verifier: &mut InputVerifier, device_id: i32);
70     }
71 
72     #[namespace = "android::input::keyboardClassifier"]
73     extern "Rust" {
74         /// Used to classify a keyboard into alphabetic and non-alphabetic
75         type KeyboardClassifier;
76         #[cxx_name = create]
create_keyboard_classifier() -> Box<KeyboardClassifier>77         fn create_keyboard_classifier() -> Box<KeyboardClassifier>;
78         #[cxx_name = notifyKeyboardChanged]
notify_keyboard_changed( classifier: &mut KeyboardClassifier, device_id: i32, identifier: RustInputDeviceIdentifier, device_classes: u32, )79         fn notify_keyboard_changed(
80             classifier: &mut KeyboardClassifier,
81             device_id: i32,
82             identifier: RustInputDeviceIdentifier,
83             device_classes: u32,
84         );
85         #[cxx_name = getKeyboardType]
get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u3286         fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32;
87         #[cxx_name = isFinalized]
is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool88         fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool;
89         #[cxx_name = processKey]
process_key( classifier: &mut KeyboardClassifier, device_id: i32, evdev_code: i32, modifier_state: u32, )90         fn process_key(
91             classifier: &mut KeyboardClassifier,
92             device_id: i32,
93             evdev_code: i32,
94             modifier_state: u32,
95         );
96     }
97 
98     #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
99     pub struct RustPointerProperties {
100         pub id: i32,
101     }
102 
103     #[derive(Debug)]
104     pub struct RustInputDeviceIdentifier {
105         pub name: String,
106         pub location: String,
107         pub unique_id: String,
108         pub bus: u16,
109         pub vendor: u16,
110         pub product: u16,
111         pub version: u16,
112         pub descriptor: String,
113     }
114 }
115 
116 use crate::ffi::{RustInputDeviceIdentifier, RustPointerProperties};
117 
create_input_verifier(name: String) -> Box<InputVerifier>118 fn create_input_verifier(name: String) -> Box<InputVerifier> {
119     Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents")))
120 }
121 
process_movement( verifier: &mut InputVerifier, device_id: i32, source: u32, action: u32, pointer_properties: &[RustPointerProperties], flags: u32, ) -> String122 fn process_movement(
123     verifier: &mut InputVerifier,
124     device_id: i32,
125     source: u32,
126     action: u32,
127     pointer_properties: &[RustPointerProperties],
128     flags: u32,
129 ) -> String {
130     let motion_flags = MotionFlags::from_bits(flags);
131     if motion_flags.is_none() {
132         panic!(
133             "The conversion of flags 0x{:08x} failed, please check if some flags have not been \
134             added to MotionFlags.",
135             flags
136         );
137     }
138     let result = verifier.process_movement(
139         DeviceId(device_id),
140         Source::from_bits(source).unwrap(),
141         action,
142         pointer_properties,
143         motion_flags.unwrap(),
144     );
145     match result {
146         Ok(()) => "".to_string(),
147         Err(e) => e,
148     }
149 }
150 
reset_device(verifier: &mut InputVerifier, device_id: i32)151 fn reset_device(verifier: &mut InputVerifier, device_id: i32) {
152     verifier.reset_device(DeviceId(device_id));
153 }
154 
create_keyboard_classifier() -> Box<KeyboardClassifier>155 fn create_keyboard_classifier() -> Box<KeyboardClassifier> {
156     // Future design: Make this data store singleton by passing it to C++ side and making it global
157     // and pass by reference to components that need to store persistent data.
158     //
159     // Currently only used by rust keyboard classifier so keeping it here.
160     let data_store = DataStore::new(Box::new(DefaultFileReaderWriter::new(
161         "/data/system/inputflinger-data.json".to_string(),
162     )));
163     Box::new(KeyboardClassifier::new(data_store))
164 }
165 
notify_keyboard_changed( classifier: &mut KeyboardClassifier, device_id: i32, identifier: RustInputDeviceIdentifier, device_classes: u32, )166 fn notify_keyboard_changed(
167     classifier: &mut KeyboardClassifier,
168     device_id: i32,
169     identifier: RustInputDeviceIdentifier,
170     device_classes: u32,
171 ) {
172     let classes = DeviceClass::from_bits(device_classes);
173     if classes.is_none() {
174         panic!(
175             "The conversion of device class 0x{:08x} failed, please check if some device classes
176              have not been added to DeviceClass.",
177             device_classes
178         );
179     }
180     classifier.notify_keyboard_changed(InputDevice {
181         device_id: DeviceId(device_id),
182         identifier,
183         classes: classes.unwrap(),
184     });
185 }
186 
get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32187 fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32 {
188     classifier.get_keyboard_type(DeviceId(device_id)) as u32
189 }
190 
is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool191 fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool {
192     classifier.is_finalized(DeviceId(device_id))
193 }
194 
process_key( classifier: &mut KeyboardClassifier, device_id: i32, evdev_code: i32, meta_state: u32, )195 fn process_key(
196     classifier: &mut KeyboardClassifier,
197     device_id: i32,
198     evdev_code: i32,
199     meta_state: u32,
200 ) {
201     let modifier_state = ModifierState::from_bits(meta_state);
202     if modifier_state.is_none() {
203         panic!(
204             "The conversion of meta state 0x{:08x} failed, please check if some meta state
205              have not been added to ModifierState.",
206             meta_state
207         );
208     }
209     classifier.process_key(DeviceId(device_id), evdev_code, modifier_state.unwrap());
210 }
211