Loading services/inputflinger/dispatcher/InputDispatcher.cpp +27 −7 Original line number Diff line number Diff line Loading @@ -137,7 +137,7 @@ constexpr std::chrono::nanoseconds KEY_WAITING_FOR_EVENTS_TIMEOUT = 500ms; // Number of recent events to keep for debugging purposes. constexpr size_t RECENT_QUEUE_MAX_SIZE = 10; // Event log tags. See EventLogTags.logtags for reference // Event log tags. See EventLogTags.logtags for reference. constexpr int LOGTAG_INPUT_INTERACTION = 62000; constexpr int LOGTAG_INPUT_FOCUS = 62001; constexpr int LOGTAG_INPUT_CANCEL = 62003; Loading Loading @@ -4903,23 +4903,42 @@ void InputDispatcher::setInputFilterEnabled(bool enabled) { mLooper->wake(); } void InputDispatcher::setInTouchMode(bool inTouchMode) { bool InputDispatcher::setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) { bool needWake = false; { std::scoped_lock lock(mLock); if (mInTouchMode == inTouchMode) { return; return false; } 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. ALOGD("Request to change touch mode from %s to %s (calling pid=%d, uid=%d, " "hasPermission=%s)", toString(mInTouchMode), toString(inTouchMode), pid, uid, toString(hasPermission)); } if (!hasPermission) { const sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(mFocusedDisplayId); // TODO(b/198487159): if no window is currently focused, then we need to check the last // interacted window (within 1 second timeout). We should allow touch mode change // if the last interacted window owner's pid/uid match the calling ones. if (focusedToken == nullptr) { return false; } const sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(focusedToken); if (windowHandle == nullptr) { return false; } const WindowInfo* windowInfo = windowHandle->getInfo(); if (pid != windowInfo->ownerPid || uid != windowInfo->ownerUid) { return false; } } // 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 Loading @@ -4927,6 +4946,7 @@ void InputDispatcher::setInTouchMode(bool inTouchMode) { if (needWake) { mLooper->wake(); } return true; } void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) { Loading services/inputflinger/dispatcher/InputDispatcher.h +1 −1 Original line number Diff line number Diff line Loading @@ -117,7 +117,7 @@ public: void setFocusedDisplay(int32_t displayId) override; void setInputDispatchMode(bool enabled, bool frozen) override; void setInputFilterEnabled(bool enabled) override; void setInTouchMode(bool inTouchMode) override; bool setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) override; void setMaximumObscuringOpacityForTouch(float opacity) override; void setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode mode) override; Loading services/inputflinger/dispatcher/include/InputDispatcherInterface.h +3 −1 Original line number Diff line number Diff line Loading @@ -123,8 +123,10 @@ public: * Touch mode is a global state that apps may enter / exit based on specific * user interactions with input devices. * If true, the device is in touch mode. * * Returns true when changing touch mode state. */ virtual void setInTouchMode(bool inTouchMode) = 0; virtual bool setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) = 0; /** * Sets the maximum allowed obscuring opacity by UID to propagate touches. Loading services/inputflinger/tests/InputDispatcher_test.cpp +16 −6 Original line number Diff line number Diff line Loading @@ -2997,6 +2997,7 @@ TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT); const WindowInfo& windowInfo = *window->getInfo(); // Set focused application. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); Loading @@ -3013,7 +3014,8 @@ TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) { window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/); SCOPED_TRACE("Disable touch mode"); mDispatcher->setInTouchMode(false); mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid, /* hasPermission */ true); window->consumeTouchModeEvent(false); window->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); Loading @@ -3026,7 +3028,8 @@ TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) { window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/); SCOPED_TRACE("Enable touch mode again"); mDispatcher->setInTouchMode(true); mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid, /* hasPermission */ true); window->consumeTouchModeEvent(true); window->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); Loading Loading @@ -6231,19 +6234,23 @@ protected: mWindow->consumeFocusEvent(true); } void changeAndVerifyTouchMode(bool inTouchMode) { mDispatcher->setInTouchMode(inTouchMode); void changeAndVerifyTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) { mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission); mWindow->consumeTouchModeEvent(inTouchMode); mSecondWindow->consumeTouchModeEvent(inTouchMode); } }; TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchModeOnFocusedWindow) { changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode); const WindowInfo& windowInfo = *mWindow->getInfo(); changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid, windowInfo.ownerUid, /* hasPermission */ false); } TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) { mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode); const WindowInfo& windowInfo = *mWindow->getInfo(); mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid, windowInfo.ownerUid, /* hasPermission */ true); mWindow->assertNoEvents(); mSecondWindow->assertNoEvents(); } Loading Loading @@ -6798,4 +6805,7 @@ TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) { window->assertNoEvents(); } // TODO(b/198487159): Add permission tests for touch mode switch once the validation is put in // place. } // namespace android::inputdispatcher Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +27 −7 Original line number Diff line number Diff line Loading @@ -137,7 +137,7 @@ constexpr std::chrono::nanoseconds KEY_WAITING_FOR_EVENTS_TIMEOUT = 500ms; // Number of recent events to keep for debugging purposes. constexpr size_t RECENT_QUEUE_MAX_SIZE = 10; // Event log tags. See EventLogTags.logtags for reference // Event log tags. See EventLogTags.logtags for reference. constexpr int LOGTAG_INPUT_INTERACTION = 62000; constexpr int LOGTAG_INPUT_FOCUS = 62001; constexpr int LOGTAG_INPUT_CANCEL = 62003; Loading Loading @@ -4903,23 +4903,42 @@ void InputDispatcher::setInputFilterEnabled(bool enabled) { mLooper->wake(); } void InputDispatcher::setInTouchMode(bool inTouchMode) { bool InputDispatcher::setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) { bool needWake = false; { std::scoped_lock lock(mLock); if (mInTouchMode == inTouchMode) { return; return false; } 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. ALOGD("Request to change touch mode from %s to %s (calling pid=%d, uid=%d, " "hasPermission=%s)", toString(mInTouchMode), toString(inTouchMode), pid, uid, toString(hasPermission)); } if (!hasPermission) { const sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(mFocusedDisplayId); // TODO(b/198487159): if no window is currently focused, then we need to check the last // interacted window (within 1 second timeout). We should allow touch mode change // if the last interacted window owner's pid/uid match the calling ones. if (focusedToken == nullptr) { return false; } const sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(focusedToken); if (windowHandle == nullptr) { return false; } const WindowInfo* windowInfo = windowHandle->getInfo(); if (pid != windowInfo->ownerPid || uid != windowInfo->ownerUid) { return false; } } // 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 Loading @@ -4927,6 +4946,7 @@ void InputDispatcher::setInTouchMode(bool inTouchMode) { if (needWake) { mLooper->wake(); } return true; } void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) { Loading
services/inputflinger/dispatcher/InputDispatcher.h +1 −1 Original line number Diff line number Diff line Loading @@ -117,7 +117,7 @@ public: void setFocusedDisplay(int32_t displayId) override; void setInputDispatchMode(bool enabled, bool frozen) override; void setInputFilterEnabled(bool enabled) override; void setInTouchMode(bool inTouchMode) override; bool setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) override; void setMaximumObscuringOpacityForTouch(float opacity) override; void setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode mode) override; Loading
services/inputflinger/dispatcher/include/InputDispatcherInterface.h +3 −1 Original line number Diff line number Diff line Loading @@ -123,8 +123,10 @@ public: * Touch mode is a global state that apps may enter / exit based on specific * user interactions with input devices. * If true, the device is in touch mode. * * Returns true when changing touch mode state. */ virtual void setInTouchMode(bool inTouchMode) = 0; virtual bool setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) = 0; /** * Sets the maximum allowed obscuring opacity by UID to propagate touches. Loading
services/inputflinger/tests/InputDispatcher_test.cpp +16 −6 Original line number Diff line number Diff line Loading @@ -2997,6 +2997,7 @@ TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT); const WindowInfo& windowInfo = *window->getInfo(); // Set focused application. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); Loading @@ -3013,7 +3014,8 @@ TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) { window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/); SCOPED_TRACE("Disable touch mode"); mDispatcher->setInTouchMode(false); mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid, /* hasPermission */ true); window->consumeTouchModeEvent(false); window->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); Loading @@ -3026,7 +3028,8 @@ TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) { window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/); SCOPED_TRACE("Enable touch mode again"); mDispatcher->setInTouchMode(true); mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid, /* hasPermission */ true); window->consumeTouchModeEvent(true); window->setFocusable(true); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); Loading Loading @@ -6231,19 +6234,23 @@ protected: mWindow->consumeFocusEvent(true); } void changeAndVerifyTouchMode(bool inTouchMode) { mDispatcher->setInTouchMode(inTouchMode); void changeAndVerifyTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) { mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission); mWindow->consumeTouchModeEvent(inTouchMode); mSecondWindow->consumeTouchModeEvent(inTouchMode); } }; TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchModeOnFocusedWindow) { changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode); const WindowInfo& windowInfo = *mWindow->getInfo(); changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid, windowInfo.ownerUid, /* hasPermission */ false); } TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) { mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode); const WindowInfo& windowInfo = *mWindow->getInfo(); mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid, windowInfo.ownerUid, /* hasPermission */ true); mWindow->assertNoEvents(); mSecondWindow->assertNoEvents(); } Loading Loading @@ -6798,4 +6805,7 @@ TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) { window->assertNoEvents(); } // TODO(b/198487159): Add permission tests for touch mode switch once the validation is put in // place. } // namespace android::inputdispatcher