Merge "PointerController: Cleanup after PointerChoreogpraher refactor" into main
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index 01f523b..bec3283 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -17,8 +17,20 @@
/**
* @addtogroup Choreographer
*
- * Choreographer coordinates the timing of frame rendering. This is the C version of the
- * android.view.Choreographer object in Java.
+ * Choreographer coordinates the timing of frame rendering. This is the C
+ * version of the android.view.Choreographer object in Java. If you do not use
+ * Choreographer to pace your render loop, you may render too quickly for the
+ * display, increasing latency between frame submission and presentation.
+ *
+ * Input events are guaranteed to be processed before the frame callback is
+ * called, and will not be run concurrently. Input and sensor events should not
+ * be handled in the Choregrapher callback.
+ *
+ * The frame callback is also the appropriate place to run any per-frame state
+ * update logic. For example, in a game, the frame callback should be
+ * responsible for updating things like physics, AI, game state, and rendering
+ * the frame. Input and sensors should be handled separately via callbacks
+ * registered with AInputQueue and ASensorManager.
*
* As of API level 33, apps can follow proper frame pacing and even choose a future frame to render.
* The API is used as follows:
@@ -38,6 +50,11 @@
* 4. SurfaceFlinger attempts to follow the chosen frame timeline, by not applying transactions or
* latching buffers before the desired presentation time.
*
+ * On older devices, AChoreographer_postFrameCallback64 or
+ * AChoreographer_postFrameCallback can be used to lesser effect. They cannot be
+ * used to precisely plan your render timeline, but will rate limit to avoid
+ * overloading the display pipeline and increasing frame latency.
+ *
* @{
*/
@@ -129,14 +146,46 @@
AChoreographer* AChoreographer_getInstance() __INTRODUCED_IN(24);
/**
- * Deprecated: Use AChoreographer_postFrameCallback64 instead.
+ * Post a callback to be run when the application should begin rendering the
+ * next frame. The data pointer provided will be passed to the callback function
+ * when it's called.
+ *
+ * The callback will only be run for the next frame, not all subsequent frames,
+ * so to render continuously the callback should itself call
+ * AChoreographer_postFrameCallback.
+ *
+ * \bug The callback receives the frame time in nanoseconds as a long. On 32-bit
+ * systems, long is 32-bit, so the frame time will roll over roughly every two
+ * seconds. If your minSdkVersion is 29 or higher, switch to
+ * AChoreographer_postFrameCallback64, which uses a 64-bit frame time for all
+ * platforms. For older OS versions, you must combine the argument with the
+ * upper bits of clock_gettime(CLOCK_MONOTONIC, ...) on 32-bit systems.
+ *
+ * \deprecated Use AChoreographer_postFrameCallback64, which does not have the
+ * bug described above.
*/
void AChoreographer_postFrameCallback(AChoreographer* choreographer,
AChoreographer_frameCallback callback, void* data)
__INTRODUCED_IN(24) __DEPRECATED_IN(29, "Use AChoreographer_postFrameCallback64 instead");
/**
- * Deprecated: Use AChoreographer_postFrameCallbackDelayed64 instead.
+ * Post a callback to be run when the application should begin rendering the
+ * next frame following the specified delay. The data pointer provided will be
+ * passed to the callback function when it's called.
+ *
+ * The callback will only be run for the next frame after the delay, not all
+ * subsequent frames, so to render continuously the callback should itself call
+ * AChoreographer_postFrameCallbackDelayed.
+ *
+ * \bug The callback receives the frame time in nanoseconds as a long. On 32-bit
+ * systems, long is 32-bit, so the frame time will roll over roughly every two
+ * seconds. If your minSdkVersion is 29 or higher, switch to
+ * AChoreographer_postFrameCallbackDelayed64, which uses a 64-bit frame time for
+ * all platforms. For older OS versions, you must combine the argument with the
+ * upper bits of clock_gettime(CLOCK_MONOTONIC, ...) on 32-bit systems.
+ *
+ * \deprecated Use AChoreographer_postFrameCallbackDelayed64, which does not
+ * have the bug described above.
*/
void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
AChoreographer_frameCallback callback, void* data,
@@ -144,8 +193,13 @@
__DEPRECATED_IN(29, "Use AChoreographer_postFrameCallbackDelayed64 instead");
/**
- * Post a callback to be run on the next frame. The data pointer provided will
- * be passed to the callback function when it's called.
+ * Post a callback to be run when the application should begin rendering the
+ * next frame. The data pointer provided will be passed to the callback function
+ * when it's called.
+ *
+ * The callback will only be run on the next frame, not all subsequent frames,
+ * so to render continuously the callback should itself call
+ * AChoreographer_postFrameCallback64.
*
* Available since API level 29.
*/
@@ -154,9 +208,13 @@
__INTRODUCED_IN(29);
/**
- * Post a callback to be run on the frame following the specified delay. The
- * data pointer provided will be passed to the callback function when it's
- * called.
+ * Post a callback to be run when the application should begin rendering the
+ * next frame following the specified delay. The data pointer provided will be
+ * passed to the callback function when it's called.
+ *
+ * The callback will only be run for the next frame after the delay, not all
+ * subsequent frames, so to render continuously the callback should itself call
+ * AChoreographer_postFrameCallbackDelayed64.
*
* Available since API level 29.
*/
@@ -165,8 +223,13 @@
uint32_t delayMillis) __INTRODUCED_IN(29);
/**
- * Posts a callback to be run on the next frame. The data pointer provided will
- * be passed to the callback function when it's called.
+ * Posts a callback to be run when the application should begin rendering the
+ * next frame. The data pointer provided will be passed to the callback function
+ * when it's called.
+ *
+ * The callback will only be run for the next frame, not all subsequent frames,
+ * so to render continuously the callback should itself call
+ * AChoreographer_postVsyncCallback.
*
* Available since API level 33.
*/
diff --git a/include/android/looper.h b/include/android/looper.h
index 6a02916..d80a366 100644
--- a/include/android/looper.h
+++ b/include/android/looper.h
@@ -182,23 +182,27 @@
* If the timeout is zero, returns immediately without blocking.
* If the timeout is negative, waits indefinitely until an event appears.
*
- * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before
+ * Returns ALOOPER_POLL_WAKE if the poll was awoken using ALooper_wake() before
* the timeout expired and no callbacks were invoked and no other file
- * descriptors were ready.
+ * descriptors were ready. **All return values may also imply
+ * ALOOPER_POLL_WAKE.**
*
- * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked.
+ * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked. The poll
+ * may also have been explicitly woken by ALooper_wake.
*
- * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given
- * timeout expired.
+ * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given timeout
+ * expired. The poll may also have been explicitly woken by ALooper_wake.
*
- * Returns ALOOPER_POLL_ERROR if an error occurred.
+ * Returns ALOOPER_POLL_ERROR if the calling thread has no associated Looper or
+ * for unrecoverable internal errors. The poll may also have been explicitly
+ * woken by ALooper_wake.
*
- * Returns a value >= 0 containing an identifier (the same identifier
- * `ident` passed to ALooper_addFd()) if its file descriptor has data
- * and it has no callback function (requiring the caller here to
- * handle it). In this (and only this) case outFd, outEvents and
- * outData will contain the poll events and data associated with the
- * fd, otherwise they will be set to NULL.
+ * Returns a value >= 0 containing an identifier (the same identifier `ident`
+ * passed to ALooper_addFd()) if its file descriptor has data and it has no
+ * callback function (requiring the caller here to handle it). In this (and
+ * only this) case outFd, outEvents and outData will contain the poll events and
+ * data associated with the fd, otherwise they will be set to NULL. The poll may
+ * also have been explicitly woken by ALooper_wake.
*
* This method does not return until it has finished invoking the appropriate callbacks
* for all file descriptors that were signalled.
@@ -210,11 +214,21 @@
* data has been consumed or a file descriptor is available with no callback.
* This function will never return ALOOPER_POLL_CALLBACK.
*
- * Removed in API 34 as ALooper_pollAll can swallow ALooper_wake calls.
- * Use ALooper_pollOnce instead.
+ * This API cannot be used safely, but a safe alternative exists (see below). As
+ * such, new builds will not be able to call this API and must migrate to the
+ * safe API. Binary compatibility is preserved to support already-compiled apps.
+ *
+ * \bug ALooper_pollAll will not wake in response to ALooper_wake calls if it
+ * also handles another event at the same time.
+ *
+ * \deprecated Calls to ALooper_pollAll should be replaced with
+ * ALooper_pollOnce. If you call ALooper_pollOnce in a loop, you *must* treat
+ * all return values as if they also indicate ALOOPER_POLL_WAKE.
*/
int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData)
- __REMOVED_IN(1, "ALooper_pollAll may ignore wakes. Use ALooper_pollOnce instead. See https://github.com/android/ndk/discussions/2020 for more information");
+ __REMOVED_IN(1,
+ "ALooper_pollAll may ignore wakes. Use ALooper_pollOnce instead. See "
+ "The API documentation for more information");
/**
* Wakes the poll asynchronously.
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
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index bc173b1..09b358a 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -117,7 +117,7 @@
// An arbitrary pid of the gesture monitor window
static constexpr gui::Pid MONITOR_PID{2001};
-static constexpr int expectedWallpaperFlags =
+static constexpr int EXPECTED_WALLPAPER_FLAGS =
AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
@@ -827,7 +827,7 @@
// Both foreground window and its wallpaper should receive the touch down
foregroundWindow->consumeMotionDown();
- wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(*mDispatcher,
@@ -837,13 +837,13 @@
<< "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
- wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
// Now the foreground window goes away, but the wallpaper stays
mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
foregroundWindow->consumeMotionCancel();
// Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
- wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
}
/**
@@ -908,7 +908,7 @@
// Both foreground window and its wallpaper should receive the touch down
foregroundWindow->consumeMotionDown();
- wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
@@ -916,7 +916,7 @@
<< "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
foregroundWindow->consumeMotionMove();
- wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
// Wallpaper closes its channel, but the window remains.
wallpaperWindow->destroyReceiver();
@@ -928,6 +928,301 @@
foregroundWindow->consumeMotionCancel();
}
+/**
+ * Two windows: left and right, and a separate wallpaper window underneath each. Device A sends a
+ * down event to the left window. Device B sends a down event to the right window. Next, the right
+ * window disappears. Both the right window and its wallpaper window should receive cancel event.
+ * The left window and its wallpaper window should not receive any events.
+ */
+TEST_F(InputDispatcherTest, MultiDeviceDisappearingWindowWithWallpaperWindows) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> leftForegroundWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
+ ADISPLAY_ID_DEFAULT);
+ leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
+ leftForegroundWindow->setDupTouchToWallpaper(true);
+ sp<FakeWindowHandle> leftWallpaperWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
+ ADISPLAY_ID_DEFAULT);
+ leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
+ leftWallpaperWindow->setIsWallpaper(true);
+
+ sp<FakeWindowHandle> rightForegroundWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
+ ADISPLAY_ID_DEFAULT);
+ rightForegroundWindow->setFrame(Rect(100, 0, 200, 100));
+ rightForegroundWindow->setDupTouchToWallpaper(true);
+ sp<FakeWindowHandle> rightWallpaperWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
+ ADISPLAY_ID_DEFAULT);
+ rightWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
+ rightWallpaperWindow->setIsWallpaper(true);
+
+ mDispatcher->onWindowInfosChanged(
+ {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
+ *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
+ {},
+ 0,
+ 0});
+
+ const DeviceId deviceA = 9;
+ const DeviceId deviceB = 3;
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .deviceId(deviceA)
+ .build());
+ leftForegroundWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
+ leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+ WithDeviceId(deviceA),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
+ .deviceId(deviceB)
+ .build());
+ rightForegroundWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
+ rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+ WithDeviceId(deviceB),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+
+ // Now right foreground window disappears, but right wallpaper window remains.
+ mDispatcher->onWindowInfosChanged(
+ {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
+ *rightWallpaperWindow->getInfo()},
+ {},
+ 0,
+ 0});
+
+ // Left foreground window and left wallpaper window still exist, and should not receive any
+ // events.
+ leftForegroundWindow->assertNoEvents();
+ leftWallpaperWindow->assertNoEvents();
+ // Since right foreground window disappeared, right wallpaper window and right foreground window
+ // should receive cancel events.
+ rightForegroundWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
+ rightWallpaperWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
+}
+
+/**
+ * Three windows arranged horizontally and without any overlap. Every window has a
+ * wallpaper window underneath. The middle window also has SLIPPERY flag.
+ * Device A sends a down event to the left window. Device B sends a down event to the middle window.
+ * Next, device B sends move event to the right window. Touch for device B should slip from the
+ * middle window to the right window. Also, the right wallpaper window should receive a down event.
+ * The middle window and its wallpaper window should receive a cancel event. The left window should
+ * not receive any events. If device B continues to report events, the right window and its
+ * wallpaper window should receive remaining events.
+ */
+TEST_F(InputDispatcherTest, MultiDeviceSlipperyTouchWithWallpaperWindow) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> leftForegroundWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
+ ADISPLAY_ID_DEFAULT);
+ leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
+ leftForegroundWindow->setDupTouchToWallpaper(true);
+ sp<FakeWindowHandle> leftWallpaperWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
+ ADISPLAY_ID_DEFAULT);
+ leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
+ leftWallpaperWindow->setIsWallpaper(true);
+
+ sp<FakeWindowHandle> middleForegroundWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
+ ADISPLAY_ID_DEFAULT);
+ middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
+ middleForegroundWindow->setDupTouchToWallpaper(true);
+ middleForegroundWindow->setSlippery(true);
+ sp<FakeWindowHandle> middleWallpaperWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
+ ADISPLAY_ID_DEFAULT);
+ middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
+ middleWallpaperWindow->setIsWallpaper(true);
+
+ sp<FakeWindowHandle> rightForegroundWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
+ ADISPLAY_ID_DEFAULT);
+ rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
+ rightForegroundWindow->setDupTouchToWallpaper(true);
+ sp<FakeWindowHandle> rightWallpaperWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
+ ADISPLAY_ID_DEFAULT);
+ rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
+ rightWallpaperWindow->setIsWallpaper(true);
+
+ mDispatcher->onWindowInfosChanged(
+ {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
+ *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
+ *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
+ {},
+ 0,
+ 0});
+
+ const DeviceId deviceA = 9;
+ const DeviceId deviceB = 3;
+ // Device A sends a DOWN event to the left window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .deviceId(deviceA)
+ .build());
+ leftForegroundWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
+ leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+ WithDeviceId(deviceA),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+ // Device B sends a DOWN event to the middle window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
+ .deviceId(deviceB)
+ .build());
+ middleForegroundWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
+ middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+ WithDeviceId(deviceB),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+ // Move the events of device B to the top of the right window.
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
+ .deviceId(deviceB)
+ .build());
+ middleForegroundWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
+ middleWallpaperWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
+ rightForegroundWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
+ rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+ WithDeviceId(deviceB),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+ // Make sure the window on the right can receive the remaining events.
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
+ .deviceId(deviceB)
+ .build());
+ leftForegroundWindow->assertNoEvents();
+ leftWallpaperWindow->assertNoEvents();
+ middleForegroundWindow->assertNoEvents();
+ middleWallpaperWindow->assertNoEvents();
+ rightForegroundWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
+ rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
+ WithDeviceId(deviceB),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+}
+
+/**
+ * Similar to the test above, we have three windows, they are arranged horizontally and without any
+ * overlap, and every window has a wallpaper window. The middle window is a simple window, without
+ * any special flags. Device A reports a down event that lands in left window. Device B sends a down
+ * event to the middle window and then touch is transferred from the middle window to the right
+ * window. The right window and its wallpaper window should receive a down event. The middle window
+ * and its wallpaper window should receive a cancel event. The left window should not receive any
+ * events. Subsequent events reported by device B should go to the right window and its wallpaper.
+ */
+TEST_F(InputDispatcherTest, MultiDeviceTouchTransferWithWallpaperWindows) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> leftForegroundWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
+ ADISPLAY_ID_DEFAULT);
+ leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
+ leftForegroundWindow->setDupTouchToWallpaper(true);
+ sp<FakeWindowHandle> leftWallpaperWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
+ ADISPLAY_ID_DEFAULT);
+ leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
+ leftWallpaperWindow->setIsWallpaper(true);
+
+ sp<FakeWindowHandle> middleForegroundWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
+ ADISPLAY_ID_DEFAULT);
+ middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
+ middleForegroundWindow->setDupTouchToWallpaper(true);
+ sp<FakeWindowHandle> middleWallpaperWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
+ ADISPLAY_ID_DEFAULT);
+ middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
+ middleWallpaperWindow->setIsWallpaper(true);
+
+ sp<FakeWindowHandle> rightForegroundWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
+ ADISPLAY_ID_DEFAULT);
+ rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
+ rightForegroundWindow->setDupTouchToWallpaper(true);
+ sp<FakeWindowHandle> rightWallpaperWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
+ ADISPLAY_ID_DEFAULT);
+ rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
+ rightWallpaperWindow->setIsWallpaper(true);
+
+ mDispatcher->onWindowInfosChanged(
+ {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
+ *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
+ *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
+ {},
+ 0,
+ 0});
+
+ const DeviceId deviceA = 9;
+ const DeviceId deviceB = 3;
+ // Device A touch down on the left window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .deviceId(deviceA)
+ .build());
+ leftForegroundWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
+ leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+ WithDeviceId(deviceA),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+ // Device B touch down on the middle window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
+ .deviceId(deviceB)
+ .build());
+ middleForegroundWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
+ middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+ WithDeviceId(deviceB),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS)));
+
+ // Transfer touch from the middle window to the right window.
+ ASSERT_TRUE(mDispatcher->transferTouchGesture(middleForegroundWindow->getToken(),
+ rightForegroundWindow->getToken()));
+
+ middleForegroundWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
+ middleWallpaperWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
+ rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+ WithDeviceId(deviceB),
+ WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
+ rightWallpaperWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
+
+ // Make sure the right window can receive the remaining events.
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
+ .deviceId(deviceB)
+ .build());
+ leftForegroundWindow->assertNoEvents();
+ leftWallpaperWindow->assertNoEvents();
+ middleForegroundWindow->assertNoEvents();
+ middleWallpaperWindow->assertNoEvents();
+ rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
+ WithDeviceId(deviceB),
+ WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
+ rightWallpaperWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
+}
+
class ShouldSplitTouchFixture : public InputDispatcherTest,
public ::testing::WithParamInterface<bool> {};
INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
@@ -959,7 +1254,7 @@
// Both top window and its wallpaper should receive the touch down
foregroundWindow->consumeMotionDown();
- wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
// Second finger down on the top window
const MotionEvent secondFingerDownEvent =
@@ -975,7 +1270,7 @@
foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
- expectedWallpaperFlags);
+ EXPECTED_WALLPAPER_FLAGS);
const MotionEvent secondFingerUpEvent =
MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
@@ -989,7 +1284,7 @@
InputEventInjectionSync::WAIT_FOR_RESULT))
<< "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
foregroundWindow->consumeMotionPointerUp(0);
- wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(*mDispatcher,
@@ -1004,7 +1299,7 @@
INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
<< "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
- wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
}
/**
@@ -1046,7 +1341,7 @@
// Both foreground window and its wallpaper should receive the touch down
leftWindow->consumeMotionDown();
- wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
// Second finger down on the right window
const MotionEvent secondFingerDownEvent =
@@ -1064,14 +1359,14 @@
// Since the touch is split, right window gets ACTION_DOWN
rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
- expectedWallpaperFlags);
+ EXPECTED_WALLPAPER_FLAGS);
// Now, leftWindow, which received the first finger, disappears.
mDispatcher->onWindowInfosChanged(
{{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
leftWindow->consumeMotionCancel();
// Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
- wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
// The pointer that's still down on the right window moves, and goes to the right window only.
// As far as the dispatcher's concerned though, both pointers are still present.
@@ -1126,7 +1421,7 @@
// Both foreground window and its wallpaper should receive the touch down
leftWindow->consumeMotionDown();
- wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
// Move to right window, the left window should receive cancel.
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -1136,7 +1431,7 @@
leftWindow->consumeMotionCancel();
rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
- wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
}
/**
@@ -5763,7 +6058,7 @@
// Only the first window should get the down event
firstWindow->consumeMotionDown();
secondWindow->assertNoEvents();
- wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
// Dispatcher reports pointer down outside focus for the wallpaper
mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
@@ -5774,7 +6069,7 @@
// The first window gets cancel and the second gets down
firstWindow->consumeMotionCancel();
secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
- wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
// There should not be any changes to the focused window when transferring touch
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
@@ -5935,7 +6230,7 @@
// Only the first window should get the down event
firstWindow->consumeMotionDown();
secondWindow->assertNoEvents();
- wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
wallpaper2->assertNoEvents();
// Transfer touch focus to the second window
@@ -5946,9 +6241,9 @@
// The first window gets cancel and the second gets down
firstWindow->consumeMotionCancel();
secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
- wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
+ wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, EXPECTED_WALLPAPER_FLAGS);
wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT,
- expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+ EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
// Send up event to the second window
mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
@@ -5958,7 +6253,7 @@
secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
wallpaper1->assertNoEvents();
wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT,
- expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+ EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
}
// For the cases of single pointer touch and two pointers non-split touch, the api's
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 9353467..a4c75a4 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -448,6 +448,7 @@
void commitTransactionsLocked(uint32_t transactionFlags) {
Mutex::Autolock lock(mFlinger->mStateLock);
ftl::FakeGuard guard(kMainThreadContext);
+ mFlinger->processDisplayChangesLocked();
mFlinger->commitTransactionsLocked(transactionFlags);
}