TouchEvent (4/n) Firing event when setting mInTouchMode
Roll forward ag/15925114
This reverts commit 967bf71311907c9d6b12ef268a8a38d7c718b17f.
Bug: 193718270
Change-Id: Iab2e33e23ce7e9dd59fa09bb81e388369e6496ef
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index f094fee..53c34f6 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -88,6 +88,9 @@
// Log debug messages about input focus tracking.
constexpr bool DEBUG_FOCUS = false;
+// Log debug messages about touch mode event
+constexpr bool DEBUG_TOUCH_MODE = false;
+
// Log debug messages about touch occlusion
// STOPSHIP(b/169067926): Set to false
constexpr bool DEBUG_TOUCH_OCCLUSION = true;
@@ -534,6 +537,23 @@
return transformedXy - transformedOrigin;
}
+// Returns true if the event type passed as argument represents a user activity.
+bool isUserActivityEvent(const EventEntry& eventEntry) {
+ switch (eventEntry.type) {
+ case EventEntry::Type::FOCUS:
+ case EventEntry::Type::POINTER_CAPTURE_CHANGED:
+ case EventEntry::Type::DRAG:
+ case EventEntry::Type::TOUCH_MODE_CHANGED:
+ case EventEntry::Type::SENSOR:
+ case EventEntry::Type::CONFIGURATION_CHANGED:
+ return false;
+ case EventEntry::Type::DEVICE_RESET:
+ case EventEntry::Type::KEY:
+ case EventEntry::Type::MOTION:
+ return true;
+ }
+}
+
} // namespace
// --- InputDispatcher ---
@@ -552,7 +572,7 @@
// mInTouchMode will be initialized by the WindowManager to the default device config.
// To avoid leaking stack in case that call never comes, and for tests,
// initialize it here anyways.
- mInTouchMode(true),
+ mInTouchMode(kDefaultInTouchMode),
mMaximumObscuringOpacityForTouch(1.0f),
mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
mWindowTokenWithPointerCapture(nullptr),
@@ -1790,9 +1810,9 @@
displayId = motionEntry.displayId;
break;
}
+ case EventEntry::Type::TOUCH_MODE_CHANGED:
case EventEntry::Type::POINTER_CAPTURE_CHANGED:
case EventEntry::Type::FOCUS:
- case EventEntry::Type::TOUCH_MODE_CHANGED:
case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET:
case EventEntry::Type::SENSOR:
@@ -2773,11 +2793,8 @@
}
void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) {
- if (eventEntry.type == EventEntry::Type::FOCUS ||
- eventEntry.type == EventEntry::Type::POINTER_CAPTURE_CHANGED ||
- eventEntry.type == EventEntry::Type::DRAG) {
- // Focus or pointer capture changed events are passed to apps, but do not represent user
- // activity.
+ if (!isUserActivityEvent(eventEntry)) {
+ // Not poking user activity if the event type does not represent a user activity
return;
}
int32_t displayId = getTargetDisplayId(eventEntry);
@@ -2813,16 +2830,7 @@
eventType = USER_ACTIVITY_EVENT_BUTTON;
break;
}
- case EventEntry::Type::TOUCH_MODE_CHANGED: {
- break;
- }
-
- case EventEntry::Type::FOCUS:
- case EventEntry::Type::CONFIGURATION_CHANGED:
- case EventEntry::Type::DEVICE_RESET:
- case EventEntry::Type::SENSOR:
- case EventEntry::Type::POINTER_CAPTURE_CHANGED:
- case EventEntry::Type::DRAG: {
+ default: {
LOG_ALWAYS_FATAL("%s events are not user activity",
ftl::enum_string(eventEntry.type).c_str());
break;
@@ -3795,7 +3803,7 @@
ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args->eventTime);
}
- bool needWake;
+ bool needWake = false;
{ // acquire lock
std::scoped_lock _l(mLock);
@@ -3890,7 +3898,7 @@
std::to_string(t.duration().count()).c_str());
}
- bool needWake;
+ bool needWake = false;
{ // acquire lock
mLock.lock();
@@ -3967,7 +3975,7 @@
std::to_string(t.duration().count()).c_str());
}
- bool needWake;
+ bool needWake = false;
{ // acquire lock
mLock.lock();
@@ -4032,7 +4040,7 @@
ftl::enum_string(args->sensorType).c_str());
}
- bool needWake;
+ bool needWake = false;
{ // acquire lock
mLock.lock();
@@ -4082,7 +4090,7 @@
args->deviceId);
}
- bool needWake;
+ bool needWake = false;
{ // acquire lock
std::scoped_lock _l(mLock);
@@ -4102,7 +4110,7 @@
args->request.enable ? "true" : "false");
}
- bool needWake;
+ bool needWake = false;
{ // acquire lock
std::scoped_lock _l(mLock);
auto entry = std::make_unique<PointerCaptureChangedEntry>(args->id, args->eventTime,
@@ -4919,9 +4927,29 @@
}
void InputDispatcher::setInTouchMode(bool inTouchMode) {
- std::scoped_lock lock(mLock);
- mInTouchMode = inTouchMode;
- // TODO(b/193718270): Fire TouchModeEvent here.
+ bool needWake = false;
+ {
+ std::scoped_lock lock(mLock);
+ if (mInTouchMode == inTouchMode) {
+ return;
+ }
+ if (DEBUG_TOUCH_MODE) {
+ ALOGD("Request to change touch mode from %s to %s", toString(mInTouchMode),
+ toString(inTouchMode));
+ // TODO(b/198487159): Also print the current last interacted apps.
+ }
+
+ // TODO(b/198499018): Store touch mode per display.
+ mInTouchMode = inTouchMode;
+
+ // TODO(b/198487159): Enforce that only last interacted apps can change touch mode.
+ auto entry = std::make_unique<TouchModeEntry>(mIdGenerator.nextId(), now(), inTouchMode);
+ needWake = enqueueInboundEventLocked(std::move(entry));
+ } // release lock
+
+ if (needWake) {
+ mLooper->wake();
+ }
}
void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 2282d91..e1544d8 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -86,6 +86,8 @@
~InputDispatcher() override;
public:
+ static constexpr bool kDefaultInTouchMode = true;
+
explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
void dump(std::string& dump) override;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 7fb2ccf..3207495 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -817,6 +817,9 @@
case AINPUT_EVENT_TYPE_CAPTURE: {
FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
}
+ case AINPUT_EVENT_TYPE_TOUCH_MODE: {
+ FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
+ }
case AINPUT_EVENT_TYPE_DRAG: {
FAIL() << "Use 'consumeDragEvent' for DRAG events";
}
@@ -874,6 +877,20 @@
EXPECT_EQ(y, dragEvent.getY());
}
+ void consumeTouchModeEvent(bool inTouchMode) {
+ const InputEvent* event = consume();
+ ASSERT_NE(nullptr, event) << mName.c_str()
+ << ": consumer should have returned non-NULL event.";
+ ASSERT_EQ(AINPUT_EVENT_TYPE_TOUCH_MODE, event->getType())
+ << "Got " << inputEventTypeToString(event->getType())
+ << " event instead of TOUCH_MODE event";
+
+ ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
+ << mName.c_str() << ": event displayId should always be NONE.";
+ const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
+ EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
+ }
+
void assertNoEvents() {
InputEvent* event = consume();
if (event == nullptr) {
@@ -895,6 +912,10 @@
const auto& captureEvent = static_cast<CaptureEvent&>(*event);
ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
<< (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
+ } else if (event->getType() == AINPUT_EVENT_TYPE_TOUCH_MODE) {
+ const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
+ ADD_FAILURE() << "Received touch mode event, inTouchMode = "
+ << (touchModeEvent.isInTouchMode() ? "true" : "false");
}
FAIL() << mName.c_str()
<< ": should not have received any events, so consume() should return NULL";
@@ -1087,6 +1108,12 @@
mInputReceiver->consumeDragEvent(isExiting, x, y);
}
+ void consumeTouchModeEvent(bool inTouchMode) {
+ ASSERT_NE(mInputReceiver, nullptr)
+ << "Cannot consume events from a window with no receiver";
+ mInputReceiver->consumeTouchModeEvent(inTouchMode);
+ }
+
std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
if (mInputReceiver == nullptr) {
ADD_FAILURE() << "Invalid receive event on window with no receiver";
@@ -2725,7 +2752,6 @@
SCOPED_TRACE("Check default value of touch mode");
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
setFocusedWindow(window);
-
window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
SCOPED_TRACE("Remove the window to trigger focus loss");
@@ -2735,6 +2761,7 @@
SCOPED_TRACE("Disable touch mode");
mDispatcher->setInTouchMode(false);
+ window->consumeTouchModeEvent(false);
window->setFocusable(true);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
setFocusedWindow(window);
@@ -2747,6 +2774,7 @@
SCOPED_TRACE("Enable touch mode again");
mDispatcher->setInTouchMode(true);
+ window->consumeTouchModeEvent(true);
window->setFocusable(true);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
setFocusedWindow(window);
@@ -5882,4 +5910,43 @@
window->assertNoEvents();
}
+class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
+protected:
+ std::shared_ptr<FakeApplicationHandle> mApp;
+ sp<FakeWindowHandle> mWindow;
+ sp<FakeWindowHandle> mSecondWindow;
+
+ void SetUp() override {
+ InputDispatcherTest::SetUp();
+
+ mApp = std::make_shared<FakeApplicationHandle>();
+ mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
+ mWindow->setFocusable(true);
+ mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
+ mSecondWindow->setFocusable(true);
+
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
+
+ setFocusedWindow(mWindow);
+ mWindow->consumeFocusEvent(true);
+ }
+
+ void changeAndVerifyTouchMode(bool inTouchMode) {
+ mDispatcher->setInTouchMode(inTouchMode);
+ mWindow->consumeTouchModeEvent(inTouchMode);
+ mSecondWindow->consumeTouchModeEvent(inTouchMode);
+ }
+};
+
+TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchModeOnFocusedWindow) {
+ changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode);
+}
+
+TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
+ mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode);
+ mWindow->assertNoEvents();
+ mSecondWindow->assertNoEvents();
+}
+
} // namespace android::inputdispatcher