Merge "Reset touch state when device resets" into udc-dev am: b49fc5d583
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/22974478
Change-Id: I51f9858a7273d45879183d9d9f25907e7ff233b6
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index ed5cd10..e4f367d 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1461,6 +1461,11 @@
CancelationOptions options(CancelationOptions::Mode::CANCEL_ALL_EVENTS, "device was reset");
options.deviceId = entry.deviceId;
synthesizeCancelationEventsForAllConnectionsLocked(options);
+
+ // Remove all active pointers from this device
+ for (auto& [_, touchState] : mTouchStatesByDisplay) {
+ touchState.removeAllPointersForDevice(entry.deviceId);
+ }
return true;
}
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index 9c443f1..0a61d48 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -242,6 +242,18 @@
clearWindowsWithoutPointers();
}
+void TouchState::removeAllPointersForDevice(int32_t removedDeviceId) {
+ for (TouchedWindow& window : windows) {
+ window.removeAllHoveringPointersForDevice(removedDeviceId);
+ }
+ if (deviceId == removedDeviceId) {
+ for (TouchedWindow& window : windows) {
+ window.removeAllTouchingPointers();
+ }
+ }
+ clearWindowsWithoutPointers();
+}
+
std::string TouchState::dump() const {
std::string out;
out += StringPrintf("deviceId=%d, source=%s\n", deviceId,
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index a20080f..15b840f 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -54,6 +54,8 @@
int32_t deviceId, int32_t hoveringPointerId);
void removeHoveringPointer(int32_t deviceId, int32_t hoveringPointerId);
void clearHoveringPointers();
+
+ void removeAllPointersForDevice(int32_t removedDeviceId);
void removeWindowByToken(const sp<IBinder>& token);
void filterNonAsIsTouchWindows();
diff --git a/services/inputflinger/dispatcher/TouchedWindow.cpp b/services/inputflinger/dispatcher/TouchedWindow.cpp
index 99c4769..d55d657 100644
--- a/services/inputflinger/dispatcher/TouchedWindow.cpp
+++ b/services/inputflinger/dispatcher/TouchedWindow.cpp
@@ -58,6 +58,10 @@
}
}
+void TouchedWindow::removeAllTouchingPointers() {
+ pointerIds.reset();
+}
+
void TouchedWindow::removeHoveringPointer(int32_t deviceId, int32_t pointerId) {
const auto it = mHoveringPointerIdsByDevice.find(deviceId);
if (it == mHoveringPointerIdsByDevice.end()) {
@@ -70,6 +74,10 @@
}
}
+void TouchedWindow::removeAllHoveringPointersForDevice(int32_t deviceId) {
+ mHoveringPointerIdsByDevice.erase(deviceId);
+}
+
std::string TouchedWindow::dump() const {
std::string out;
std::string hoveringPointers =
diff --git a/services/inputflinger/dispatcher/TouchedWindow.h b/services/inputflinger/dispatcher/TouchedWindow.h
index aa2e9dd..43e7169 100644
--- a/services/inputflinger/dispatcher/TouchedWindow.h
+++ b/services/inputflinger/dispatcher/TouchedWindow.h
@@ -44,6 +44,9 @@
void addHoveringPointer(int32_t deviceId, int32_t pointerId);
void removeHoveringPointer(int32_t deviceId, int32_t pointerId);
void removeTouchingPointer(int32_t pointerId);
+
+ void removeAllTouchingPointers();
+ void removeAllHoveringPointersForDevice(int32_t deviceId);
void clearHoveringPointers();
std::string dump() const;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 0741be0..147b7d4 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -3678,6 +3678,30 @@
AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
}
+TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
+ "Fake Window", ADISPLAY_ID_DEFAULT);
+
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
+ .build());
+
+ window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
+
+ // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
+ mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
+ window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
+
+ // After the device has been reset, a new hovering stream can be sent to the window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
+ .build());
+ window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
+}
+
TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,