From 44e6e832e93ab37ed29b08b462a3a0bf3aa6f4f1 Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Tue, 6 Jun 2023 00:03:25 +0000 Subject: Bootstrap IInputFlingerRust - the Rust component of inputflinger When inputflinger boots, we create the Rust component of inputflinger, which we interact with from C++ through the local AIDL interface IInputFlingerRust. After we have access to the IInputFlingerRust binder object in C++, all communication between C++ and Rust can take place purely through AIDL interfaces. To initialize the interface, we must first pass a raw pointer to an AIDL implementation across the language barrier through some other means. In this CL, we use cxxbridge to bootstrap the local AIDL interface for IInputFlingerRust. Bug: 278783893 Test: manual, boot Change-Id: Ifbd0168ae4fadaa5b357f6064113f1691e6cf5a7 --- services/inputflinger/InputManager.cpp | 70 ++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 8 deletions(-) (limited to 'services/inputflinger/InputManager.cpp') diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index c90356459f..da79ae3a48 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -23,22 +23,22 @@ #include "InputReaderFactory.h" #include "UnwantedInteractionBlocker.h" +#include +#include #include #include - +#include #include -#include - #include namespace android { -static const bool ENABLE_INPUT_DEVICE_USAGE_METRICS = - sysprop::InputProperties::enable_input_device_usage_metrics().value_or(true); +namespace { -using gui::FocusRequest; +const bool ENABLE_INPUT_DEVICE_USAGE_METRICS = + sysprop::InputProperties::enable_input_device_usage_metrics().value_or(true); -static int32_t exceptionCodeFromStatusT(status_t status) { +int32_t exceptionCodeFromStatusT(status_t status) { switch (status) { case OK: return binder::Status::EX_NONE; @@ -57,6 +57,58 @@ static int32_t exceptionCodeFromStatusT(status_t status) { } } +// Convert a binder interface into a raw pointer to an AIBinder. +using IInputFlingerRustBootstrapCallback = aidl::com::android::server::inputflinger:: + IInputFlingerRust::IInputFlingerRustBootstrapCallback; +IInputFlingerRustBootstrapCallbackAIBinder* binderToPointer( + IInputFlingerRustBootstrapCallback& interface) { + ndk::SpAIBinder spAIBinder = interface.asBinder(); + auto* ptr = spAIBinder.get(); + AIBinder_incStrong(ptr); + return ptr; +} + +// Create the Rust component of InputFlinger that uses AIDL interfaces as a the foreign function +// interface (FFI). The bootstraping process for IInputFlingerRust is as follows: +// - Create BnInputFlingerRustBootstrapCallback in C++. +// - Use the cxxbridge ffi interface to call the Rust function `create_inputflinger_rust()`, and +// pass the callback binder object as a raw pointer. +// - The Rust implementation will create the implementation of IInputFlingerRust, and pass it +// to C++ through the callback. +// - After the Rust function returns, the binder interface provided to the callback will be the +// only strong reference to the IInputFlingerRust. +std::shared_ptr createInputFlingerRust() { + using namespace aidl::com::android::server::inputflinger; + + class Callback : public IInputFlingerRust::BnInputFlingerRustBootstrapCallback { + ndk::ScopedAStatus onProvideInputFlingerRust( + const std::shared_ptr& inputFlingerRust) override { + mService = inputFlingerRust; + return ndk::ScopedAStatus::ok(); + } + + public: + std::shared_ptr consumeInputFlingerRust() { + auto service = mService; + mService.reset(); + return service; + } + + private: + std::shared_ptr mService; + }; + + auto callback = ndk::SharedRefBase::make(); + create_inputflinger_rust(binderToPointer(*callback)); + auto service = callback->consumeInputFlingerRust(); + LOG_ALWAYS_FATAL_IF(!service, + "create_inputflinger_rust did not provide the IInputFlingerRust " + "implementation through the callback."); + return service; +} + +} // namespace + /** * The event flow is via the "InputListener" interface, as follows: * InputReader @@ -67,6 +119,8 @@ static int32_t exceptionCodeFromStatusT(status_t status) { */ InputManager::InputManager(const sp& readerPolicy, InputDispatcherPolicyInterface& dispatcherPolicy) { + mInputFlingerRust = createInputFlingerRust(); + mDispatcher = createInputDispatcher(dispatcherPolicy); if (ENABLE_INPUT_DEVICE_USAGE_METRICS) { @@ -190,7 +244,7 @@ status_t InputManager::dump(int fd, const Vector& args) { return NO_ERROR; } -binder::Status InputManager::setFocusedWindow(const FocusRequest& request) { +binder::Status InputManager::setFocusedWindow(const gui::FocusRequest& request) { mDispatcher->setFocusedWindow(request); return binder::Status::ok(); } -- cgit v1.2.3-59-g8ed1b