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

Commit 8e8f9faf authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Send events from InputEventReceiver in order" into sc-dev am: 3385f3c2

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

Change-Id: Ib9ab73192211e9300c0c59a79358d88ee1b719ed
parents 19fdf4ab 3385f3c2
Loading
Loading
Loading
Loading
+35 −56
Original line number Diff line number Diff line
@@ -45,12 +45,6 @@ static const char* toString(bool value) {
    return value ? "true" : "false";
}

enum class HandleEventResponse : int {
    // Allowed return values of 'handleEvent' function as documented in LooperCallback::handleEvent
    REMOVE_CALLBACK = 0,
    KEEP_CALLBACK = 1
};

static struct {
    jclass clazz;

@@ -77,14 +71,6 @@ static std::string addPrefix(std::string str, std::string_view prefix) {
    return str;
}

/**
 * Convert an enumeration to its underlying type. Replace with std::to_underlying when available.
 */
template <class T>
static std::underlying_type_t<T> toUnderlying(const T& t) {
    return static_cast<std::underlying_type_t<T>>(t);
}

class NativeInputEventReceiver : public LooperCallback {
public:
    NativeInputEventReceiver(JNIEnv* env, jobject receiverWeak,
@@ -121,16 +107,11 @@ private:
        return mInputConsumer.getChannel()->getName();
    }

    HandleEventResponse processOutboundEvents();
    status_t processOutboundEvents();
    // From 'LooperCallback'
    int handleEvent(int receiveFd, int events, void* data) override;
};

// Ensure HandleEventResponse underlying type matches the return type of LooperCallback::handleEvent
static_assert(std::is_same<std::underlying_type_t<HandleEventResponse>,
                           std::invoke_result_t<decltype(&LooperCallback::handleEvent),
                                                NativeInputEventReceiver, int, int, void*>>::value);

NativeInputEventReceiver::NativeInputEventReceiver(
        JNIEnv* env, jobject receiverWeak, const std::shared_ptr<InputChannel>& inputChannel,
        const sp<MessageQueue>& messageQueue)
@@ -167,26 +148,12 @@ status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled)
        ALOGD("channel '%s' ~ Finished input event.", getInputChannelName().c_str());
    }

    status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
    if (status != OK) {
        if (status == WOULD_BLOCK) {
            if (kDebugDispatchCycle) {
                ALOGD("channel '%s' ~ Could not send finished signal immediately.  "
                        "Enqueued for later.", getInputChannelName().c_str());
            }
            Finish finish;
            finish.seq = seq;
            finish.handled = handled;
    Finish finish{
            .seq = seq,
            .handled = handled,
    };
    mFinishQueue.push_back(finish);
            if (mFinishQueue.size() == 1) {
                setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
            }
            return OK;
        }
        ALOGW("Failed to send finished signal on channel '%s'.  status=%d",
                getInputChannelName().c_str(), status);
    }
    return status;
    return processOutboundEvents();
}

void NativeInputEventReceiver::setFdEvents(int events) {
@@ -217,7 +184,7 @@ void NativeInputEventReceiver::setFdEvents(int events) {
 * InputPublisher. If no events are remaining, let the looper know so that it doesn't wake up
 * unnecessarily.
 */
HandleEventResponse NativeInputEventReceiver::processOutboundEvents() {
status_t NativeInputEventReceiver::processOutboundEvents() {
    while (!mFinishQueue.empty()) {
        const Finish& finish = *mFinishQueue.begin();
        status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);
@@ -233,7 +200,8 @@ HandleEventResponse NativeInputEventReceiver::processOutboundEvents() {
                ALOGD("channel '%s' ~ Remaining outbound events: %zu.",
                      getInputChannelName().c_str(), mFinishQueue.size());
            }
            return HandleEventResponse::KEEP_CALLBACK; // try again later
            setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
            return WOULD_BLOCK; // try again later
        }

        // Some other error. Give up
@@ -247,42 +215,49 @@ HandleEventResponse NativeInputEventReceiver::processOutboundEvents() {
            jniThrowRuntimeException(env, message.c_str());
            mMessageQueue->raiseAndClearException(env, "finishInputEvent");
        }
        return HandleEventResponse::REMOVE_CALLBACK;
        return status;
    }

    // The queue is now empty. Tell looper there's no more output to expect.
    setFdEvents(ALOOPER_EVENT_INPUT);
    return HandleEventResponse::KEEP_CALLBACK;
    return OK;
}

int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
    // Allowed return values of this function as documented in LooperCallback::handleEvent
    constexpr int REMOVE_CALLBACK = 0;
    constexpr int KEEP_CALLBACK = 1;

    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
        // This error typically occurs when the publisher has closed the input channel
        // as part of removing a window or finishing an IME session, in which case
        // the consumer will soon be disposed as well.
        if (kDebugDispatchCycle) {
            ALOGD("channel '%s' ~ Publisher closed input channel or an error occurred.  "
                    "events=0x%x", getInputChannelName().c_str(), events);
            ALOGD("channel '%s' ~ Publisher closed input channel or an error occurred. events=0x%x",
                  getInputChannelName().c_str(), events);
        }
        return toUnderlying(HandleEventResponse::REMOVE_CALLBACK);
        return REMOVE_CALLBACK;
    }

    if (events & ALOOPER_EVENT_INPUT) {
        JNIEnv* env = AndroidRuntime::getJNIEnv();
        status_t status = consumeEvents(env, false /*consumeBatches*/, -1, nullptr);
        mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
        return status == OK || status == NO_MEMORY
                ? toUnderlying(HandleEventResponse::KEEP_CALLBACK)
                : toUnderlying(HandleEventResponse::REMOVE_CALLBACK);
        return status == OK || status == NO_MEMORY ? KEEP_CALLBACK : REMOVE_CALLBACK;
    }

    if (events & ALOOPER_EVENT_OUTPUT) {
        return toUnderlying(processOutboundEvents());
        const status_t status = processOutboundEvents();
        if (status == OK || status == WOULD_BLOCK) {
            return KEEP_CALLBACK;
        } else {
            return REMOVE_CALLBACK;
        }
    }

    ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
            "events=0x%x", getInputChannelName().c_str(), events);
    return toUnderlying(HandleEventResponse::KEEP_CALLBACK);
    ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  events=0x%x",
          getInputChannelName().c_str(), events);
    return KEEP_CALLBACK;
}

status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
@@ -503,9 +478,13 @@ static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jlong receiverPtr,
    sp<NativeInputEventReceiver> receiver =
            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
    status_t status = receiver->finishInputEvent(seq, handled);
    if (status && status != DEAD_OBJECT) {
    if (status == OK || status == WOULD_BLOCK) {
        return; // normal operation
    }
    if (status != DEAD_OBJECT) {
        std::string message =
                android::base::StringPrintf("Failed to finish input event.  status=%d", status);
                android::base::StringPrintf("Failed to finish input event.  status=%s(%d)",
                                            strerror(-status), status);
        jniThrowRuntimeException(env, message.c_str());
    }
}
+7 −8
Original line number Diff line number Diff line
@@ -172,16 +172,16 @@ int NativeInputEventSender::handleEvent(int receiveFd, int events, void* data) {
        // as part of finishing an IME session, in which case the publisher will
        // soon be disposed as well.
        if (kDebugDispatchCycle) {
            ALOGD("channel '%s' ~ Consumer closed input channel or an error occurred.  "
                    "events=0x%x", getInputChannelName().c_str(), events);
            ALOGD("channel '%s' ~ Consumer closed input channel or an error occurred.  events=0x%x",
                  getInputChannelName().c_str(), events);
        }

        return 0; // remove the callback
    }

    if (!(events & ALOOPER_EVENT_INPUT)) {
        ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
                "events=0x%x", getInputChannelName().c_str(), events);
        ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  events=0x%x",
              getInputChannelName().c_str(), events);
        return 1;
    }

@@ -219,8 +219,7 @@ status_t NativeInputEventSender::receiveFinishedSignals(JNIEnv* env) {
        mPublishedSeqMap.erase(it);

        if (kDebugDispatchCycle) {
            ALOGD("channel '%s' ~ Received finished signal, seq=%u, handled=%s, "
                  "pendingEvents=%zu.",
            ALOGD("channel '%s' ~ Received finished signal, seq=%u, handled=%s, pendingEvents=%zu.",
                  getInputChannelName().c_str(), seq, result->handled ? "true" : "false",
                  mPublishedSeqMap.size());
        }
@@ -229,8 +228,8 @@ status_t NativeInputEventSender::receiveFinishedSignals(JNIEnv* env) {
            if (!senderObj.get()) {
                senderObj.reset(jniGetReferent(env, mSenderWeakGlobal));
                if (!senderObj.get()) {
                    ALOGW("channel '%s' ~ Sender object was finalized "
                            "without being disposed.", getInputChannelName().c_str());
                    ALOGW("channel '%s' ~ Sender object was finalized without being disposed.",
                          getInputChannelName().c_str());
                    return DEAD_OBJECT;
                }
            }