Cancel touchscreen gestures from Dispatcher when display rotates
When the display rotates, previously, touchscreen devices were reset,
and a notifyDeviceReset is sent to Displatcher. When that happens,
Dispatcher cancells all active gestures from that device.
With this CL, we skip a device reset when the display rotates because
there is nothing that changes for the touchscreen device. Instead, when
we get a new set of input windows from SF in dispatcher, we track if the
orientation changes, and if it does, issue a cancellation for all
pointer events.
Bug: 185943742
Test: manual
Change-Id: Ic8ff19c0dc9cca7b1053a137ea041e5a0da82a76
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 6d405d8..16abd48 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -90,6 +90,14 @@
namespace android::inputdispatcher {
+// When per-window-input-rotation is enabled, InputFlinger works in the un-rotated display
+// coordinates and SurfaceFlinger includes the display rotation in the input window transforms.
+static bool isPerWindowInputRotationEnabled() {
+ static const bool PER_WINDOW_INPUT_ROTATION =
+ base::GetBoolProperty("persist.debug.per_window_input_rotation", false);
+ return PER_WINDOW_INPUT_ROTATION;
+}
+
// Default input dispatching timeout if there is no focused application or paused window
// from which to determine an appropriate dispatching timeout.
const std::chrono::duration DEFAULT_INPUT_DISPATCHING_TIMEOUT = std::chrono::milliseconds(
@@ -4441,6 +4449,13 @@
// Copy old handles for release if they are no longer present.
const std::vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
+ // Save the old windows' orientation by ID before it gets updated.
+ std::unordered_map<int32_t, uint32_t> oldWindowOrientations;
+ for (const sp<InputWindowHandle>& handle : oldWindowHandles) {
+ oldWindowOrientations.emplace(handle->getId(),
+ handle->getInfo()->transform.getOrientation());
+ }
+
updateWindowHandlesForDisplayLocked(inputWindowHandles, displayId);
const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId);
@@ -4489,6 +4504,25 @@
}
}
+ if (isPerWindowInputRotationEnabled()) {
+ // Determine if the orientation of any of the input windows have changed, and cancel all
+ // pointer events if necessary.
+ for (const sp<InputWindowHandle>& oldWindowHandle : oldWindowHandles) {
+ const sp<InputWindowHandle> newWindowHandle = getWindowHandleLocked(oldWindowHandle);
+ if (newWindowHandle != nullptr &&
+ newWindowHandle->getInfo()->transform.getOrientation() !=
+ oldWindowOrientations[oldWindowHandle->getId()]) {
+ std::shared_ptr<InputChannel> inputChannel =
+ getInputChannelLocked(newWindowHandle->getToken());
+ if (inputChannel != nullptr) {
+ CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
+ "touched window's orientation changed");
+ synthesizeCancelationEventsForInputChannelLocked(inputChannel, options);
+ }
+ }
+ }
+ }
+
// Release information for windows that are no longer present.
// This ensures that unused input channels are released promptly.
// Otherwise, they might stick around until the window handle is destroyed