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
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index 3672387..a807d82 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -62,3 +62,10 @@
   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"
+}
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 76729ef..10f386e 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -76,6 +76,7 @@
     srcs: [
         "InputCommonConverter.cpp",
         "InputDeviceMetricsCollector.cpp",
+        "InputFilter.cpp",
         "InputProcessor.cpp",
         "PointerChoreographer.cpp",
         "PreferStylusOverTouchBlocker.cpp",
diff --git a/services/inputflinger/InputFilter.cpp b/services/inputflinger/InputFilter.cpp
new file mode 100644
index 0000000..1b8fad3
--- /dev/null
+++ b/services/inputflinger/InputFilter.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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
diff --git a/services/inputflinger/InputFilter.h b/services/inputflinger/InputFilter.h
new file mode 100644
index 0000000..699f3a0
--- /dev/null
+++ b/services/inputflinger/InputFilter.h
@@ -0,0 +1,64 @@
+/*
+ * 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
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 92c65e1..8cf61f9 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -42,6 +42,7 @@
         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 @@
  * The event flow is via the "InputListener" interface, as follows:
  *   InputReader
  *     -> UnwantedInteractionBlocker
+ *     -> InputFilter
  *     -> PointerChoreographer
  *     -> InputProcessor
  *     -> InputDeviceMetricsCollector
@@ -132,6 +134,12 @@
     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(
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 20b9fd5..aea7bd5 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -21,6 +21,7 @@
  */
 
 #include "InputDeviceMetricsCollector.h"
+#include "InputFilter.h"
 #include "InputProcessor.h"
 #include "InputReaderBase.h"
 #include "PointerChoreographer.h"
@@ -40,6 +41,7 @@
 
 using android::os::BnInputFlinger;
 
+using aidl::com::android::server::inputflinger::IInputFilter;
 using aidl::com::android::server::inputflinger::IInputFlingerRust;
 
 namespace android {
@@ -137,6 +139,8 @@
 
     std::unique_ptr<UnwantedInteractionBlockerInterface> mBlocker;
 
+    std::unique_ptr<InputFilterInterface> mInputFilter;
+
     std::unique_ptr<PointerChoreographerInterface> mChoreographer;
 
     std::unique_ptr<InputProcessorInterface> mProcessor;
diff --git a/services/inputflinger/aidl/com/android/server/inputflinger/IInputFilter.aidl b/services/inputflinger/aidl/com/android/server/inputflinger/IInputFilter.aidl
new file mode 100644
index 0000000..44f959e
--- /dev/null
+++ b/services/inputflinger/aidl/com/android/server/inputflinger/IInputFilter.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package com.android.server.inputflinger;
+
+import com.android.server.inputflinger.KeyEvent;
+
+/**
+ * A local AIDL interface used as a foreign function interface (ffi) to
+ * filter input events.
+ *
+ * NOTE: Since we use this as a local interface, all processing happens on the
+ * calling thread.
+ */
+interface IInputFilter {
+
+    /** Callbacks for the rust InputFilter to call into C++. */
+    interface IInputFilterCallbacks {
+        /** Sends back a filtered key event */
+        void sendKeyEvent(in KeyEvent event);
+    }
+
+    /** Returns if InputFilter is enabled */
+    boolean isEnabled();
+
+    /** Notifies if a key event occurred */
+    void notifyKey(in KeyEvent event);
+
+    /** Notifies if any InputDevice list changed and provides the list of connected peripherals */
+    void notifyInputDevicesChanged(in int[] deviceIds);
+}
+
diff --git a/services/inputflinger/aidl/com/android/server/inputflinger/IInputFlingerRust.aidl b/services/inputflinger/aidl/com/android/server/inputflinger/IInputFlingerRust.aidl
index 8e826fd..de852c0 100644
--- a/services/inputflinger/aidl/com/android/server/inputflinger/IInputFlingerRust.aidl
+++ b/services/inputflinger/aidl/com/android/server/inputflinger/IInputFlingerRust.aidl
@@ -16,6 +16,9 @@
 
 package com.android.server.inputflinger;
 
+import com.android.server.inputflinger.IInputFilter;
+import com.android.server.inputflinger.IInputFilter.IInputFilterCallbacks;
+
 /**
  * A local AIDL interface used as a foreign function interface (ffi) to
  * communicate with the Rust component of inputflinger.
@@ -31,4 +34,7 @@
     interface IInputFlingerRustBootstrapCallback {
         void onProvideInputFlingerRust(in IInputFlingerRust inputFlingerRust);
     }
+
+    /** Create the rust implementation of InputFilter. */
+    IInputFilter createInputFilter(IInputFilterCallbacks callbacks);
 }
diff --git a/services/inputflinger/aidl/com/android/server/inputflinger/KeyEvent.aidl b/services/inputflinger/aidl/com/android/server/inputflinger/KeyEvent.aidl
new file mode 100644
index 0000000..e213221
--- /dev/null
+++ b/services/inputflinger/aidl/com/android/server/inputflinger/KeyEvent.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package com.android.server.inputflinger;
+
+/**
+ * Analogous to Android's native KeyEvent / NotifyKeyArgs.
+ * Stores the basic information about Key events.
+ */
+parcelable KeyEvent {
+    int id;
+    int deviceId;
+    long downTime;
+    long readTime;
+    long eventTime;
+    int source;
+    int displayId;
+    int policyFlags;
+    int action;
+    int flags;
+    int keyCode;
+    int scanCode;
+    int metaState;
+}
\ No newline at end of file
diff --git a/services/inputflinger/rust/Android.bp b/services/inputflinger/rust/Android.bp
index 23c1691..2775bcc 100644
--- a/services/inputflinger/rust/Android.bp
+++ b/services/inputflinger/rust/Android.bp
@@ -31,8 +31,8 @@
     out: ["inputflinger_bootstrap.rs.h"],
 }
 
-rust_ffi_static {
-    name: "libinputflinger_rs",
+rust_defaults {
+    name: "libinputflinger_rs_defaults",
     crate_name: "inputflinger",
     srcs: ["lib.rs"],
     rustlibs: [
@@ -45,6 +45,24 @@
     host_supported: true,
 }
 
+rust_ffi_static {
+    name: "libinputflinger_rs",
+    defaults: ["libinputflinger_rs_defaults"],
+}
+
+rust_test {
+    name: "libinputflinger_rs_test",
+    defaults: ["libinputflinger_rs_defaults"],
+    test_options: {
+        unit_test: true,
+    },
+    test_suites: ["device_tests"],
+    sanitize: {
+        address: true,
+        hwaddress: true,
+    },
+}
+
 cc_library_headers {
     name: "inputflinger_rs_bootstrap_cxx_headers",
     host_supported: true,
diff --git a/services/inputflinger/rust/input_filter.rs b/services/inputflinger/rust/input_filter.rs
new file mode 100644
index 0000000..5851877
--- /dev/null
+++ b/services/inputflinger/rust/input_filter.rs
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+//! InputFilter manages all the filtering components that can intercept events, modify the events,
+//! block events, etc depending on the situation. This will be used support Accessibility features
+//! like Slow keys, Bounce keys, etc.
+
+use binder::{Interface, Strong};
+use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
+    IInputFilter::{IInputFilter, IInputFilterCallbacks::IInputFilterCallbacks},
+    KeyEvent::KeyEvent,
+};
+
+/// The rust implementation of InputFilter
+pub struct InputFilter {
+    callbacks: Strong<dyn IInputFilterCallbacks>,
+}
+
+impl Interface for InputFilter {}
+
+impl InputFilter {
+    /// Create a new InputFilter instance.
+    pub fn new(callbacks: Strong<dyn IInputFilterCallbacks>) -> InputFilter {
+        Self { callbacks }
+    }
+}
+
+impl IInputFilter for InputFilter {
+    fn isEnabled(&self) -> binder::Result<bool> {
+        // TODO(b/294546335): Return true if any filters are to be applied, false otherwise
+        Result::Ok(false)
+    }
+    fn notifyKey(&self, event: &KeyEvent) -> binder::Result<()> {
+        // TODO(b/294546335): Handle key event and modify key events here
+        // Just send back the event without processing for now.
+        let _ = self.callbacks.sendKeyEvent(event);
+        Result::Ok(())
+    }
+    fn notifyInputDevicesChanged(&self, _device_ids: &[i32]) -> binder::Result<()> {
+        // TODO(b/294546335): Update data based on device changes here
+        Result::Ok(())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::input_filter::InputFilter;
+    use binder::{Interface, Strong};
+    use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
+        IInputFilter::IInputFilter, IInputFilter::IInputFilterCallbacks::IInputFilterCallbacks,
+        KeyEvent::KeyEvent,
+    };
+
+    struct FakeCallbacks {}
+
+    impl Interface for FakeCallbacks {}
+
+    impl IInputFilterCallbacks for FakeCallbacks {
+        fn sendKeyEvent(&self, _event: &KeyEvent) -> binder::Result<()> {
+            Result::Ok(())
+        }
+    }
+
+    #[test]
+    fn test_is_enabled() {
+        let fake_callbacks: Strong<dyn IInputFilterCallbacks> =
+            Strong::new(Box::new(FakeCallbacks {}));
+        let filter: Box<dyn IInputFilter> = Box::new(InputFilter::new(fake_callbacks));
+        let result = filter.isEnabled();
+        assert!(result.is_ok());
+        assert!(!result.unwrap());
+    }
+
+    #[test]
+    fn test_notify_key() {
+        let fake_callbacks: Strong<dyn IInputFilterCallbacks> =
+            Strong::new(Box::new(FakeCallbacks {}));
+        let filter: Box<dyn IInputFilter> = Box::new(InputFilter::new(fake_callbacks));
+        let event = create_key_event();
+        assert!(filter.notifyKey(&event).is_ok());
+    }
+
+    #[test]
+    fn test_notify_devices_changed() {
+        let fake_callbacks: Strong<dyn IInputFilterCallbacks> =
+            Strong::new(Box::new(FakeCallbacks {}));
+        let filter: Box<dyn IInputFilter> = Box::new(InputFilter::new(fake_callbacks));
+        let result = filter.notifyInputDevicesChanged(&[0]);
+        assert!(result.is_ok());
+    }
+
+    fn create_key_event() -> KeyEvent {
+        KeyEvent {
+            id: 1,
+            deviceId: 1,
+            downTime: 0,
+            readTime: 0,
+            eventTime: 0,
+            source: 0,
+            displayId: 0,
+            policyFlags: 0,
+            action: 0,
+            flags: 0,
+            keyCode: 0,
+            scanCode: 0,
+            metaState: 0,
+        }
+    }
+}
diff --git a/services/inputflinger/rust/lib.rs b/services/inputflinger/rust/lib.rs
index 501e435..a4049d5 100644
--- a/services/inputflinger/rust/lib.rs
+++ b/services/inputflinger/rust/lib.rs
@@ -19,13 +19,19 @@
 //! We use cxxbridge to create IInputFlingerRust - the Rust component of inputflinger - and
 //! pass it back to C++ as a local AIDL interface.
 
+mod input_filter;
+
+use crate::input_filter::InputFilter;
 use binder::{
-    unstable_api::{AIBinder, new_spibinder,},
+    unstable_api::{new_spibinder, AIBinder},
     BinderFeatures, Interface, StatusCode, Strong,
 };
-use com_android_server_inputflinger::aidl::com::android::server::inputflinger::IInputFlingerRust::{
-    BnInputFlingerRust, IInputFlingerRust,
-    IInputFlingerRustBootstrapCallback::IInputFlingerRustBootstrapCallback,
+use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
+    IInputFilter::{BnInputFilter, IInputFilter, IInputFilterCallbacks::IInputFilterCallbacks},
+    IInputFlingerRust::{
+        BnInputFlingerRust, IInputFlingerRust,
+        IInputFlingerRustBootstrapCallback::IInputFlingerRustBootstrapCallback,
+    },
 };
 use log::debug;
 
@@ -71,8 +77,8 @@
     // SAFETY: Our caller guaranteed that `callback` is a valid pointer to an `AIBinder` and its
     // reference count has been incremented..
     let Some(callback) = (unsafe { new_spibinder(callback) }) else {
-            panic!("Failed to get SpAIBinder from raw callback pointer");
-        };
+        panic!("Failed to get SpAIBinder from raw callback pointer");
+    };
 
     let callback: Result<Strong<dyn IInputFlingerRustBootstrapCallback>, StatusCode> =
         callback.into_interface();
@@ -93,7 +99,19 @@
 
 impl Interface for InputFlingerRust {}
 
-impl IInputFlingerRust for InputFlingerRust {}
+impl IInputFlingerRust for InputFlingerRust {
+    fn createInputFilter(
+        &self,
+        callbacks: &Strong<dyn IInputFilterCallbacks>,
+    ) -> binder::Result<Strong<dyn IInputFilter>> {
+        debug!("Creating InputFilter");
+        let filter = BnInputFilter::new_binder(
+            InputFilter::new(callbacks.clone()),
+            BinderFeatures::default(),
+        );
+        Result::Ok(filter)
+    }
+}
 
 impl Drop for InputFlingerRust {
     fn drop(&mut self) {