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

Commit d5333215 authored by Vaibhav Devmurari's avatar Vaibhav Devmurari Committed by Android (Google) Code Review
Browse files

Merge "Add InputFilter rust component as InputListener stage." into main

parents 34a5980f 5766aee0
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