Add outside targets explicitly
Before this CL, the action of adding outside targets was a by-product of
finding the touched window.
In this CL, the change is made to add these targets explicitly. This
simplifies some of the code and allows us to stop generating targets for
cases where isDown is false.
Eventually, we may consider adding the outside targets back into touch
state to unify the security checks.
Bug: 211379801
Test: atest inputflinger_tests
Change-Id: I1373c28d306e154dac8b35879bb7d0497d1ff832
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 482e23f..cc3f4d2 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1106,7 +1106,8 @@
const auto [x, y] = resolveTouchedPosition(motionEntry);
const bool isStylus = isPointerFromStylus(motionEntry, /*pointerIndex=*/0);
- auto [touchedWindowHandle, _] = findTouchedWindowAtLocked(displayId, x, y, isStylus);
+ sp<WindowInfoHandle> touchedWindowHandle =
+ findTouchedWindowAtLocked(displayId, x, y, isStylus);
if (touchedWindowHandle != nullptr &&
touchedWindowHandle->getApplicationToken() !=
mAwaitedFocusedApplication->getApplicationToken()) {
@@ -1230,11 +1231,10 @@
}
}
-std::pair<sp<WindowInfoHandle>, std::vector<InputTarget>>
-InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, float x, float y, bool isStylus,
- bool ignoreDragWindow) const {
+sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, float x, float y,
+ bool isStylus,
+ bool ignoreDragWindow) const {
// Traverse windows from front to back to find touched window.
- std::vector<InputTarget> outsideTargets;
const auto& windowHandles = getWindowHandlesLocked(displayId);
for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) {
@@ -1244,16 +1244,35 @@
const WindowInfo& info = *windowHandle->getInfo();
if (!info.isSpy() &&
windowAcceptsTouchAt(info, displayId, x, y, isStylus, getTransformLocked(displayId))) {
- return {windowHandle, outsideTargets};
+ return windowHandle;
+ }
+ }
+ return nullptr;
+}
+
+std::vector<InputTarget> InputDispatcher::findOutsideTargetsLocked(
+ int32_t displayId, const sp<WindowInfoHandle>& touchedWindow) const {
+ if (touchedWindow == nullptr) {
+ return {};
+ }
+ // Traverse windows from front to back until we encounter the touched window.
+ std::vector<InputTarget> outsideTargets;
+ const auto& windowHandles = getWindowHandlesLocked(displayId);
+ for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
+ if (windowHandle == touchedWindow) {
+ // Stop iterating once we found a touched window. Any WATCH_OUTSIDE_TOUCH window
+ // below the touched window will not get ACTION_OUTSIDE event.
+ return outsideTargets;
}
+ const WindowInfo& info = *windowHandle->getInfo();
if (info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
addWindowTargetLocked(windowHandle, InputTarget::Flags::DISPATCH_AS_OUTSIDE,
/*pointerIds=*/{}, /*firstDownTimeInTarget=*/std::nullopt,
outsideTargets);
}
}
- return {nullptr, {}};
+ return outsideTargets;
}
std::vector<sp<WindowInfoHandle>> InputDispatcher::findTouchedSpyWindowsAtLocked(
@@ -2311,11 +2330,11 @@
// Outside targets should be added upon first dispatched DOWN event. That means, this should
// be a pointer that would generate ACTION_DOWN, *and* touch should not already be down.
const bool isStylus = isPointerFromStylus(entry, pointerIndex);
- auto [newTouchedWindowHandle, outsideTargets] =
+ sp<WindowInfoHandle> newTouchedWindowHandle =
findTouchedWindowAtLocked(displayId, x, y, isStylus);
if (isDown) {
- targets += outsideTargets;
+ targets += findOutsideTargetsLocked(displayId, newTouchedWindowHandle);
}
// Handle the case where we did not find a window.
if (newTouchedWindowHandle == nullptr) {
@@ -2489,7 +2508,8 @@
sp<WindowInfoHandle> oldTouchedWindowHandle =
tempTouchState.getFirstForegroundWindowHandle();
LOG_ALWAYS_FATAL_IF(oldTouchedWindowHandle == nullptr);
- auto [newTouchedWindowHandle, _] = findTouchedWindowAtLocked(displayId, x, y, isStylus);
+ sp<WindowInfoHandle> newTouchedWindowHandle =
+ findTouchedWindowAtLocked(displayId, x, y, isStylus);
// Verify targeted injection.
if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
@@ -2747,7 +2767,7 @@
// have an explicit reason to support it.
constexpr bool isStylus = false;
- auto [dropWindow, _] =
+ sp<WindowInfoHandle> dropWindow =
findTouchedWindowAtLocked(displayId, x, y, isStylus, /*ignoreDragWindow=*/true);
if (dropWindow) {
vec2 local = dropWindow->getInfo()->transform.transform(x, y);
@@ -2801,8 +2821,9 @@
// until we have an explicit reason to support it.
constexpr bool isStylus = false;
- auto [hoverWindowHandle, _] = findTouchedWindowAtLocked(entry.displayId, x, y, isStylus,
- /*ignoreDragWindow=*/true);
+ sp<WindowInfoHandle> hoverWindowHandle =
+ findTouchedWindowAtLocked(entry.displayId, x, y, isStylus,
+ /*ignoreDragWindow=*/true);
// enqueue drag exit if needed.
if (hoverWindowHandle != mDragState->dragHoverWindowHandle &&
!haveSameToken(hoverWindowHandle, mDragState->dragHoverWindowHandle)) {