diff options
7 files changed, 86 insertions, 49 deletions
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 12eeea60cb..3d4dd7eabb 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -112,8 +112,6 @@ private: void notifyDropWindow(const sp<IBinder>&, float x, float y) override {} - bool isPerDisplayTouchModeEnabled() override { return false; } - InputDispatcherConfiguration mConfig; }; diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp index 8046bbe25c..33e7e17ec0 100644 --- a/services/inputflinger/dispatcher/Entry.cpp +++ b/services/inputflinger/dispatcher/Entry.cpp @@ -195,9 +195,10 @@ void KeyEntry::recycle() { // --- TouchModeEntry --- -TouchModeEntry::TouchModeEntry(int32_t id, nsecs_t eventTime, bool inTouchMode) +TouchModeEntry::TouchModeEntry(int32_t id, nsecs_t eventTime, bool inTouchMode, int displayId) : EventEntry(id, Type::TOUCH_MODE_CHANGED, eventTime, POLICY_FLAG_PASS_TO_USER), - inTouchMode(inTouchMode) {} + inTouchMode(inTouchMode), + displayId(displayId) {} TouchModeEntry::~TouchModeEntry() {} diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index 1f916f39e4..60f319a056 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -210,8 +210,9 @@ struct SensorEntry : EventEntry { struct TouchModeEntry : EventEntry { bool inTouchMode; + int32_t displayId; - TouchModeEntry(int32_t id, nsecs_t eventTime, bool inTouchMode); + TouchModeEntry(int32_t id, nsecs_t eventTime, bool inTouchMode, int32_t displayId); std::string getDescription() const override; ~TouchModeEntry() override; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index ff63a6f05f..399153c0d7 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -544,17 +544,12 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false), - // 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(kDefaultInTouchMode), mMaximumObscuringOpacityForTouch(1.0f), mFocusedDisplayId(ADISPLAY_ID_DEFAULT), mWindowTokenWithPointerCapture(nullptr), mStaleEventTimeout(staleEventTimeout), mLatencyAggregator(), - mLatencyTracker(&mLatencyAggregator), - kPerDisplayTouchModeEnabled(mPolicy->isPerDisplayTouchModeEnabled()) { + mLatencyTracker(&mLatencyAggregator) { mLooper = sp<Looper>::make(false); mReporter = createInputReporter(); @@ -562,7 +557,6 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener); mKeyRepeatState.lastKeyEntry = nullptr; - policy->getDispatcherConfiguration(&mConfig); } @@ -1435,7 +1429,7 @@ void InputDispatcher::dispatchPointerCaptureChangedLocked( void InputDispatcher::dispatchTouchModeChangeLocked(nsecs_t currentTime, const std::shared_ptr<TouchModeEntry>& entry) { const std::vector<sp<WindowInfoHandle>>& windowHandles = - getWindowHandlesLocked(mFocusedDisplayId); + getWindowHandlesLocked(entry->displayId); if (windowHandles.empty()) { return; } @@ -1452,7 +1446,6 @@ std::vector<InputTarget> InputDispatcher::getInputTargetsFromWindowHandlesLocked const std::vector<sp<WindowInfoHandle>>& windowHandles) const { std::vector<InputTarget> inputTargets; for (const sp<WindowInfoHandle>& handle : windowHandles) { - // TODO(b/193718270): Due to performance concerns, consider notifying visible windows only. const sp<IBinder>& token = handle->getToken(); if (token == nullptr) { continue; @@ -5012,15 +5005,20 @@ bool InputDispatcher::setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool needWake = false; { std::scoped_lock lock(mLock); - if (mInTouchMode == inTouchMode) { + ALOGD_IF(DEBUG_TOUCH_MODE, + "Request to change touch mode to %s (calling pid=%d, uid=%d, " + "hasPermission=%s, target displayId=%d, mTouchModePerDisplay[displayId]=%s)", + toString(inTouchMode), pid, uid, toString(hasPermission), displayId, + mTouchModePerDisplay.count(displayId) == 0 + ? "not set" + : std::to_string(mTouchModePerDisplay[displayId]).c_str()); + + // TODO(b/198499018): Ensure that WM can guarantee that touch mode is properly set when + // display is created. + auto touchModeIt = mTouchModePerDisplay.find(displayId); + if (touchModeIt != mTouchModePerDisplay.end() && touchModeIt->second == inTouchMode) { return false; } - if (DEBUG_TOUCH_MODE) { - ALOGD("Request to change touch mode from %s to %s (calling pid=%d, uid=%d, " - "hasPermission=%s, target displayId=%d, perDisplayTouchModeEnabled=%s)", - toString(mInTouchMode), toString(inTouchMode), pid, uid, toString(hasPermission), - displayId, toString(kPerDisplayTouchModeEnabled)); - } if (!hasPermission) { if (!focusedWindowIsOwnedByLocked(pid, uid) && !recentWindowsAreOwnedByLocked(pid, uid)) { @@ -5030,11 +5028,9 @@ bool InputDispatcher::setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, return false; } } - - // TODO(b/198499018): Store touch mode per display (kPerDisplayTouchModeEnabled) - mInTouchMode = inTouchMode; - - auto entry = std::make_unique<TouchModeEntry>(mIdGenerator.nextId(), now(), inTouchMode); + mTouchModePerDisplay[displayId] = inTouchMode; + auto entry = std::make_unique<TouchModeEntry>(mIdGenerator.nextId(), now(), inTouchMode, + displayId); needWake = enqueueInboundEventLocked(std::move(entry)); } // release lock @@ -5474,6 +5470,16 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += INDENT "AppSwitch: not pending\n"; } + if (!mTouchModePerDisplay.empty()) { + dump += INDENT "TouchModePerDisplay:\n"; + for (const auto& [displayId, touchMode] : mTouchModePerDisplay) { + dump += StringPrintf(INDENT2 "Display: %" PRId32 " TouchMode: %s\n", displayId, + std::to_string(touchMode).c_str()); + } + } else { + dump += INDENT "TouchModePerDisplay: <none>\n"; + } + dump += INDENT "Configuration:\n"; dump += StringPrintf(INDENT2 "KeyRepeatDelay: %" PRId64 "ms\n", ns2ms(mConfig.keyRepeatDelay)); dump += StringPrintf(INDENT2 "KeyRepeatTimeout: %" PRId64 "ms\n", @@ -6366,6 +6372,8 @@ void InputDispatcher::displayRemoved(int32_t displayId) { mFocusResolver.displayRemoved(displayId); // Reset pointer capture eligibility, regardless of previous state. std::erase(mIneligibleDisplaysForPointerCapture, displayId); + // Remove the associated touch mode state. + mTouchModePerDisplay.erase(displayId); } // release lock // Wake up poll loop since it may need to make new input dispatching choices. diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 0cf2a1a86f..630d21a95d 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -342,9 +342,13 @@ private: bool mDispatchEnabled GUARDED_BY(mLock); bool mDispatchFrozen GUARDED_BY(mLock); bool mInputFilterEnabled GUARDED_BY(mLock); - bool mInTouchMode GUARDED_BY(mLock); float mMaximumObscuringOpacityForTouch GUARDED_BY(mLock); + // This map is not really needed, but it helps a lot with debugging (dumpsys input). + // In the java layer, touch mode states are spread across multiple DisplayContent objects, + // making harder to snapshot and retrieve them. + std::map<int32_t /*displayId*/, bool /*inTouchMode*/> mTouchModePerDisplay GUARDED_BY(mLock); + class DispatcherWindowListener : public gui::WindowInfosListener { public: explicit DispatcherWindowListener(InputDispatcher& dispatcher) : mDispatcher(dispatcher){}; @@ -383,7 +387,7 @@ private: bool hasResponsiveConnectionLocked(android::gui::WindowInfoHandle& windowHandle) const REQUIRES(mLock); - // Gets all the input targets (with their respective input channels) from the window handles + // Returns all the input targets (with their respective input channels) from the window handles // passed as argument. std::vector<InputTarget> getInputTargetsFromWindowHandlesLocked( const std::vector<sp<android::gui::WindowInfoHandle>>& windowHandles) const @@ -684,9 +688,6 @@ private: bool focusedWindowIsOwnedByLocked(int32_t pid, int32_t uid) REQUIRES(mLock); bool recentWindowsAreOwnedByLocked(int32_t pid, int32_t uid) REQUIRES(mLock); - // Per display touch mode enabled - const bool kPerDisplayTouchModeEnabled; - sp<InputReporterInterface> mReporter; }; diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index 44f3baf204..7843923a1f 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -136,9 +136,6 @@ public: /* Notifies the policy that the drag window has moved over to another window */ virtual void notifyDropWindow(const sp<IBinder>& token, float x, float y) = 0; - - /* If touch mode is enabled per display or global */ - virtual bool isPerDisplayTouchModeEnabled() = 0; }; } // namespace android diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 7ee6950b09..985c9c570c 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -63,10 +63,14 @@ static constexpr int32_t POINTER_3_DOWN = static constexpr int32_t POINTER_1_UP = AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); -// The default pid and uid for windows created by the test. +// The default pid and uid for windows created on the primary display by the test. static constexpr int32_t WINDOW_PID = 999; static constexpr int32_t WINDOW_UID = 1001; +// The default pid and uid for the windows created on the secondary display by the test. +static constexpr int32_t SECONDARY_WINDOW_PID = 1010; +static constexpr int32_t SECONDARY_WINDOW_UID = 1012; + // The default policy flags to use for event injection by tests. static constexpr uint32_t DEFAULT_POLICY_FLAGS = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER; @@ -500,11 +504,6 @@ private: verify(*mFilteredEvent); mFilteredEvent = nullptr; } - - bool isPerDisplayTouchModeEnabled() { - // TODO(b/198499018): Make this a regular property once per display touch mode is enabled - return false; - } }; // --- InputDispatcherTest --- @@ -5461,7 +5460,6 @@ class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest { sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Window without input channel", ADISPLAY_ID_DEFAULT, std::make_optional<sp<IBinder>>(nullptr) /*token*/); - mNoInputWindow->setNoInputChannel(true); mNoInputWindow->setFrame(Rect(0, 0, 100, 100)); // It's perfectly valid for this window to not have an associated input channel @@ -6806,44 +6804,67 @@ TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) { class InputDispatcherTouchModeChangedTests : public InputDispatcherTest { protected: std::shared_ptr<FakeApplicationHandle> mApp; + std::shared_ptr<FakeApplicationHandle> mSecondaryApp; sp<FakeWindowHandle> mWindow; sp<FakeWindowHandle> mSecondWindow; + sp<FakeWindowHandle> mThirdWindow; void SetUp() override { InputDispatcherTest::SetUp(); mApp = std::make_shared<FakeApplicationHandle>(); + mSecondaryApp = std::make_shared<FakeApplicationHandle>(); mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT); mWindow->setFocusable(true); setFocusedWindow(mWindow); mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT); mSecondWindow->setFocusable(true); + mThirdWindow = + sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher, + "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID); + mThirdWindow->setFocusable(true); mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp); - mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}}); + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}, + {SECOND_DISPLAY_ID, {mThirdWindow}}}); + mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID); mWindow->consumeFocusEvent(true); - // Set initial touch mode to InputDispatcher::kDefaultInTouchMode. + // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode. if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID, - WINDOW_UID, true /*hasPermission*/, ADISPLAY_ID_DEFAULT)) { + WINDOW_UID, true /* hasPermission */, + ADISPLAY_ID_DEFAULT)) { mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode); mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode); + mThirdWindow->assertNoEvents(); + } + + // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode. + if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID, + SECONDARY_WINDOW_UID, true /* hasPermission */, + SECOND_DISPLAY_ID)) { + mWindow->assertNoEvents(); + mSecondWindow->assertNoEvents(); + mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode); } } - void changeAndVerifyTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) { + void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid, + bool hasPermission) { ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission, ADISPLAY_ID_DEFAULT)); mWindow->consumeTouchModeEvent(inTouchMode); mSecondWindow->consumeTouchModeEvent(inTouchMode); + mThirdWindow->assertNoEvents(); } }; TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) { const WindowInfo& windowInfo = *mWindow->getInfo(); - changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid, - windowInfo.ownerUid, false /*hasPermission*/); + changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, + windowInfo.ownerPid, windowInfo.ownerUid, + false /* hasPermission */); } TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) { @@ -6863,8 +6884,8 @@ TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnP int32_t ownerPid = windowInfo.ownerPid; int32_t ownerUid = windowInfo.ownerUid; mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1); - changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode, ownerPid, ownerUid, - true /*hasPermission*/); + changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid, + ownerUid, true /*hasPermission*/); } TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) { @@ -6876,6 +6897,16 @@ TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTou mSecondWindow->assertNoEvents(); } +TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) { + const WindowInfo& windowInfo = *mThirdWindow->getInfo(); + ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode, + windowInfo.ownerPid, windowInfo.ownerUid, + true /*hasPermission*/, SECOND_DISPLAY_ID)); + mWindow->assertNoEvents(); + mSecondWindow->assertNoEvents(); + mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode); +} + TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) { // Interact with the window first. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT)) |