Loading services/inputflinger/dispatcher/InputDispatcher.cpp +7 −11 Original line number Diff line number Diff line Loading @@ -1894,8 +1894,6 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<con doInterceptKeyBeforeDispatchingCommand(focusedWindowToken, *entry); }; postCommandLocked(std::move(command)); // Poke user activity for keys not passed to user pokeUserActivityLocked(*entry); return false; // wait for the command to run } else { entry->interceptKeyResult = KeyEntry::InterceptKeyResult::CONTINUE; Loading @@ -1912,8 +1910,12 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<con *dropReason == DropReason::POLICY ? InputEventInjectionResult::SUCCEEDED : InputEventInjectionResult::FAILED); mReporter->reportDroppedKey(entry->id); // Poke user activity for undispatched keys // Poke user activity for consumed keys, as it may have not been reported due to // the focused window requesting user activity to be disabled if (*dropReason == DropReason::POLICY && mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) { pokeUserActivityLocked(*entry); } return true; } Loading Loading @@ -3313,22 +3315,16 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { if (keyEntry.flags & AKEY_EVENT_FLAG_CANCELED) { return; } // If the key code is unknown, we don't consider it user activity if (keyEntry.keyCode == AKEYCODE_UNKNOWN) { return; } // Don't inhibit events that were intercepted or are not passed to // the apps, like system shortcuts if (windowDisablingUserActivityInfo != nullptr && keyEntry.interceptKeyResult != KeyEntry::InterceptKeyResult::SKIP && keyEntry.policyFlags & POLICY_FLAG_PASS_TO_USER) { keyEntry.interceptKeyResult != KeyEntry::InterceptKeyResult::SKIP) { if (DEBUG_DISPATCH_CYCLE) { ALOGD("Not poking user activity: disabled by window '%s'.", windowDisablingUserActivityInfo->name.c_str()); } return; } break; } default: { Loading services/inputflinger/tests/FakeInputDispatcherPolicy.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -215,6 +215,10 @@ void FakeInputDispatcherPolicy::setStaleEventTimeout(std::chrono::nanoseconds ti mStaleEventTimeout = timeout; } void FakeInputDispatcherPolicy::setConsumeKeyBeforeDispatching(bool consumeKeyBeforeDispatching) { mConsumeKeyBeforeDispatching = consumeKeyBeforeDispatching; } void FakeInputDispatcherPolicy::assertUserActivityNotPoked() { std::unique_lock lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); Loading Loading @@ -401,6 +405,9 @@ void FakeInputDispatcherPolicy::interceptMotionBeforeQueueing(ui::LogicalDisplay nsecs_t FakeInputDispatcherPolicy::interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) { if (mConsumeKeyBeforeDispatching) { return -1; } nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count(); // Clear intercept state so we could dispatch the event in next wake. mInterceptKeyTimeout = 0ms; Loading services/inputflinger/tests/FakeInputDispatcherPolicy.h +3 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ public: void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler); void assertUnhandledKeyReported(int32_t keycode); void assertUnhandledKeyNotReported(); void setConsumeKeyBeforeDispatching(bool consumeKeyBeforeDispatching); private: std::mutex mLock; Loading Loading @@ -144,6 +145,8 @@ private: std::chrono::nanoseconds mStaleEventTimeout = 1000ms; bool mConsumeKeyBeforeDispatching = false; BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions; std::condition_variable mNotifyUnhandledKey; Loading services/inputflinger/tests/InputDispatcher_test.cpp +29 −36 Original line number Diff line number Diff line Loading @@ -610,28 +610,6 @@ static NotifyKeyArgs generateKeyArgs( return args; } static NotifyKeyArgs generateSystemShortcutArgs( int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) { nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC); // Define a valid key event. NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON, currentTime); return args; } static NotifyKeyArgs generateAssistantKeyArgs( int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) { nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC); // Define a valid key event. NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT, AMETA_NONE, currentTime); return args; } [[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, ui::LogicalDisplayId displayId, const std::vector<PointF>& points) { Loading Loading @@ -6628,17 +6606,18 @@ TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) { window->consumeFocusEvent(true); mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT)); mDispatcher->notifyKey( KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build()); // Window should receive key down event. window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT); // Should have poked user activity // Should have not poked user activity mDispatcher->waitForIdle(); mFakePolicy->assertUserActivityNotPoked(); } TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) { TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window", Loading @@ -6650,31 +6629,36 @@ TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) { window->consumeFocusEvent(true); mFakePolicy->setConsumeKeyBeforeDispatching(true); mDispatcher->notifyKey( generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT)); KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build()); mDispatcher->waitForIdle(); // System key is not passed down // Key is not passed down window->assertNoEvents(); // Should have poked user activity mFakePolicy->assertUserActivityPoked(); } TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) { TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window", ui::LogicalDisplayId::DEFAULT); window->setDisableUserActivity(true); window->setFocusable(true); mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0}); setFocusedWindow(window); window->consumeFocusEvent(true); mFakePolicy->setConsumeKeyBeforeDispatching(true); mDispatcher->notifyKey( generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT)); KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build()); mDispatcher->waitForIdle(); // System key is not passed down Loading @@ -6684,30 +6668,39 @@ TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) { mFakePolicy->assertUserActivityPoked(); } TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) { class DisableUserActivityInputDispatcherTest : public InputDispatcherTest, public ::testing::WithParamInterface<bool> {}; TEST_P(DisableUserActivityInputDispatcherTest, NotPassedToUserUserActivity) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window", ui::LogicalDisplayId::DEFAULT); window->setDisableUserActivity(true); window->setDisableUserActivity(GetParam()); window->setFocusable(true); mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0}); setFocusedWindow(window); window->consumeFocusEvent(true); mDispatcher->notifyKey( generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT)); mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD) .keyCode(AKEYCODE_A) .policyFlags(0) .build()); mDispatcher->waitForIdle(); // System key is not passed down // Key is not passed down window->assertNoEvents(); // Should have poked user activity mFakePolicy->assertUserActivityPoked(); // Should not have poked user activity mFakePolicy->assertUserActivityNotPoked(); } INSTANTIATE_TEST_CASE_P(DisableUserActivity, DisableUserActivityInputDispatcherTest, ::testing::Bool()); TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = Loading Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +7 −11 Original line number Diff line number Diff line Loading @@ -1894,8 +1894,6 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<con doInterceptKeyBeforeDispatchingCommand(focusedWindowToken, *entry); }; postCommandLocked(std::move(command)); // Poke user activity for keys not passed to user pokeUserActivityLocked(*entry); return false; // wait for the command to run } else { entry->interceptKeyResult = KeyEntry::InterceptKeyResult::CONTINUE; Loading @@ -1912,8 +1910,12 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<con *dropReason == DropReason::POLICY ? InputEventInjectionResult::SUCCEEDED : InputEventInjectionResult::FAILED); mReporter->reportDroppedKey(entry->id); // Poke user activity for undispatched keys // Poke user activity for consumed keys, as it may have not been reported due to // the focused window requesting user activity to be disabled if (*dropReason == DropReason::POLICY && mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) { pokeUserActivityLocked(*entry); } return true; } Loading Loading @@ -3313,22 +3315,16 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { if (keyEntry.flags & AKEY_EVENT_FLAG_CANCELED) { return; } // If the key code is unknown, we don't consider it user activity if (keyEntry.keyCode == AKEYCODE_UNKNOWN) { return; } // Don't inhibit events that were intercepted or are not passed to // the apps, like system shortcuts if (windowDisablingUserActivityInfo != nullptr && keyEntry.interceptKeyResult != KeyEntry::InterceptKeyResult::SKIP && keyEntry.policyFlags & POLICY_FLAG_PASS_TO_USER) { keyEntry.interceptKeyResult != KeyEntry::InterceptKeyResult::SKIP) { if (DEBUG_DISPATCH_CYCLE) { ALOGD("Not poking user activity: disabled by window '%s'.", windowDisablingUserActivityInfo->name.c_str()); } return; } break; } default: { Loading
services/inputflinger/tests/FakeInputDispatcherPolicy.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -215,6 +215,10 @@ void FakeInputDispatcherPolicy::setStaleEventTimeout(std::chrono::nanoseconds ti mStaleEventTimeout = timeout; } void FakeInputDispatcherPolicy::setConsumeKeyBeforeDispatching(bool consumeKeyBeforeDispatching) { mConsumeKeyBeforeDispatching = consumeKeyBeforeDispatching; } void FakeInputDispatcherPolicy::assertUserActivityNotPoked() { std::unique_lock lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); Loading Loading @@ -401,6 +405,9 @@ void FakeInputDispatcherPolicy::interceptMotionBeforeQueueing(ui::LogicalDisplay nsecs_t FakeInputDispatcherPolicy::interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) { if (mConsumeKeyBeforeDispatching) { return -1; } nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count(); // Clear intercept state so we could dispatch the event in next wake. mInterceptKeyTimeout = 0ms; Loading
services/inputflinger/tests/FakeInputDispatcherPolicy.h +3 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ public: void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler); void assertUnhandledKeyReported(int32_t keycode); void assertUnhandledKeyNotReported(); void setConsumeKeyBeforeDispatching(bool consumeKeyBeforeDispatching); private: std::mutex mLock; Loading Loading @@ -144,6 +145,8 @@ private: std::chrono::nanoseconds mStaleEventTimeout = 1000ms; bool mConsumeKeyBeforeDispatching = false; BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions; std::condition_variable mNotifyUnhandledKey; Loading
services/inputflinger/tests/InputDispatcher_test.cpp +29 −36 Original line number Diff line number Diff line Loading @@ -610,28 +610,6 @@ static NotifyKeyArgs generateKeyArgs( return args; } static NotifyKeyArgs generateSystemShortcutArgs( int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) { nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC); // Define a valid key event. NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON, currentTime); return args; } static NotifyKeyArgs generateAssistantKeyArgs( int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) { nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC); // Define a valid key event. NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT, AMETA_NONE, currentTime); return args; } [[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, ui::LogicalDisplayId displayId, const std::vector<PointF>& points) { Loading Loading @@ -6628,17 +6606,18 @@ TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) { window->consumeFocusEvent(true); mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT)); mDispatcher->notifyKey( KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build()); // Window should receive key down event. window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT); // Should have poked user activity // Should have not poked user activity mDispatcher->waitForIdle(); mFakePolicy->assertUserActivityNotPoked(); } TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) { TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window", Loading @@ -6650,31 +6629,36 @@ TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) { window->consumeFocusEvent(true); mFakePolicy->setConsumeKeyBeforeDispatching(true); mDispatcher->notifyKey( generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT)); KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build()); mDispatcher->waitForIdle(); // System key is not passed down // Key is not passed down window->assertNoEvents(); // Should have poked user activity mFakePolicy->assertUserActivityPoked(); } TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) { TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window", ui::LogicalDisplayId::DEFAULT); window->setDisableUserActivity(true); window->setFocusable(true); mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0}); setFocusedWindow(window); window->consumeFocusEvent(true); mFakePolicy->setConsumeKeyBeforeDispatching(true); mDispatcher->notifyKey( generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT)); KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build()); mDispatcher->waitForIdle(); // System key is not passed down Loading @@ -6684,30 +6668,39 @@ TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) { mFakePolicy->assertUserActivityPoked(); } TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) { class DisableUserActivityInputDispatcherTest : public InputDispatcherTest, public ::testing::WithParamInterface<bool> {}; TEST_P(DisableUserActivityInputDispatcherTest, NotPassedToUserUserActivity) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window", ui::LogicalDisplayId::DEFAULT); window->setDisableUserActivity(true); window->setDisableUserActivity(GetParam()); window->setFocusable(true); mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0}); setFocusedWindow(window); window->consumeFocusEvent(true); mDispatcher->notifyKey( generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT)); mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD) .keyCode(AKEYCODE_A) .policyFlags(0) .build()); mDispatcher->waitForIdle(); // System key is not passed down // Key is not passed down window->assertNoEvents(); // Should have poked user activity mFakePolicy->assertUserActivityPoked(); // Should not have poked user activity mFakePolicy->assertUserActivityNotPoked(); } INSTANTIATE_TEST_CASE_P(DisableUserActivity, DisableUserActivityInputDispatcherTest, ::testing::Bool()); TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = Loading