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

Commit 9c258710 authored by Jeff Brown's avatar Jeff Brown Committed by Android (Google) Code Review
Browse files

Merge "Fix app switch latency optimization." into gingerbread

parents 4b164c1b 54a18251
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -851,8 +851,8 @@ private:

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

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

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

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

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

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

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

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

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

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

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

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

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

bool InputDispatcher::dispatchKeyLocked(
        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.
    if (! entry->dispatchInProgress) {
        logOutboundKeyDetailsLocked("dispatchKey - ", entry);
@@ -521,7 +554,7 @@ bool InputDispatcher::dispatchKeyLocked(
        }

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

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

        addMonitoringTargetsLocked();
        finishFindingTargetsLocked(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;
        commitTargetsLocked(window);
    }

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

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.
    if (! entry->dispatchInProgress) {
        logOutboundMotionDetailsLocked("dispatchMotion - ", entry);

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

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

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

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

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

void InputDispatcher::finishFindingTargetsLocked(const InputWindow* window) {
void InputDispatcher::commitTargetsLocked(const InputWindow* window) {
    mCurrentInputWindowType = window->layoutParamsType;
    mCurrentInputChannel = window->inputChannel;
    mCurrentInputTargetsValid = true;
+17 −24
Original line number Diff line number Diff line
@@ -408,10 +408,15 @@ status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,

jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
        const sp<InputChannel>& inputChannel) {
    InputChannel* inputChannelPtr = inputChannel.get();
    if (! inputChannelPtr) {
        return NULL;
    }

    {
        AutoMutex _l(mInputChannelRegistryLock);

        ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
        ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannelPtr);
        if (index < 0) {
            return NULL;
        }
@@ -718,13 +723,7 @@ nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApp
        tokenObjLocal = NULL;
    }

    jobject inputChannelObjLocal;
    if (inputChannel.get()) {
        inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
    } else {
        inputChannelObjLocal = NULL;
    }

    jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
    jlong newTimeout = env->CallLongMethod(mCallbacksObj,
                gCallbacksClassInfo.notifyANR, tokenObjLocal, inputChannelObjLocal);
    if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
@@ -957,8 +956,8 @@ bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& i

    JNIEnv* env = jniEnv();

    // Note: inputChannel may be null.
    jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
    if (inputChannelObj) {
    jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
            gCallbacksClassInfo.interceptKeyBeforeDispatching,
            inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
@@ -967,13 +966,7 @@ bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& i
    bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");

    env->DeleteLocalRef(inputChannelObj);

    return consumed && ! error;
    } else {
        LOGW("Could not apply key dispatch policy because input channel '%s' is "
                "no longer valid.", inputChannel->getName().string());
        return false;
    }
}

void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t windowType, int32_t eventType) {