Loading services/inputflinger/dispatcher/InputDispatcher.cpp +10 −8 Original line number Original line Diff line number Diff line Loading @@ -160,10 +160,7 @@ const std::chrono::duration DEFAULT_INPUT_DISPATCHING_TIMEOUT = std::chrono::mil // when an application takes too long to respond and the user has pressed an app switch key. // when an application takes too long to respond and the user has pressed an app switch key. constexpr nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec constexpr nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec // Amount of time to allow for an event to be dispatched (measured since its eventTime) const std::chrono::duration STALE_EVENT_TIMEOUT = std::chrono::seconds(10) * HwTimeoutMultiplier(); // before considering it stale and dropping it. const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL // 10sec * HwTimeoutMultiplier(); // Log a warning when an event takes longer than this to process, even if an ANR does not occur. // Log a warning when an event takes longer than this to process, even if an ANR does not occur. constexpr nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec constexpr nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec Loading Loading @@ -364,10 +361,6 @@ bool haveSameApplicationToken(const WindowInfo* first, const WindowInfo* second) first->applicationInfo.token == second->applicationInfo.token; first->applicationInfo.token == second->applicationInfo.token; } } bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry) { return currentTime - entry.eventTime >= STALE_EVENT_TIMEOUT; } std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inputTarget, std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inputTarget, std::shared_ptr<EventEntry> eventEntry, std::shared_ptr<EventEntry> eventEntry, int32_t inputTargetFlags) { int32_t inputTargetFlags) { Loading Loading @@ -568,6 +561,10 @@ bool isPointerFromStylus(const MotionEntry& entry, int32_t pointerIndex) { // --- InputDispatcher --- // --- InputDispatcher --- InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) : InputDispatcher(policy, STALE_EVENT_TIMEOUT) {} InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy, std::chrono::nanoseconds staleEventTimeout) : mPolicy(policy), : mPolicy(policy), mPendingEvent(nullptr), mPendingEvent(nullptr), mLastDropReason(DropReason::NOT_DROPPED), mLastDropReason(DropReason::NOT_DROPPED), Loading @@ -586,6 +583,7 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic mMaximumObscuringOpacityForTouch(1.0f), mMaximumObscuringOpacityForTouch(1.0f), mFocusedDisplayId(ADISPLAY_ID_DEFAULT), mFocusedDisplayId(ADISPLAY_ID_DEFAULT), mWindowTokenWithPointerCapture(nullptr), mWindowTokenWithPointerCapture(nullptr), mStaleEventTimeout(staleEventTimeout), mLatencyAggregator(), mLatencyAggregator(), mLatencyTracker(&mLatencyAggregator) { mLatencyTracker(&mLatencyAggregator) { mLooper = new Looper(false); mLooper = new Looper(false); Loading Loading @@ -943,6 +941,10 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { } } } } bool InputDispatcher::isStaleEvent(nsecs_t currentTime, const EventEntry& entry) { return std::chrono::nanoseconds(currentTime - entry.eventTime) >= mStaleEventTimeout; } /** /** * Return true if the events preceding this incoming motion event should be dropped * Return true if the events preceding this incoming motion event should be dropped * Return false otherwise (the default behaviour) * Return false otherwise (the default behaviour) Loading services/inputflinger/dispatcher/InputDispatcher.h +7 −0 Original line number Original line Diff line number Diff line Loading @@ -84,6 +84,8 @@ public: static constexpr bool kDefaultInTouchMode = true; static constexpr bool kDefaultInTouchMode = true; explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy); explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy); explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy, std::chrono::nanoseconds staleEventTimeout); ~InputDispatcher() override; ~InputDispatcher() override; void dump(std::string& dump) override; void dump(std::string& dump) override; Loading Loading @@ -471,6 +473,11 @@ private: */ */ std::optional<nsecs_t> mNoFocusedWindowTimeoutTime GUARDED_BY(mLock); std::optional<nsecs_t> mNoFocusedWindowTimeoutTime GUARDED_BY(mLock); // Amount of time to allow for an event to be dispatched (measured since its eventTime) // before considering it stale and dropping it. const std::chrono::nanoseconds mStaleEventTimeout; bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry); bool shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) REQUIRES(mLock); bool shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) REQUIRES(mLock); /** /** Loading services/inputflinger/tests/InputDispatcher_test.cpp +35 −1 Original line number Original line Diff line number Diff line Loading @@ -65,6 +65,8 @@ static const int32_t INJECTOR_UID = 1001; // An arbitrary pid of the gesture monitor window // An arbitrary pid of the gesture monitor window static constexpr int32_t MONITOR_PID = 2001; static constexpr int32_t MONITOR_PID = 2001; static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms; struct PointF { struct PointF { float x; float x; float y; float y; Loading Loading @@ -489,7 +491,7 @@ protected: void SetUp() override { void SetUp() override { mFakePolicy = new FakeInputDispatcherPolicy(); mFakePolicy = new FakeInputDispatcherPolicy(); mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy); mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy, STALE_EVENT_TIMEOUT); mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false); mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false); // Start InputDispatcher thread // Start InputDispatcher thread ASSERT_EQ(OK, mDispatcher->start()); ASSERT_EQ(OK, mDispatcher->start()); Loading Loading @@ -4451,6 +4453,38 @@ TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) { ASSERT_TRUE(mDispatcher->waitForIdle()); ASSERT_TRUE(mDispatcher->waitForIdle()); } } /** * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window, * there will not be an ANR. */ TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) { mWindow->setFocusable(false); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}}); mWindow->consumeFocusEvent(false); KeyEvent event; const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) - std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count(); // Define a valid key down event that is stale (too old). event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE, 1 /*repeatCount*/, eventTime, eventTime); const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER; InputEventInjectionResult result = mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT, policyFlags); ASSERT_EQ(InputEventInjectionResult::FAILED, result) << "Injection should fail because the event is stale"; ASSERT_TRUE(mDispatcher->waitForIdle()); mFakePolicy->assertNotifyAnrWasNotCalled(); mWindow->assertNoEvents(); } // We have a focused application, but no focused window // We have a focused application, but no focused window // Make sure that we don't notify policy twice about the same ANR. // Make sure that we don't notify policy twice about the same ANR. TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) { TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) { Loading Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +10 −8 Original line number Original line Diff line number Diff line Loading @@ -160,10 +160,7 @@ const std::chrono::duration DEFAULT_INPUT_DISPATCHING_TIMEOUT = std::chrono::mil // when an application takes too long to respond and the user has pressed an app switch key. // when an application takes too long to respond and the user has pressed an app switch key. constexpr nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec constexpr nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec // Amount of time to allow for an event to be dispatched (measured since its eventTime) const std::chrono::duration STALE_EVENT_TIMEOUT = std::chrono::seconds(10) * HwTimeoutMultiplier(); // before considering it stale and dropping it. const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL // 10sec * HwTimeoutMultiplier(); // Log a warning when an event takes longer than this to process, even if an ANR does not occur. // Log a warning when an event takes longer than this to process, even if an ANR does not occur. constexpr nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec constexpr nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec Loading Loading @@ -364,10 +361,6 @@ bool haveSameApplicationToken(const WindowInfo* first, const WindowInfo* second) first->applicationInfo.token == second->applicationInfo.token; first->applicationInfo.token == second->applicationInfo.token; } } bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry) { return currentTime - entry.eventTime >= STALE_EVENT_TIMEOUT; } std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inputTarget, std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inputTarget, std::shared_ptr<EventEntry> eventEntry, std::shared_ptr<EventEntry> eventEntry, int32_t inputTargetFlags) { int32_t inputTargetFlags) { Loading Loading @@ -568,6 +561,10 @@ bool isPointerFromStylus(const MotionEntry& entry, int32_t pointerIndex) { // --- InputDispatcher --- // --- InputDispatcher --- InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) : InputDispatcher(policy, STALE_EVENT_TIMEOUT) {} InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy, std::chrono::nanoseconds staleEventTimeout) : mPolicy(policy), : mPolicy(policy), mPendingEvent(nullptr), mPendingEvent(nullptr), mLastDropReason(DropReason::NOT_DROPPED), mLastDropReason(DropReason::NOT_DROPPED), Loading @@ -586,6 +583,7 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic mMaximumObscuringOpacityForTouch(1.0f), mMaximumObscuringOpacityForTouch(1.0f), mFocusedDisplayId(ADISPLAY_ID_DEFAULT), mFocusedDisplayId(ADISPLAY_ID_DEFAULT), mWindowTokenWithPointerCapture(nullptr), mWindowTokenWithPointerCapture(nullptr), mStaleEventTimeout(staleEventTimeout), mLatencyAggregator(), mLatencyAggregator(), mLatencyTracker(&mLatencyAggregator) { mLatencyTracker(&mLatencyAggregator) { mLooper = new Looper(false); mLooper = new Looper(false); Loading Loading @@ -943,6 +941,10 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { } } } } bool InputDispatcher::isStaleEvent(nsecs_t currentTime, const EventEntry& entry) { return std::chrono::nanoseconds(currentTime - entry.eventTime) >= mStaleEventTimeout; } /** /** * Return true if the events preceding this incoming motion event should be dropped * Return true if the events preceding this incoming motion event should be dropped * Return false otherwise (the default behaviour) * Return false otherwise (the default behaviour) Loading
services/inputflinger/dispatcher/InputDispatcher.h +7 −0 Original line number Original line Diff line number Diff line Loading @@ -84,6 +84,8 @@ public: static constexpr bool kDefaultInTouchMode = true; static constexpr bool kDefaultInTouchMode = true; explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy); explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy); explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy, std::chrono::nanoseconds staleEventTimeout); ~InputDispatcher() override; ~InputDispatcher() override; void dump(std::string& dump) override; void dump(std::string& dump) override; Loading Loading @@ -471,6 +473,11 @@ private: */ */ std::optional<nsecs_t> mNoFocusedWindowTimeoutTime GUARDED_BY(mLock); std::optional<nsecs_t> mNoFocusedWindowTimeoutTime GUARDED_BY(mLock); // Amount of time to allow for an event to be dispatched (measured since its eventTime) // before considering it stale and dropping it. const std::chrono::nanoseconds mStaleEventTimeout; bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry); bool shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) REQUIRES(mLock); bool shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) REQUIRES(mLock); /** /** Loading
services/inputflinger/tests/InputDispatcher_test.cpp +35 −1 Original line number Original line Diff line number Diff line Loading @@ -65,6 +65,8 @@ static const int32_t INJECTOR_UID = 1001; // An arbitrary pid of the gesture monitor window // An arbitrary pid of the gesture monitor window static constexpr int32_t MONITOR_PID = 2001; static constexpr int32_t MONITOR_PID = 2001; static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms; struct PointF { struct PointF { float x; float x; float y; float y; Loading Loading @@ -489,7 +491,7 @@ protected: void SetUp() override { void SetUp() override { mFakePolicy = new FakeInputDispatcherPolicy(); mFakePolicy = new FakeInputDispatcherPolicy(); mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy); mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy, STALE_EVENT_TIMEOUT); mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false); mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false); // Start InputDispatcher thread // Start InputDispatcher thread ASSERT_EQ(OK, mDispatcher->start()); ASSERT_EQ(OK, mDispatcher->start()); Loading Loading @@ -4451,6 +4453,38 @@ TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) { ASSERT_TRUE(mDispatcher->waitForIdle()); ASSERT_TRUE(mDispatcher->waitForIdle()); } } /** * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window, * there will not be an ANR. */ TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) { mWindow->setFocusable(false); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}}); mWindow->consumeFocusEvent(false); KeyEvent event; const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) - std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count(); // Define a valid key down event that is stale (too old). event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE, 1 /*repeatCount*/, eventTime, eventTime); const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER; InputEventInjectionResult result = mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT, policyFlags); ASSERT_EQ(InputEventInjectionResult::FAILED, result) << "Injection should fail because the event is stale"; ASSERT_TRUE(mDispatcher->waitForIdle()); mFakePolicy->assertNotifyAnrWasNotCalled(); mWindow->assertNoEvents(); } // We have a focused application, but no focused window // We have a focused application, but no focused window // Make sure that we don't notify policy twice about the same ANR. // Make sure that we don't notify policy twice about the same ANR. TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) { TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) { Loading