summaryrefslogtreecommitdiff
path: root/services/inputflinger/InputManager.cpp
diff options
context:
space:
mode:
author Prabir Pradhan <prabirmsp@google.com> 2023-06-06 00:03:25 +0000
committer Prabir Pradhan <prabirmsp@google.com> 2023-08-17 17:15:52 +0000
commit44e6e832e93ab37ed29b08b462a3a0bf3aa6f4f1 (patch)
tree6ca9e79d6b4d8cdf45eadb8eb33ede88a442eec3 /services/inputflinger/InputManager.cpp
parent3540b698b64bd5ae24393e71c86af3c5cbaad1f1 (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.cpp70
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();
}