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

Commit a431be1b authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 11586940 from 9cf64484 to 24Q3-release

Change-Id: Ie461cfbcc46206eb99918fc7475d39dd6c4bf157
parents 12b896f4 9cf64484
Loading
Loading
Loading
Loading
+194 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <stdint.h>
#include <android/input.h>
#include <android/surface_control.h>
#include <android/input_transfer_token_jni.h>

__BEGIN_DECLS

/**
 * The AInputReceiver_onMotionEvent callback is invoked when the registered input channel receives
 * a motion event.
 *
 * \param context Optional context provided by the client that is passed when creating the
 * AInputReceiverCallbacks.
 *
 * \param motionEvent The motion event. This must be released with AInputEvent_release.
 *
 * Available since API level 35.
 */
typedef bool (*AInputReceiver_onMotionEvent)(void *_Null_unspecified context,
                                             AInputEvent *_Nonnull motionEvent)
                                            __INTRODUCED_IN(__ANDROID_API_V__);
/**
 * The AInputReceiver_onKeyEvent callback is invoked when the registered input channel receives
 * a key event.
 *
 * \param context Optional context provided by the client that is passed when creating the
 * AInputReceiverCallbacks.
 *
 * \param keyEvent The key event. This must be released with AInputEvent_release.
 *
 * Available since API level 35.
 */
typedef bool (*AInputReceiver_onKeyEvent)(void *_Null_unspecified context,
                                          AInputEvent *_Nonnull keyEvent)
                                          __INTRODUCED_IN(__ANDROID_API_V__);

struct AInputReceiverCallbacks;

struct AInputReceiver;

/**
 * The InputReceiver that holds the reference to the registered input channel. This must be released
 * using AInputReceiver_release
 *
 * Available since API level 35.
 */
typedef struct AInputReceiver AInputReceiver __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Registers an input receiver for an ASurfaceControl that will receive batched input event. For
 * those events that are batched, the invocation will happen once per AChoreographer frame, and
 * other input events will be delivered immediately.
 *
 * This is different from AInputReceiver_createUnbatchedInputReceiver in that the input events are
 * received batched. The caller must invoke AInputReceiver_release to cleanv up the resources when
 * no longer needing to use the input receiver.
 *
 * \param aChoreographer         The AChoreographer used for batching. This should match the
 *                               rendering AChoreographer.
 * \param hostInputTransferToken The host token to link the embedded. This is used to handle
 *                               transferring touch gesture from host to embedded and for ANRs
 *                               to ensure the host receives the ANR if any issues with
 *                               touch on the embedded. This can be retrieved for the host window
 *                               by calling AttachedSurfaceControl#getInputTransferToken()
 * \param aSurfaceControl        The ASurfaceControl to register the InputChannel for
 * \param aInputReceiverCallbacks The SurfaceControlInputReceiver that will receive the input events
 *
 * Returns the reference to AInputReceiver to clean up resources when done.
 *
 * Available since API level 35.
 */
AInputReceiver* _Nonnull
AInputReceiver_createBatchedInputReceiver(AChoreographer* _Nonnull aChoreographer,
                                        const AInputTransferToken* _Nonnull hostInputTransferToken,
                                        const ASurfaceControl* _Nonnull aSurfaceControl,
                                        AInputReceiverCallbacks* _Nonnull aInputReceiverCallbacks)
                                        __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Registers an input receiver for an ASurfaceControl that will receive every input event.
 * This is different from AInputReceiver_createBatchedInputReceiver in that the input events are
 * received unbatched. The caller must invoke AInputReceiver_release to clean up the resources when
 * no longer needing to use the input receiver.
 *
 * \param aLooper                The looper to use when invoking callbacks.
 * \param hostInputTransferToken The host token to link the embedded. This is used to handle
 *                               transferring touch gesture from host to embedded and for ANRs
 *                               to ensure the host receives the ANR if any issues with
 *                               touch on the embedded. This can be retrieved for the host window
 *                               by calling AttachedSurfaceControl#getInputTransferToken()
 * \param aSurfaceControl        The ASurfaceControl to register the InputChannel for
 * \param aInputReceiverCallbacks The SurfaceControlInputReceiver that will receive the input events
 *
 * Returns the reference to AInputReceiver to clean up resources when done.
 *
 * Available since API level 35.
 */
AInputReceiver* _Nonnull
AInputReceiver_createUnbatchedInputReceiver(ALooper* _Nonnull aLooper,
                                         const AInputTransferToken* _Nonnull hostInputTransferToken,
                                         const ASurfaceControl* _Nonnull aSurfaceControl,
                                         AInputReceiverCallbacks* _Nonnull aInputReceiverCallbacks)
                                         __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Returns the AInputTransferToken that can be used to transfer touch gesture to or from other
 * windows. This InputTransferToken is associated with the SurfaceControl that registered an input
 * receiver and can be used with the host token for things like transfer touch gesture via
 * WindowManager#transferTouchGesture().
 *
 * This must be released with AInputTransferToken_release.
 *
 * \param aInputReceiver The inputReceiver object to retrieve the AInputTransferToken for.
 *
 * Available since API level 35.
 */
const AInputTransferToken *_Nonnull
AInputReceiver_getInputTransferToken(AInputReceiver *_Nonnull aInputReceiver)
        __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Unregisters the input channel and deletes the AInputReceiver. This must be called on the same
 * looper thread it was created with.
 *
 * \param aInputReceiver The inputReceiver object to release.
 *
 * Available since API level 35.
 */
void
AInputReceiver_release(AInputReceiver *_Nonnull aInputReceiver) __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Creates a AInputReceiverCallbacks object that is used when registering for an AInputReceiver.
 * This must be released using AInputReceiverCallbacks_release
 *
 * \param context Optional context provided by the client that will be passed into the callbacks.
 *
 * Available since API level 35.
 */
AInputReceiverCallbacks* _Nonnull AInputReceiverCallbacks_create(void* _Nullable context)
                                                        __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Releases the AInputReceiverCallbacks. This must be called on the same
 * looper thread the AInputReceiver was created with. The receiver will not invoke any callbacks
 * once it's been released.
 *
 * Available since API level 35
 */
void AInputReceiverCallbacks_release(AInputReceiverCallbacks* _Nonnull callbacks)
                                     __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Sets a AInputReceiver_onMotionEvent callback for an AInputReceiverCallbacks
 *
 * \param callbacks The callback object to set the motion event on.
 * \param onMotionEvent The motion event that will be invoked
 *
 * Available since API level 35.
 */
void AInputReceiverCallbacks_setMotionEventCallback(AInputReceiverCallbacks* _Nonnull callbacks,
                                                AInputReceiver_onMotionEvent _Nonnull onMotionEvent)
                                                __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Sets a AInputReceiver_onKeyEvent callback for an AInputReceiverCallbacks
 *
 * \param callbacks The callback object to set the motion event on.
 * \param onMotionEvent The key event that will be invoked
 *
 * Available since API level 35.
 */
void AInputReceiverCallbacks_setKeyEventCallback(AInputReceiverCallbacks* _Nonnull callbacks,
                                                 AInputReceiver_onKeyEvent _Nonnull onKeyEvent)
                                                 __INTRODUCED_IN(__ANDROID_API_V__);

__END_DECLS
+6 −6
Original line number Diff line number Diff line
@@ -29,8 +29,8 @@ namespace android {
class InputConsumerCallbacks {
public:
    virtual ~InputConsumerCallbacks(){};
    virtual void onKeyEvent(KeyEvent&& event, uint32_t seq) = 0;
    virtual void onMotionEvent(MotionEvent&& event, uint32_t seq) = 0;
    virtual void onKeyEvent(std::unique_ptr<KeyEvent> event, uint32_t seq) = 0;
    virtual void onMotionEvent(std::unique_ptr<MotionEvent> event, uint32_t seq) = 0;
    /**
     * When you receive this callback, you must (eventually) call "consumeBatchedInputEvents".
     * If you don't want batching, then call "consumeBatchedInputEvents" immediately with
@@ -38,10 +38,10 @@ public:
     * @param pendingBatchSource the source of the pending batch.
     */
    virtual void onBatchedInputEventPending(int32_t pendingBatchSource) = 0;
    virtual void onFocusEvent(FocusEvent&& event, uint32_t seq) = 0;
    virtual void onCaptureEvent(CaptureEvent&& event, uint32_t seq) = 0;
    virtual void onDragEvent(DragEvent&& event, uint32_t seq) = 0;
    virtual void onTouchModeEvent(TouchModeEvent&& event, uint32_t seq) = 0;
    virtual void onFocusEvent(std::unique_ptr<FocusEvent> event, uint32_t seq) = 0;
    virtual void onCaptureEvent(std::unique_ptr<CaptureEvent> event, uint32_t seq) = 0;
    virtual void onDragEvent(std::unique_ptr<DragEvent> event, uint32_t seq) = 0;
    virtual void onTouchModeEvent(std::unique_ptr<TouchModeEvent> event, uint32_t seq) = 0;
};

/**
+4 −0
Original line number Diff line number Diff line
@@ -425,4 +425,8 @@ int64_t Choreographer::getStartTimeNanosForVsyncId(AVsyncId vsyncId) {
    return iter->second;
}

const sp<Looper> Choreographer::getLooper() {
    return mLooper;
}

} // namespace android
+1 −0
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ public:
    virtual ~Choreographer() override EXCLUDES(gChoreographers.lock);
    int64_t getFrameInterval() const;
    bool inCallback() const;
    const sp<Looper> getLooper();

private:
    Choreographer(const Choreographer&) = delete;
+51 −45
Original line number Diff line number Diff line
@@ -44,28 +44,37 @@ namespace {
const bool DEBUG_TRANSPORT_CONSUMER =
        __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Consumer", ANDROID_LOG_INFO);

void initializeKeyEvent(KeyEvent& event, const InputMessage& msg) {
    event.initialize(msg.body.key.eventId, msg.body.key.deviceId, msg.body.key.source,
std::unique_ptr<KeyEvent> createKeyEvent(const InputMessage& msg) {
    std::unique_ptr<KeyEvent> event = std::make_unique<KeyEvent>();
    event->initialize(msg.body.key.eventId, msg.body.key.deviceId, msg.body.key.source,
                      msg.body.key.displayId, msg.body.key.hmac, msg.body.key.action,
                      msg.body.key.flags, msg.body.key.keyCode, msg.body.key.scanCode,
                      msg.body.key.metaState, msg.body.key.repeatCount, msg.body.key.downTime,
                      msg.body.key.eventTime);
    return event;
}

void initializeFocusEvent(FocusEvent& event, const InputMessage& msg) {
    event.initialize(msg.body.focus.eventId, msg.body.focus.hasFocus);
std::unique_ptr<FocusEvent> createFocusEvent(const InputMessage& msg) {
    std::unique_ptr<FocusEvent> event = std::make_unique<FocusEvent>();
    event->initialize(msg.body.focus.eventId, msg.body.focus.hasFocus);
    return event;
}

void initializeCaptureEvent(CaptureEvent& event, const InputMessage& msg) {
    event.initialize(msg.body.capture.eventId, msg.body.capture.pointerCaptureEnabled);
std::unique_ptr<CaptureEvent> createCaptureEvent(const InputMessage& msg) {
    std::unique_ptr<CaptureEvent> event = std::make_unique<CaptureEvent>();
    event->initialize(msg.body.capture.eventId, msg.body.capture.pointerCaptureEnabled);
    return event;
}

void initializeDragEvent(DragEvent& event, const InputMessage& msg) {
    event.initialize(msg.body.drag.eventId, msg.body.drag.x, msg.body.drag.y,
std::unique_ptr<DragEvent> createDragEvent(const InputMessage& msg) {
    std::unique_ptr<DragEvent> event = std::make_unique<DragEvent>();
    event->initialize(msg.body.drag.eventId, msg.body.drag.x, msg.body.drag.y,
                      msg.body.drag.isExiting);
    return event;
}

void initializeMotionEvent(MotionEvent& event, const InputMessage& msg) {
std::unique_ptr<MotionEvent> createMotionEvent(const InputMessage& msg) {
    std::unique_ptr<MotionEvent> event = std::make_unique<MotionEvent>();
    const uint32_t pointerCount = msg.body.motion.pointerCount;
    std::vector<PointerProperties> pointerProperties;
    pointerProperties.reserve(pointerCount);
@@ -83,15 +92,16 @@ void initializeMotionEvent(MotionEvent& event, const InputMessage& msg) {
    displayTransform.set({msg.body.motion.dsdxRaw, msg.body.motion.dtdxRaw, msg.body.motion.txRaw,
                          msg.body.motion.dtdyRaw, msg.body.motion.dsdyRaw, msg.body.motion.tyRaw,
                          0, 0, 1});
    event.initialize(msg.body.motion.eventId, msg.body.motion.deviceId, msg.body.motion.source,
    event->initialize(msg.body.motion.eventId, msg.body.motion.deviceId, msg.body.motion.source,
                      msg.body.motion.displayId, msg.body.motion.hmac, msg.body.motion.action,
                     msg.body.motion.actionButton, msg.body.motion.flags, msg.body.motion.edgeFlags,
                     msg.body.motion.metaState, msg.body.motion.buttonState,
                     msg.body.motion.classification, transform, msg.body.motion.xPrecision,
                     msg.body.motion.yPrecision, msg.body.motion.xCursorPosition,
                     msg.body.motion.yCursorPosition, displayTransform, msg.body.motion.downTime,
                     msg.body.motion.eventTime, pointerCount, pointerProperties.data(),
                     pointerCoords.data());
                      msg.body.motion.actionButton, msg.body.motion.flags,
                      msg.body.motion.edgeFlags, msg.body.motion.metaState,
                      msg.body.motion.buttonState, msg.body.motion.classification, transform,
                      msg.body.motion.xPrecision, msg.body.motion.yPrecision,
                      msg.body.motion.xCursorPosition, msg.body.motion.yCursorPosition,
                      displayTransform, msg.body.motion.downTime, msg.body.motion.eventTime,
                      pointerCount, pointerProperties.data(), pointerCoords.data());
    return event;
}

void addSample(MotionEvent& event, const InputMessage& msg) {
@@ -107,8 +117,10 @@ void addSample(MotionEvent& event, const InputMessage& msg) {
    event.addSample(msg.body.motion.eventTime, pointerCoords.data());
}

void initializeTouchModeEvent(TouchModeEvent& event, const InputMessage& msg) {
    event.initialize(msg.body.touchMode.eventId, msg.body.touchMode.isInTouchMode);
std::unique_ptr<TouchModeEvent> createTouchModeEvent(const InputMessage& msg) {
    std::unique_ptr<TouchModeEvent> event = std::make_unique<TouchModeEvent>();
    event->initialize(msg.body.touchMode.eventId, msg.body.touchMode.isInTouchMode);
    return event;
}

std::string outboundMessageToString(const InputMessage& outboundMsg) {
@@ -388,15 +400,13 @@ std::vector<InputMessage> InputConsumerNoResampling::readAllMessages() {
void InputConsumerNoResampling::handleMessage(const InputMessage& msg) const {
    switch (msg.header.type) {
        case InputMessage::Type::KEY: {
            KeyEvent keyEvent;
            initializeKeyEvent(keyEvent, msg);
            std::unique_ptr<KeyEvent> keyEvent = createKeyEvent(msg);
            mCallbacks.onKeyEvent(std::move(keyEvent), msg.header.seq);
            break;
        }

        case InputMessage::Type::MOTION: {
            MotionEvent motionEvent;
            initializeMotionEvent(motionEvent, msg);
            std::unique_ptr<MotionEvent> motionEvent = createMotionEvent(msg);
            mCallbacks.onMotionEvent(std::move(motionEvent), msg.header.seq);
            break;
        }
@@ -411,29 +421,25 @@ void InputConsumerNoResampling::handleMessage(const InputMessage& msg) const {
        }

        case InputMessage::Type::FOCUS: {
            FocusEvent focusEvent;
            initializeFocusEvent(focusEvent, msg);
            std::unique_ptr<FocusEvent> focusEvent = createFocusEvent(msg);
            mCallbacks.onFocusEvent(std::move(focusEvent), msg.header.seq);
            break;
        }

        case InputMessage::Type::CAPTURE: {
            CaptureEvent captureEvent;
            initializeCaptureEvent(captureEvent, msg);
            std::unique_ptr<CaptureEvent> captureEvent = createCaptureEvent(msg);
            mCallbacks.onCaptureEvent(std::move(captureEvent), msg.header.seq);
            break;
        }

        case InputMessage::Type::DRAG: {
            DragEvent dragEvent;
            initializeDragEvent(dragEvent, msg);
            std::unique_ptr<DragEvent> dragEvent = createDragEvent(msg);
            mCallbacks.onDragEvent(std::move(dragEvent), msg.header.seq);
            break;
        }

        case InputMessage::Type::TOUCH_MODE: {
            TouchModeEvent touchModeEvent;
            initializeTouchModeEvent(touchModeEvent, msg);
            std::unique_ptr<TouchModeEvent> touchModeEvent = createTouchModeEvent(msg);
            mCallbacks.onTouchModeEvent(std::move(touchModeEvent), msg.header.seq);
            break;
        }
@@ -448,7 +454,7 @@ bool InputConsumerNoResampling::consumeBatchedInputEvents(
    const nsecs_t frameTime = requestedFrameTime.value_or(std::numeric_limits<nsecs_t>::max());
    bool producedEvents = false;
    for (auto& [deviceId, messages] : mBatches) {
        MotionEvent motion;
        std::unique_ptr<MotionEvent> motion;
        std::optional<uint32_t> firstSeqForBatch;
        std::vector<uint32_t> sequences;
        while (!messages.empty()) {
@@ -456,20 +462,21 @@ bool InputConsumerNoResampling::consumeBatchedInputEvents(
            if (msg.body.motion.eventTime > frameTime) {
                break;
            }
            if (!firstSeqForBatch.has_value()) {
                initializeMotionEvent(motion, msg);
            if (motion == nullptr) {
                motion = createMotionEvent(msg);
                firstSeqForBatch = msg.header.seq;
                const auto [_, inserted] = mBatchedSequenceNumbers.insert({*firstSeqForBatch, {}});
                if (!inserted) {
                    LOG(FATAL) << "The sequence " << msg.header.seq << " was already present!";
                }
            } else {
                addSample(motion, msg);
                addSample(*motion, msg);
                mBatchedSequenceNumbers[*firstSeqForBatch].push_back(msg.header.seq);
            }
            messages.pop();
        }
        if (firstSeqForBatch.has_value()) {
        if (motion != nullptr) {
            LOG_ALWAYS_FATAL_IF(!firstSeqForBatch.has_value());
            mCallbacks.onMotionEvent(std::move(motion), *firstSeqForBatch);
            producedEvents = true;
        } else {
@@ -520,9 +527,8 @@ std::string InputConsumerNoResampling::dump() const {
            std::queue<InputMessage> tmpQueue = messages;
            while (!tmpQueue.empty()) {
                LOG_ALWAYS_FATAL_IF(tmpQueue.front().header.type != InputMessage::Type::MOTION);
                MotionEvent motion;
                initializeMotionEvent(motion, tmpQueue.front());
                out += std::string("    ") + streamableToString(motion) + "\n";
                std::unique_ptr<MotionEvent> motion = createMotionEvent(tmpQueue.front());
                out += std::string("    ") + streamableToString(*motion) + "\n";
                tmpQueue.pop();
            }
        }
Loading