diff options
| author | 2023-06-06 00:03:25 +0000 | |
|---|---|---|
| committer | 2023-08-17 17:15:52 +0000 | |
| commit | 44e6e832e93ab37ed29b08b462a3a0bf3aa6f4f1 (patch) | |
| tree | 6ca9e79d6b4d8cdf45eadb8eb33ede88a442eec3 /services/inputflinger/InputManager.cpp | |
| parent | 3540b698b64bd5ae24393e71c86af3c5cbaad1f1 (diff) | |
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
Diffstat (limited to 'services/inputflinger/InputManager.cpp')
| -rw-r--r-- | services/inputflinger/InputManager.cpp | 70 |
1 files changed, 62 insertions, 8 deletions
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 <aidl/com/android/server/inputflinger/IInputFlingerRust.h> +#include <android/binder_interface_utils.h> #include <android/sysprop/InputProperties.sysprop.h> #include <binder/IPCThreadState.h> - +#include <inputflinger_bootstrap.rs.h> #include <log/log.h> -#include <unordered_map> - #include <private/android_filesystem_config.h> 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<IInputFlingerRust> createInputFlingerRust() { + using namespace aidl::com::android::server::inputflinger; + + class Callback : public IInputFlingerRust::BnInputFlingerRustBootstrapCallback { + ndk::ScopedAStatus onProvideInputFlingerRust( + const std::shared_ptr<IInputFlingerRust>& inputFlingerRust) override { + mService = inputFlingerRust; + return ndk::ScopedAStatus::ok(); + } + + public: + std::shared_ptr<IInputFlingerRust> consumeInputFlingerRust() { + auto service = mService; + mService.reset(); + return service; + } + + private: + std::shared_ptr<IInputFlingerRust> mService; + }; + + auto callback = ndk::SharedRefBase::make<Callback>(); + 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<InputReaderPolicyInterface>& 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<String16>& 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(); } |