Merge "Turn off integer overflow UBSAN checks for hash functions" 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/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index 6ccc6ca..81f6a58 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -40,6 +40,9 @@
static constexpr uint64_t NSEC_PER_SEC = 1000000000;
static constexpr uint64_t NSEC_PER_YEAR = NSEC_PER_SEC * 60 * 60 * 24 * 365;
+// Declare busy loop variable globally to prevent removal during optimization
+static long sum __attribute__((used)) = 0;
+
using std::vector;
class TimeInStateTest : public testing::Test {
@@ -576,7 +579,7 @@
// Keeps CPU busy with some number crunching
void useCpu() {
- long sum = 0;
+ sum = 0;
for (int i = 0; i < 100000; i++) {
sum *= i;
}
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/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 77e672c..4d8ed99 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -61,9 +61,6 @@
// The display size or orientation changed.
DISPLAY_INFO = 1u << 2,
- // The visible touches option changed.
- SHOW_TOUCHES = 1u << 3,
-
// The keyboard layouts must be reloaded.
KEYBOARD_LAYOUTS = 1u << 4,
@@ -214,9 +211,6 @@
// will cover this portion of the display diagonal.
float pointerGestureZoomSpeedRatio;
- // True to show the location of touches on the touch screen as spots.
- bool showTouches;
-
// The latest request to enable or disable Pointer Capture.
PointerCaptureRequest pointerCaptureRequest;
@@ -268,7 +262,6 @@
pointerGestureSwipeMaxWidthRatio(0.25f),
pointerGestureMovementSpeedRatio(0.8f),
pointerGestureZoomSpeedRatio(0.3f),
- showTouches(false),
pointerCaptureRequest(),
touchpadPointerSpeed(0),
touchpadNaturalScrollingEnabled(true),
@@ -449,10 +442,6 @@
/* Gets the input reader configuration. */
virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) = 0;
- /* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
- virtual std::shared_ptr<PointerControllerInterface> obtainPointerController(
- int32_t deviceId) = 0;
-
/* Notifies the input reader policy that some input devices have changed
* and provides information about all current input devices.
*/
diff --git a/services/inputflinger/include/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
index 6b26e81..c1467b3 100644
--- a/services/inputflinger/include/PointerControllerInterface.h
+++ b/services/inputflinger/include/PointerControllerInterface.h
@@ -61,8 +61,6 @@
* TODO(b/293587049): Refactor the PointerController class into different controller types.
*/
enum class ControllerType {
- // The PointerController that is responsible for drawing all icons.
- LEGACY,
// Represents a single mouse pointer.
MOUSE,
// Represents multiple touch spots.
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 9608210..903c6ed 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -402,10 +402,6 @@
ALOGI("Reconfiguring input devices, changes=%s", changes.string().c_str());
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- if (changes.test(Change::DISPLAY_INFO)) {
- updatePointerDisplayLocked();
- }
-
if (changes.test(Change::MUST_REOPEN)) {
mEventHub->requestReopenDevices();
} else {
@@ -490,47 +486,6 @@
}
}
-std::shared_ptr<PointerControllerInterface> InputReader::getPointerControllerLocked(
- int32_t deviceId) {
- std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
- if (controller == nullptr) {
- controller = mPolicy->obtainPointerController(deviceId);
- mPointerController = controller;
- updatePointerDisplayLocked();
- }
- return controller;
-}
-
-void InputReader::updatePointerDisplayLocked() {
- std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
- if (controller == nullptr) {
- return;
- }
-
- std::optional<DisplayViewport> viewport =
- mConfig.getDisplayViewportById(mConfig.defaultPointerDisplayId);
- if (!viewport) {
- ALOGW("Can't find the designated viewport with ID %" PRId32 " to update cursor input "
- "mapper. Fall back to default display",
- mConfig.defaultPointerDisplayId);
- viewport = mConfig.getDisplayViewportById(ADISPLAY_ID_DEFAULT);
- }
- if (!viewport) {
- ALOGE("Still can't find a viable viewport to update cursor input mapper. Skip setting it to"
- " PointerController.");
- return;
- }
-
- controller->setDisplayViewport(*viewport);
-}
-
-void InputReader::fadePointerLocked() {
- std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
- if (controller != nullptr) {
- controller->fade(PointerControllerInterface::Transition::GRADUAL);
- }
-}
-
void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
if (when < mNextTimeout) {
mNextTimeout = when;
@@ -1067,17 +1022,6 @@
return mReader->shouldDropVirtualKeyLocked(now, keyCode, scanCode);
}
-void InputReader::ContextImpl::fadePointer() {
- // lock is already held by the input loop
- mReader->fadePointerLocked();
-}
-
-std::shared_ptr<PointerControllerInterface> InputReader::ContextImpl::getPointerController(
- int32_t deviceId) {
- // lock is already held by the input loop
- return mReader->getPointerControllerLocked(deviceId);
-}
-
void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
// lock is already held by the input loop
mReader->requestTimeoutAtTimeLocked(when);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 4c78db3..5f882cf 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -16,7 +16,6 @@
#pragma once
-#include <PointerControllerInterface.h>
#include <android-base/thread_annotations.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
@@ -141,9 +140,6 @@
void disableVirtualKeysUntil(nsecs_t time) REQUIRES(mReader->mLock) override;
bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode)
REQUIRES(mReader->mLock) override;
- void fadePointer() REQUIRES(mReader->mLock) override;
- std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId)
- REQUIRES(mReader->mLock) override;
void requestTimeoutAtTime(nsecs_t when) REQUIRES(mReader->mLock) override;
int32_t bumpGeneration() NO_THREAD_SAFETY_ANALYSIS override;
void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices)
@@ -230,13 +226,6 @@
[[nodiscard]] std::list<NotifyArgs> dispatchExternalStylusStateLocked(const StylusState& state)
REQUIRES(mLock);
- // The PointerController that is shared among all the input devices that need it.
- std::weak_ptr<PointerControllerInterface> mPointerController;
- std::shared_ptr<PointerControllerInterface> getPointerControllerLocked(int32_t deviceId)
- REQUIRES(mLock);
- void updatePointerDisplayLocked() REQUIRES(mLock);
- void fadePointerLocked() REQUIRES(mLock);
-
int32_t mGeneration GUARDED_BY(mLock);
int32_t bumpGenerationLocked() REQUIRES(mLock);
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
index 69b2315..907a49f 100644
--- a/services/inputflinger/reader/include/InputReaderContext.h
+++ b/services/inputflinger/reader/include/InputReaderContext.h
@@ -28,7 +28,6 @@
class InputListenerInterface;
class InputMapper;
class InputReaderPolicyInterface;
-class PointerControllerInterface;
struct StylusState;
/* Internal interface used by individual input devices to access global input device state
@@ -45,9 +44,6 @@
virtual void disableVirtualKeysUntil(nsecs_t time) = 0;
virtual bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) = 0;
- virtual void fadePointer() = 0;
- virtual std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId) = 0;
-
virtual void requestTimeoutAtTime(nsecs_t when) = 0;
virtual int32_t bumpGeneration() = 0;
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 738517b..658ceab 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -483,16 +483,11 @@
void KeyboardInputMapper::onKeyDownProcessed(nsecs_t downTime) {
InputReaderContext& context = *getContext();
context.setLastKeyDownTimestamp(downTime);
- if (context.isPreventingTouchpadTaps()) {
- // avoid pinging java service unnecessarily, just fade pointer again if it became visible
- context.fadePointer();
- return;
- }
+ // TODO(b/338652288): Move cursor fading logic into PointerChoreographer.
// Ignore meta keys or multiple simultaneous down keys as they are likely to be keyboard
// shortcuts
bool shouldHideCursor = mKeyDowns.size() == 1 && !isMetaKey(mKeyDowns[0].keyCode);
if (shouldHideCursor && context.getPolicy()->isInputMethodConnectionActive()) {
- context.fadePointer();
context.setPreventingTouchpadTaps(true);
}
}
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
index e9118a9..e2dcb41 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
@@ -155,11 +155,6 @@
mConfig.disabledDevices.erase(deviceId);
}
-void FakeInputReaderPolicy::setPointerController(
- std::shared_ptr<FakePointerController> controller) {
- mPointerController = std::move(controller);
-}
-
const InputReaderConfiguration& FakeInputReaderPolicy::getReaderConfiguration() const {
return mConfig;
}
@@ -183,10 +178,6 @@
return mConfig.pointerCaptureRequest;
}
-void FakeInputReaderPolicy::setShowTouches(bool enabled) {
- mConfig.showTouches = enabled;
-}
-
void FakeInputReaderPolicy::setDefaultPointerDisplayId(int32_t pointerDisplayId) {
mConfig.defaultPointerDisplayId = pointerDisplayId;
}
@@ -228,11 +219,6 @@
*outConfig = mConfig;
}
-std::shared_ptr<PointerControllerInterface> FakeInputReaderPolicy::obtainPointerController(
- int32_t /*deviceId*/) {
- return mPointerController;
-}
-
void FakeInputReaderPolicy::notifyInputDevicesChanged(
const std::vector<InputDeviceInfo>& inputDevices) {
std::scoped_lock lock(mLock);
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.h b/services/inputflinger/tests/FakeInputReaderPolicy.h
index 710bb54..88f0ba7 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.h
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.h
@@ -26,7 +26,6 @@
#include <InputDevice.h>
#include <InputReaderBase.h>
-#include "FakePointerController.h"
#include "input/DisplayViewport.h"
#include "input/InputDevice.h"
@@ -62,14 +61,12 @@
const KeyboardLayoutInfo& layoutInfo);
void addDisabledDevice(int32_t deviceId);
void removeDisabledDevice(int32_t deviceId);
- void setPointerController(std::shared_ptr<FakePointerController> controller);
const InputReaderConfiguration& getReaderConfiguration() const;
const std::vector<InputDeviceInfo> getInputDevices() const;
TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
ui::Rotation surfaceRotation);
void setTouchAffineTransformation(const TouchAffineTransformation t);
PointerCaptureRequest setPointerCapture(const sp<IBinder>& window);
- void setShowTouches(bool enabled);
void setDefaultPointerDisplayId(int32_t pointerDisplayId);
void setPointerGestureEnabled(bool enabled);
float getPointerGestureMovementSpeedRatio();
@@ -84,8 +81,6 @@
private:
void getReaderConfiguration(InputReaderConfiguration* outConfig) override;
- std::shared_ptr<PointerControllerInterface> obtainPointerController(
- int32_t /*deviceId*/) override;
void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override;
std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
const InputDeviceIdentifier&, const std::optional<KeyboardLayoutInfo>) override;
@@ -97,7 +92,6 @@
std::condition_variable mDevicesChangedCondition;
InputReaderConfiguration mConfig;
- std::shared_ptr<FakePointerController> mPointerController;
std::vector<InputDeviceInfo> mInputDevices GUARDED_BY(mLock);
bool mInputDevicesChanged GUARDED_BY(mLock){false};
std::vector<DisplayViewport> mViewports;
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/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index e1b46fa..92489ae 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -46,7 +46,6 @@
#include <thread>
#include "FakeEventHub.h"
#include "FakeInputReaderPolicy.h"
-#include "FakePointerController.h"
#include "InputMapperTest.h"
#include "InstrumentedInputReader.h"
#include "TestConstants.h"
@@ -1349,8 +1348,6 @@
sp<FakeInputReaderPolicy> mFakePolicy;
std::unique_ptr<InputReaderInterface> mReader;
- std::shared_ptr<FakePointerController> mFakePointerController;
-
constexpr static auto EVENT_HAPPENED_TIMEOUT = 2000ms;
constexpr static auto EVENT_DID_NOT_HAPPEN_TIMEOUT = 30ms;
@@ -1359,8 +1356,6 @@
GTEST_SKIP();
#endif
mFakePolicy = sp<FakeInputReaderPolicy>::make();
- mFakePointerController = std::make_shared<FakePointerController>();
- mFakePolicy->setPointerController(mFakePointerController);
setupInputReader();
}
@@ -1654,8 +1649,6 @@
} else {
mFakePolicy->addInputUniqueIdAssociation(INPUT_PORT, UNIQUE_ID);
}
- mFakePointerController = std::make_shared<FakePointerController>();
- mFakePolicy->setPointerController(mFakePointerController);
InputReaderIntegrationTest::setupInputReader();
diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h
index db89168..6389cdc 100644
--- a/services/inputflinger/tests/InterfaceMocks.h
+++ b/services/inputflinger/tests/InterfaceMocks.h
@@ -28,7 +28,6 @@
#include <EventHub.h>
#include <InputReaderBase.h>
#include <NotifyArgs.h>
-#include <PointerControllerInterface.h>
#include <StylusState.h>
#include <VibrationElement.h>
#include <android-base/logging.h>
@@ -54,10 +53,6 @@
MOCK_METHOD(bool, shouldDropVirtualKey, (nsecs_t now, int32_t keyCode, int32_t scanCode),
(override));
- MOCK_METHOD(void, fadePointer, (), (override));
- MOCK_METHOD(std::shared_ptr<PointerControllerInterface>, getPointerController,
- (int32_t deviceId), (override));
-
MOCK_METHOD(void, requestTimeoutAtTime, (nsecs_t when), (override));
int32_t bumpGeneration() override { return ++mGeneration; }
diff --git a/services/inputflinger/tests/KeyboardInputMapper_test.cpp b/services/inputflinger/tests/KeyboardInputMapper_test.cpp
index b44529b..031b77d 100644
--- a/services/inputflinger/tests/KeyboardInputMapper_test.cpp
+++ b/services/inputflinger/tests/KeyboardInputMapper_test.cpp
@@ -72,8 +72,6 @@
}
void testPointerVisibilityForKeys(const std::vector<int32_t>& keyCodes, bool expectVisible) {
- EXPECT_CALL(mMockInputReaderContext, fadePointer)
- .Times(expectVisible ? 0 : keyCodes.size());
for (int32_t keyCode : keyCodes) {
process(EV_KEY, keyCode, 1);
process(EV_SYN, SYN_REPORT, 0);
@@ -84,7 +82,6 @@
void testTouchpadTapStateForKeys(const std::vector<int32_t>& keyCodes,
const bool expectPrevent) {
- EXPECT_CALL(mMockInputReaderContext, isPreventingTouchpadTaps).Times(keyCodes.size());
if (expectPrevent) {
EXPECT_CALL(mMockInputReaderContext, setPreventingTouchpadTaps(true))
.Times(keyCodes.size());
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index 2602ebb..e020ca9 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -258,57 +258,16 @@
void sysfsNodeChanged(const std::string& sysfsNodePath) override {}
};
-class FuzzPointerController : public PointerControllerInterface {
- std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp;
-
-public:
- FuzzPointerController(std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp) : mFdp(mFdp) {}
- ~FuzzPointerController() {}
- std::optional<FloatRect> getBounds() const override {
- if (mFdp->ConsumeBool()) {
- return {};
- } else {
- return FloatRect{mFdp->ConsumeFloatingPoint<float>(),
- mFdp->ConsumeFloatingPoint<float>(),
- mFdp->ConsumeFloatingPoint<float>(),
- mFdp->ConsumeFloatingPoint<float>()};
- }
- }
- void move(float deltaX, float deltaY) override {}
- void setPosition(float x, float y) override {}
- FloatPoint getPosition() const override {
- return {mFdp->ConsumeFloatingPoint<float>(), mFdp->ConsumeFloatingPoint<float>()};
- }
- void fade(Transition transition) override {}
- void unfade(Transition transition) override {}
- void setPresentation(Presentation presentation) override {}
- void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
- BitSet32 spotIdBits, int32_t displayId) override {}
- void clearSpots() override {}
- int32_t getDisplayId() const override { return mFdp->ConsumeIntegral<int32_t>(); }
- void setDisplayViewport(const DisplayViewport& displayViewport) override {}
- void updatePointerIcon(PointerIconStyle iconId) override {}
- void setCustomPointerIcon(const SpriteIcon& icon) override {}
- void setSkipScreenshot(int32_t displayId, bool skip) override{};
- std::string dump() override { return ""; }
-};
-
class FuzzInputReaderPolicy : public InputReaderPolicyInterface {
TouchAffineTransformation mTransform;
- std::shared_ptr<FuzzPointerController> mPointerController;
std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp;
protected:
~FuzzInputReaderPolicy() {}
public:
- FuzzInputReaderPolicy(std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp) : mFdp(mFdp) {
- mPointerController = std::make_shared<FuzzPointerController>(mFdp);
- }
+ FuzzInputReaderPolicy(std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp) : mFdp(mFdp) {}
void getReaderConfiguration(InputReaderConfiguration* outConfig) override {}
- std::shared_ptr<PointerControllerInterface> obtainPointerController(int32_t deviceId) override {
- return mPointerController;
- }
void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {}
std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
const InputDeviceIdentifier& identifier,
@@ -360,10 +319,6 @@
bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) override {
return mFdp->ConsumeBool();
}
- void fadePointer() override {}
- std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId) override {
- return mPolicy->obtainPointerController(0);
- }
void requestTimeoutAtTime(nsecs_t when) override {}
int32_t bumpGeneration() override { return mFdp->ConsumeIntegral<int32_t>(); }
void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) override {}
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);
}