InputDispatcher: Use a single dispatch mode per target
Previously, the concept of dispatch mode was intertwined with
InputTarget flags. Since dispatch modes were part of the flags, it was
possible for an InputTarget of one event to be receive the event through
more than one dispatch mode.
Right now, there should be no use case for a target to have one event
dispatched through multiple dispatch modes. Even for the case in which
an ACTION_DOWN for a hovering pointer should generate both HOVER_EXIT
and ACTION_DOWN, this process is handled by using two InputTargets
instead of reusing one target to send both events.
We pull out the dispatch modes from the target flags into its own enum.
Dispatch modes are no longer flags, so each input target will have
exactly one dispatch mode. If an event should be dispatched via multiple
modes to the same window, mutiple InputTargets should be used.
Bug: 210460522
Test: atest inpuflinger_tests
Change-Id: I6c3f082ad48e312db6fcdeb7ef7c158d9dc53c2d
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 6ad3de0..a4529e6 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -649,7 +649,7 @@
if (newWindows.find(oldWindow) == newWindows.end()) {
TouchedWindow touchedWindow;
touchedWindow.windowHandle = oldWindow;
- touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_HOVER_EXIT;
+ touchedWindow.dispatchMode = InputTarget::DispatchMode::HOVER_EXIT;
out.push_back(touchedWindow);
}
}
@@ -660,7 +660,7 @@
if (oldWindows.find(newWindow) == oldWindows.end()) {
// Any windows that have this pointer now, and didn't have it before, should get
// HOVER_ENTER
- touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_HOVER_ENTER;
+ touchedWindow.dispatchMode = InputTarget::DispatchMode::HOVER_ENTER;
} else {
// This pointer was already sent to the window. Use ACTION_HOVER_MOVE.
if (CC_UNLIKELY(maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE)) {
@@ -674,7 +674,7 @@
}
LOG(severity) << "Expected ACTION_HOVER_MOVE instead of " << entry.getDescription();
}
- touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_IS;
+ touchedWindow.dispatchMode = InputTarget::DispatchMode::AS_IS;
}
touchedWindow.addHoveringPointer(entry.deviceId, pointerId);
if (canReceiveForegroundTouches(*newWindow->getInfo())) {
@@ -1316,8 +1316,8 @@
if (info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
std::bitset<MAX_POINTER_ID + 1> pointerIds;
pointerIds.set(pointerId);
- addPointerWindowTargetLocked(windowHandle, InputTarget::Flags::DISPATCH_AS_OUTSIDE,
- pointerIds,
+ addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::OUTSIDE,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
/*firstDownTimeInTarget=*/std::nullopt, outsideTargets);
}
}
@@ -1595,7 +1595,6 @@
}
InputTarget target;
target.inputChannel = channel;
- target.flags = InputTarget::Flags::DISPATCH_AS_IS;
entry->dispatchInProgress = true;
std::string message = std::string("Focus ") + (entry->hasFocus ? "entering " : "leaving ") +
channel->getName();
@@ -1669,7 +1668,6 @@
}
InputTarget target;
target.inputChannel = channel;
- target.flags = InputTarget::Flags::DISPATCH_AS_IS;
entry->dispatchInProgress = true;
dispatchEventLocked(currentTime, entry, {target});
@@ -1706,7 +1704,6 @@
}
InputTarget target;
target.inputChannel = channel;
- target.flags = InputTarget::Flags::DISPATCH_AS_IS;
inputTargets.push_back(target);
}
return inputTargets;
@@ -1822,9 +1819,8 @@
LOG_ALWAYS_FATAL_IF(focusedWindow == nullptr);
std::vector<InputTarget> inputTargets;
- addWindowTargetLocked(focusedWindow,
- InputTarget::Flags::FOREGROUND | InputTarget::Flags::DISPATCH_AS_IS,
- getDownTime(*entry), inputTargets);
+ addWindowTargetLocked(focusedWindow, InputTarget::DispatchMode::AS_IS,
+ InputTarget::Flags::FOREGROUND, getDownTime(*entry), inputTargets);
// Add monitor channels from event's or focused display.
addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
@@ -1929,10 +1925,9 @@
findFocusedWindowTargetLocked(currentTime, *entry, nextWakeupTime, injectionResult);
if (injectionResult == InputEventInjectionResult::SUCCEEDED) {
LOG_ALWAYS_FATAL_IF(focusedWindow == nullptr);
- addWindowTargetLocked(focusedWindow,
- InputTarget::Flags::FOREGROUND |
- InputTarget::Flags::DISPATCH_AS_IS,
- getDownTime(*entry), inputTargets);
+ addWindowTargetLocked(focusedWindow, InputTarget::DispatchMode::AS_IS,
+ InputTarget::Flags::FOREGROUND, getDownTime(*entry),
+ inputTargets);
}
}
if (injectionResult == InputEventInjectionResult::PENDING) {
@@ -1979,7 +1974,6 @@
}
InputTarget target;
target.inputChannel = channel;
- target.flags = InputTarget::Flags::DISPATCH_AS_IS;
entry->dispatchInProgress = true;
dispatchEventLocked(currentTime, entry, {target});
}
@@ -2391,7 +2385,7 @@
}
// Set target flags.
- ftl::Flags<InputTarget::Flags> targetFlags = InputTarget::Flags::DISPATCH_AS_IS;
+ ftl::Flags<InputTarget::Flags> targetFlags;
if (canReceiveForegroundTouches(*windowHandle->getInfo())) {
// There should only be one touched window that can be "foreground" for the pointer.
@@ -2414,8 +2408,8 @@
pointerIds.set(pointerId);
const bool isDownOrPointerDown = maskedAction == AMOTION_EVENT_ACTION_DOWN ||
maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN;
- tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, entry.deviceId,
- pointerIds,
+ tempTouchState.addOrUpdateWindow(windowHandle, InputTarget::DispatchMode::AS_IS,
+ targetFlags, entry.deviceId, pointerIds,
isDownOrPointerDown
? std::make_optional(entry.eventTime)
: std::nullopt);
@@ -2432,13 +2426,14 @@
if (wallpaper != nullptr) {
ftl::Flags<InputTarget::Flags> wallpaperFlags =
InputTarget::Flags::WINDOW_IS_OBSCURED |
- InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED |
- InputTarget::Flags::DISPATCH_AS_IS;
+ InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
if (isSplit) {
wallpaperFlags |= InputTarget::Flags::SPLIT;
}
- tempTouchState.addOrUpdateWindow(wallpaper, wallpaperFlags, entry.deviceId,
- pointerIds, entry.eventTime);
+ tempTouchState.addOrUpdateWindow(wallpaper,
+ InputTarget::DispatchMode::AS_IS,
+ wallpaperFlags, entry.deviceId, pointerIds,
+ entry.eventTime);
}
}
}
@@ -2528,8 +2523,8 @@
const TouchedWindow& touchedWindow =
tempTouchState.getTouchedWindow(oldTouchedWindowHandle);
addPointerWindowTargetLocked(oldTouchedWindowHandle,
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT,
- pointerIds,
+ InputTarget::DispatchMode::SLIPPERY_EXIT,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
touchedWindow.getDownTimeInTarget(entry.deviceId),
targets);
@@ -2538,8 +2533,7 @@
isSplit = !isFromMouse;
}
- ftl::Flags<InputTarget::Flags> targetFlags =
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER;
+ ftl::Flags<InputTarget::Flags> targetFlags;
if (canReceiveForegroundTouches(*newTouchedWindowHandle->getInfo())) {
targetFlags |= InputTarget::Flags::FOREGROUND;
}
@@ -2552,8 +2546,10 @@
targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
}
- tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags,
- entry.deviceId, pointerIds, entry.eventTime);
+ tempTouchState.addOrUpdateWindow(newTouchedWindowHandle,
+ InputTarget::DispatchMode::SLIPPERY_ENTER,
+ targetFlags, entry.deviceId, pointerIds,
+ entry.eventTime);
// Check if the wallpaper window should deliver the corresponding event.
slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
@@ -2586,7 +2582,8 @@
getHoveringWindowsLocked(oldState, tempTouchState, entry);
for (const TouchedWindow& touchedWindow : hoveringWindows) {
std::optional<InputTarget> target =
- createInputTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
+ createInputTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
+ touchedWindow.targetFlags,
touchedWindow.getDownTimeInTarget(entry.deviceId));
if (!target) {
continue;
@@ -2623,7 +2620,7 @@
if (foregroundWindowHandle) {
const auto foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
for (InputTarget& target : targets) {
- if (target.flags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
+ if (target.dispatchMode == InputTarget::DispatchMode::OUTSIDE) {
sp<WindowInfoHandle> targetWindow =
getWindowHandleLocked(target.inputChannel->getConnectionToken());
if (targetWindow->getInfo()->ownerUid != foregroundWindowUid) {
@@ -2649,8 +2646,8 @@
if (touchingPointers.none()) {
continue;
}
- addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
- touchingPointers,
+ addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
+ touchedWindow.targetFlags, touchingPointers,
touchedWindow.getDownTimeInTarget(entry.deviceId), targets);
}
@@ -2675,7 +2672,7 @@
// If we only have windows getting ACTION_OUTSIDE, then drop the event, because there is no
// window that is actually receiving the entire gesture.
if (std::all_of(targets.begin(), targets.end(), [](const InputTarget& target) {
- return target.flags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE);
+ return target.dispatchMode == InputTarget::DispatchMode::OUTSIDE;
})) {
LOG(INFO) << "Dropping event because all windows would just receive ACTION_OUTSIDE: "
<< entry.getDescription();
@@ -2687,9 +2684,8 @@
for (TouchedWindow& touchedWindow : tempTouchState.windows) {
// Targets that we entered in a slippery way will now become AS-IS targets
- if (touchedWindow.targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
- touchedWindow.targetFlags.clear(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER);
- touchedWindow.targetFlags |= InputTarget::Flags::DISPATCH_AS_IS;
+ if (touchedWindow.dispatchMode == InputTarget::DispatchMode::SLIPPERY_ENTER) {
+ touchedWindow.dispatchMode = InputTarget::DispatchMode::AS_IS;
}
}
@@ -2823,7 +2819,7 @@
std::optional<InputTarget> InputDispatcher::createInputTargetLocked(
const sp<android::gui::WindowInfoHandle>& windowHandle,
- ftl::Flags<InputTarget::Flags> targetFlags,
+ InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
std::optional<nsecs_t> firstDownTimeInTarget) const {
std::shared_ptr<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());
if (inputChannel == nullptr) {
@@ -2833,6 +2829,7 @@
InputTarget inputTarget;
inputTarget.inputChannel = inputChannel;
inputTarget.windowHandle = windowHandle;
+ inputTarget.dispatchMode = dispatchMode;
inputTarget.flags = targetFlags;
inputTarget.globalScaleFactor = windowHandle->getInfo()->globalScaleFactor;
inputTarget.firstDownTimeInTarget = firstDownTimeInTarget;
@@ -2847,6 +2844,7 @@
}
void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags,
std::optional<nsecs_t> firstDownTimeInTarget,
std::vector<InputTarget>& inputTargets) const {
@@ -2861,7 +2859,8 @@
if (it == inputTargets.end()) {
std::optional<InputTarget> target =
- createInputTargetLocked(windowHandle, targetFlags, firstDownTimeInTarget);
+ createInputTargetLocked(windowHandle, dispatchMode, targetFlags,
+ firstDownTimeInTarget);
if (!target) {
return;
}
@@ -2880,9 +2879,9 @@
void InputDispatcher::addPointerWindowTargetLocked(
const sp<android::gui::WindowInfoHandle>& windowHandle,
- ftl::Flags<InputTarget::Flags> targetFlags, std::bitset<MAX_POINTER_ID + 1> pointerIds,
- std::optional<nsecs_t> firstDownTimeInTarget, std::vector<InputTarget>& inputTargets) const
- REQUIRES(mLock) {
+ InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
+ std::bitset<MAX_POINTER_ID + 1> pointerIds, std::optional<nsecs_t> firstDownTimeInTarget,
+ std::vector<InputTarget>& inputTargets) const REQUIRES(mLock) {
if (pointerIds.none()) {
for (const auto& target : inputTargets) {
LOG(INFO) << "Target: " << target;
@@ -2903,7 +2902,7 @@
// input targets for hovering pointers and for touching pointers.
// If we picked an existing input target above, but it's for HOVER_EXIT - let's use a new
// target instead.
- if (it != inputTargets.end() && it->flags.test(InputTarget::Flags::DISPATCH_AS_HOVER_EXIT)) {
+ if (it != inputTargets.end() && it->dispatchMode == InputTarget::DispatchMode::HOVER_EXIT) {
// Force the code below to create a new input target
it = inputTargets.end();
}
@@ -2912,7 +2911,8 @@
if (it == inputTargets.end()) {
std::optional<InputTarget> target =
- createInputTargetLocked(windowHandle, targetFlags, firstDownTimeInTarget);
+ createInputTargetLocked(windowHandle, dispatchMode, targetFlags,
+ firstDownTimeInTarget);
if (!target) {
return;
}
@@ -2920,11 +2920,16 @@
it = inputTargets.end() - 1;
}
+ if (it->dispatchMode != dispatchMode) {
+ LOG(ERROR) << __func__ << ": DispatchMode doesn't match! ignoring new mode="
+ << ftl::enum_string(dispatchMode) << ", it=" << *it;
+ }
if (it->flags != targetFlags) {
- LOG(ERROR) << "Flags don't match! targetFlags=" << targetFlags.string() << ", it=" << *it;
+ LOG(ERROR) << __func__ << ": Flags don't match! new targetFlags=" << targetFlags.string()
+ << ", it=" << *it;
}
if (it->globalScaleFactor != windowInfo->globalScaleFactor) {
- LOG(ERROR) << "Mismatch! it->globalScaleFactor=" << it->globalScaleFactor
+ LOG(ERROR) << __func__ << ": Mismatch! it->globalScaleFactor=" << it->globalScaleFactor
<< ", windowInfo->globalScaleFactor=" << windowInfo->globalScaleFactor;
}
@@ -2939,7 +2944,6 @@
for (const Monitor& monitor : selectResponsiveMonitorsLocked(monitorsIt->second)) {
InputTarget target;
target.inputChannel = monitor.inputChannel;
- target.flags = InputTarget::Flags::DISPATCH_AS_IS;
// target.firstDownTimeInTarget is not set for global monitors. It is only required in split
// touch and global monitoring works as intended even without setting firstDownTimeInTarget
if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) {
@@ -3266,41 +3270,29 @@
connection->getInputChannelName().c_str());
logOutboundMotionDetails(" ", *splitMotionEntry);
}
- enqueueDispatchEntriesLocked(currentTime, connection, std::move(splitMotionEntry),
- inputTarget);
+ enqueueDispatchEntryAndStartDispatchCycleLocked(currentTime, connection,
+ std::move(splitMotionEntry),
+ inputTarget);
return;
}
}
// Not splitting. Enqueue dispatch entries for the event as is.
- enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
+ enqueueDispatchEntryAndStartDispatchCycleLocked(currentTime, connection, eventEntry,
+ inputTarget);
}
-void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
- const std::shared_ptr<Connection>& connection,
- std::shared_ptr<const EventEntry> eventEntry,
- const InputTarget& inputTarget) {
+void InputDispatcher::enqueueDispatchEntryAndStartDispatchCycleLocked(
+ nsecs_t currentTime, const std::shared_ptr<Connection>& connection,
+ std::shared_ptr<const EventEntry> eventEntry, const InputTarget& inputTarget) {
ATRACE_NAME_IF(ATRACE_ENABLED(),
- StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, id=0x%" PRIx32 ")",
+ StringPrintf("enqueueDispatchEntryAndStartDispatchCycleLocked(inputChannel=%s, "
+ "id=0x%" PRIx32 ")",
connection->getInputChannelName().c_str(), eventEntry->id));
- LOG_ALWAYS_FATAL_IF(!inputTarget.flags.any(InputTarget::DISPATCH_MASK),
- "No dispatch flags are set for %s", eventEntry->getDescription().c_str());
const bool wasEmpty = connection->outboundQueue.empty();
- // Enqueue dispatch entries for the requested modes.
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::Flags::DISPATCH_AS_HOVER_EXIT);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::Flags::DISPATCH_AS_OUTSIDE);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::Flags::DISPATCH_AS_HOVER_ENTER);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::Flags::DISPATCH_AS_IS);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER);
+ enqueueDispatchEntryLocked(connection, eventEntry, inputTarget);
// If the outbound queue was previously empty, start the dispatch cycle going.
if (wasEmpty && !connection->outboundQueue.empty()) {
@@ -3310,20 +3302,11 @@
void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection,
std::shared_ptr<const EventEntry> eventEntry,
- const InputTarget& inputTarget,
- ftl::Flags<InputTarget::Flags> dispatchMode) {
- ftl::Flags<InputTarget::Flags> inputTargetFlags = inputTarget.flags;
- if (!inputTargetFlags.any(dispatchMode)) {
- return;
- }
-
- inputTargetFlags.clear(InputTarget::DISPATCH_MASK);
- inputTargetFlags |= dispatchMode;
-
+ const InputTarget& inputTarget) {
// This is a new event.
// Enqueue a new dispatch entry onto the outbound queue for this connection.
std::unique_ptr<DispatchEntry> dispatchEntry =
- createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);
+ createDispatchEntry(inputTarget, eventEntry, inputTarget.flags);
// Use the eventEntry from dispatchEntry since the entry may have changed and can now be a
// different EventEntry than what was passed in.
@@ -3349,15 +3332,15 @@
int32_t resolvedAction = motionEntry.action;
int32_t resolvedFlags = motionEntry.flags;
- if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
+ if (inputTarget.dispatchMode == InputTarget::DispatchMode::OUTSIDE) {
resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
- } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_EXIT)) {
+ } else if (inputTarget.dispatchMode == InputTarget::DispatchMode::HOVER_EXIT) {
resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
- } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_ENTER)) {
+ } else if (inputTarget.dispatchMode == InputTarget::DispatchMode::HOVER_ENTER) {
resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
- } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
+ } else if (inputTarget.dispatchMode == InputTarget::DispatchMode::SLIPPERY_EXIT) {
resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
- } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
+ } else if (inputTarget.dispatchMode == InputTarget::DispatchMode::SLIPPERY_ENTER) {
resolvedAction = AMOTION_EVENT_ACTION_DOWN;
}
if (resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE &&
@@ -3429,7 +3412,7 @@
<< cancelEvent->getDescription();
std::unique_ptr<DispatchEntry> cancelDispatchEntry =
createDispatchEntry(inputTarget, std::move(cancelEvent),
- InputTarget::Flags::DISPATCH_AS_IS);
+ ftl::Flags<InputTarget::Flags>());
// Send these cancel events to the queue before sending the event from the new
// device.
@@ -3529,7 +3512,7 @@
std::unordered_set<sp<IBinder>, StrongPointerHash<IBinder>> newConnectionTokens;
std::vector<std::shared_ptr<Connection>> newConnections;
for (const InputTarget& target : targets) {
- if (target.flags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
+ if (target.dispatchMode == InputTarget::DispatchMode::OUTSIDE) {
continue; // Skip windows that receive ACTION_OUTSIDE
}
@@ -4006,8 +3989,7 @@
const bool wasEmpty = connection->outboundQueue.empty();
// 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};
+ const InputTarget fallbackTarget{.inputChannel = connection->inputChannel};
const auto& token = connection->inputChannel->getConnectionToken();
for (size_t i = 0; i < cancelationEvents.size(); i++) {
@@ -4021,8 +4003,8 @@
? std::make_optional(keyEntry.displayId)
: std::nullopt;
if (const auto& window = getWindowHandleLocked(token, targetDisplay); window) {
- addWindowTargetLocked(window, InputTarget::Flags::DISPATCH_AS_IS,
- keyEntry.downTime, targets);
+ addWindowTargetLocked(window, InputTarget::DispatchMode::AS_IS,
+ /*targetFlags=*/{}, keyEntry.downTime, targets);
} else {
targets.emplace_back(fallbackTarget);
}
@@ -4049,8 +4031,9 @@
sendDropWindowCommandLocked(nullptr, /*x=*/0, /*y=*/0);
mDragState.reset();
}
- addPointerWindowTargetLocked(window, InputTarget::Flags::DISPATCH_AS_IS,
- pointerIds, motionEntry.downTime, targets);
+ addPointerWindowTargetLocked(window, InputTarget::DispatchMode::AS_IS,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
+ motionEntry.downTime, targets);
} else {
targets.emplace_back(fallbackTarget);
const auto it = mDisplayInfos.find(motionEntry.displayId);
@@ -4080,8 +4063,7 @@
}
if (targets.size() != 1) LOG(FATAL) << __func__ << ": InputTarget not created";
- enqueueDispatchEntryLocked(connection, std::move(cancelationEventEntry), targets[0],
- InputTarget::Flags::DISPATCH_AS_IS);
+ enqueueDispatchEntryLocked(connection, std::move(cancelationEventEntry), targets[0]);
}
// If the outbound queue was previously empty, start the dispatch cycle going.
@@ -4124,8 +4106,9 @@
pointerIndex++) {
pointerIds.set(motionEntry.pointerProperties[pointerIndex].id);
}
- addPointerWindowTargetLocked(windowHandle, targetFlags, pointerIds,
- motionEntry.downTime, targets);
+ addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::AS_IS,
+ targetFlags, pointerIds, motionEntry.downTime,
+ targets);
} else {
targets.emplace_back(InputTarget{.inputChannel = connection->inputChannel,
.flags = targetFlags});
@@ -4154,8 +4137,7 @@
}
if (targets.size() != 1) LOG(FATAL) << __func__ << ": InputTarget not created";
- enqueueDispatchEntryLocked(connection, std::move(downEventEntry), targets[0],
- InputTarget::Flags::DISPATCH_AS_IS);
+ enqueueDispatchEntryLocked(connection, std::move(downEventEntry), targets[0]);
}
// If the outbound queue was previously empty, start the dispatch cycle going.
@@ -5502,12 +5484,12 @@
// Add new window.
nsecs_t downTimeInTarget = now();
ftl::Flags<InputTarget::Flags> newTargetFlags =
- oldTargetFlags & (InputTarget::Flags::SPLIT | InputTarget::Flags::DISPATCH_AS_IS);
+ oldTargetFlags & (InputTarget::Flags::SPLIT);
if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) {
newTargetFlags |= InputTarget::Flags::FOREGROUND;
}
- state->addOrUpdateWindow(toWindowHandle, newTargetFlags, deviceId, pointerIds,
- downTimeInTarget);
+ state->addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
+ deviceId, pointerIds, downTimeInTarget);
// Store the dragging window.
if (isDragDrop) {
@@ -6210,8 +6192,7 @@
if (fallbackKeyEntry && connection->status == Connection::Status::NORMAL) {
const InputTarget target{.inputChannel = connection->inputChannel,
.flags = dispatchEntry->targetFlags};
- enqueueDispatchEntryLocked(connection, std::move(fallbackKeyEntry), target,
- InputTarget::Flags::DISPATCH_AS_IS);
+ enqueueDispatchEntryLocked(connection, std::move(fallbackKeyEntry), target);
}
releaseDispatchEntry(std::move(dispatchEntry));
}
@@ -6854,18 +6835,15 @@
if (oldWallpaper != nullptr) {
const TouchedWindow& oldTouchedWindow = state.getTouchedWindow(oldWallpaper);
- addPointerWindowTargetLocked(oldWallpaper,
- oldTouchedWindow.targetFlags |
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT,
- pointerIds, oldTouchedWindow.getDownTimeInTarget(deviceId),
- targets);
+ addPointerWindowTargetLocked(oldWallpaper, InputTarget::DispatchMode::SLIPPERY_EXIT,
+ oldTouchedWindow.targetFlags, pointerIds,
+ oldTouchedWindow.getDownTimeInTarget(deviceId), targets);
state.removeTouchingPointerFromWindow(deviceId, pointerId, oldWallpaper);
}
if (newWallpaper != nullptr) {
- state.addOrUpdateWindow(newWallpaper,
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER |
- InputTarget::Flags::WINDOW_IS_OBSCURED |
+ state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::SLIPPERY_ENTER,
+ InputTarget::Flags::WINDOW_IS_OBSCURED |
InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED,
deviceId, pointerIds);
}
@@ -6901,12 +6879,11 @@
if (newWallpaper != nullptr) {
nsecs_t downTimeInTarget = now();
- ftl::Flags<InputTarget::Flags> wallpaperFlags =
- oldTargetFlags & (InputTarget::Flags::SPLIT | InputTarget::Flags::DISPATCH_AS_IS);
+ ftl::Flags<InputTarget::Flags> wallpaperFlags = oldTargetFlags & InputTarget::Flags::SPLIT;
wallpaperFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED |
InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
- state.addOrUpdateWindow(newWallpaper, wallpaperFlags, deviceId, pointerIds,
- downTimeInTarget);
+ state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags,
+ deviceId, pointerIds, downTimeInTarget);
std::shared_ptr<Connection> wallpaperConnection =
getConnectionLocked(newWallpaper->getToken());
if (wallpaperConnection != nullptr) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 8aa4a87..fbbde4b 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -528,13 +528,15 @@
std::optional<InputTarget> createInputTargetLocked(
const sp<android::gui::WindowInfoHandle>& windowHandle,
- ftl::Flags<InputTarget::Flags> targetFlags,
+ InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
std::optional<nsecs_t> firstDownTimeInTarget) const REQUIRES(mLock);
void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags,
std::optional<nsecs_t> firstDownTimeInTarget,
std::vector<InputTarget>& inputTargets) const REQUIRES(mLock);
void addPointerWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags,
std::bitset<MAX_POINTER_ID + 1> pointerIds,
std::optional<nsecs_t> firstDownTimeInTarget,
@@ -580,14 +582,12 @@
const std::shared_ptr<Connection>& connection,
std::shared_ptr<const EventEntry>,
const InputTarget& inputTarget) REQUIRES(mLock);
- void enqueueDispatchEntriesLocked(nsecs_t currentTime,
- const std::shared_ptr<Connection>& connection,
- std::shared_ptr<const EventEntry>,
- const InputTarget& inputTarget) REQUIRES(mLock);
+ void enqueueDispatchEntryAndStartDispatchCycleLocked(
+ nsecs_t currentTime, const std::shared_ptr<Connection>& connection,
+ std::shared_ptr<const EventEntry>, const InputTarget& inputTarget) REQUIRES(mLock);
void enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection,
std::shared_ptr<const EventEntry>,
- const InputTarget& inputTarget,
- ftl::Flags<InputTarget::Flags> dispatchMode) REQUIRES(mLock);
+ const InputTarget& inputTarget) REQUIRES(mLock);
status_t publishMotionEvent(Connection& connection, DispatchEntry& dispatchEntry) const;
void startDispatchCycleLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection) REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/InputTarget.cpp b/services/inputflinger/dispatcher/InputTarget.cpp
index 343630c..c02c5d6 100644
--- a/services/inputflinger/dispatcher/InputTarget.cpp
+++ b/services/inputflinger/dispatcher/InputTarget.cpp
@@ -95,6 +95,7 @@
} else {
out << "<null>";
}
+ out << ", dispatchMode=" << ftl::enum_string(target.dispatchMode).c_str();
out << ", targetFlags=" << target.flags.string();
out << ", pointers=" << target.getPointerInfoString();
out << "}";
diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h
index 8b8a35a..aef866b 100644
--- a/services/inputflinger/dispatcher/InputTarget.h
+++ b/services/inputflinger/dispatcher/InputTarget.h
@@ -51,46 +51,39 @@
* the same UID from watching all touches. */
ZERO_COORDS = 1 << 3,
- /* This flag indicates that the event should be sent as is.
- * Should always be set unless the event is to be transmuted. */
- DISPATCH_AS_IS = 1 << 8,
-
- /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
- * of the area of this target and so should instead be delivered as an
- * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
- DISPATCH_AS_OUTSIDE = 1 << 9,
-
- /* This flag indicates that a hover sequence is starting in the given window.
- * The event is transmuted into ACTION_HOVER_ENTER. */
- DISPATCH_AS_HOVER_ENTER = 1 << 10,
-
- /* This flag indicates that a hover event happened outside of a window which handled
- * previous hover events, signifying the end of the current hover sequence for that
- * window.
- * The event is transmuted into ACTION_HOVER_ENTER. */
- DISPATCH_AS_HOVER_EXIT = 1 << 11,
-
- /* This flag indicates that the event should be canceled.
- * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
- * outside of a window. */
- DISPATCH_AS_SLIPPERY_EXIT = 1 << 12,
-
- /* This flag indicates that the event should be dispatched as an initial down.
- * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
- * into a new window. */
- DISPATCH_AS_SLIPPERY_ENTER = 1 << 13,
-
/* This flag indicates that the target of a MotionEvent is partly or wholly
* obscured by another visible window above it. The motion event should be
* delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */
WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,
};
- /* Mask for all dispatch modes. */
- static constexpr const ftl::Flags<InputTarget::Flags> DISPATCH_MASK =
- ftl::Flags<InputTarget::Flags>() | Flags::DISPATCH_AS_IS | Flags::DISPATCH_AS_OUTSIDE |
- Flags::DISPATCH_AS_HOVER_ENTER | Flags::DISPATCH_AS_HOVER_EXIT |
- Flags::DISPATCH_AS_SLIPPERY_EXIT | Flags::DISPATCH_AS_SLIPPERY_ENTER;
+ enum class DispatchMode {
+ /* This flag indicates that the event should be sent as is.
+ * Should always be set unless the event is to be transmuted. */
+ AS_IS,
+ /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
+ * of the area of this target and so should instead be delivered as an
+ * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
+ OUTSIDE,
+ /* This flag indicates that a hover sequence is starting in the given window.
+ * The event is transmuted into ACTION_HOVER_ENTER. */
+ HOVER_ENTER,
+ /* This flag indicates that a hover event happened outside of a window which handled
+ * previous hover events, signifying the end of the current hover sequence for that
+ * window.
+ * The event is transmuted into ACTION_HOVER_ENTER. */
+ HOVER_EXIT,
+ /* This flag indicates that the event should be canceled.
+ * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
+ * outside of a window. */
+ SLIPPERY_EXIT,
+ /* This flag indicates that the event should be dispatched as an initial down.
+ * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
+ * into a new window. */
+ SLIPPERY_ENTER,
+
+ ftl_last = SLIPPERY_ENTER,
+ };
// The input channel to be targeted.
std::shared_ptr<InputChannel> inputChannel;
@@ -98,6 +91,9 @@
// Flags for the input target.
ftl::Flags<Flags> flags;
+ // The dispatch mode that should be used for this target.
+ DispatchMode dispatchMode = DispatchMode::AS_IS;
+
// Scaling factor to apply to MotionEvent as it is delivered.
// (ignored for KeyEvents)
float globalScaleFactor = 1.0f;
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index 2ead171..e8d8c18 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -71,6 +71,7 @@
}
void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags, DeviceId deviceId,
std::bitset<MAX_POINTER_ID + 1> touchingPointerIds,
std::optional<nsecs_t> firstDownTimeInTarget) {
@@ -85,10 +86,8 @@
// An alternative design choice here would have been to compare here by token, but to
// store per-pointer transform.
if (touchedWindow.windowHandle == windowHandle) {
+ touchedWindow.dispatchMode = dispatchMode;
touchedWindow.targetFlags |= targetFlags;
- if (targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
- touchedWindow.targetFlags.clear(InputTarget::Flags::DISPATCH_AS_IS);
- }
// For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have
// downTime set initially. Need to update existing window when a pointer is down for the
// window.
@@ -101,6 +100,7 @@
}
TouchedWindow touchedWindow;
touchedWindow.windowHandle = windowHandle;
+ touchedWindow.dispatchMode = dispatchMode;
touchedWindow.targetFlags = targetFlags;
touchedWindow.addTouchingPointers(deviceId, touchingPointerIds);
if (firstDownTimeInTarget) {
@@ -133,20 +133,6 @@
}
}
-void TouchState::filterNonAsIsTouchWindows() {
- for (size_t i = 0; i < windows.size();) {
- TouchedWindow& window = windows[i];
- if (window.targetFlags.any(InputTarget::Flags::DISPATCH_AS_IS |
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
- window.targetFlags.clear(InputTarget::DISPATCH_MASK);
- window.targetFlags |= InputTarget::Flags::DISPATCH_AS_IS;
- i += 1;
- } else {
- windows.erase(windows.begin() + i);
- }
- }
-}
-
void TouchState::cancelPointersForWindowsExcept(DeviceId deviceId,
std::bitset<MAX_POINTER_ID + 1> pointerIds,
const sp<IBinder>& token) {
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index e79c73b..e0a84e8 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -44,6 +44,7 @@
void removeTouchingPointerFromWindow(DeviceId deviceId, int32_t pointerId,
const sp<android::gui::WindowInfoHandle>& windowHandle);
void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags, DeviceId deviceId,
std::bitset<MAX_POINTER_ID + 1> touchingPointerIds,
std::optional<nsecs_t> firstDownTimeInTarget = std::nullopt);
@@ -54,7 +55,6 @@
void removeAllPointersForDevice(DeviceId deviceId);
void removeWindowByToken(const sp<IBinder>& token);
- void filterNonAsIsTouchWindows();
// Cancel pointers for current set of windows except the window with particular binder token.
void cancelPointersForWindowsExcept(DeviceId deviceId,
diff --git a/services/inputflinger/dispatcher/TouchedWindow.h b/services/inputflinger/dispatcher/TouchedWindow.h
index 9a31678..c604353 100644
--- a/services/inputflinger/dispatcher/TouchedWindow.h
+++ b/services/inputflinger/dispatcher/TouchedWindow.h
@@ -31,6 +31,7 @@
// Focus tracking for touch.
struct TouchedWindow {
sp<gui::WindowInfoHandle> windowHandle;
+ InputTarget::DispatchMode dispatchMode = InputTarget::DispatchMode::AS_IS;
ftl::Flags<InputTarget::Flags> targetFlags;
// Hovering