Skip to content

Commit 523b461

Browse files
author
Jimmy
committed
Add support for search modifier fallbacks
Fixes a bug in where kcm fallbacks with search based modifiers could not activate since PhoneWindowManager would consume all search events. This prevented the InputDispatcher from generating the fallback. This change modifies the behavior so InputDispatcher handles whether the search-based event will attempt to generate a fallback. Bug: 384113980 Test: atest InputDispatcherTest Flag: com.android.hardware.input.fix_search_modifier_fallbacks Change-Id: Ib7eca10f00ec93fd46a93396b7908ff925dd705b
1 parent 4c54b76 commit 523b461

8 files changed

Lines changed: 169 additions & 20 deletions

File tree

services/inputflinger/dispatcher/Entry.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,17 @@ struct KeyEntry : EventEntry {
125125
bool syntheticRepeat; // set to true for synthetic key repeats
126126

127127
enum class InterceptKeyResult {
128+
// The interception result is unknown.
128129
UNKNOWN,
130+
// The event should be skipped and not sent to the application.
129131
SKIP,
132+
// The event should be sent to the application.
130133
CONTINUE,
134+
// The event should eventually be sent to the application, after a delay.
131135
TRY_AGAIN_LATER,
136+
// The event should not be initially sent to the application, but instead go through
137+
// post-processing to generate a fallback key event and then sent to the application.
138+
FALLBACK,
132139
};
133140
// These are special fields that may need to be modified while the event is being dispatched.
134141
mutable InterceptKeyResult interceptKeyResult; // set based on the interception result

services/inputflinger/dispatcher/InputDispatcher.cpp

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,7 @@ InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
952952
new LatencyAggregatorWithHistograms()))
953953
: std::move(std::unique_ptr<InputEventTimelineProcessor>(
954954
new LatencyAggregator()))),
955-
mLatencyTracker(*mInputEventTimelineProcessor) {
955+
mLatencyTracker(*mInputEventTimelineProcessor, mInputDevices) {
956956
mReporter = createInputReporter();
957957

958958
mWindowInfoListener = sp<DispatcherWindowListener>::make(*this);
@@ -1961,11 +1961,74 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<con
19611961
}
19621962
}
19631963

1964+
if (entry->interceptKeyResult == KeyEntry::InterceptKeyResult::FALLBACK) {
1965+
findAndDispatchFallbackEvent(currentTime, entry, inputTargets);
1966+
// Drop the key.
1967+
return true;
1968+
}
1969+
19641970
// Dispatch the key.
19651971
dispatchEventLocked(currentTime, entry, inputTargets);
19661972
return true;
19671973
}
19681974

1975+
void InputDispatcher::findAndDispatchFallbackEvent(nsecs_t currentTime,
1976+
std::shared_ptr<const KeyEntry> entry,
1977+
std::vector<InputTarget>& inputTargets) {
1978+
// Find the fallback associated with the incoming key event and dispatch it.
1979+
KeyEvent event = createKeyEvent(*entry);
1980+
const int32_t originalKeyCode = entry->keyCode;
1981+
1982+
// Fetch the fallback event.
1983+
KeyCharacterMap::FallbackAction fallback;
1984+
for (const InputDeviceInfo& deviceInfo : mInputDevices) {
1985+
if (deviceInfo.getId() == entry->deviceId) {
1986+
const KeyCharacterMap* map = deviceInfo.getKeyCharacterMap();
1987+
1988+
LOG_ALWAYS_FATAL_IF(map == nullptr, "No KeyCharacterMap for device %d",
1989+
entry->deviceId);
1990+
map->getFallbackAction(entry->keyCode, entry->metaState, &fallback);
1991+
break;
1992+
}
1993+
}
1994+
1995+
if (fallback.keyCode == AKEYCODE_UNKNOWN) {
1996+
// No fallback detected.
1997+
return;
1998+
}
1999+
2000+
std::unique_ptr<KeyEntry> fallbackKeyEntry =
2001+
std::make_unique<KeyEntry>(mIdGenerator.nextId(), entry->injectionState,
2002+
event.getEventTime(), event.getDeviceId(), event.getSource(),
2003+
event.getDisplayId(), entry->policyFlags, entry->action,
2004+
event.getFlags() | AKEY_EVENT_FLAG_FALLBACK,
2005+
fallback.keyCode, event.getScanCode(), /*metaState=*/0,
2006+
event.getRepeatCount(), event.getDownTime());
2007+
2008+
if (mTracer) {
2009+
fallbackKeyEntry->traceTracker =
2010+
mTracer->traceDerivedEvent(*fallbackKeyEntry, *entry->traceTracker);
2011+
}
2012+
2013+
for (const InputTarget& inputTarget : inputTargets) {
2014+
std::shared_ptr<Connection> connection = inputTarget.connection;
2015+
if (!connection->responsive || (connection->status != Connection::Status::NORMAL)) {
2016+
return;
2017+
}
2018+
2019+
connection->inputState.setFallbackKey(originalKeyCode, fallback.keyCode);
2020+
if (entry->action == AKEY_EVENT_ACTION_UP) {
2021+
connection->inputState.removeFallbackKey(originalKeyCode);
2022+
}
2023+
2024+
if (mTracer) {
2025+
mTracer->dispatchToTargetHint(*fallbackKeyEntry->traceTracker, inputTarget);
2026+
}
2027+
enqueueDispatchEntryAndStartDispatchCycleLocked(currentTime, connection,
2028+
std::move(fallbackKeyEntry), inputTarget);
2029+
}
2030+
}
2031+
19692032
void InputDispatcher::logOutboundKeyDetails(const char* prefix, const KeyEntry& entry) {
19702033
LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
19712034
<< prefix << "eventTime=" << entry.eventTime << ", deviceId=" << entry.deviceId
@@ -4346,7 +4409,7 @@ void InputDispatcher::notifyInputDevicesChanged(const NotifyInputDevicesChangedA
43464409
std::scoped_lock _l(mLock);
43474410
// Reset key repeating in case a keyboard device was added or removed or something.
43484411
resetKeyRepeatLocked();
4349-
mLatencyTracker.setInputDevices(args.inputDeviceInfos);
4412+
mInputDevices = args.inputDeviceInfos;
43504413
}
43514414

43524415
void InputDispatcher::notifyKey(const NotifyKeyArgs& args) {

services/inputflinger/dispatcher/InputDispatcher.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,10 +918,14 @@ class InputDispatcher : public android::InputDispatcherInterface {
918918
std::unique_ptr<const KeyEntry> afterKeyEventLockedInterruptable(
919919
const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry,
920920
bool handled) REQUIRES(mLock);
921+
void findAndDispatchFallbackEvent(nsecs_t currentTime, std::shared_ptr<const KeyEntry> entry,
922+
std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
921923

922924
// Statistics gathering.
923925
nsecs_t mLastStatisticPushTime = 0;
924926
std::unique_ptr<InputEventTimelineProcessor> mInputEventTimelineProcessor GUARDED_BY(mLock);
927+
// Must outlive `mLatencyTracker`.
928+
std::vector<InputDeviceInfo> mInputDevices;
925929
LatencyTracker mLatencyTracker GUARDED_BY(mLock);
926930
void traceInboundQueueLengthLocked() REQUIRES(mLock);
927931
void traceOutboundQueueLength(const Connection& connection);

services/inputflinger/dispatcher/LatencyTracker.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ static void eraseByValue(std::multimap<K, V>& map, const V& value) {
6767

6868
} // namespace
6969

70-
LatencyTracker::LatencyTracker(InputEventTimelineProcessor& processor)
71-
: mTimelineProcessor(&processor) {}
70+
LatencyTracker::LatencyTracker(InputEventTimelineProcessor& processor,
71+
std::vector<InputDeviceInfo>& inputDevices)
72+
: mTimelineProcessor(&processor), mInputDevices(inputDevices) {}
7273

7374
void LatencyTracker::trackListener(const NotifyArgs& args) {
7475
if (const NotifyKeyArgs* keyArgs = std::get_if<NotifyKeyArgs>(&args)) {
@@ -248,8 +249,4 @@ std::string LatencyTracker::dump(const char* prefix) const {
248249
StringPrintf("%s mEventTimes.size() = %zu\n", prefix, mEventTimes.size());
249250
}
250251

251-
void LatencyTracker::setInputDevices(const std::vector<InputDeviceInfo>& inputDevices) {
252-
mInputDevices = inputDevices;
253-
}
254-
255252
} // namespace android::inputdispatcher

services/inputflinger/dispatcher/LatencyTracker.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020

2121
#include <map>
2222
#include <unordered_map>
23+
#include <vector>
2324

2425
#include <binder/IBinder.h>
2526
#include <input/Input.h>
27+
#include <input/InputDevice.h>
2628

2729
#include "InputEventTimeline.h"
2830
#include "NotifyArgs.h"
@@ -41,8 +43,10 @@ class LatencyTracker {
4143
/**
4244
* Create a LatencyTracker.
4345
* param reportingFunction: the function that will be called in order to report full latency.
46+
* param inputDevices: input devices relevant for tracking.
4447
*/
45-
LatencyTracker(InputEventTimelineProcessor& processor);
48+
LatencyTracker(InputEventTimelineProcessor& processor,
49+
std::vector<InputDeviceInfo>& inputDevices);
4650
/**
4751
* Start keeping track of an event identified by the args. This must be called first.
4852
* If duplicate events are encountered (events that have the same eventId), none of them will be
@@ -60,7 +64,6 @@ class LatencyTracker {
6064
std::array<nsecs_t, GraphicsTimeline::SIZE> timeline);
6165

6266
std::string dump(const char* prefix) const;
63-
void setInputDevices(const std::vector<InputDeviceInfo>& inputDevices);
6467

6568
private:
6669
/**
@@ -81,7 +84,7 @@ class LatencyTracker {
8184
std::multimap<nsecs_t /*eventTime*/, int32_t /*inputEventId*/> mEventTimes;
8285

8386
InputEventTimelineProcessor* mTimelineProcessor;
84-
std::vector<InputDeviceInfo> mInputDevices;
87+
std::vector<InputDeviceInfo>& mInputDevices;
8588

8689
void trackListener(int32_t inputEventId, nsecs_t eventTime, nsecs_t readTime, DeviceId deviceId,
8790
const std::set<InputDeviceUsageSource>& sources, int32_t inputEventAction,

services/inputflinger/tests/InputDispatcher_test.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <input/BlockingQueue.h>
3838
#include <input/Input.h>
3939
#include <input/InputConsumer.h>
40+
#include <input/KeyCharacterMap.h>
4041
#include <input/PrintTools.h>
4142
#include <linux/input.h>
4243
#include <sys/epoll.h>
@@ -139,6 +140,30 @@ static KeyEvent getTestKeyEvent() {
139140
return event;
140141
}
141142

143+
InputDeviceInfo generateTestDeviceInfo(uint16_t vendorId, uint16_t productId, DeviceId deviceId) {
144+
InputDeviceIdentifier identifier;
145+
identifier.vendor = vendorId;
146+
identifier.product = productId;
147+
auto info = InputDeviceInfo();
148+
info.initialize(deviceId, /*generation=*/1, /*controllerNumber=*/1, identifier, "Test Device",
149+
/*isExternal=*/false, /*hasMic=*/false, ui::LogicalDisplayId::INVALID);
150+
return info;
151+
}
152+
153+
std::unique_ptr<KeyCharacterMap> loadKeyCharacterMap(const char* name) {
154+
InputDeviceIdentifier identifier;
155+
identifier.name = name;
156+
std::string path = getInputDeviceConfigurationFilePathByName(identifier.getCanonicalName(),
157+
InputDeviceConfigurationFileType::
158+
KEY_CHARACTER_MAP);
159+
160+
if (path.empty()) {
161+
return nullptr;
162+
}
163+
164+
return *KeyCharacterMap::load(path, KeyCharacterMap::Format::BASE);
165+
}
166+
142167
} // namespace
143168

144169
// --- InputDispatcherTest ---
@@ -7480,6 +7505,50 @@ TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserAct
74807505
mFakePolicy->assertUserActivityPoked();
74817506
}
74827507

7508+
TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyFallbackKey) {
7509+
#if !defined(__ANDROID__)
7510+
GTEST_SKIP() << "b/253299089 Generic files are currently read directly from device.";
7511+
#endif
7512+
InputDeviceInfo testDevice = generateTestDeviceInfo(/*vendorId=*/0,
7513+
/*productId=*/0, /*deviceId=*/1);
7514+
std::unique_ptr<KeyCharacterMap> kcm = loadKeyCharacterMap("Generic");
7515+
ASSERT_NE(nullptr, kcm);
7516+
7517+
testDevice.setKeyCharacterMap(std::move(kcm));
7518+
mDispatcher->notifyInputDevicesChanged(NotifyInputDevicesChangedArgs(/*id=*/1, {testDevice}));
7519+
7520+
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7521+
sp<FakeWindowHandle> window =
7522+
sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7523+
ui::LogicalDisplayId::DEFAULT);
7524+
7525+
window->setFocusable(true);
7526+
mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7527+
setFocusedWindow(window);
7528+
7529+
window->consumeFocusEvent(true);
7530+
7531+
mFakePolicy->setInterceptKeyBeforeDispatchingResult(
7532+
inputdispatcher::KeyEntry::InterceptKeyResult::FALLBACK);
7533+
7534+
// In the Generic KCM fallbacks, Meta + Space => SEARCH.
7535+
mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7536+
.keyCode(AKEYCODE_SPACE)
7537+
.metaState(AMETA_META_ON)
7538+
.build());
7539+
mDispatcher->waitForIdle();
7540+
7541+
// Should have poked user activity
7542+
mFakePolicy->assertUserActivityPoked();
7543+
7544+
// Fallback is generated and sent instead.
7545+
std::unique_ptr<KeyEvent> consumedEvent = window->consumeKey(/*handled=*/false);
7546+
ASSERT_NE(nullptr, consumedEvent);
7547+
ASSERT_THAT(*consumedEvent,
7548+
AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_SEARCH),
7549+
WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7550+
}
7551+
74837552
class DisableUserActivityInputDispatcherTest : public InputDispatcherTest,
74847553
public ::testing::WithParamInterface<bool> {};
74857554

services/inputflinger/tests/LatencyTracker_test.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@
1919
#include "NotifyArgsBuilders.h"
2020
#include "android/input.h"
2121

22+
#include <vector>
23+
2224
#include <android-base/logging.h>
2325
#include <android-base/properties.h>
2426
#include <binder/Binder.h>
2527
#include <gtest/gtest.h>
28+
#include <input/InputDevice.h>
2629
#include <input/PrintTools.h>
2730
#include <inttypes.h>
2831
#include <linux/input.h>
@@ -51,11 +54,6 @@ static InputDeviceInfo generateTestDeviceInfo(uint16_t vendorId, uint16_t produc
5154
return info;
5255
}
5356

54-
void setDefaultInputDeviceInfo(LatencyTracker& tracker) {
55-
InputDeviceInfo deviceInfo = generateTestDeviceInfo(/*vendorId=*/0, /*productId=*/0, DEVICE_ID);
56-
tracker.setInputDevices({deviceInfo});
57-
}
58-
5957
const auto FIRST_TOUCH_POINTER = PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200);
6058
const auto FIRST_MOUSE_POINTER = PointerBuilder(/*id=*/1, ToolType::MOUSE);
6159

@@ -120,13 +118,14 @@ class LatencyTrackerTest : public testing::Test, public InputEventTimelineProces
120118
std::unique_ptr<LatencyTracker> mTracker;
121119
sp<IBinder> connection1;
122120
sp<IBinder> connection2;
121+
std::vector<InputDeviceInfo> inputDevices;
123122

124123
void SetUp() override {
125124
connection1 = sp<BBinder>::make();
126125
connection2 = sp<BBinder>::make();
127126

128-
mTracker = std::make_unique<LatencyTracker>(*this);
129-
setDefaultInputDeviceInfo(*mTracker);
127+
inputDevices.push_back(generateTestDeviceInfo(/*vendorId=*/0, /*productId=*/0, DEVICE_ID));
128+
mTracker = std::make_unique<LatencyTracker>(*this, inputDevices);
130129
}
131130
void TearDown() override {}
132131

@@ -140,6 +139,10 @@ class LatencyTrackerTest : public testing::Test, public InputEventTimelineProces
140139
*/
141140
void assertReceivedTimelines(const std::vector<InputEventTimeline>& timelines);
142141

142+
void updateInputDevices(const std::vector<InputDeviceInfo>& inputDevicesUpdated) {
143+
inputDevices = inputDevicesUpdated;
144+
}
145+
143146
private:
144147
void processTimeline(const InputEventTimeline& timeline) override {
145148
mReceivedTimelines.push_back(timeline);
@@ -448,7 +451,7 @@ TEST_F(LatencyTrackerTest, TrackListenerCheck_DeviceInfoFieldsInputEventTimeline
448451
deviceInfo2.addSource(AINPUT_SOURCE_TOUCHSCREEN);
449452
deviceInfo2.addSource(AINPUT_SOURCE_STYLUS);
450453

451-
mTracker->setInputDevices({deviceInfo1, deviceInfo2});
454+
updateInputDevices({deviceInfo1, deviceInfo2});
452455
mTracker->trackListener(
453456
MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL,
454457
AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, inputEventId)

services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <fuzzer/FuzzedDataProvider.h>
1818
#include <linux/input.h>
1919

20+
#include <vector>
21+
2022
#include "../../InputDeviceMetricsSource.h"
2123
#include "../InputEventTimeline.h"
2224
#include "NotifyArgsBuilders.h"
@@ -58,7 +60,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
5860
FuzzedDataProvider fdp(data, size);
5961

6062
EmptyProcessor emptyProcessor;
61-
LatencyTracker tracker(emptyProcessor);
63+
std::vector<InputDeviceInfo> emptyDevices;
64+
LatencyTracker tracker(emptyProcessor, emptyDevices);
6265

6366
// Make some pre-defined tokens to ensure that some timelines are complete.
6467
std::array<sp<IBinder> /*token*/, 10> predefinedTokens;

0 commit comments

Comments
 (0)