Implement KeyboardClassifier interface in rust

DD: go/project-imposter-android
This CL includes:
- Rust interface setup

Next CL to include:
- Basic categorization into alphabetic and non-alphabetic
- Updating categorization based on key presses

Test: atest --host libinput_rust_test
Test: atest inputflinger_tests
Bug: 263559234
Flag: com.android.input.flags.enable_keyboard_classifier_rust_impl
Change-Id: I52773be992ddd8efaa9546e0af8b0a78515d931c
diff --git a/libs/input/rust/lib.rs b/libs/input/rust/lib.rs
index fb3f520..5010475 100644
--- a/libs/input/rust/lib.rs
+++ b/libs/input/rust/lib.rs
@@ -18,9 +18,13 @@
 
 mod input;
 mod input_verifier;
+mod keyboard_classifier;
 
-pub use input::{DeviceId, MotionAction, MotionFlags, Source};
+pub use input::{
+    DeviceClass, DeviceId, InputDevice, ModifierState, MotionAction, MotionFlags, Source,
+};
 pub use input_verifier::InputVerifier;
+pub use keyboard_classifier::KeyboardClassifier;
 
 #[cxx::bridge(namespace = "android::input")]
 #[allow(unsafe_op_in_unsafe_fn)]
@@ -47,7 +51,8 @@
         /// }
         /// ```
         type InputVerifier;
-        fn create(name: String) -> Box<InputVerifier>;
+        #[cxx_name = create]
+        fn create_input_verifier(name: String) -> Box<InputVerifier>;
         fn process_movement(
             verifier: &mut InputVerifier,
             device_id: i32,
@@ -59,15 +64,53 @@
         fn reset_device(verifier: &mut InputVerifier, device_id: i32);
     }
 
+    #[namespace = "android::input::keyboardClassifier"]
+    extern "Rust" {
+        /// Used to classify a keyboard into alphabetic and non-alphabetic
+        type KeyboardClassifier;
+        #[cxx_name = create]
+        fn create_keyboard_classifier() -> Box<KeyboardClassifier>;
+        #[cxx_name = notifyKeyboardChanged]
+        fn notify_keyboard_changed(
+            classifier: &mut KeyboardClassifier,
+            device_id: i32,
+            identifier: RustInputDeviceIdentifier,
+            device_classes: u32,
+        );
+        #[cxx_name = getKeyboardType]
+        fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32;
+        #[cxx_name = isFinalized]
+        fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool;
+        #[cxx_name = processKey]
+        fn process_key(
+            classifier: &mut KeyboardClassifier,
+            device_id: i32,
+            evdev_code: i32,
+            modifier_state: u32,
+        );
+    }
+
     #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
     pub struct RustPointerProperties {
         pub id: i32,
     }
+
+    #[derive(Debug)]
+    pub struct RustInputDeviceIdentifier {
+        pub name: String,
+        pub location: String,
+        pub unique_id: String,
+        pub bus: u16,
+        pub vendor: u16,
+        pub product: u16,
+        pub version: u16,
+        pub descriptor: String,
+    }
 }
 
-use crate::ffi::RustPointerProperties;
+use crate::ffi::{RustInputDeviceIdentifier, RustPointerProperties};
 
-fn create(name: String) -> Box<InputVerifier> {
+fn create_input_verifier(name: String) -> Box<InputVerifier> {
     Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents")))
 }
 
@@ -103,3 +146,53 @@
 fn reset_device(verifier: &mut InputVerifier, device_id: i32) {
     verifier.reset_device(DeviceId(device_id));
 }
+
+fn create_keyboard_classifier() -> Box<KeyboardClassifier> {
+    Box::new(KeyboardClassifier::new())
+}
+
+fn notify_keyboard_changed(
+    classifier: &mut KeyboardClassifier,
+    device_id: i32,
+    identifier: RustInputDeviceIdentifier,
+    device_classes: u32,
+) {
+    let classes = DeviceClass::from_bits(device_classes);
+    if classes.is_none() {
+        panic!(
+            "The conversion of device class 0x{:08x} failed, please check if some device classes
+             have not been added to DeviceClass.",
+            device_classes
+        );
+    }
+    classifier.notify_keyboard_changed(InputDevice {
+        device_id: DeviceId(device_id),
+        identifier,
+        classes: classes.unwrap(),
+    });
+}
+
+fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32 {
+    classifier.get_keyboard_type(DeviceId(device_id)) as u32
+}
+
+fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool {
+    classifier.is_finalized(DeviceId(device_id))
+}
+
+fn process_key(
+    classifier: &mut KeyboardClassifier,
+    device_id: i32,
+    evdev_code: i32,
+    meta_state: u32,
+) {
+    let modifier_state = ModifierState::from_bits(meta_state);
+    if modifier_state.is_none() {
+        panic!(
+            "The conversion of meta state 0x{:08x} failed, please check if some meta state
+             have not been added to ModifierState.",
+            meta_state
+        );
+    }
+    classifier.process_key(DeviceId(device_id), evdev_code, modifier_state.unwrap());
+}