Loading include/android/surface_control_input_receiver.h 0 → 100644 +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 include/input/InputConsumerNoResampling.h +6 −6 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; }; /** Loading libs/gui/Choreographer.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -425,4 +425,8 @@ int64_t Choreographer::getStartTimeNanosForVsyncId(AVsyncId vsyncId) { return iter->second; } const sp<Looper> Choreographer::getLooper() { return mLooper; } } // namespace android libs/gui/include/gui/Choreographer.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading libs/input/InputConsumerNoResampling.cpp +51 −45 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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) { Loading @@ -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) { Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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()) { Loading @@ -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 { Loading Loading @@ -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 Loading
include/android/surface_control_input_receiver.h 0 → 100644 +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
include/input/InputConsumerNoResampling.h +6 −6 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; }; /** Loading
libs/gui/Choreographer.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -425,4 +425,8 @@ int64_t Choreographer::getStartTimeNanosForVsyncId(AVsyncId vsyncId) { return iter->second; } const sp<Looper> Choreographer::getLooper() { return mLooper; } } // namespace android
libs/gui/include/gui/Choreographer.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
libs/input/InputConsumerNoResampling.cpp +51 −45 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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) { Loading @@ -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) { Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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()) { Loading @@ -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 { Loading Loading @@ -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