InputDispatcher: Use correct coordinate space when canceling motions
Input targets for synthesized cancellations were not created using the
same pipeline as normal dispatching. Due to this, things like window and
display transforms were not being applied to the events. This means
ACTION_CANCEL events did not have the correct coordinates in many cases.
Here, we fix that by attempting to use the same pipeline as normal
dispatching for creating the input target. When it's not possible to do
due to there being no window (e.g. for global monitors), we fall back to
creating the target ourselves.
Bug: 287908447
Test: atest inputflinger_tests
Change-Id: Ic82f87c55e4eaf3e87b07986a14933fbdb69e042
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 6226a19..7fbd322 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -3944,7 +3944,6 @@
android_log_event_list(LOGTAG_INPUT_CANCEL)
<< connection->getInputChannelName().c_str() << reason << LOG_ID_EVENTS;
- InputTarget target;
sp<WindowInfoHandle> windowHandle;
if (options.displayId) {
windowHandle = getWindowHandleLocked(connection->inputChannel->getConnectionToken(),
@@ -3952,27 +3951,47 @@
} else {
windowHandle = getWindowHandleLocked(connection->inputChannel->getConnectionToken());
}
- if (windowHandle != nullptr) {
- const WindowInfo* windowInfo = windowHandle->getInfo();
- target.setDefaultPointerTransform(windowInfo->transform);
- target.globalScaleFactor = windowInfo->globalScaleFactor;
- }
- target.inputChannel = connection->inputChannel;
- target.flags = InputTarget::Flags::DISPATCH_AS_IS;
const bool wasEmpty = connection->outboundQueue.empty();
for (size_t i = 0; i < cancelationEvents.size(); i++) {
std::unique_ptr<EventEntry> cancelationEventEntry = std::move(cancelationEvents[i]);
+ std::vector<InputTarget> targets{};
+ // The target to use if we don't find a window associated with the channel.
+ const InputTarget fallbackTarget{.inputChannel = connection->inputChannel,
+ .flags = InputTarget::Flags::DISPATCH_AS_IS};
+
switch (cancelationEventEntry->type) {
case EventEntry::Type::KEY: {
- logOutboundKeyDetails("cancel - ",
- static_cast<const KeyEntry&>(*cancelationEventEntry));
+ const auto& keyEntry = static_cast<const KeyEntry&>(*cancelationEventEntry);
+ if (windowHandle != nullptr) {
+ addWindowTargetLocked(windowHandle, InputTarget::Flags::DISPATCH_AS_IS,
+ /*pointerIds=*/{}, keyEntry.downTime, targets);
+ } else {
+ targets.emplace_back(fallbackTarget);
+ }
+ logOutboundKeyDetails("cancel - ", keyEntry);
break;
}
case EventEntry::Type::MOTION: {
- logOutboundMotionDetails("cancel - ",
- static_cast<const MotionEntry&>(*cancelationEventEntry));
+ const auto& motionEntry = static_cast<const MotionEntry&>(*cancelationEventEntry);
+ if (windowHandle != nullptr) {
+ std::bitset<MAX_POINTER_ID + 1> pointerIds;
+ for (uint32_t pointerIndex = 0; pointerIndex < motionEntry.pointerCount;
+ pointerIndex++) {
+ pointerIds.set(motionEntry.pointerProperties[pointerIndex].id);
+ }
+ addWindowTargetLocked(windowHandle, InputTarget::Flags::DISPATCH_AS_IS,
+ pointerIds, motionEntry.downTime, targets);
+ } else {
+ targets.emplace_back(fallbackTarget);
+ const auto it = mDisplayInfos.find(motionEntry.displayId);
+ if (it != mDisplayInfos.end()) {
+ targets.back().displayTransform = it->second.transform;
+ targets.back().setDefaultPointerTransform(it->second.transform);
+ }
+ }
+ logOutboundMotionDetails("cancel - ", motionEntry);
break;
}
case EventEntry::Type::FOCUS:
@@ -3992,7 +4011,8 @@
}
}
- enqueueDispatchEntryLocked(connection, std::move(cancelationEventEntry), target,
+ if (targets.size() != 1) LOG(FATAL) << __func__ << ": InputTarget not created";
+ enqueueDispatchEntryLocked(connection, std::move(cancelationEventEntry), targets[0],
InputTarget::Flags::DISPATCH_AS_IS);
}