Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c02a719 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Convert InputVerifier to rust

To establish some basic rust infrastructure for input code, convert the
InputVerifier into rust.

Currently, we use bindgen for interfacing between cpp and rust. In a
future CL, this may be changed to an aidl interface instead.

The logs and verifications can be enabled via:
adb shell setprop log.tag.InputTransportVerifyEvents DEBUG
adb shell setprop log.tag.InputVerifierLogEvents DEBUG
adb shell setprop log.tag.InputDispatcherVerifyEvents DEBUG

Bug: 271455682
Test: m inputflinger_tests && $ANDROID_HOST_OUT/nativetest64/inputflinger_tests/inputflinger_tests
Change-Id: I607fed9f6fc9c38e2c8392f59e9c4facdaf6c68a
parent 6778bd40
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -36,6 +36,14 @@ license {
    ],
}

cc_library_headers {
    name: "native_headers",
    host_supported: true,
    export_include_dirs: [
        "include/",
    ],
}

ndk_headers {
    name: "libandroid_headers",
    from: "include/android",
+19 −10
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 * 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.
@@ -16,13 +16,25 @@

#pragma once

#include <android-base/result.h>
#include <input/Input.h>
#include <map>
#include "rust/cxx.h"

namespace android {

namespace input {
namespace verifier {
struct InputVerifier;
}
} // namespace input

/*
 * Crash if the provided touch stream is inconsistent.
 * This class is a pass-through to the rust implementation of InputVerifier.
 * The rust class could also be used directly, but it would be less convenient.
 * We can't directly invoke the rust methods on a rust object. So, there's no way to do:
 * mVerifier.process_movement(...).
 * This C++ class makes it a bit easier to use.
 *
 * TODO(b/211379801): Add support for hover events:
 * - No hover move without enter
@@ -34,16 +46,13 @@ class InputVerifier {
public:
    InputVerifier(const std::string& name);

    void processMovement(int32_t deviceId, int32_t action, uint32_t pointerCount,
    android::base::Result<void> processMovement(int32_t deviceId, int32_t action,
                                                uint32_t pointerCount,
                                                const PointerProperties* pointerProperties,
                                                const PointerCoords* pointerCoords, int32_t flags);

private:
    const std::string mName;
    std::map<int32_t /*deviceId*/, std::bitset<MAX_POINTER_ID + 1>> mTouchingPointerIdsByDevice;
    void ensureTouchingPointersMatch(int32_t deviceId, uint32_t pointerCount,
                                     const PointerProperties* pointerProperties,
                                     const char* action) const;
    rust::Box<android::input::verifier::InputVerifier> mVerifier;
};

} // namespace android
+147 −4
Original line number Diff line number Diff line
@@ -33,6 +33,138 @@ filegroup {
    ],
}

aidl_interface {
    name: "inputconstants",
    host_supported: true,
    vendor_available: true,
    unstable: true,
    srcs: [
        ":inputconstants_aidl",
    ],

    backend: {
        rust: {
            enabled: true,
        },
    },
}

rust_bindgen {
    name: "libinput_bindgen",
    host_supported: true,
    crate_name: "input_bindgen",
    visibility: ["//frameworks/native/services/inputflinger"],
    wrapper_src: "InputWrapper.hpp",

    include_dirs: [
        "frameworks/native/include",
    ],

    source_stem: "bindings",

    bindgen_flags: [
        "--verbose",
        "--allowlist-var=AMOTION_EVENT_FLAG_CANCELED",
        "--allowlist-var=AMOTION_EVENT_ACTION_CANCEL",
        "--allowlist-var=AMOTION_EVENT_ACTION_UP",
        "--allowlist-var=AMOTION_EVENT_ACTION_POINTER_DOWN",
        "--allowlist-var=AMOTION_EVENT_ACTION_DOWN",
        "--allowlist-var=AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT",
        "--allowlist-var=MAX_POINTER_ID",
    ],

    static_libs: [
        "inputconstants-cpp",
        "libui-types",
    ],
    shared_libs: ["libc++"],
    header_libs: [
        "native_headers",
        "jni_headers",
        "flatbuffer_headers",
    ],
}

// Contains methods to help access C++ code from rust
cc_library_static {
    name: "libinput_from_rust_to_cpp",
    cpp_std: "c++20",
    host_supported: true,
    cflags: [
        "-Wall",
        "-Wextra",
        "-Werror",
    ],
    srcs: [
        "FromRustToCpp.cpp",
    ],

    generated_headers: [
        "cxx-bridge-header",
    ],
    generated_sources: ["libinput_cxx_bridge_code"],

    shared_libs: [
        "libbase",
    ],
}

genrule {
    name: "libinput_cxx_bridge_code",
    tools: ["cxxbridge"],
    cmd: "$(location cxxbridge) $(in) >> $(out)",
    srcs: ["input_verifier.rs"],
    out: ["inputverifier_generated.cpp"],
}

genrule {
    name: "libinput_cxx_bridge_header",
    tools: ["cxxbridge"],
    cmd: "$(location cxxbridge) $(in) --header >> $(out)",
    srcs: ["input_verifier.rs"],
    out: ["input_verifier.rs.h"],
}

rust_defaults {
    name: "libinput_rust_defaults",
    srcs: ["input_verifier.rs"],
    host_supported: true,
    rustlibs: [
        "libbitflags",
        "libcxx",
        "libinput_bindgen",
        "liblogger",
        "liblog_rust",
        "inputconstants-rust",
    ],

    shared_libs: [
        "libbase",
        "liblog",
    ],
}

rust_ffi_static {
    name: "libinput_rust",
    crate_name: "input",
    defaults: ["libinput_rust_defaults"],
}

rust_test {
    name: "libinput_rust_test",
    defaults: ["libinput_rust_defaults"],
    whole_static_libs: [
        "libinput_from_rust_to_cpp",
    ],
    test_options: {
        unit_test: true,
    },
    test_suites: ["device_tests"],
    sanitize: {
        hwaddress: true,
    },
}

cc_library {
    name: "libinput",
    cpp_std: "c++20",
@@ -44,6 +176,7 @@ cc_library {
        "-Wno-unused-parameter",
    ],
    srcs: [
        "FromRustToCpp.cpp",
        "Input.cpp",
        "InputDevice.cpp",
        "InputEventLabels.cpp",
@@ -70,9 +203,13 @@ cc_library {
    export_header_lib_headers: ["jni_headers"],

    generated_headers: [
        "cxx-bridge-header",
        "libinput_cxx_bridge_header",
        "toolbox_input_labels",
    ],

    generated_sources: ["libinput_cxx_bridge_code"],

    shared_libs: [
        "libbase",
        "libcutils",
@@ -92,20 +229,29 @@ cc_library {
    },

    static_libs: [
        "inputconstants-cpp",
        "libui-types",
        "libtflite_static",
    ],

    whole_static_libs: [
        "libinput_rust",
    ],

    export_static_lib_headers: [
        "libui-types",
    ],

    export_generated_headers: [
        "cxx-bridge-header",
        "libinput_cxx_bridge_header",
    ],

    target: {
        android: {
            srcs: [
                "InputTransport.cpp",
                "android/os/IInputFlinger.aidl",
                ":inputconstants_aidl",
            ],

            export_shared_lib_headers: ["libbinder"],
@@ -140,9 +286,6 @@ cc_library {
        host_linux: {
            srcs: [
                "InputTransport.cpp",
                "android/os/IInputConstants.aidl",
                "android/os/IInputFlinger.aidl",
                "android/os/InputConfig.aidl",
            ],
            static_libs: [
                "libhostgraphics",
+26 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#include <android-base/logging.h>
#include <ffi/FromRustToCpp.h>

namespace android {

bool shouldLog(rust::Str tag) {
    return android::base::ShouldLog(android::base::LogSeverity::DEBUG, tag.data());
}

} // namespace android
+8 −2
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <sys/types.h>
#include <unistd.h>

#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <binder/Parcel.h>
@@ -81,6 +82,7 @@ const bool DEBUG_RESAMPLING =

} // namespace

using android::base::Result;
using android::base::StringPrintf;

namespace android {
@@ -621,8 +623,12 @@ status_t InputPublisher::publishMotionEvent(
        ATRACE_NAME(message.c_str());
    }
    if (verifyEvents()) {
        Result<void> result =
                mInputVerifier.processMovement(deviceId, action, pointerCount, pointerProperties,
                                               pointerCoords, flags);
        if (!result.ok()) {
            LOG(FATAL) << "Bad stream: " << result.error();
        }
    }
    if (debugTransportPublisher()) {
        std::string transformString;
Loading