input: allow touchpads to be disabled
For accessibility reasons, we want users to be able to disable
touchpads. For example, users who are visually impaired may want to
disable the touchpad from a keyboard/touchpad combo device to avoid
accidental clicks or pointer movements, while still using the keyboard.
This can be tested with the following ADB command:
$ adb shell settings put system touchpad_enabled 0
(Or the same with 1 to re-enable.)
Test: connect a touchpad, disable touchpads, check it stops working.
Turn the toggle back on, check it starts working
Test: with touchpads disabled, connect a touchpad, check it doesn't
work. Turn the toggle back on, check it starts working
Test: with a keyboard/touchpad combo (I tested with the Lenovo P12 Pro's
detachable unit), check that the keyboard remains usable when the
touchpad is disabled
Flag: com.android.hardware.input.touchpad_disable
Bug: 372857036
Change-Id: Ia2701cba221c4664673836e1a8267203022c34cd
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index f45ed57..da08504 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -190,6 +190,9 @@
// True to enable system gestures (three- and four-finger swipes) on touchpads.
bool touchpadSystemGesturesEnabled;
+ // True to enable touchpads.
+ bool touchpadsEnabled;
+
// The set of currently disabled input devices.
std::set<int32_t> disabledDevices;
@@ -233,6 +236,7 @@
touchpadRightClickZoneEnabled(false),
touchpadThreeFingerTapShortcutEnabled(false),
touchpadSystemGesturesEnabled(true),
+ touchpadsEnabled(true),
stylusButtonMotionEventsEnabled(true),
stylusPointerIconEnabled(false),
mouseReverseVerticalScrollingEnabled(false),
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 98713cc..cc42e6d 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -23,6 +23,7 @@
#include <android/sysprop/InputProperties.sysprop.h>
#include <ftl/flags.h>
+#include <input/Input.h>
#include "CursorInputMapper.h"
#include "ExternalStylusInputMapper.h"
@@ -91,7 +92,11 @@
}
std::list<NotifyArgs> out;
- if (isEnabled() == enable) {
+ // Generally, we can't enable/disable subdevices - this is only possible for the "InputDevice"
+ // object, which is the composite device. However, for touchpads, it's possible that a touchpad
+ // is a subdevice. For those cases, we need to go into the code below to see if this touchpad is
+ // part of a device.
+ if (isEnabled() == enable && !isFromSource(mSources, AINPUT_SOURCE_TOUCHPAD)) {
return out;
}
@@ -99,7 +104,20 @@
// performed. The querying must happen when the device is enabled, so we reset after enabling
// but before disabling the device. See MultiTouchMotionAccumulator::reset for more information.
if (enable) {
- for_each_subdevice([](auto& context) { context.enableDevice(); });
+ for_each_subdevice([this, &readerConfig](auto& context) {
+ uint32_t sources = 0;
+ for_each_mapper_in_subdevice(context.getEventHubId(),
+ [&](auto& mapper) { sources |= mapper.getSources(); });
+ if (!readerConfig.touchpadsEnabled && isFromSource(sources, AINPUT_SOURCE_TOUCHPAD)) {
+ ALOGI("Disabling subdevice of '%s' with eventHubId %d because touchpads are "
+ "disabled and it has source %s",
+ getName().c_str(), context.getEventHubId(),
+ inputEventSourceToString(sources).c_str());
+ context.disableDevice();
+ } else {
+ context.enableDevice();
+ }
+ });
out += reset(when);
} else {
out += reset(when);