Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 289e9249 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Ensure stale event does not cause ANR

Does a stale key event cause 'no focused window' ANR? It shouldn't, but
it wasn't already covered by tests.

Adding a test for that here to explicitly check the behaviour.

Bug: 219401047
Test: atest inputflinger_tests:InputDispatcherSingleWindowAnr
Change-Id: I0b1e33a7e705a4b968e3159bd15c70f00eda0191
(cherry picked from commit 673ce1e6)
parent 10839214
Loading
Loading
Loading
Loading
+10 −8
Original line number Original line Diff line number Diff line
@@ -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
@@ -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) {
@@ -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),
@@ -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);
@@ -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)
+7 −0
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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);


    /**
    /**
+35 −1
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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());
@@ -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) {