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

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

Tell system server whether the app handled input events.

Refactored ViewRoot, NativeActivity and related classes to tell the
dispatcher whether an input event was actually handled by the application.

This will be used to move more of the global default key processing
into the system server instead of the application.

Change-Id: If06b98b6f45c543e5ac5b1eae2b3baf9371fba28
parent 6a73d867
Loading
Loading
Loading
Loading
+10 −2
Original line number Original line Diff line number Diff line
@@ -304,6 +304,10 @@ public:
    virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
    virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
            const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
            const KeyEvent* keyEvent, uint32_t policyFlags) = 0;


    /* Allows the policy a chance to perform default processing for an unhandled key. */
    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
            const KeyEvent* keyEvent, uint32_t policyFlags) = 0;

    /* Notifies the policy about switch events.
    /* Notifies the policy about switch events.
     */
     */
    virtual void notifySwitch(nsecs_t when,
    virtual void notifySwitch(nsecs_t when,
@@ -609,6 +613,7 @@ private:
        sp<InputChannel> inputChannel;
        sp<InputChannel> inputChannel;
        sp<InputApplicationHandle> inputApplicationHandle;
        sp<InputApplicationHandle> inputApplicationHandle;
        int32_t userActivityEventType;
        int32_t userActivityEventType;
        bool handled;
    };
    };


    // Generic queue implementation.
    // Generic queue implementation.
@@ -1030,7 +1035,8 @@ private:
            EventEntry* eventEntry, const InputTarget* inputTarget,
            EventEntry* eventEntry, const InputTarget* inputTarget,
            bool resumeWithAppendedMotionSample);
            bool resumeWithAppendedMotionSample);
    void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
    void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
    void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
    void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
            bool handled);
    void startNextDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
    void startNextDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
    void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
    void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
    void drainOutboundQueueLocked(Connection* connection);
    void drainOutboundQueueLocked(Connection* connection);
@@ -1061,7 +1067,7 @@ private:
    void onDispatchCycleStartedLocked(
    void onDispatchCycleStartedLocked(
            nsecs_t currentTime, const sp<Connection>& connection);
            nsecs_t currentTime, const sp<Connection>& connection);
    void onDispatchCycleFinishedLocked(
    void onDispatchCycleFinishedLocked(
            nsecs_t currentTime, const sp<Connection>& connection);
            nsecs_t currentTime, const sp<Connection>& connection, bool handled);
    void onDispatchCycleBrokenLocked(
    void onDispatchCycleBrokenLocked(
            nsecs_t currentTime, const sp<Connection>& connection);
            nsecs_t currentTime, const sp<Connection>& connection);
    void onANRLocked(
    void onANRLocked(
@@ -1073,7 +1079,9 @@ private:
    void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);
    void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);
    void doNotifyANRLockedInterruptible(CommandEntry* commandEntry);
    void doNotifyANRLockedInterruptible(CommandEntry* commandEntry);
    void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry);
    void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry);
    void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry);
    void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry);
    void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry);
    void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);


    // Statistics gathering.
    // Statistics gathering.
    void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
    void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
+4 −3
Original line number Original line Diff line number Diff line
@@ -250,12 +250,13 @@ public:
    status_t sendDispatchSignal();
    status_t sendDispatchSignal();


    /* Receives the finished signal from the consumer in reply to the original dispatch signal.
    /* Receives the finished signal from the consumer in reply to the original dispatch signal.
     * Returns whether the consumer handled the message.
     *
     *
     * Returns OK on success.
     * Returns OK on success.
     * Returns WOULD_BLOCK if there is no signal present.
     * Returns WOULD_BLOCK if there is no signal present.
     * Other errors probably indicate that the channel is broken.
     * Other errors probably indicate that the channel is broken.
     */
     */
    status_t receiveFinishedSignal();
    status_t receiveFinishedSignal(bool& outHandled);


private:
private:
    sp<InputChannel> mChannel;
    sp<InputChannel> mChannel;
@@ -305,12 +306,12 @@ public:
    status_t consume(InputEventFactoryInterface* factory, InputEvent** outEvent);
    status_t consume(InputEventFactoryInterface* factory, InputEvent** outEvent);


    /* Sends a finished signal to the publisher to inform it that the current message is
    /* Sends a finished signal to the publisher to inform it that the current message is
     * finished processing.
     * finished processing and specifies whether the message was handled by the consumer.
     *
     *
     * Returns OK on success.
     * Returns OK on success.
     * Errors probably indicate that the channel is broken.
     * Errors probably indicate that the channel is broken.
     */
     */
    status_t sendFinishedSignal();
    status_t sendFinishedSignal(bool handled);


    /* Receives the dispatched signal from the publisher.
    /* Receives the dispatched signal from the publisher.
     *
     *
+46 −13
Original line number Original line Diff line number Diff line
@@ -1770,13 +1770,14 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
}
}


void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection) {
        const sp<Connection>& connection, bool handled) {
#if DEBUG_DISPATCH_CYCLE
#if DEBUG_DISPATCH_CYCLE
    LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
    LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
            "%01.1fms since dispatch",
            "%01.1fms since dispatch, handled=%s",
            connection->getInputChannelName(),
            connection->getInputChannelName(),
            connection->getEventLatencyMillis(currentTime),
            connection->getEventLatencyMillis(currentTime),
            connection->getDispatchLatencyMillis(currentTime));
            connection->getDispatchLatencyMillis(currentTime),
            toString(handled));
#endif
#endif


    if (connection->status == Connection::STATUS_BROKEN
    if (connection->status == Connection::STATUS_BROKEN
@@ -1784,9 +1785,6 @@ void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
        return;
        return;
    }
    }


    // Notify other system components.
    onDispatchCycleFinishedLocked(currentTime, connection);

    // Reset the publisher since the event has been consumed.
    // Reset the publisher since the event has been consumed.
    // We do this now so that the publisher can release some of its internal resources
    // We do this now so that the publisher can release some of its internal resources
    // while waiting for the next dispatch cycle to begin.
    // while waiting for the next dispatch cycle to begin.
@@ -1798,7 +1796,8 @@ void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
        return;
        return;
    }
    }


    startNextDispatchCycleLocked(currentTime, connection);
    // Notify other system components and prepare to start the next dispatch cycle.
    onDispatchCycleFinishedLocked(currentTime, connection, handled);
}
}


void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
@@ -1898,7 +1897,8 @@ int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data
            return 1;
            return 1;
        }
        }


        status_t status = connection->inputPublisher.receiveFinishedSignal();
        bool handled = false;
        status_t status = connection->inputPublisher.receiveFinishedSignal(handled);
        if (status) {
        if (status) {
            LOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
            LOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
                    connection->getInputChannelName(), status);
                    connection->getInputChannelName(), status);
@@ -1907,7 +1907,7 @@ int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data
            return 0; // remove the callback
            return 0; // remove the callback
        }
        }


        d->finishDispatchCycleLocked(currentTime, connection);
        d->finishDispatchCycleLocked(currentTime, connection, handled);
        d->runCommandsLockedInterruptible();
        d->runCommandsLockedInterruptible();
        return 1;
        return 1;
    } // release lock
    } // release lock
@@ -2945,7 +2945,11 @@ void InputDispatcher::onDispatchCycleStartedLocked(
}
}


void InputDispatcher::onDispatchCycleFinishedLocked(
void InputDispatcher::onDispatchCycleFinishedLocked(
        nsecs_t currentTime, const sp<Connection>& connection) {
        nsecs_t currentTime, const sp<Connection>& connection, bool handled) {
    CommandEntry* commandEntry = postCommandLocked(
            & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
    commandEntry->connection = connection;
    commandEntry->handled = handled;
}
}


void InputDispatcher::onDispatchCycleBrokenLocked(
void InputDispatcher::onDispatchCycleBrokenLocked(
@@ -3014,9 +3018,7 @@ void InputDispatcher::doNotifyANRLockedInterruptible(
void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
        CommandEntry* commandEntry) {
        CommandEntry* commandEntry) {
    KeyEntry* entry = commandEntry->keyEntry;
    KeyEntry* entry = commandEntry->keyEntry;
    mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
    initializeKeyEvent(&mReusableKeyEvent, entry);
            entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
            entry->downTime, entry->eventTime);


    mLock.unlock();
    mLock.unlock();


@@ -3031,6 +3033,31 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
    mAllocator.releaseKeyEntry(entry);
    mAllocator.releaseKeyEntry(entry);
}
}


void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
        CommandEntry* commandEntry) {
    sp<Connection> connection = commandEntry->connection;
    bool handled = commandEntry->handled;

    if (!handled && !connection->outboundQueue.isEmpty()) {
        DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
        if (dispatchEntry->inProgress
                && dispatchEntry->hasForegroundTarget()
                && dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
            KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
            initializeKeyEvent(&mReusableKeyEvent, keyEntry);

            mLock.unlock();

            mPolicy->dispatchUnhandledKey(connection->inputChannel,
                    & mReusableKeyEvent, keyEntry->policyFlags);

            mLock.lock();
        }
    }

    startNextDispatchCycleLocked(now(), connection);
}

void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
    mLock.unlock();
    mLock.unlock();


@@ -3039,6 +3066,12 @@ void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* comman
    mLock.lock();
    mLock.lock();
}
}


void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) {
    event->initialize(entry->deviceId, entry->source, entry->action, entry->flags,
            entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
            entry->downTime, entry->eventTime);
}

void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
        int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
        int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
    // TODO Write some statistics about how long we spend waiting.
    // TODO Write some statistics about how long we spend waiting.
+19 −8
Original line number Original line Diff line number Diff line
@@ -35,8 +35,12 @@ static const int DEFAULT_MESSAGE_BUFFER_SIZE = 16384;
static const char INPUT_SIGNAL_DISPATCH = 'D';
static const char INPUT_SIGNAL_DISPATCH = 'D';


// Signal sent by the consumer to the producer to inform it that it has finished
// Signal sent by the consumer to the producer to inform it that it has finished
// consuming the most recent message.
// consuming the most recent message and it handled it.
static const char INPUT_SIGNAL_FINISHED = 'f';
static const char INPUT_SIGNAL_FINISHED_HANDLED = 'f';

// Signal sent by the consumer to the producer to inform it that it has finished
// consuming the most recent message but it did not handle it.
static const char INPUT_SIGNAL_FINISHED_UNHANDLED = 'u';




// --- InputChannel ---
// --- InputChannel ---
@@ -497,7 +501,7 @@ status_t InputPublisher::sendDispatchSignal() {
    return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);
    return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);
}
}


status_t InputPublisher::receiveFinishedSignal() {
status_t InputPublisher::receiveFinishedSignal(bool& outHandled) {
#if DEBUG_TRANSPORT_ACTIONS
#if DEBUG_TRANSPORT_ACTIONS
    LOGD("channel '%s' publisher ~ receiveFinishedSignal",
    LOGD("channel '%s' publisher ~ receiveFinishedSignal",
            mChannel->getName().string());
            mChannel->getName().string());
@@ -506,9 +510,14 @@ status_t InputPublisher::receiveFinishedSignal() {
    char signal;
    char signal;
    status_t result = mChannel->receiveSignal(& signal);
    status_t result = mChannel->receiveSignal(& signal);
    if (result) {
    if (result) {
        outHandled = false;
        return result;
        return result;
    }
    }
    if (signal != INPUT_SIGNAL_FINISHED) {
    if (signal == INPUT_SIGNAL_FINISHED_HANDLED) {
        outHandled = true;
    } else if (signal == INPUT_SIGNAL_FINISHED_UNHANDLED) {
        outHandled = false;
    } else {
        LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer",
        LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer",
                mChannel->getName().string(), signal);
                mChannel->getName().string(), signal);
        return UNKNOWN_ERROR;
        return UNKNOWN_ERROR;
@@ -626,13 +635,15 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent*
    return OK;
    return OK;
}
}


status_t InputConsumer::sendFinishedSignal() {
status_t InputConsumer::sendFinishedSignal(bool handled) {
#if DEBUG_TRANSPORT_ACTIONS
#if DEBUG_TRANSPORT_ACTIONS
    LOGD("channel '%s' consumer ~ sendFinishedSignal",
    LOGD("channel '%s' consumer ~ sendFinishedSignal: handled=%d",
            mChannel->getName().string());
            mChannel->getName().string(), handled);
#endif
#endif


    return mChannel->sendSignal(INPUT_SIGNAL_FINISHED);
    return mChannel->sendSignal(handled
            ? INPUT_SIGNAL_FINISHED_HANDLED
            : INPUT_SIGNAL_FINISHED_UNHANDLED);
}
}


status_t InputConsumer::receiveDispatchSignal() {
status_t InputConsumer::receiveDispatchSignal() {
+5 −0
Original line number Original line Diff line number Diff line
@@ -67,6 +67,11 @@ private:
        return false;
        return false;
    }
    }


    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
            const KeyEvent* keyEvent, uint32_t policyFlags) {
        return false;
    }

    virtual void notifySwitch(nsecs_t when,
    virtual void notifySwitch(nsecs_t when,
            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
    }
    }
Loading