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

Commit 5766aee0 authored by Vaibhav Devmurari's avatar Vaibhav Devmurari
Browse files

Add InputFilter rust component as InputListener stage.

Test: TEST=libinputflinger_rs_test; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST
Bug: 294546335
Change-Id: I2731d45f141c12c1e61b794ee614690b0a121e28
parent e560468e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -62,3 +62,10 @@ flag {
  description: "Disable touch rejection when the stylus hovers the screen"
  bug: "301216095"
}

flag {
  name: "enable_input_filter_rust_impl"
  namespace: "input"
  description: "Enable input filter rust implementation"
  bug: "294546335"
}
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ filegroup {
    srcs: [
        "InputCommonConverter.cpp",
        "InputDeviceMetricsCollector.cpp",
        "InputFilter.cpp",
        "InputProcessor.cpp",
        "PointerChoreographer.cpp",
        "PreferStylusOverTouchBlocker.cpp",
+129 −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.
 */

#define LOG_TAG "InputFilter"

#include "InputFilter.h"

namespace android {

using aidl::com::android::server::inputflinger::IInputFilter;
using AidlKeyEvent = aidl::com::android::server::inputflinger::KeyEvent;

AidlKeyEvent notifyKeyArgsToKeyEvent(const NotifyKeyArgs& args) {
    AidlKeyEvent event;
    event.id = args.id;
    event.eventTime = args.eventTime;
    event.deviceId = args.deviceId;
    event.source = args.source;
    event.displayId = args.displayId;
    event.policyFlags = args.policyFlags;
    event.action = args.action;
    event.flags = args.flags;
    event.keyCode = args.keyCode;
    event.scanCode = args.scanCode;
    event.metaState = args.metaState;
    event.downTime = args.downTime;
    event.readTime = args.readTime;
    return event;
}

NotifyKeyArgs keyEventToNotifyKeyArgs(const AidlKeyEvent& event) {
    return NotifyKeyArgs(event.id, event.eventTime, event.readTime, event.deviceId, event.source,
                         event.displayId, event.policyFlags, event.action, event.flags,
                         event.keyCode, event.scanCode, event.metaState, event.downTime);
}

namespace {

class RustCallbacks : public IInputFilter::BnInputFilterCallbacks {
public:
    RustCallbacks(InputListenerInterface& nextListener) : mNextListener(nextListener) {}
    ndk::ScopedAStatus sendKeyEvent(const AidlKeyEvent& event) override {
        mNextListener.notifyKey(keyEventToNotifyKeyArgs(event));
        return ndk::ScopedAStatus::ok();
    }

private:
    InputListenerInterface& mNextListener;
};

} // namespace

InputFilter::InputFilter(InputListenerInterface& listener, IInputFlingerRust& rust)
      : mNextListener(listener), mCallbacks(ndk::SharedRefBase::make<RustCallbacks>(listener)) {
    LOG_ALWAYS_FATAL_IF(!rust.createInputFilter(mCallbacks, &mInputFilterRust).isOk());
    LOG_ALWAYS_FATAL_IF(!mInputFilterRust);
}

void InputFilter::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
    if (isFilterEnabled()) {
        std::vector<int32_t> deviceIds;
        for (auto info : args.inputDeviceInfos) {
            deviceIds.push_back(info.getId());
        }
        LOG_ALWAYS_FATAL_IF(!mInputFilterRust->notifyInputDevicesChanged(deviceIds).isOk());
    }
    mNextListener.notify(args);
}

void InputFilter::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
    mNextListener.notify(args);
}

void InputFilter::notifyKey(const NotifyKeyArgs& args) {
    if (!isFilterEnabled()) {
        mNextListener.notifyKey(args);
        return;
    }
    LOG_ALWAYS_FATAL_IF(!mInputFilterRust->notifyKey(notifyKeyArgsToKeyEvent(args)).isOk());
}

void InputFilter::notifyMotion(const NotifyMotionArgs& args) {
    mNextListener.notify(args);
}

void InputFilter::notifySwitch(const NotifySwitchArgs& args) {
    mNextListener.notify(args);
}

void InputFilter::notifySensor(const NotifySensorArgs& args) {
    mNextListener.notify(args);
}

void InputFilter::notifyVibratorState(const NotifyVibratorStateArgs& args) {
    mNextListener.notify(args);
}

void InputFilter::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
    mNextListener.notify(args);
}

void InputFilter::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) {
    mNextListener.notify(args);
}

bool InputFilter::isFilterEnabled() {
    bool result;
    LOG_ALWAYS_FATAL_IF(!mInputFilterRust->isEnabled(&result).isOk());
    return result;
}

void InputFilter::dump(std::string& dump) {
    dump += "InputFilter:\n";
}

} // namespace android
+64 −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.
 */

#pragma once

#include <aidl/com/android/server/inputflinger/IInputFlingerRust.h>
#include "InputListener.h"
#include "NotifyArgs.h"

namespace android {

/**
 * The C++ component of InputFilter designed as a wrapper around the rust implementation.
 */
class InputFilterInterface : public InputListenerInterface {
public:
    /**
     * This method may be called on any thread (usually by the input manager on a binder thread).
     */
    virtual void dump(std::string& dump) = 0;
};

class InputFilter : public InputFilterInterface {
public:
    using IInputFlingerRust = aidl::com::android::server::inputflinger::IInputFlingerRust;
    using IInputFilter = aidl::com::android::server::inputflinger::IInputFilter;
    using IInputFilterCallbacks =
            aidl::com::android::server::inputflinger::IInputFilter::IInputFilterCallbacks;

    explicit InputFilter(InputListenerInterface& listener, IInputFlingerRust&);
    ~InputFilter() override = default;
    void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
    void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
    void notifyKey(const NotifyKeyArgs& args) override;
    void notifyMotion(const NotifyMotionArgs& args) override;
    void notifySwitch(const NotifySwitchArgs& args) override;
    void notifySensor(const NotifySensorArgs& args) override;
    void notifyVibratorState(const NotifyVibratorStateArgs& args) override;
    void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
    void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
    void dump(std::string& dump) override;

private:
    InputListenerInterface& mNextListener;
    std::shared_ptr<IInputFilterCallbacks> mCallbacks;
    std::shared_ptr<IInputFilter> mInputFilterRust;

    bool isFilterEnabled();
};

} // namespace android
+8 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ const bool ENABLE_INPUT_DEVICE_USAGE_METRICS =
        sysprop::InputProperties::enable_input_device_usage_metrics().value_or(true);

const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer();
const bool ENABLE_INPUT_FILTER_RUST = input_flags::enable_input_filter_rust_impl();

int32_t exceptionCodeFromStatusT(status_t status) {
    switch (status) {
@@ -118,6 +119,7 @@ std::shared_ptr<IInputFlingerRust> createInputFlingerRust() {
 * The event flow is via the "InputListener" interface, as follows:
 *   InputReader
 *     -> UnwantedInteractionBlocker
 *     -> InputFilter
 *     -> PointerChoreographer
 *     -> InputProcessor
 *     -> InputDeviceMetricsCollector
@@ -132,6 +134,12 @@ InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,
    mTracingStages.emplace_back(
            std::make_unique<TracedInputListener>("InputDispatcher", *mDispatcher));

    if (ENABLE_INPUT_FILTER_RUST) {
        mInputFilter = std::make_unique<InputFilter>(*mTracingStages.back(), *mInputFlingerRust);
        mTracingStages.emplace_back(
                std::make_unique<TracedInputListener>("InputFilter", *mInputFilter));
    }

    if (ENABLE_INPUT_DEVICE_USAGE_METRICS) {
        mCollector = std::make_unique<InputDeviceMetricsCollector>(*mTracingStages.back());
        mTracingStages.emplace_back(
Loading