| /* | |
| * Copyright 2023 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| //! # The rust component of InputFlinger | |
| //! | |
| //! We use cxxbridge to create IInputFlingerRust - the Rust component of inputflinger - and | |
| //! pass it back to C++ as a local AIDL interface. | |
| mod bounce_keys_filter; | |
| mod input_filter; | |
| mod input_filter_thread; | |
| mod slow_keys_filter; | |
| mod sticky_keys_filter; | |
| use crate::input_filter::InputFilter; | |
| use binder::{ | |
| unstable_api::{new_spibinder, AIBinder}, | |
| BinderFeatures, Interface, StatusCode, Strong, | |
| }; | |
| use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{ | |
| IInputFilter::{BnInputFilter, IInputFilter, IInputFilterCallbacks::IInputFilterCallbacks}, | |
| IInputFlingerRust::{ | |
| BnInputFlingerRust, IInputFlingerRust, | |
| IInputFlingerRustBootstrapCallback::IInputFlingerRustBootstrapCallback, | |
| }, | |
| }; | |
| use log::debug; | |
| const LOG_TAG: &str = "inputflinger_bootstrap"; | |
| #[cxx::bridge] | |
| #[allow(unsafe_op_in_unsafe_fn)] | |
| mod ffi { | |
| extern "C++" { | |
| include!("InputFlingerBootstrap.h"); | |
| type IInputFlingerRustBootstrapCallbackAIBinder; | |
| } | |
| extern "Rust" { | |
| unsafe fn create_inputflinger_rust( | |
| callback: *mut IInputFlingerRustBootstrapCallbackAIBinder, | |
| ); | |
| } | |
| } | |
| /// Create the IInputFlingerRust implementation. | |
| /// This is the singular entry point from C++ into Rust. | |
| /// The `callback` parameter must be a valid pointer to an AIBinder implementation of | |
| /// the `IInputFlingerRustBootstrapCallback` interface. The IInputFlingerRust implementation that | |
| /// is created will be passed back through the callback from within this function. | |
| /// NOTE: This function must not hold a strong reference to the callback beyond its scope. | |
| /// | |
| /// # Safety | |
| /// | |
| /// The provided `callback` must be a valid pointer to an `AIBinder` interface of type | |
| /// `IInputFlingerRustBootstrapCallback`, and the caller must give this function ownership of one | |
| /// strong refcount to the interface. See `binder::unstable_api::new_spibinder`. | |
| unsafe fn create_inputflinger_rust(callback: *mut ffi::IInputFlingerRustBootstrapCallbackAIBinder) { | |
| logger::init( | |
| logger::Config::default() | |
| .with_tag_on_device(LOG_TAG) | |
| .with_max_level(log::LevelFilter::Trace), | |
| ); | |
| let callback = callback as *mut AIBinder; | |
| if callback.is_null() { | |
| panic!("create_inputflinger_rust cannot be called with a null callback"); | |
| } | |
| // SAFETY: Our caller guaranteed that `callback` is a valid pointer to an `AIBinder` and its | |
| // reference count has been incremented.. | |
| let Some(callback) = (unsafe { new_spibinder(callback) }) else { | |
| panic!("Failed to get SpAIBinder from raw callback pointer"); | |
| }; | |
| let callback: Result<Strong<dyn IInputFlingerRustBootstrapCallback>, StatusCode> = | |
| callback.into_interface(); | |
| match callback { | |
| Ok(callback) => { | |
| debug!("Creating InputFlingerRust"); | |
| let service = | |
| BnInputFlingerRust::new_binder(InputFlingerRust {}, BinderFeatures::default()); | |
| callback.onProvideInputFlingerRust(&service).unwrap(); | |
| } | |
| Err(status) => { | |
| panic!("Failed to convert AIBinder into the callback interface: {}", status); | |
| } | |
| } | |
| } | |
| struct InputFlingerRust {} | |
| impl Interface for InputFlingerRust {} | |
| impl IInputFlingerRust for InputFlingerRust { | |
| fn createInputFilter( | |
| &self, | |
| callbacks: &Strong<dyn IInputFilterCallbacks>, | |
| ) -> binder::Result<Strong<dyn IInputFilter>> { | |
| debug!("Creating InputFilter"); | |
| let filter = BnInputFilter::new_binder( | |
| InputFilter::new(callbacks.clone()), | |
| BinderFeatures::default(), | |
| ); | |
| Result::Ok(filter) | |
| } | |
| } | |
| impl Drop for InputFlingerRust { | |
| fn drop(&mut self) { | |
| debug!("Destroying InputFlingerRust"); | |
| } | |
| } |