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

Commit 58854c2a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix resampling logic for duplicate events."

parents 2b3b34cf 0aeec079
Loading
Loading
Loading
Loading
+23 −8
Original line number Diff line number Diff line
@@ -370,14 +370,14 @@ private:
        int32_t idToIndex[MAX_POINTER_ID + 1];
        PointerCoords pointers[MAX_POINTERS];

        void initializeFrom(const InputMessage* msg) {
            eventTime = msg->body.motion.eventTime;
        void initializeFrom(const InputMessage& msg) {
            eventTime = msg.body.motion.eventTime;
            idBits.clear();
            for (uint32_t i = 0; i < msg->body.motion.pointerCount; i++) {
                uint32_t id = msg->body.motion.pointers[i].properties.id;
            for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
                uint32_t id = msg.body.motion.pointers[i].properties.id;
                idBits.markBit(id);
                idToIndex[id] = i;
                pointers[i].copyFrom(msg->body.motion.pointers[i].coords);
                pointers[i].copyFrom(msg.body.motion.pointers[i].coords);
            }
        }

@@ -402,7 +402,7 @@ private:
            lastResample.idBits.clear();
        }

        void addHistory(const InputMessage* msg) {
        void addHistory(const InputMessage& msg) {
            historyCurrent ^= 1;
            if (historySize < 2) {
                historySize += 1;
@@ -413,6 +413,21 @@ private:
        const History* getHistory(size_t index) const {
            return &history[(historyCurrent + index) & 1];
        }

        bool recentCoordinatesAreIdentical(uint32_t id) const {
            // Return true if the two most recently received "raw" coordinates are identical
            if (historySize < 2) {
                return false;
            }
            float currentX = getHistory(0)->getPointerById(id).getX();
            float currentY = getHistory(0)->getPointerById(id).getY();
            float previousX = getHistory(1)->getPointerById(id).getX();
            float previousY = getHistory(1)->getPointerById(id).getY();
            if (currentX == previousX && currentY == previousY) {
                return true;
            }
            return false;
        }
    };
    Vector<TouchState> mTouchStates;

@@ -432,8 +447,8 @@ private:
            Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent,
            int32_t* displayId);

    void updateTouchState(InputMessage* msg);
    void rewriteMessage(const TouchState& state, InputMessage* msg);
    void updateTouchState(InputMessage& msg);
    bool rewriteMessage(const TouchState& state, InputMessage& msg);
    void resampleTouchState(nsecs_t frameTime, MotionEvent* event,
            const InputMessage *next);

+39 −29
Original line number Diff line number Diff line
@@ -496,7 +496,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory,
            MotionEvent* motionEvent = factory->createMotionEvent();
            if (! motionEvent) return NO_MEMORY;

            updateTouchState(&mMsg);
            updateTouchState(mMsg);
            initializeMotionEvent(motionEvent, &mMsg);
            *outSeq = mMsg.body.motion.seq;
            *outEvent = motionEvent;
@@ -564,7 +564,7 @@ status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory,
    uint32_t chain = 0;
    for (size_t i = 0; i < count; i++) {
        InputMessage& msg = batch.samples.editItemAt(i);
        updateTouchState(&msg);
        updateTouchState(msg);
        if (i) {
            SeqChain seqChain;
            seqChain.seq = msg.body.motion.seq;
@@ -584,20 +584,19 @@ status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory,
    return OK;
}

void InputConsumer::updateTouchState(InputMessage* msg) {
void InputConsumer::updateTouchState(InputMessage& msg) {
    if (!mResampleTouch ||
            !(msg->body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
            !(msg.body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
        return;
    }

    int32_t deviceId = msg->body.motion.deviceId;
    int32_t source = msg->body.motion.source;
    nsecs_t eventTime = msg->body.motion.eventTime;
    int32_t deviceId = msg.body.motion.deviceId;
    int32_t source = msg.body.motion.source;

    // Update the touch state history to incorporate the new input message.
    // If the message is in the past relative to the most recently produced resampled
    // touch, then use the resampled time and coordinates instead.
    switch (msg->body.motion.action & AMOTION_EVENT_ACTION_MASK) {
    switch (msg.body.motion.action & AMOTION_EVENT_ACTION_MASK) {
    case AMOTION_EVENT_ACTION_DOWN: {
        ssize_t index = findTouchState(deviceId, source);
        if (index < 0) {
@@ -615,9 +614,8 @@ void InputConsumer::updateTouchState(InputMessage* msg) {
        if (index >= 0) {
            TouchState& touchState = mTouchStates.editItemAt(index);
            touchState.addHistory(msg);
            if (eventTime < touchState.lastResample.eventTime) {
                rewriteMessage(touchState, msg);
            } else {
            bool messageRewritten = rewriteMessage(touchState, msg);
            if (!messageRewritten) {
                touchState.lastResample.idBits.clear();
            }
        }
@@ -628,7 +626,7 @@ void InputConsumer::updateTouchState(InputMessage* msg) {
        ssize_t index = findTouchState(deviceId, source);
        if (index >= 0) {
            TouchState& touchState = mTouchStates.editItemAt(index);
            touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId());
            touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
            rewriteMessage(touchState, msg);
        }
        break;
@@ -639,7 +637,7 @@ void InputConsumer::updateTouchState(InputMessage* msg) {
        if (index >= 0) {
            TouchState& touchState = mTouchStates.editItemAt(index);
            rewriteMessage(touchState, msg);
            touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId());
            touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
        }
        break;
    }
@@ -666,24 +664,29 @@ void InputConsumer::updateTouchState(InputMessage* msg) {
    }
}

void InputConsumer::rewriteMessage(const TouchState& state, InputMessage* msg) {
    for (uint32_t i = 0; i < msg->body.motion.pointerCount; i++) {
        uint32_t id = msg->body.motion.pointers[i].properties.id;
bool InputConsumer::rewriteMessage(const TouchState& state, InputMessage& msg) {
    bool messageRewritten = false;
    nsecs_t eventTime = msg.body.motion.eventTime;
    for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
        uint32_t id = msg.body.motion.pointers[i].properties.id;
        if (state.lastResample.idBits.hasBit(id)) {
            PointerCoords& msgCoords = msg->body.motion.pointers[i].coords;
            PointerCoords& msgCoords = msg.body.motion.pointers[i].coords;
            const PointerCoords& resampleCoords = state.lastResample.getPointerById(id);
            if (eventTime < state.lastResample.eventTime ||
                    state.recentCoordinatesAreIdentical(id)) {
                msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
                msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
#if DEBUG_RESAMPLING
                ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id,
                    resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
                    resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_Y),
                    msgCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
                    msgCoords.getAxisValue(AMOTION_EVENT_AXIS_Y));
                        resampleCoords.getX(), resampleCoords.getY(),
                        msgCoords.getX(), msgCoords.getY());
#endif
            msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
            msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
                messageRewritten = true;
            }
        }
    }
    return messageRewritten;
}

void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
    const InputMessage* next) {
@@ -710,6 +713,7 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
    }

    // Ensure that the current sample has all of the pointers that need to be reported.
    // Also ensure that the past two "real" touch events do not contain duplicate coordinates
    const History* current = touchState.getHistory(0);
    size_t pointerCount = event->getPointerCount();
    for (size_t i = 0; i < pointerCount; i++) {
@@ -717,6 +721,12 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
        if (!current->idBits.hasBit(id)) {
#if DEBUG_RESAMPLING
            ALOGD("Not resampled, missing id %d", id);
#endif
            return;
        }
        if (touchState.recentCoordinatesAreIdentical(id)) {
#if DEBUG_RESAMPLING
            ALOGD("Not resampled, past two historical events have duplicate coordinates");
#endif
            return;
        }
@@ -729,12 +739,12 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
    if (next) {
        // Interpolate between current sample and future sample.
        // So current->eventTime <= sampleTime <= future.eventTime.
        future.initializeFrom(next);
        future.initializeFrom(*next);
        other = &future;
        nsecs_t delta = future.eventTime - current->eventTime;
        if (delta < RESAMPLE_MIN_DELTA) {
#if DEBUG_RESAMPLING
            ALOGD("Not resampled, delta time is too small: %lld ns.", delta);
            ALOGD("Not resampled, delta time is too small: %" PRId64 " ns.", delta);
#endif
            return;
        }
@@ -746,12 +756,12 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
        nsecs_t delta = current->eventTime - other->eventTime;
        if (delta < RESAMPLE_MIN_DELTA) {
#if DEBUG_RESAMPLING
            ALOGD("Not resampled, delta time is too small: %lld ns.", delta);
            ALOGD("Not resampled, delta time is too small: %" PRId64 " ns.", delta);
#endif
            return;
        } else if (delta > RESAMPLE_MAX_DELTA) {
#if DEBUG_RESAMPLING
            ALOGD("Not resampled, delta time is too large: %lld ns.", delta);
            ALOGD("Not resampled, delta time is too large: %" PRId64 " ns.", delta);
#endif
            return;
        }
@@ -759,7 +769,7 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
        if (sampleTime > maxPredict) {
#if DEBUG_RESAMPLING
            ALOGD("Sample time is too far in the future, adjusting prediction "
                    "from %lld to %lld ns.",
                    "from %" PRId64 " to %" PRId64 " ns.",
                    sampleTime - current->eventTime, maxPredict - current->eventTime);
#endif
            sampleTime = maxPredict;