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

Commit d8816c3c authored by Jeff Brown's avatar Jeff Brown
Browse files

Fix app switch latency optimization.

This optimization was broken due to recent changes in how ANRs are handled.

Change-Id: Ic99248a12755fadac8d4893e7d305b773e038d3d
parent 128e3342
Loading
Loading
Loading
Loading
+6 −6
Original line number Original line Diff line number Diff line
@@ -851,8 +851,8 @@ private:


    // Inbound event processing.
    // Inbound event processing.
    void drainInboundQueueLocked();
    void drainInboundQueueLocked();
    void releasePendingEventLocked(bool wasDropped);
    void releasePendingEventLocked();
    void releaseInboundEventLocked(EventEntry* entry, bool wasDropped);
    void releaseInboundEventLocked(EventEntry* entry);
    bool isEventFromReliableSourceLocked(EventEntry* entry);
    bool isEventFromReliableSourceLocked(EventEntry* entry);


    // Dispatch state.
    // Dispatch state.
@@ -886,10 +886,10 @@ private:
            nsecs_t currentTime, ConfigurationChangedEntry* entry);
            nsecs_t currentTime, ConfigurationChangedEntry* entry);
    bool dispatchKeyLocked(
    bool dispatchKeyLocked(
            nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
            nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
            nsecs_t* nextWakeupTime);
            bool dropEvent, nsecs_t* nextWakeupTime);
    bool dispatchMotionLocked(
    bool dispatchMotionLocked(
            nsecs_t currentTime, MotionEntry* entry,
            nsecs_t currentTime, MotionEntry* entry,
            nsecs_t* nextWakeupTime);
            bool dropEvent, nsecs_t* nextWakeupTime);
    void dispatchEventToCurrentInputTargetsLocked(
    void dispatchEventToCurrentInputTargetsLocked(
            nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);
            nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);


@@ -914,8 +914,8 @@ private:
    bool mInputTargetWaitTimeoutExpired;
    bool mInputTargetWaitTimeoutExpired;


    // Finding targets for input events.
    // Finding targets for input events.
    void startFindingTargetsLocked();
    void resetTargetsLocked();
    void finishFindingTargetsLocked(const InputWindow* window);
    void commitTargetsLocked(const InputWindow* window);
    int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
    int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
            const InputApplication* application, const InputWindow* window,
            const InputApplication* application, const InputWindow* window,
            nsecs_t* nextWakeupTime);
            nsecs_t* nextWakeupTime);
+75 −48
Original line number Original line Diff line number Diff line
@@ -122,7 +122,7 @@ InputDispatcher::~InputDispatcher() {
        AutoMutex _l(mLock);
        AutoMutex _l(mLock);


        resetKeyRepeatLocked();
        resetKeyRepeatLocked();
        releasePendingEventLocked(true);
        releasePendingEventLocked();
        drainInboundQueueLocked();
        drainInboundQueueLocked();
    }
    }


@@ -174,7 +174,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
    if (! mDispatchEnabled) {
    if (! mDispatchEnabled) {
        if (mPendingEvent || ! mInboundQueue.isEmpty()) {
        if (mPendingEvent || ! mInboundQueue.isEmpty()) {
            LOGI("Dropping pending events because input dispatch is disabled.");
            LOGI("Dropping pending events because input dispatch is disabled.");
            releasePendingEventLocked(true);
            releasePendingEventLocked();
            drainInboundQueueLocked();
            drainInboundQueueLocked();
        }
        }
        return;
        return;
@@ -281,51 +281,50 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,


    // Now we have an event to dispatch.
    // Now we have an event to dispatch.
    assert(mPendingEvent != NULL);
    assert(mPendingEvent != NULL);
    bool wasDispatched = false;
    bool done = false;
    bool wasDropped = false;
    switch (mPendingEvent->type) {
    switch (mPendingEvent->type) {
    case EventEntry::TYPE_CONFIGURATION_CHANGED: {
    case EventEntry::TYPE_CONFIGURATION_CHANGED: {
        ConfigurationChangedEntry* typedEntry =
        ConfigurationChangedEntry* typedEntry =
                static_cast<ConfigurationChangedEntry*>(mPendingEvent);
                static_cast<ConfigurationChangedEntry*>(mPendingEvent);
        wasDispatched = dispatchConfigurationChangedLocked(currentTime, typedEntry);
        done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
        break;
        break;
    }
    }


    case EventEntry::TYPE_KEY: {
    case EventEntry::TYPE_KEY: {
        KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
        KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
        if (isAppSwitchPendingLocked()) {
        bool appSwitchKey = isAppSwitchKey(typedEntry->keyCode);
            if (isAppSwitchKey(typedEntry->keyCode)) {
        bool dropEvent = isAppSwitchDue && ! appSwitchKey;
        done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout, dropEvent,
                nextWakeupTime);
        if (done) {
            if (dropEvent) {
                LOGI("Dropped key because of pending overdue app switch.");
            } else if (appSwitchKey) {
                resetPendingAppSwitchLocked(true);
                resetPendingAppSwitchLocked(true);
            } else if (isAppSwitchDue) {
                LOGI("Dropping key because of pending overdue app switch.");
                wasDropped = true;
                break;
            }
            }
        }
        }
        wasDispatched = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
                nextWakeupTime);
        break;
        break;
    }
    }


    case EventEntry::TYPE_MOTION: {
    case EventEntry::TYPE_MOTION: {
        MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
        MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
        if (isAppSwitchDue) {
        bool dropEvent = isAppSwitchDue;
            LOGI("Dropping motion because of pending overdue app switch.");
        done = dispatchMotionLocked(currentTime, typedEntry, dropEvent, nextWakeupTime);
            wasDropped = true;
        if (done) {
            break;
            if (dropEvent) {
                LOGI("Dropped motion because of pending overdue app switch.");
            }
        }
        }
        wasDispatched = dispatchMotionLocked(currentTime, typedEntry, nextWakeupTime);
        break;
        break;
    }
    }


    default:
    default:
        assert(false);
        assert(false);
        wasDropped = true;
        break;
        break;
    }
    }


    if (wasDispatched || wasDropped) {
    if (done) {
        releasePendingEventLocked(wasDropped);
        releasePendingEventLocked();
        *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
        *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
    }
    }
}
}
@@ -403,21 +402,21 @@ InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command comman
void InputDispatcher::drainInboundQueueLocked() {
void InputDispatcher::drainInboundQueueLocked() {
    while (! mInboundQueue.isEmpty()) {
    while (! mInboundQueue.isEmpty()) {
        EventEntry* entry = mInboundQueue.dequeueAtHead();
        EventEntry* entry = mInboundQueue.dequeueAtHead();
        releaseInboundEventLocked(entry, true /*wasDropped*/);
        releaseInboundEventLocked(entry);
    }
    }
}
}


void InputDispatcher::releasePendingEventLocked(bool wasDropped) {
void InputDispatcher::releasePendingEventLocked() {
    if (mPendingEvent) {
    if (mPendingEvent) {
        releaseInboundEventLocked(mPendingEvent, wasDropped);
        releaseInboundEventLocked(mPendingEvent);
        mPendingEvent = NULL;
        mPendingEvent = NULL;
    }
    }
}
}


void InputDispatcher::releaseInboundEventLocked(EventEntry* entry, bool wasDropped) {
void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
    if (wasDropped) {
    if (entry->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
#if DEBUG_DISPATCH_CYCLE
#if DEBUG_DISPATCH_CYCLE
        LOGD("Pending event was dropped.");
        LOGD("Inbound event was dropped.  Setting injection result to failed.");
#endif
#endif
        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
    }
    }
@@ -492,7 +491,41 @@ bool InputDispatcher::dispatchConfigurationChangedLocked(


bool InputDispatcher::dispatchKeyLocked(
bool InputDispatcher::dispatchKeyLocked(
        nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
        nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
        nsecs_t* nextWakeupTime) {
        bool dropEvent, nsecs_t* nextWakeupTime) {
    // Give the policy a chance to intercept the key.
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
        bool trusted;
        if (! dropEvent && mFocusedWindow) {
            trusted = checkInjectionPermission(mFocusedWindow,
                    entry->injectorPid, entry->injectorUid);
        } else {
            trusted = isEventFromReliableSourceLocked(entry);
        }
        if (trusted) {
            CommandEntry* commandEntry = postCommandLocked(
                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
            if (! dropEvent && mFocusedWindow) {
                commandEntry->inputChannel = mFocusedWindow->inputChannel;
            }
            commandEntry->keyEntry = entry;
            entry->refCount += 1;
            return false; // wait for the command to run
        } else {
            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
        }
    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
        resetTargetsLocked();
        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_SUCCEEDED);
        return true;
    }

    // Clean up if dropping the event.
    if (dropEvent) {
        resetTargetsLocked();
        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
        return true;
    }

    // Preprocessing.
    // Preprocessing.
    if (! entry->dispatchInProgress) {
    if (! entry->dispatchInProgress) {
        logOutboundKeyDetailsLocked("dispatchKey - ", entry);
        logOutboundKeyDetailsLocked("dispatchKey - ", entry);
@@ -521,7 +554,7 @@ bool InputDispatcher::dispatchKeyLocked(
        }
        }


        entry->dispatchInProgress = true;
        entry->dispatchInProgress = true;
        startFindingTargetsLocked(); // resets mCurrentInputTargetsValid
        resetTargetsLocked();
    }
    }


    // Identify targets.
    // Identify targets.
@@ -539,20 +572,7 @@ bool InputDispatcher::dispatchKeyLocked(
        }
        }


        addMonitoringTargetsLocked();
        addMonitoringTargetsLocked();
        finishFindingTargetsLocked(window);
        commitTargetsLocked(window);
    }

    // Give the policy a chance to intercept the key.
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
        CommandEntry* commandEntry = postCommandLocked(
                & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
        commandEntry->inputChannel = mCurrentInputChannel;
        commandEntry->keyEntry = entry;
        entry->refCount += 1;
        return false; // wait for the command to run
    }
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
        return true;
    }
    }


    // Dispatch the key.
    // Dispatch the key.
@@ -576,13 +596,20 @@ void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyE
}
}


bool InputDispatcher::dispatchMotionLocked(
bool InputDispatcher::dispatchMotionLocked(
        nsecs_t currentTime, MotionEntry* entry, nsecs_t* nextWakeupTime) {
        nsecs_t currentTime, MotionEntry* entry, bool dropEvent, nsecs_t* nextWakeupTime) {
    // Clean up if dropping the event.
    if (dropEvent) {
        resetTargetsLocked();
        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
        return true;
    }

    // Preprocessing.
    // Preprocessing.
    if (! entry->dispatchInProgress) {
    if (! entry->dispatchInProgress) {
        logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
        logOutboundMotionDetailsLocked("dispatchMotion - ", entry);


        entry->dispatchInProgress = true;
        entry->dispatchInProgress = true;
        startFindingTargetsLocked(); // resets mCurrentInputTargetsValid
        resetTargetsLocked();
    }
    }


    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
@@ -610,7 +637,7 @@ bool InputDispatcher::dispatchMotionLocked(
        }
        }


        addMonitoringTargetsLocked();
        addMonitoringTargetsLocked();
        finishFindingTargetsLocked(window);
        commitTargetsLocked(window);
    }
    }


    // Dispatch the motion.
    // Dispatch the motion.
@@ -705,14 +732,14 @@ void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTi
    }
    }
}
}


void InputDispatcher::startFindingTargetsLocked() {
void InputDispatcher::resetTargetsLocked() {
    mCurrentInputTargetsValid = false;
    mCurrentInputTargetsValid = false;
    mCurrentInputTargets.clear();
    mCurrentInputTargets.clear();
    mCurrentInputChannel.clear();
    mCurrentInputChannel.clear();
    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
}
}


void InputDispatcher::finishFindingTargetsLocked(const InputWindow* window) {
void InputDispatcher::commitTargetsLocked(const InputWindow* window) {
    mCurrentInputWindowType = window->layoutParamsType;
    mCurrentInputWindowType = window->layoutParamsType;
    mCurrentInputChannel = window->inputChannel;
    mCurrentInputChannel = window->inputChannel;
    mCurrentInputTargetsValid = true;
    mCurrentInputTargetsValid = true;