blob: 0b930d88bf6b54871d7209ce21634544c5a542c2 [file] [log] [blame]
Chavi Weingartend57801e2024-03-04 22:49:03 +00001/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <android/choreographer.h>
18#include <android/surface_control_input_receiver.h>
19#include <binder/Binder.h>
20#include <gui/Choreographer.h>
21#include <gui/InputTransferToken.h>
22#include <input/Input.h>
23#include <input/InputConsumerNoResampling.h>
24
25#include "android_view_WindowManagerGlobal.h"
26
27using namespace android;
28
29extern void InputTransferToken_acquire(InputTransferToken* inputTransferToken);
30
31struct AInputReceiverCallbacks {
32 AInputReceiverCallbacks(void* context) : context(context) {}
33 void* context;
34 AInputReceiver_onMotionEvent onMotionEvent = nullptr;
35 AInputReceiver_onKeyEvent onKeyEvent = nullptr;
36};
37
38class InputReceiver : public InputConsumerCallbacks {
39public:
40 InputReceiver(const sp<Looper>& looper, const std::shared_ptr<InputChannel>& inputChannel,
41 const sp<IBinder>& clientToken, const sp<InputTransferToken>& inputTransferToken,
42 AInputReceiverCallbacks* callbacks)
43 : mCallbacks(callbacks),
44 mInputConsumer(inputChannel, looper, *this),
45 mClientToken(clientToken),
46 mInputTransferToken(inputTransferToken) {}
47
48 ~InputReceiver() {
49 remove();
50 }
51
52 void onKeyEvent(std::unique_ptr<KeyEvent> event, uint32_t seq) override {
53 if (mCallbacks->onKeyEvent != nullptr) {
54 const bool handled = mCallbacks->onKeyEvent(mCallbacks->context,
55 static_cast<AInputEvent*>(event.release()));
56 mInputConsumer.finishInputEvent(seq, handled);
57 }
58 }
59
60 void onMotionEvent(std::unique_ptr<MotionEvent> event, uint32_t seq) override {
61 if (mCallbacks->onMotionEvent != nullptr) {
62 const bool handled =
63 mCallbacks->onMotionEvent(mCallbacks->context,
64 static_cast<AInputEvent*>(event.release()));
65 mInputConsumer.finishInputEvent(seq, handled);
66 }
67 }
68
69 void onFocusEvent(std::unique_ptr<FocusEvent>, uint32_t seq) override {
70 mInputConsumer.finishInputEvent(seq, false);
71 }
72 void onCaptureEvent(std::unique_ptr<CaptureEvent>, uint32_t seq) override {
73 mInputConsumer.finishInputEvent(seq, false);
74 }
75 void onDragEvent(std::unique_ptr<DragEvent>, uint32_t seq) override {
76 mInputConsumer.finishInputEvent(seq, false);
77 }
78 void onTouchModeEvent(std::unique_ptr<TouchModeEvent>, uint32_t seq) override {
79 mInputConsumer.finishInputEvent(seq, false);
80 }
81
82 virtual void onBatchedInputEventPending(int32_t) override {
83 mInputConsumer.consumeBatchedInputEvents(std::nullopt);
84 }
85
86 const AInputTransferToken* getInputTransferToken() {
87 InputTransferToken_acquire(mInputTransferToken.get());
88 return reinterpret_cast<const AInputTransferToken*>(mInputTransferToken.get());
89 }
90
91 void remove() {
92 removeInputChannel(mClientToken);
93 }
94
95 AInputReceiverCallbacks* mCallbacks;
96
97protected:
98 InputConsumerNoResampling mInputConsumer;
99
100private:
101 const sp<IBinder> mClientToken;
102 const sp<InputTransferToken> mInputTransferToken;
103};
104
105class BatchedInputReceiver : public InputReceiver {
106public:
107 BatchedInputReceiver(Choreographer& choreographer,
108 const std::shared_ptr<InputChannel>& inputChannel,
109 const sp<IBinder>& clientToken,
110 const sp<InputTransferToken>& inputTransferToken,
111 AInputReceiverCallbacks* callbacks)
112 : InputReceiver(choreographer.getLooper(), inputChannel, clientToken, inputTransferToken,
113 callbacks),
114 mChoreographer(choreographer) {}
115
116 static void vsyncCallback(const AChoreographerFrameCallbackData* callbackData, void* data) {
117 BatchedInputReceiver* receiver = static_cast<BatchedInputReceiver*>(data);
118 receiver->onVsyncCallback(callbackData);
119 }
120
121 void onVsyncCallback(const AChoreographerFrameCallbackData* callbackData) {
122 int64_t frameTimeNanos = AChoreographerFrameCallbackData_getFrameTimeNanos(callbackData);
123 mInputConsumer.consumeBatchedInputEvents(frameTimeNanos);
124 mBatchedInputScheduled = false;
125 }
126
127 void onBatchedInputEventPending(int32_t) override {
128 scheduleBatchedInput();
129 }
130
131private:
132 Choreographer& mChoreographer;
133 bool mBatchedInputScheduled = false;
134
135 void scheduleBatchedInput() {
136 if (!mBatchedInputScheduled) {
137 mBatchedInputScheduled = true;
138 mChoreographer.postFrameCallbackDelayed(nullptr, nullptr, vsyncCallback, this, 0,
139 CallbackType::CALLBACK_INPUT);
140 }
141 }
142};
143
144static inline AInputReceiver* InputReceiver_to_AInputReceiver(InputReceiver* inputReceiver) {
145 return reinterpret_cast<AInputReceiver*>(inputReceiver);
146}
147
148static inline InputReceiver* AInputReceiver_to_InputReceiver(AInputReceiver* aInputReceiver) {
149 return reinterpret_cast<InputReceiver*>(aInputReceiver);
150}
151
152AInputReceiver* AInputReceiver_createBatchedInputReceiver(AChoreographer* aChoreographer,
153 const AInputTransferToken* hostToken,
154 const ASurfaceControl* aSurfaceControl,
155 AInputReceiverCallbacks* callbacks) {
156 // create input channel here through WMS
157 sp<IBinder> clientToken = sp<BBinder>::make();
158 sp<InputTransferToken> clientInputTransferToken = sp<InputTransferToken>::make();
159
160 std::shared_ptr<InputChannel> inputChannel =
161 createInputChannel(clientToken, reinterpret_cast<const InputTransferToken&>(*hostToken),
162 reinterpret_cast<const SurfaceControl&>(*aSurfaceControl),
163 *clientInputTransferToken);
164 return InputReceiver_to_AInputReceiver(
165 new BatchedInputReceiver(reinterpret_cast<Choreographer&>(*aChoreographer),
166 inputChannel, clientToken, clientInputTransferToken,
167 callbacks));
168}
169
170AInputReceiver* AInputReceiver_createUnbatchedInputReceiver(ALooper* aLooper,
171 const AInputTransferToken* hostToken,
172 const ASurfaceControl* aSurfaceControl,
173 AInputReceiverCallbacks* callbacks) {
174 // create input channel here through WMS
175 sp<IBinder> clientToken = sp<BBinder>::make();
176 sp<InputTransferToken> clientInputTransferToken = sp<InputTransferToken>::make();
177
178 std::shared_ptr<InputChannel> inputChannel =
179 createInputChannel(clientToken, reinterpret_cast<const InputTransferToken&>(*hostToken),
180 reinterpret_cast<const SurfaceControl&>(*aSurfaceControl),
181 *clientInputTransferToken);
182 return InputReceiver_to_AInputReceiver(new InputReceiver(reinterpret_cast<Looper*>(aLooper),
183 inputChannel, clientToken,
184 clientInputTransferToken, callbacks));
185}
186
187const AInputTransferToken* AInputReceiver_getInputTransferToken(AInputReceiver* aInputReceiver) {
188 return AInputReceiver_to_InputReceiver(aInputReceiver)->getInputTransferToken();
189}
190
191void AInputReceiver_release(AInputReceiver* aInputReceiver) {
192 InputReceiver* inputReceiver = AInputReceiver_to_InputReceiver(aInputReceiver);
Chavi Weingarten0cd72102024-03-19 20:24:45 +0000193 if (inputReceiver != nullptr) {
194 inputReceiver->remove();
195 }
Chavi Weingartend57801e2024-03-04 22:49:03 +0000196 delete inputReceiver;
197}
198
199void AInputReceiverCallbacks_setMotionEventCallback(AInputReceiverCallbacks* callbacks,
200 AInputReceiver_onMotionEvent onMotionEvent) {
201 callbacks->onMotionEvent = onMotionEvent;
202}
203
204void AInputReceiverCallbacks_setKeyEventCallback(AInputReceiverCallbacks* callbacks,
205 AInputReceiver_onKeyEvent onKeyEvent) {
206 callbacks->onKeyEvent = onKeyEvent;
207}
208
209AInputReceiverCallbacks* AInputReceiverCallbacks_create(void* context) {
210 return new AInputReceiverCallbacks(context);
211}
212
213void AInputReceiverCallbacks_release(AInputReceiverCallbacks* callbacks) {
214 delete callbacks;
215}