Skip to content

Commit 5dde97f

Browse files
Treehugger RobotAndroid (Google) Code Review
authored andcommitted
Merge "Add support for search modifier fallbacks" into main
2 parents bcbec20 + 523b461 commit 5dde97f

File tree

8 files changed

+169
-20
lines changed

8 files changed

+169
-20
lines changed

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)