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

Commit 004c8403 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Ensure stale event does not cause ANR" into tm-dev am: 39cece1e

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/17128496

Change-Id: Idb23c32d5fb1f7ac8bac0d73ef0a8b4bbb3e2d0d
parents b4ccddb9 39cece1e
Loading
Loading
Loading
Loading
+10 −8
Original line number 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.
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)
// before considering it stale and dropping it.
const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL // 10sec
        * HwTimeoutMultiplier();
const std::chrono::duration STALE_EVENT_TIMEOUT = std::chrono::seconds(10) * HwTimeoutMultiplier();

// 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
@@ -364,10 +361,6 @@ bool haveSameApplicationToken(const WindowInfo* first, const WindowInfo* second)
            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::shared_ptr<EventEntry> eventEntry,
                                                   int32_t inputTargetFlags) {
@@ -568,6 +561,10 @@ bool isPointerFromStylus(const MotionEntry& entry, int32_t pointerIndex) {
// --- InputDispatcher ---

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
      : InputDispatcher(policy, STALE_EVENT_TIMEOUT) {}

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy,
                                 std::chrono::nanoseconds staleEventTimeout)
      : mPolicy(policy),
        mPendingEvent(nullptr),
        mLastDropReason(DropReason::NOT_DROPPED),
@@ -586,6 +583,7 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic
        mMaximumObscuringOpacityForTouch(1.0f),
        mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
        mWindowTokenWithPointerCapture(nullptr),
        mStaleEventTimeout(staleEventTimeout),
        mLatencyAggregator(),
        mLatencyTracker(&mLatencyAggregator) {
    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 false otherwise (the default behaviour)
+7 −0
Original line number Diff line number Diff line
@@ -84,6 +84,8 @@ public:
    static constexpr bool kDefaultInTouchMode = true;

    explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
    explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy,
                             std::chrono::nanoseconds staleEventTimeout);
    ~InputDispatcher() override;

    void dump(std::string& dump) override;
@@ -471,6 +473,11 @@ private:
     */
    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);

    /**
+35 −1
Original line number Diff line number Diff line
@@ -65,6 +65,8 @@ static const int32_t INJECTOR_UID = 1001;
// An arbitrary pid of the gesture monitor window
static constexpr int32_t MONITOR_PID = 2001;

static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;

struct PointF {
    float x;
    float y;
@@ -489,7 +491,7 @@ protected:

    void SetUp() override {
        mFakePolicy = new FakeInputDispatcherPolicy();
        mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
        mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy, STALE_EVENT_TIMEOUT);
        mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
        // Start InputDispatcher thread
        ASSERT_EQ(OK, mDispatcher->start());
@@ -4451,6 +4453,38 @@ TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
    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
// Make sure that we don't notify policy twice about the same ANR.
TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {