blob: bb4e617bde2631eee9d349094d7c87105182680d [file]
/*
* 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;
using aidl::com::android::server::inputflinger::KeyEventAction;
using AidlDeviceInfo = aidl::com::android::server::inputflinger::DeviceInfo;
using aidl::android::hardware::input::common::Source;
AidlKeyEvent notifyKeyArgsToKeyEvent(const NotifyKeyArgs& args) {
AidlKeyEvent event;
event.id = args.id;
event.eventTime = args.eventTime;
event.deviceId = args.deviceId;
event.source = static_cast<Source>(args.source);
event.displayId = args.displayId.val();
event.policyFlags = args.policyFlags;
event.action = static_cast<KeyEventAction>(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;
}
InputFilter::InputFilter(InputListenerInterface& listener, IInputFlingerRust& rust,
InputFilterPolicyInterface& policy)
: mNextListener(listener),
mCallbacks(ndk::SharedRefBase::make<InputFilterCallbacks>(listener, policy)),
mPolicy(policy) {
LOG_ALWAYS_FATAL_IF(!rust.createInputFilter(mCallbacks, &mInputFilterRust).isOk());
LOG_ALWAYS_FATAL_IF(!mInputFilterRust);
}
void InputFilter::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
mDeviceInfos.clear();
mDeviceInfos.reserve(args.inputDeviceInfos.size());
for (const auto& info : args.inputDeviceInfos) {
AidlDeviceInfo& aidlInfo = mDeviceInfos.emplace_back();
aidlInfo.deviceId = info.getId();
aidlInfo.external = info.isExternal();
aidlInfo.keyboardType = info.getKeyboardType();
}
if (isFilterEnabled()) {
LOG_ALWAYS_FATAL_IF(!mInputFilterRust->notifyInputDevicesChanged(mDeviceInfos).isOk());
}
mNextListener.notify(args);
}
void InputFilter::notifyKey(const NotifyKeyArgs& args) {
if (isFilterEnabled()) {
LOG_ALWAYS_FATAL_IF(!mInputFilterRust->notifyKey(notifyKeyArgsToKeyEvent(args)).isOk());
return;
}
mNextListener.notify(args);
}
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::setAccessibilityBounceKeysThreshold(nsecs_t threshold) {
std::scoped_lock _l(mLock);
if (mConfig.bounceKeysThresholdNs != threshold) {
mConfig.bounceKeysThresholdNs = threshold;
notifyConfigurationChangedLocked();
}
}
void InputFilter::setAccessibilitySlowKeysThreshold(nsecs_t threshold) {
std::scoped_lock _l(mLock);
if (mConfig.slowKeysThresholdNs != threshold) {
mConfig.slowKeysThresholdNs = threshold;
notifyConfigurationChangedLocked();
}
}
void InputFilter::setAccessibilityStickyKeysEnabled(bool enabled) {
std::scoped_lock _l(mLock);
if (mConfig.stickyKeysEnabled != enabled) {
mConfig.stickyKeysEnabled = enabled;
notifyConfigurationChangedLocked();
if (!enabled) {
// When Sticky keys is disabled, send callback to clear any saved sticky state.
mPolicy.notifyStickyModifierStateChanged(0, 0);
}
}
}
void InputFilter::notifyConfigurationChangedLocked() {
LOG_ALWAYS_FATAL_IF(!mInputFilterRust->notifyConfigurationChanged(mConfig).isOk());
if (isFilterEnabled()) {
LOG_ALWAYS_FATAL_IF(!mInputFilterRust->notifyInputDevicesChanged(mDeviceInfos).isOk());
}
}
void InputFilter::dump(std::string& dump) {
dump += "InputFilter:\n";
if (isFilterEnabled()) {
std::string result;
LOG_ALWAYS_FATAL_IF(!mInputFilterRust->dumpFilter(&result).isOk());
dump += result;
dump += "\n";
}
}
} // namespace android