Associate device id with getWallpaperWindow
Because we have supported multi-device event streams in the
InputDispatcher, but there are still some logics that use the previous
single-device stream logic. Here, associating getWallpaperWindow with
deviceId can solve wallpaper window is wrong issue in event transfer.
In addition to that, this patch also attempts to fix an issue where the
foreground target window with a wallpaper could not receive subsequent
remaining events after a transferTouchGesture. This is because, in
transferWallpaperTouch, we merged part of the state from the InputState
of the target foreground window into its corresponding wallpaper window,
causing the firstNewPointerIdx in its InputState to be reset. Here,
we try to resolve this issue by moving the synthesis operation of
the down event for the target foreground window to after the
transferWallpaperTouch.
Bug: 328718622
Test: atest inputflinger_tests
Change-Id: If1085c8aefd962cf1e05b7bf68d87c9f2c8bacc9
Signed-off-by: Linnan Li <lilinnan@xiaomi.corp-partner.google.com>
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index de841ba..79b8560 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -5363,31 +5363,32 @@
onFocusChangedLocked(*changes, traceContext.getTracker(), removedFocusedWindowHandle);
}
- std::unordered_map<int32_t, TouchState>::iterator stateIt =
- mTouchStatesByDisplay.find(displayId);
- if (stateIt != mTouchStatesByDisplay.end()) {
- TouchState& state = stateIt->second;
+ if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
+ TouchState& state = it->second;
for (size_t i = 0; i < state.windows.size();) {
TouchedWindow& touchedWindow = state.windows[i];
- if (getWindowHandleLocked(touchedWindow.windowHandle) == nullptr) {
- LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
- << " in display %" << displayId;
- CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
- "touched window was removed", traceContext.getTracker());
- synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
- // Since we are about to drop the touch, cancel the events for the wallpaper as
- // well.
- if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
- touchedWindow.windowHandle->getInfo()->inputConfig.test(
- gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
- if (const auto& ww = state.getWallpaperWindow(); ww) {
+ if (getWindowHandleLocked(touchedWindow.windowHandle) != nullptr) {
+ i++;
+ continue;
+ }
+ LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
+ << " in display %" << displayId;
+ CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+ "touched window was removed", traceContext.getTracker());
+ synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
+ // Since we are about to drop the touch, cancel the events for the wallpaper as
+ // well.
+ if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
+ touchedWindow.windowHandle->getInfo()->inputConfig.test(
+ gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
+ for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds()) {
+ if (const auto& ww = state.getWallpaperWindow(deviceId); ww != nullptr) {
+ options.deviceId = deviceId;
synthesizeCancelationEventsForWindowLocked(ww, options);
}
}
- state.windows.erase(state.windows.begin() + i);
- } else {
- ++i;
}
+ state.windows.erase(state.windows.begin() + i);
}
// If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
@@ -5662,13 +5663,13 @@
ALOGD("Touch transfer failed because from window is not being touched.");
return false;
}
- std::set<int32_t> deviceIds = touchedWindow->getTouchingDeviceIds();
+ std::set<DeviceId> deviceIds = touchedWindow->getTouchingDeviceIds();
if (deviceIds.size() != 1) {
LOG(INFO) << "Can't transfer touch. Currently touching devices: " << dumpSet(deviceIds)
<< " for window: " << touchedWindow->dump();
return false;
}
- const int32_t deviceId = *deviceIds.begin();
+ const DeviceId deviceId = *deviceIds.begin();
const sp<WindowInfoHandle> fromWindowHandle = touchedWindow->windowHandle;
const sp<WindowInfoHandle> toWindowHandle = getWindowHandleLocked(toToken, displayId);
@@ -5722,13 +5723,18 @@
"transferring touch from this window to another window",
traceContext.getTracker());
synthesizeCancelationEventsForWindowLocked(fromWindowHandle, options, fromConnection);
- synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection,
- newTargetFlags,
- traceContext.getTracker());
// Check if the wallpaper window should deliver the corresponding event.
transferWallpaperTouch(oldTargetFlags, newTargetFlags, fromWindowHandle, toWindowHandle,
*state, deviceId, pointers, traceContext.getTracker());
+
+ // Because new window may have a wallpaper window, it will merge input state from it
+ // parent window, after this the firstNewPointerIdx in input state will be reset, then
+ // it will cause new move event be thought inconsistent, so we should synthesize the
+ // down event after it reset.
+ synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection,
+ newTargetFlags,
+ traceContext.getTracker());
}
} // release lock
@@ -7039,7 +7045,7 @@
void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
const sp<WindowInfoHandle>& oldWindowHandle,
const sp<WindowInfoHandle>& newWindowHandle,
- TouchState& state, int32_t deviceId,
+ TouchState& state, DeviceId deviceId,
const PointerProperties& pointerProperties,
std::vector<InputTarget>& targets) const {
std::vector<PointerProperties> pointers{pointerProperties};
@@ -7049,7 +7055,7 @@
newWindowHandle->getInfo()->inputConfig.test(
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
const sp<WindowInfoHandle> oldWallpaper =
- oldHasWallpaper ? state.getWallpaperWindow() : nullptr;
+ oldHasWallpaper ? state.getWallpaperWindow(deviceId) : nullptr;
const sp<WindowInfoHandle> newWallpaper =
newHasWallpaper ? findWallpaperWindowBelow(newWindowHandle) : nullptr;
if (oldWallpaper == newWallpaper) {
@@ -7075,7 +7081,7 @@
void InputDispatcher::transferWallpaperTouch(
ftl::Flags<InputTarget::Flags> oldTargetFlags,
ftl::Flags<InputTarget::Flags> newTargetFlags, const sp<WindowInfoHandle> fromWindowHandle,
- const sp<WindowInfoHandle> toWindowHandle, TouchState& state, int32_t deviceId,
+ const sp<WindowInfoHandle> toWindowHandle, TouchState& state, DeviceId deviceId,
const std::vector<PointerProperties>& pointers,
const std::unique_ptr<trace::EventTrackerInterface>& traceTracker) {
const bool oldHasWallpaper = oldTargetFlags.test(InputTarget::Flags::FOREGROUND) &&
@@ -7086,7 +7092,7 @@
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
const sp<WindowInfoHandle> oldWallpaper =
- oldHasWallpaper ? state.getWallpaperWindow() : nullptr;
+ oldHasWallpaper ? state.getWallpaperWindow(deviceId) : nullptr;
const sp<WindowInfoHandle> newWallpaper =
newHasWallpaper ? findWallpaperWindowBelow(toWindowHandle) : nullptr;
if (oldWallpaper == newWallpaper) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 3579a67..3d127c2 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -701,14 +701,14 @@
void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
const sp<android::gui::WindowInfoHandle>& newWindowHandle,
- TouchState& state, int32_t deviceId,
+ TouchState& state, DeviceId deviceId,
const PointerProperties& pointerProperties,
std::vector<InputTarget>& targets) const REQUIRES(mLock);
void transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags,
ftl::Flags<InputTarget::Flags> newTargetFlags,
const sp<android::gui::WindowInfoHandle> fromWindowHandle,
const sp<android::gui::WindowInfoHandle> toWindowHandle,
- TouchState& state, int32_t deviceId,
+ TouchState& state, DeviceId deviceId,
const std::vector<PointerProperties>& pointers,
const std::unique_ptr<trace::EventTrackerInterface>& traceTracker)
REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index 296c334..0c9ad3c 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -211,9 +211,11 @@
return haveSlipperyForegroundWindow;
}
-sp<WindowInfoHandle> TouchState::getWallpaperWindow() const {
- for (size_t i = 0; i < windows.size(); i++) {
- const TouchedWindow& window = windows[i];
+sp<WindowInfoHandle> TouchState::getWallpaperWindow(DeviceId deviceId) const {
+ for (const auto& window : windows) {
+ if (!window.hasTouchingPointers(deviceId)) {
+ continue;
+ }
if (window.windowHandle->getInfo()->inputConfig.test(
gui::WindowInfo::InputConfig::IS_WALLPAPER)) {
return window.windowHandle;
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index 9ddb4e2..9d4bb3d 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -66,7 +66,7 @@
sp<android::gui::WindowInfoHandle> getFirstForegroundWindowHandle(DeviceId deviceId) const;
bool isSlippery(DeviceId deviceId) const;
- sp<android::gui::WindowInfoHandle> getWallpaperWindow() const;
+ sp<android::gui::WindowInfoHandle> getWallpaperWindow(DeviceId deviceId) const;
const TouchedWindow& getTouchedWindow(
const sp<android::gui::WindowInfoHandle>& windowHandle) const;
// Whether any of the windows are currently being touched