1 /*
2 * Copyright (C) 2010 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 #define LOG_TAG "MotionEvent-JNI"
18
19 #include "android_view_MotionEvent.h"
20
21 #include <android/graphics/matrix.h>
22 #include <android_runtime/AndroidRuntime.h>
23 #include <android_runtime/Log.h>
24 #include <attestation/HmacKeyManager.h>
25 #include <gui/constants.h>
26 #include <input/Input.h>
27 #include <log/log.h>
28 #include <nativehelper/JNIHelp.h>
29 #include <nativehelper/ScopedUtfChars.h>
30
31 #include "android_os_Parcel.h"
32 #include "android_util_Binder.h"
33 #include "core_jni_helpers.h"
34
35 namespace android {
36
37 // ----------------------------------------------------------------------------
38
39 static struct {
40 jclass clazz;
41
42 jmethodID obtain;
43 jmethodID recycle;
44
45 jfieldID mNativePtr;
46 } gMotionEventClassInfo;
47
48 static struct {
49 jfieldID mPackedAxisBits;
50 jfieldID mPackedAxisValues;
51 jfieldID x;
52 jfieldID y;
53 jfieldID pressure;
54 jfieldID size;
55 jfieldID touchMajor;
56 jfieldID touchMinor;
57 jfieldID toolMajor;
58 jfieldID toolMinor;
59 jfieldID orientation;
60 jfieldID relativeX;
61 jfieldID relativeY;
62 jfieldID isResampled;
63 } gPointerCoordsClassInfo;
64
65 static struct {
66 jfieldID id;
67 jfieldID toolType;
68 } gPointerPropertiesClassInfo;
69
70 // ----------------------------------------------------------------------------
71
android_view_MotionEvent_getNativePtr(JNIEnv * env,jobject eventObj)72 MotionEvent* android_view_MotionEvent_getNativePtr(JNIEnv* env, jobject eventObj) {
73 if (!eventObj) {
74 return NULL;
75 }
76 return reinterpret_cast<MotionEvent*>(
77 env->GetLongField(eventObj, gMotionEventClassInfo.mNativePtr));
78 }
79
android_view_MotionEvent_setNativePtr(JNIEnv * env,jobject eventObj,MotionEvent * event)80 static void android_view_MotionEvent_setNativePtr(JNIEnv* env, jobject eventObj,
81 MotionEvent* event) {
82 env->SetLongField(eventObj, gMotionEventClassInfo.mNativePtr,
83 reinterpret_cast<jlong>(event));
84 }
85
android_view_MotionEvent_obtainAsCopy(JNIEnv * env,const MotionEvent & event)86 jobject android_view_MotionEvent_obtainAsCopy(JNIEnv* env, const MotionEvent& event) {
87 jobject eventObj = env->CallStaticObjectMethod(gMotionEventClassInfo.clazz,
88 gMotionEventClassInfo.obtain);
89 if (env->ExceptionCheck() || !eventObj) {
90 ALOGE("An exception occurred while obtaining a motion event.");
91 LOGE_EX(env);
92 env->ExceptionClear();
93 return NULL;
94 }
95
96 MotionEvent* destEvent = android_view_MotionEvent_getNativePtr(env, eventObj);
97 if (!destEvent) {
98 destEvent = new MotionEvent();
99 android_view_MotionEvent_setNativePtr(env, eventObj, destEvent);
100 }
101
102 destEvent->copyFrom(&event, true);
103 return eventObj;
104 }
105
android_view_MotionEvent_obtainFromNative(JNIEnv * env,std::unique_ptr<MotionEvent> event)106 jobject android_view_MotionEvent_obtainFromNative(JNIEnv* env, std::unique_ptr<MotionEvent> event) {
107 if (event == nullptr) {
108 return nullptr;
109 }
110 jobject eventObj =
111 env->CallStaticObjectMethod(gMotionEventClassInfo.clazz, gMotionEventClassInfo.obtain);
112 if (env->ExceptionCheck() || !eventObj) {
113 LOGE_EX(env);
114 LOG_ALWAYS_FATAL("An exception occurred while obtaining a Java motion event.");
115 }
116 android_view_MotionEvent_setNativePtr(env, eventObj, event.release());
117 return eventObj;
118 }
119
android_view_MotionEvent_recycle(JNIEnv * env,jobject eventObj)120 status_t android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj) {
121 env->CallVoidMethod(eventObj, gMotionEventClassInfo.recycle);
122 if (env->ExceptionCheck()) {
123 ALOGW("An exception occurred while recycling a motion event.");
124 LOGW_EX(env);
125 env->ExceptionClear();
126 return UNKNOWN_ERROR;
127 }
128 return OK;
129 }
130
131 // ----------------------------------------------------------------------------
132
133 static const jint HISTORY_CURRENT = -0x80000000;
134
validatePointerCount(JNIEnv * env,jint pointerCount)135 static bool validatePointerCount(JNIEnv* env, jint pointerCount) {
136 if (pointerCount < 1) {
137 jniThrowException(env, "java/lang/IllegalArgumentException",
138 "pointerCount must be at least 1");
139 return false;
140 }
141 return true;
142 }
143
validatePointerPropertiesArray(JNIEnv * env,jobjectArray pointerPropertiesObjArray,size_t pointerCount)144 static bool validatePointerPropertiesArray(JNIEnv* env, jobjectArray pointerPropertiesObjArray,
145 size_t pointerCount) {
146 if (!pointerPropertiesObjArray) {
147 jniThrowException(env, "java/lang/IllegalArgumentException",
148 "pointerProperties array must not be null");
149 return false;
150 }
151 size_t length = size_t(env->GetArrayLength(pointerPropertiesObjArray));
152 if (length < pointerCount) {
153 jniThrowException(env, "java/lang/IllegalArgumentException",
154 "pointerProperties array must be large enough to hold all pointers");
155 return false;
156 }
157 return true;
158 }
159
validatePointerCoordsObjArray(JNIEnv * env,jobjectArray pointerCoordsObjArray,size_t pointerCount)160 static bool validatePointerCoordsObjArray(JNIEnv* env, jobjectArray pointerCoordsObjArray,
161 size_t pointerCount) {
162 if (!pointerCoordsObjArray) {
163 jniThrowException(env, "java/lang/IllegalArgumentException",
164 "pointerCoords array must not be null");
165 return false;
166 }
167 size_t length = size_t(env->GetArrayLength(pointerCoordsObjArray));
168 if (length < pointerCount) {
169 jniThrowException(env, "java/lang/IllegalArgumentException",
170 "pointerCoords array must be large enough to hold all pointers");
171 return false;
172 }
173 return true;
174 }
175
validatePointerIndex(JNIEnv * env,jint pointerIndex,const MotionEvent & event)176 static bool validatePointerIndex(JNIEnv* env, jint pointerIndex, const MotionEvent& event) {
177 if (pointerIndex < 0 || size_t(pointerIndex) >= event.getPointerCount()) {
178 std::stringstream message;
179 message << "invalid pointerIndex " << pointerIndex << " for " << event;
180 jniThrowException(env, "java/lang/IllegalArgumentException", message.str().c_str());
181 return false;
182 }
183 return true;
184 }
185
validateHistoryPos(JNIEnv * env,jint historyPos,const MotionEvent & event)186 static bool validateHistoryPos(JNIEnv* env, jint historyPos, const MotionEvent& event) {
187 if (historyPos < 0 || size_t(historyPos) >= event.getHistorySize()) {
188 std::stringstream message;
189 message << "historyPos " << historyPos << " out of range for " << event;
190 jniThrowException(env, "java/lang/IllegalArgumentException", message.str().c_str());
191 return false;
192 }
193 return true;
194 }
195
validatePointerCoords(JNIEnv * env,jobject pointerCoordsObj)196 static bool validatePointerCoords(JNIEnv* env, jobject pointerCoordsObj) {
197 if (!pointerCoordsObj) {
198 jniThrowException(env, "java/lang/IllegalArgumentException",
199 "pointerCoords must not be null");
200 return false;
201 }
202 return true;
203 }
204
validatePointerProperties(JNIEnv * env,jobject pointerPropertiesObj)205 static bool validatePointerProperties(JNIEnv* env, jobject pointerPropertiesObj) {
206 if (!pointerPropertiesObj) {
207 jniThrowException(env, "java/lang/IllegalArgumentException",
208 "pointerProperties must not be null");
209 return false;
210 }
211 return true;
212 }
213
pointerCoordsToNative(JNIEnv * env,jobject pointerCoordsObj,float xOffset,float yOffset,PointerCoords * outRawPointerCoords)214 static void pointerCoordsToNative(JNIEnv* env, jobject pointerCoordsObj,
215 float xOffset, float yOffset, PointerCoords* outRawPointerCoords) {
216 outRawPointerCoords->clear();
217 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_X,
218 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.x) - xOffset);
219 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_Y,
220 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.y) - yOffset);
221 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
222 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.pressure));
223 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_SIZE,
224 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.size));
225 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
226 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMajor));
227 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR,
228 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMinor));
229 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR,
230 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMajor));
231 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR,
232 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMinor));
233 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
234 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.orientation));
235 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X,
236 env->GetFloatField(pointerCoordsObj,
237 gPointerCoordsClassInfo.relativeX));
238 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y,
239 env->GetFloatField(pointerCoordsObj,
240 gPointerCoordsClassInfo.relativeY));
241 outRawPointerCoords->isResampled =
242 env->GetBooleanField(pointerCoordsObj, gPointerCoordsClassInfo.isResampled);
243
244 BitSet64 bits =
245 BitSet64(env->GetLongField(pointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits));
246 if (!bits.isEmpty()) {
247 jfloatArray valuesArray = jfloatArray(env->GetObjectField(pointerCoordsObj,
248 gPointerCoordsClassInfo.mPackedAxisValues));
249 if (valuesArray) {
250 jfloat* values = static_cast<jfloat*>(
251 env->GetPrimitiveArrayCritical(valuesArray, NULL));
252
253 uint32_t index = 0;
254 do {
255 uint32_t axis = bits.clearFirstMarkedBit();
256 outRawPointerCoords->setAxisValue(axis, values[index++]);
257 } while (!bits.isEmpty());
258
259 env->ReleasePrimitiveArrayCritical(valuesArray, values, JNI_ABORT);
260 env->DeleteLocalRef(valuesArray);
261 }
262 }
263 }
264
obtainPackedAxisValuesArray(JNIEnv * env,uint32_t minSize,jobject outPointerCoordsObj)265 static jfloatArray obtainPackedAxisValuesArray(JNIEnv* env, uint32_t minSize,
266 jobject outPointerCoordsObj) {
267 jfloatArray outValuesArray = jfloatArray(env->GetObjectField(outPointerCoordsObj,
268 gPointerCoordsClassInfo.mPackedAxisValues));
269 if (outValuesArray) {
270 uint32_t size = env->GetArrayLength(outValuesArray);
271 if (minSize <= size) {
272 return outValuesArray;
273 }
274 env->DeleteLocalRef(outValuesArray);
275 }
276 uint32_t size = 8;
277 while (size < minSize) {
278 size *= 2;
279 }
280 outValuesArray = env->NewFloatArray(size);
281 env->SetObjectField(outPointerCoordsObj,
282 gPointerCoordsClassInfo.mPackedAxisValues, outValuesArray);
283 return outValuesArray;
284 }
285
pointerCoordsFromNative(JNIEnv * env,const PointerCoords * rawPointerCoords,const BitSet64 & axesBitsToCopy,jobject outPointerCoordsObj)286 static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointerCoords,
287 const BitSet64& axesBitsToCopy, jobject outPointerCoordsObj) {
288 BitSet64 bits = axesBitsToCopy;
289 uint64_t outBits = 0;
290 if (!bits.isEmpty()) {
291 uint32_t packedAxesCount = bits.count();
292 jfloatArray outValuesArray = obtainPackedAxisValuesArray(env, packedAxesCount,
293 outPointerCoordsObj);
294 if (!outValuesArray) {
295 return; // OOM
296 }
297
298 jfloat* outValues = static_cast<jfloat*>(env->GetPrimitiveArrayCritical(
299 outValuesArray, NULL));
300
301 uint32_t index = 0;
302 do {
303 uint32_t axis = bits.clearFirstMarkedBit();
304 outBits |= BitSet64::valueForBit(axis);
305 outValues[index++] = rawPointerCoords->getAxisValue(axis);
306 } while (!bits.isEmpty());
307
308 env->ReleasePrimitiveArrayCritical(outValuesArray, outValues, 0);
309 env->DeleteLocalRef(outValuesArray);
310 }
311 env->SetLongField(outPointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits, outBits);
312 }
313
pointerPropertiesToNative(JNIEnv * env,jobject pointerPropertiesObj,PointerProperties * outPointerProperties)314 static void pointerPropertiesToNative(JNIEnv* env, jobject pointerPropertiesObj,
315 PointerProperties* outPointerProperties) {
316 outPointerProperties->clear();
317 outPointerProperties->id = env->GetIntField(pointerPropertiesObj,
318 gPointerPropertiesClassInfo.id);
319 const int32_t toolType = env->GetIntField(pointerPropertiesObj,
320 gPointerPropertiesClassInfo.toolType);
321 outPointerProperties->toolType = static_cast<ToolType>(toolType);
322 }
323
pointerPropertiesFromNative(JNIEnv * env,const PointerProperties * pointerProperties,jobject outPointerPropertiesObj)324 static void pointerPropertiesFromNative(JNIEnv* env, const PointerProperties* pointerProperties,
325 jobject outPointerPropertiesObj) {
326 env->SetIntField(outPointerPropertiesObj, gPointerPropertiesClassInfo.id,
327 pointerProperties->id);
328 env->SetIntField(outPointerPropertiesObj, gPointerPropertiesClassInfo.toolType,
329 static_cast<int32_t>(pointerProperties->toolType));
330 }
331
332
333 // ----------------------------------------------------------------------------
334
android_view_MotionEvent_nativeInitialize(JNIEnv * env,jclass clazz,jlong nativePtr,jint deviceId,jint source,jint displayId,jint action,jint flags,jint edgeFlags,jint metaState,jint buttonState,jint classification,jfloat xOffset,jfloat yOffset,jfloat xPrecision,jfloat yPrecision,jlong downTimeNanos,jlong eventTimeNanos,jint pointerCount,jobjectArray pointerPropertiesObjArray,jobjectArray pointerCoordsObjArray)335 static jlong android_view_MotionEvent_nativeInitialize(
336 JNIEnv* env, jclass clazz, jlong nativePtr, jint deviceId, jint source, jint displayId,
337 jint action, jint flags, jint edgeFlags, jint metaState, jint buttonState,
338 jint classification, jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision,
339 jlong downTimeNanos, jlong eventTimeNanos, jint pointerCount,
340 jobjectArray pointerPropertiesObjArray, jobjectArray pointerCoordsObjArray) {
341 if (!validatePointerCount(env, pointerCount)
342 || !validatePointerPropertiesArray(env, pointerPropertiesObjArray, pointerCount)
343 || !validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
344 return 0;
345 }
346
347 std::unique_ptr<MotionEvent> event;
348 if (nativePtr) {
349 event = std::unique_ptr<MotionEvent>(reinterpret_cast<MotionEvent*>(nativePtr));
350 } else {
351 event = std::make_unique<MotionEvent>();
352 }
353
354 PointerProperties pointerProperties[pointerCount];
355 PointerCoords rawPointerCoords[pointerCount];
356
357 for (jint i = 0; i < pointerCount; i++) {
358 jobject pointerPropertiesObj = env->GetObjectArrayElement(pointerPropertiesObjArray, i);
359 if (!pointerPropertiesObj) {
360 return 0;
361 }
362 pointerPropertiesToNative(env, pointerPropertiesObj, &pointerProperties[i]);
363 env->DeleteLocalRef(pointerPropertiesObj);
364
365 jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
366 if (!pointerCoordsObj) {
367 jniThrowNullPointerException(env, "pointerCoords");
368 return 0;
369 }
370 pointerCoordsToNative(env, pointerCoordsObj, xOffset, yOffset, &rawPointerCoords[i]);
371 env->DeleteLocalRef(pointerCoordsObj);
372 }
373
374 ui::Transform transform;
375 transform.set(xOffset, yOffset);
376 ui::Transform identityTransform;
377 event->initialize(InputEvent::nextId(), deviceId, source, displayId, INVALID_HMAC, action, 0,
378 flags, edgeFlags, metaState, buttonState,
379 static_cast<MotionClassification>(classification), transform, xPrecision,
380 yPrecision, AMOTION_EVENT_INVALID_CURSOR_POSITION,
381 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, downTimeNanos,
382 eventTimeNanos, pointerCount, pointerProperties, rawPointerCoords);
383
384 return reinterpret_cast<jlong>(event.release());
385 }
386
android_view_MotionEvent_nativeDispose(JNIEnv * env,jclass clazz,jlong nativePtr)387 static void android_view_MotionEvent_nativeDispose(JNIEnv* env, jclass clazz,
388 jlong nativePtr) {
389 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
390 delete event;
391 }
392
android_view_MotionEvent_nativeAddBatch(JNIEnv * env,jclass clazz,jlong nativePtr,jlong eventTimeNanos,jobjectArray pointerCoordsObjArray,jint metaState)393 static void android_view_MotionEvent_nativeAddBatch(JNIEnv* env, jclass clazz,
394 jlong nativePtr, jlong eventTimeNanos, jobjectArray pointerCoordsObjArray,
395 jint metaState) {
396 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
397 size_t pointerCount = event->getPointerCount();
398 if (!validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
399 return;
400 }
401
402 PointerCoords rawPointerCoords[pointerCount];
403
404 for (size_t i = 0; i < pointerCount; i++) {
405 jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
406 if (!pointerCoordsObj) {
407 jniThrowNullPointerException(env, "pointerCoords");
408 return;
409 }
410 pointerCoordsToNative(env, pointerCoordsObj,
411 event->getXOffset(), event->getYOffset(), &rawPointerCoords[i]);
412 env->DeleteLocalRef(pointerCoordsObj);
413 }
414
415 event->addSample(eventTimeNanos, rawPointerCoords);
416 event->setMetaState(event->getMetaState() | metaState);
417 }
418
android_view_MotionEvent_nativeGetPointerCoords(JNIEnv * env,jclass clazz,jlong nativePtr,jint pointerIndex,jint historyPos,jobject outPointerCoordsObj)419 static void android_view_MotionEvent_nativeGetPointerCoords(JNIEnv* env, jclass clazz,
420 jlong nativePtr, jint pointerIndex, jint historyPos, jobject outPointerCoordsObj) {
421 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
422 if (!validatePointerIndex(env, pointerIndex, *event) ||
423 !validatePointerCoords(env, outPointerCoordsObj)) {
424 return;
425 }
426 if (historyPos != HISTORY_CURRENT && !validateHistoryPos(env, historyPos, *event)) {
427 return;
428 }
429
430 // Obtain the following axis values directly from the MotionEvent instead of from the raw
431 // PointerCoords.
432 const static std::array<std::pair<int32_t /*axis*/, jfieldID>, 11> kAxesFromMotionEvent = {{
433 {AMOTION_EVENT_AXIS_X, gPointerCoordsClassInfo.x},
434 {AMOTION_EVENT_AXIS_Y, gPointerCoordsClassInfo.y},
435 {AMOTION_EVENT_AXIS_PRESSURE, gPointerCoordsClassInfo.pressure},
436 {AMOTION_EVENT_AXIS_SIZE, gPointerCoordsClassInfo.size},
437 {AMOTION_EVENT_AXIS_TOUCH_MAJOR, gPointerCoordsClassInfo.touchMajor},
438 {AMOTION_EVENT_AXIS_TOUCH_MINOR, gPointerCoordsClassInfo.touchMinor},
439 {AMOTION_EVENT_AXIS_TOOL_MAJOR, gPointerCoordsClassInfo.toolMajor},
440 {AMOTION_EVENT_AXIS_TOOL_MINOR, gPointerCoordsClassInfo.toolMinor},
441 {AMOTION_EVENT_AXIS_ORIENTATION, gPointerCoordsClassInfo.orientation},
442 {AMOTION_EVENT_AXIS_RELATIVE_X, gPointerCoordsClassInfo.relativeX},
443 {AMOTION_EVENT_AXIS_RELATIVE_Y, gPointerCoordsClassInfo.relativeY},
444 }};
445 for (const auto& [axis, fieldId] : kAxesFromMotionEvent) {
446 const float value = historyPos == HISTORY_CURRENT
447 ? event->getAxisValue(axis, pointerIndex)
448 : event->getHistoricalAxisValue(axis, pointerIndex, historyPos);
449 env->SetFloatField(outPointerCoordsObj, fieldId, value);
450 }
451
452 const PointerCoords* rawPointerCoords = historyPos == HISTORY_CURRENT
453 ? event->getRawPointerCoords(pointerIndex)
454 : event->getHistoricalRawPointerCoords(pointerIndex, historyPos);
455
456 BitSet64 bits = BitSet64(rawPointerCoords->bits);
457 for (const auto [axis, _] : kAxesFromMotionEvent) {
458 bits.clearBit(axis);
459 }
460 pointerCoordsFromNative(env, rawPointerCoords, bits, outPointerCoordsObj);
461
462 const bool isResampled = historyPos == HISTORY_CURRENT
463 ? event->isResampled(pointerIndex, event->getHistorySize())
464 : event->isResampled(pointerIndex, historyPos);
465 env->SetBooleanField(outPointerCoordsObj, gPointerCoordsClassInfo.isResampled, isResampled);
466 }
467
android_view_MotionEvent_nativeGetPointerProperties(JNIEnv * env,jclass clazz,jlong nativePtr,jint pointerIndex,jobject outPointerPropertiesObj)468 static void android_view_MotionEvent_nativeGetPointerProperties(JNIEnv* env, jclass clazz,
469 jlong nativePtr, jint pointerIndex, jobject outPointerPropertiesObj) {
470 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
471 if (!validatePointerIndex(env, pointerIndex, *event) ||
472 !validatePointerProperties(env, outPointerPropertiesObj)) {
473 return;
474 }
475
476 const PointerProperties* pointerProperties = event->getPointerProperties(pointerIndex);
477 pointerPropertiesFromNative(env, pointerProperties, outPointerPropertiesObj);
478 }
479
android_view_MotionEvent_nativeReadFromParcel(JNIEnv * env,jclass clazz,jlong nativePtr,jobject parcelObj)480 static jlong android_view_MotionEvent_nativeReadFromParcel(JNIEnv* env, jclass clazz,
481 jlong nativePtr, jobject parcelObj) {
482 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
483 if (!event) {
484 event = new MotionEvent();
485 }
486
487 Parcel* parcel = parcelForJavaObject(env, parcelObj);
488
489 status_t status = event->readFromParcel(parcel);
490 if (status) {
491 if (!nativePtr) {
492 delete event;
493 }
494 jniThrowRuntimeException(env, "Failed to read MotionEvent parcel.");
495 return 0;
496 }
497 return reinterpret_cast<jlong>(event);
498 }
499
android_view_MotionEvent_nativeWriteToParcel(JNIEnv * env,jclass clazz,jlong nativePtr,jobject parcelObj)500 static void android_view_MotionEvent_nativeWriteToParcel(JNIEnv* env, jclass clazz,
501 jlong nativePtr, jobject parcelObj) {
502 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
503 Parcel* parcel = parcelForJavaObject(env, parcelObj);
504
505 status_t status = event->writeToParcel(parcel);
506 if (status) {
507 jniThrowRuntimeException(env, "Failed to write MotionEvent parcel.");
508 }
509 }
510
android_view_MotionEvent_nativeAxisToString(JNIEnv * env,jclass clazz,jint axis)511 static jstring android_view_MotionEvent_nativeAxisToString(JNIEnv* env, jclass clazz,
512 jint axis) {
513 return env->NewStringUTF(MotionEvent::getLabel(static_cast<int32_t>(axis)));
514 }
515
android_view_MotionEvent_nativeAxisFromString(JNIEnv * env,jclass clazz,jstring label)516 static jint android_view_MotionEvent_nativeAxisFromString(JNIEnv* env, jclass clazz,
517 jstring label) {
518 ScopedUtfChars axisLabel(env, label);
519 return static_cast<jint>(MotionEvent::getAxisFromLabel(axisLabel.c_str()).value_or(-1));
520 }
521
522 // ---------------- @FastNative ----------------------------------
523
android_view_MotionEvent_nativeGetPointerId(JNIEnv * env,jclass clazz,jlong nativePtr,jint pointerIndex)524 static jint android_view_MotionEvent_nativeGetPointerId(JNIEnv* env, jclass clazz,
525 jlong nativePtr, jint pointerIndex) {
526 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
527 if (!validatePointerIndex(env, pointerIndex, *event)) {
528 return -1;
529 }
530 return event->getPointerId(pointerIndex);
531 }
532
android_view_MotionEvent_nativeGetToolType(JNIEnv * env,jclass clazz,jlong nativePtr,jint pointerIndex)533 static jint android_view_MotionEvent_nativeGetToolType(JNIEnv* env, jclass clazz,
534 jlong nativePtr, jint pointerIndex) {
535 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
536 if (!validatePointerIndex(env, pointerIndex, *event)) {
537 return -1;
538 }
539 return static_cast<jint>(event->getToolType(pointerIndex));
540 }
541
android_view_MotionEvent_nativeGetEventTimeNanos(JNIEnv * env,jclass clazz,jlong nativePtr,jint historyPos)542 static jlong android_view_MotionEvent_nativeGetEventTimeNanos(JNIEnv* env, jclass clazz,
543 jlong nativePtr, jint historyPos) {
544 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
545 if (historyPos == HISTORY_CURRENT) {
546 return event->getEventTime();
547 } else {
548 if (!validateHistoryPos(env, historyPos, *event)) {
549 return 0;
550 }
551 return event->getHistoricalEventTime(historyPos);
552 }
553 }
554
android_view_MotionEvent_nativeGetRawAxisValue(JNIEnv * env,jclass clazz,jlong nativePtr,jint axis,jint pointerIndex,jint historyPos)555 static jfloat android_view_MotionEvent_nativeGetRawAxisValue(JNIEnv* env, jclass clazz,
556 jlong nativePtr, jint axis,
557 jint pointerIndex, jint historyPos) {
558 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
559 if (!validatePointerIndex(env, pointerIndex, *event)) {
560 return 0;
561 }
562
563 if (historyPos == HISTORY_CURRENT) {
564 return event->getRawAxisValue(axis, pointerIndex);
565 } else {
566 if (!validateHistoryPos(env, historyPos, *event)) {
567 return 0;
568 }
569 return event->getHistoricalRawAxisValue(axis, pointerIndex, historyPos);
570 }
571 }
572
android_view_MotionEvent_nativeGetAxisValue(JNIEnv * env,jclass clazz,jlong nativePtr,jint axis,jint pointerIndex,jint historyPos)573 static jfloat android_view_MotionEvent_nativeGetAxisValue(JNIEnv* env, jclass clazz,
574 jlong nativePtr, jint axis, jint pointerIndex, jint historyPos) {
575 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
576 if (!validatePointerIndex(env, pointerIndex, *event)) {
577 return 0;
578 }
579
580 if (historyPos == HISTORY_CURRENT) {
581 return event->getAxisValue(axis, pointerIndex);
582 } else {
583 if (!validateHistoryPos(env, historyPos, (*event))) {
584 return 0;
585 }
586 return event->getHistoricalAxisValue(axis, pointerIndex, historyPos);
587 }
588 }
589
android_view_MotionEvent_nativeTransform(JNIEnv * env,jclass clazz,jlong nativePtr,jobject matrixObj)590 static void android_view_MotionEvent_nativeTransform(JNIEnv* env, jclass clazz,
591 jlong nativePtr, jobject matrixObj) {
592 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
593
594 std::array<float, 9> matrix;
595 AMatrix_getContents(env, matrixObj, matrix.data());
596 event->transform(matrix);
597 }
598
android_view_MotionEvent_nativeApplyTransform(JNIEnv * env,jclass clazz,jlong nativePtr,jobject matrixObj)599 static void android_view_MotionEvent_nativeApplyTransform(JNIEnv* env, jclass clazz,
600 jlong nativePtr, jobject matrixObj) {
601 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
602
603 std::array<float, 9> matrix;
604 AMatrix_getContents(env, matrixObj, matrix.data());
605 event->applyTransform(matrix);
606 }
607
608 // ----------------- @CriticalNative ------------------------------
609
android_view_MotionEvent_nativeCopy(jlong destNativePtr,jlong sourceNativePtr,jboolean keepHistory)610 static jlong android_view_MotionEvent_nativeCopy(jlong destNativePtr, jlong sourceNativePtr,
611 jboolean keepHistory) {
612 MotionEvent* destEvent = reinterpret_cast<MotionEvent*>(destNativePtr);
613 if (!destEvent) {
614 destEvent = new MotionEvent();
615 }
616 MotionEvent* sourceEvent = reinterpret_cast<MotionEvent*>(sourceNativePtr);
617 destEvent->copyFrom(sourceEvent, keepHistory);
618 return reinterpret_cast<jlong>(destEvent);
619 }
620
android_view_MotionEvent_nativeGetId(jlong nativePtr)621 static jint android_view_MotionEvent_nativeGetId(jlong nativePtr) {
622 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
623 return event->getId();
624 }
625
android_view_MotionEvent_nativeGetDeviceId(jlong nativePtr)626 static jint android_view_MotionEvent_nativeGetDeviceId(jlong nativePtr) {
627 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
628 return event->getDeviceId();
629 }
630
android_view_MotionEvent_nativeGetSource(jlong nativePtr)631 static jint android_view_MotionEvent_nativeGetSource(jlong nativePtr) {
632 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
633 return event->getSource();
634 }
635
android_view_MotionEvent_nativeSetSource(jlong nativePtr,jint source)636 static void android_view_MotionEvent_nativeSetSource(jlong nativePtr, jint source) {
637 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
638 event->setSource(source);
639 }
640
android_view_MotionEvent_nativeGetDisplayId(jlong nativePtr)641 static jint android_view_MotionEvent_nativeGetDisplayId(jlong nativePtr) {
642 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
643 return event->getDisplayId();
644 }
645
android_view_MotionEvent_nativeSetDisplayId(jlong nativePtr,jint displayId)646 static void android_view_MotionEvent_nativeSetDisplayId(jlong nativePtr, jint displayId) {
647 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
648 return event->setDisplayId(displayId);
649 }
650
android_view_MotionEvent_nativeGetAction(jlong nativePtr)651 static jint android_view_MotionEvent_nativeGetAction(jlong nativePtr) {
652 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
653 return event->getAction();
654 }
655
android_view_MotionEvent_nativeSetAction(jlong nativePtr,jint action)656 static void android_view_MotionEvent_nativeSetAction(jlong nativePtr, jint action) {
657 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
658 event->setAction(action);
659 }
660
android_view_MotionEvent_nativeGetActionButton(jlong nativePtr)661 static int android_view_MotionEvent_nativeGetActionButton(jlong nativePtr) {
662 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
663 return event->getActionButton();
664 }
665
android_view_MotionEvent_nativeSetActionButton(jlong nativePtr,jint button)666 static void android_view_MotionEvent_nativeSetActionButton(jlong nativePtr, jint button) {
667 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
668 event->setActionButton(button);
669 }
670
android_view_MotionEvent_nativeIsTouchEvent(jlong nativePtr)671 static jboolean android_view_MotionEvent_nativeIsTouchEvent(jlong nativePtr) {
672 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
673 return event->isTouchEvent();
674 }
675
android_view_MotionEvent_nativeGetFlags(jlong nativePtr)676 static jint android_view_MotionEvent_nativeGetFlags(jlong nativePtr) {
677 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
678 return event->getFlags();
679 }
680
android_view_MotionEvent_nativeSetFlags(jlong nativePtr,jint flags)681 static void android_view_MotionEvent_nativeSetFlags(jlong nativePtr, jint flags) {
682 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
683 event->setFlags(flags);
684 }
685
android_view_MotionEvent_nativeGetEdgeFlags(jlong nativePtr)686 static jint android_view_MotionEvent_nativeGetEdgeFlags(jlong nativePtr) {
687 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
688 return event->getEdgeFlags();
689 }
690
android_view_MotionEvent_nativeSetEdgeFlags(jlong nativePtr,jint edgeFlags)691 static void android_view_MotionEvent_nativeSetEdgeFlags(jlong nativePtr, jint edgeFlags) {
692 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
693 event->setEdgeFlags(edgeFlags);
694 }
695
android_view_MotionEvent_nativeGetMetaState(jlong nativePtr)696 static jint android_view_MotionEvent_nativeGetMetaState(jlong nativePtr) {
697 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
698 return event->getMetaState();
699 }
700
android_view_MotionEvent_nativeGetButtonState(jlong nativePtr)701 static jint android_view_MotionEvent_nativeGetButtonState(jlong nativePtr) {
702 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
703 return event->getButtonState();
704 }
705
android_view_MotionEvent_nativeSetButtonState(jlong nativePtr,jint buttonState)706 static void android_view_MotionEvent_nativeSetButtonState(jlong nativePtr, jint buttonState) {
707 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
708 event->setButtonState(buttonState);
709 }
710
android_view_MotionEvent_nativeGetClassification(jlong nativePtr)711 static jint android_view_MotionEvent_nativeGetClassification(jlong nativePtr) {
712 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
713 return static_cast<jint>(event->getClassification());
714 }
715
android_view_MotionEvent_nativeOffsetLocation(jlong nativePtr,jfloat deltaX,jfloat deltaY)716 static void android_view_MotionEvent_nativeOffsetLocation(jlong nativePtr, jfloat deltaX,
717 jfloat deltaY) {
718 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
719 return event->offsetLocation(deltaX, deltaY);
720 }
721
android_view_MotionEvent_nativeGetXOffset(jlong nativePtr)722 static jfloat android_view_MotionEvent_nativeGetXOffset(jlong nativePtr) {
723 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
724 return event->getXOffset();
725 }
726
android_view_MotionEvent_nativeGetYOffset(jlong nativePtr)727 static jfloat android_view_MotionEvent_nativeGetYOffset(jlong nativePtr) {
728 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
729 return event->getYOffset();
730 }
731
android_view_MotionEvent_nativeGetXPrecision(jlong nativePtr)732 static jfloat android_view_MotionEvent_nativeGetXPrecision(jlong nativePtr) {
733 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
734 return event->getXPrecision();
735 }
736
android_view_MotionEvent_nativeGetYPrecision(jlong nativePtr)737 static jfloat android_view_MotionEvent_nativeGetYPrecision(jlong nativePtr) {
738 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
739 return event->getYPrecision();
740 }
741
android_view_MotionEvent_nativeGetXCursorPosition(jlong nativePtr)742 static jfloat android_view_MotionEvent_nativeGetXCursorPosition(jlong nativePtr) {
743 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
744 return event->getXCursorPosition();
745 }
746
android_view_MotionEvent_nativeGetYCursorPosition(jlong nativePtr)747 static jfloat android_view_MotionEvent_nativeGetYCursorPosition(jlong nativePtr) {
748 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
749 return event->getYCursorPosition();
750 }
751
android_view_MotionEvent_nativeSetCursorPosition(jlong nativePtr,jfloat x,jfloat y)752 static void android_view_MotionEvent_nativeSetCursorPosition(jlong nativePtr, jfloat x, jfloat y) {
753 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
754 event->setCursorPosition(x, y);
755 }
756
android_view_MotionEvent_nativeGetDownTimeNanos(jlong nativePtr)757 static jlong android_view_MotionEvent_nativeGetDownTimeNanos(jlong nativePtr) {
758 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
759 return event->getDownTime();
760 }
761
android_view_MotionEvent_nativeSetDownTimeNanos(jlong nativePtr,jlong downTimeNanos)762 static void android_view_MotionEvent_nativeSetDownTimeNanos(jlong nativePtr, jlong downTimeNanos) {
763 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
764 event->setDownTime(downTimeNanos);
765 }
766
android_view_MotionEvent_nativeGetPointerCount(jlong nativePtr)767 static jint android_view_MotionEvent_nativeGetPointerCount(jlong nativePtr) {
768 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
769 return jint(event->getPointerCount());
770 }
771
android_view_MotionEvent_nativeFindPointerIndex(jlong nativePtr,jint pointerId)772 static jint android_view_MotionEvent_nativeFindPointerIndex(jlong nativePtr, jint pointerId) {
773 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
774 return jint(event->findPointerIndex(pointerId));
775 }
776
android_view_MotionEvent_nativeGetHistorySize(jlong nativePtr)777 static jint android_view_MotionEvent_nativeGetHistorySize(jlong nativePtr) {
778 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
779 return jint(event->getHistorySize());
780 }
781
android_view_MotionEvent_nativeScale(jlong nativePtr,jfloat scale)782 static void android_view_MotionEvent_nativeScale(jlong nativePtr, jfloat scale) {
783 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
784 event->scale(scale);
785 }
786
android_view_MotionEvent_nativeGetSurfaceRotation(jlong nativePtr)787 static jint android_view_MotionEvent_nativeGetSurfaceRotation(jlong nativePtr) {
788 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
789 auto rotation = event->getSurfaceRotation();
790 if (rotation) {
791 return static_cast<jint>(rotation.value());
792 } else {
793 return -1;
794 }
795 }
796
797 // ----------------------------------------------------------------------------
798
799 static const JNINativeMethod gMotionEventMethods[] = {
800 /* name, signature, funcPtr */
801 {"nativeInitialize",
802 "(JIIIIIIIIIFFFFJJI[Landroid/view/MotionEvent$PointerProperties;"
803 "[Landroid/view/MotionEvent$PointerCoords;)J",
804 (void*)android_view_MotionEvent_nativeInitialize},
805 {"nativeDispose", "(J)V", (void*)android_view_MotionEvent_nativeDispose},
806 {"nativeAddBatch", "(JJ[Landroid/view/MotionEvent$PointerCoords;I)V",
807 (void*)android_view_MotionEvent_nativeAddBatch},
808 {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J",
809 (void*)android_view_MotionEvent_nativeReadFromParcel},
810 {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
811 (void*)android_view_MotionEvent_nativeWriteToParcel},
812 {"nativeAxisToString", "(I)Ljava/lang/String;",
813 (void*)android_view_MotionEvent_nativeAxisToString},
814 {"nativeAxisFromString", "(Ljava/lang/String;)I",
815 (void*)android_view_MotionEvent_nativeAxisFromString},
816 {"nativeGetPointerProperties", "(JILandroid/view/MotionEvent$PointerProperties;)V",
817 (void*)android_view_MotionEvent_nativeGetPointerProperties},
818 {"nativeGetPointerCoords", "(JIILandroid/view/MotionEvent$PointerCoords;)V",
819 (void*)android_view_MotionEvent_nativeGetPointerCoords},
820
821 // --------------- @FastNative ----------------------
822 {"nativeGetPointerId", "(JI)I", (void*)android_view_MotionEvent_nativeGetPointerId},
823 {"nativeGetToolType", "(JI)I", (void*)android_view_MotionEvent_nativeGetToolType},
824 {"nativeGetEventTimeNanos", "(JI)J",
825 (void*)android_view_MotionEvent_nativeGetEventTimeNanos},
826 {"nativeGetRawAxisValue", "(JIII)F", (void*)android_view_MotionEvent_nativeGetRawAxisValue},
827 {"nativeGetAxisValue", "(JIII)F", (void*)android_view_MotionEvent_nativeGetAxisValue},
828 {"nativeTransform", "(JLandroid/graphics/Matrix;)V",
829 (void*)android_view_MotionEvent_nativeTransform},
830 {"nativeApplyTransform", "(JLandroid/graphics/Matrix;)V",
831 (void*)android_view_MotionEvent_nativeApplyTransform},
832
833 // --------------- @CriticalNative ------------------
834
835 {"nativeCopy", "(JJZ)J", (void*)android_view_MotionEvent_nativeCopy},
836 {"nativeGetId", "(J)I", (void*)android_view_MotionEvent_nativeGetId},
837 {"nativeGetDeviceId", "(J)I", (void*)android_view_MotionEvent_nativeGetDeviceId},
838 {"nativeGetSource", "(J)I", (void*)android_view_MotionEvent_nativeGetSource},
839 {"nativeSetSource", "(JI)V", (void*)android_view_MotionEvent_nativeSetSource},
840 {"nativeGetDisplayId", "(J)I", (void*)android_view_MotionEvent_nativeGetDisplayId},
841 {"nativeSetDisplayId", "(JI)V", (void*)android_view_MotionEvent_nativeSetDisplayId},
842 {"nativeGetAction", "(J)I", (void*)android_view_MotionEvent_nativeGetAction},
843 {"nativeSetAction", "(JI)V", (void*)android_view_MotionEvent_nativeSetAction},
844 {"nativeGetActionButton", "(J)I", (void*)android_view_MotionEvent_nativeGetActionButton},
845 {"nativeSetActionButton", "(JI)V", (void*)android_view_MotionEvent_nativeSetActionButton},
846 {"nativeIsTouchEvent", "(J)Z", (void*)android_view_MotionEvent_nativeIsTouchEvent},
847 {"nativeGetFlags", "(J)I", (void*)android_view_MotionEvent_nativeGetFlags},
848 {"nativeSetFlags", "(JI)V", (void*)android_view_MotionEvent_nativeSetFlags},
849 {"nativeGetEdgeFlags", "(J)I", (void*)android_view_MotionEvent_nativeGetEdgeFlags},
850 {"nativeSetEdgeFlags", "(JI)V", (void*)android_view_MotionEvent_nativeSetEdgeFlags},
851 {"nativeGetMetaState", "(J)I", (void*)android_view_MotionEvent_nativeGetMetaState},
852 {"nativeGetButtonState", "(J)I", (void*)android_view_MotionEvent_nativeGetButtonState},
853 {"nativeSetButtonState", "(JI)V", (void*)android_view_MotionEvent_nativeSetButtonState},
854 {"nativeGetClassification", "(J)I",
855 (void*)android_view_MotionEvent_nativeGetClassification},
856 {"nativeOffsetLocation", "(JFF)V", (void*)android_view_MotionEvent_nativeOffsetLocation},
857 {"nativeGetXOffset", "(J)F", (void*)android_view_MotionEvent_nativeGetXOffset},
858 {"nativeGetYOffset", "(J)F", (void*)android_view_MotionEvent_nativeGetYOffset},
859 {"nativeGetXPrecision", "(J)F", (void*)android_view_MotionEvent_nativeGetXPrecision},
860 {"nativeGetYPrecision", "(J)F", (void*)android_view_MotionEvent_nativeGetYPrecision},
861 {"nativeGetXCursorPosition", "(J)F",
862 (void*)android_view_MotionEvent_nativeGetXCursorPosition},
863 {"nativeGetYCursorPosition", "(J)F",
864 (void*)android_view_MotionEvent_nativeGetYCursorPosition},
865 {"nativeSetCursorPosition", "(JFF)V",
866 (void*)android_view_MotionEvent_nativeSetCursorPosition},
867 {"nativeGetDownTimeNanos", "(J)J", (void*)android_view_MotionEvent_nativeGetDownTimeNanos},
868 {"nativeSetDownTimeNanos", "(JJ)V", (void*)android_view_MotionEvent_nativeSetDownTimeNanos},
869 {"nativeGetPointerCount", "(J)I", (void*)android_view_MotionEvent_nativeGetPointerCount},
870 {"nativeFindPointerIndex", "(JI)I", (void*)android_view_MotionEvent_nativeFindPointerIndex},
871 {"nativeGetHistorySize", "(J)I", (void*)android_view_MotionEvent_nativeGetHistorySize},
872 {"nativeScale", "(JF)V", (void*)android_view_MotionEvent_nativeScale},
873 {"nativeGetSurfaceRotation", "(J)I",
874 (void*)android_view_MotionEvent_nativeGetSurfaceRotation},
875 };
876
register_android_view_MotionEvent(JNIEnv * env)877 int register_android_view_MotionEvent(JNIEnv* env) {
878 int res = RegisterMethodsOrDie(env, "android/view/MotionEvent", gMotionEventMethods,
879 NELEM(gMotionEventMethods));
880
881 gMotionEventClassInfo.clazz = FindClassOrDie(env, "android/view/MotionEvent");
882 gMotionEventClassInfo.clazz = MakeGlobalRefOrDie(env, gMotionEventClassInfo.clazz);
883
884 gMotionEventClassInfo.obtain = GetStaticMethodIDOrDie(env, gMotionEventClassInfo.clazz,
885 "obtain", "()Landroid/view/MotionEvent;");
886 gMotionEventClassInfo.recycle = GetMethodIDOrDie(env, gMotionEventClassInfo.clazz,
887 "recycle", "()V");
888 gMotionEventClassInfo.mNativePtr = GetFieldIDOrDie(env, gMotionEventClassInfo.clazz,
889 "mNativePtr", "J");
890
891 jclass clazz = FindClassOrDie(env, "android/view/MotionEvent$PointerCoords");
892
893 gPointerCoordsClassInfo.mPackedAxisBits = GetFieldIDOrDie(env, clazz, "mPackedAxisBits", "J");
894 gPointerCoordsClassInfo.mPackedAxisValues = GetFieldIDOrDie(env, clazz, "mPackedAxisValues",
895 "[F");
896 gPointerCoordsClassInfo.x = GetFieldIDOrDie(env, clazz, "x", "F");
897 gPointerCoordsClassInfo.y = GetFieldIDOrDie(env, clazz, "y", "F");
898 gPointerCoordsClassInfo.pressure = GetFieldIDOrDie(env, clazz, "pressure", "F");
899 gPointerCoordsClassInfo.size = GetFieldIDOrDie(env, clazz, "size", "F");
900 gPointerCoordsClassInfo.touchMajor = GetFieldIDOrDie(env, clazz, "touchMajor", "F");
901 gPointerCoordsClassInfo.touchMinor = GetFieldIDOrDie(env, clazz, "touchMinor", "F");
902 gPointerCoordsClassInfo.toolMajor = GetFieldIDOrDie(env, clazz, "toolMajor", "F");
903 gPointerCoordsClassInfo.toolMinor = GetFieldIDOrDie(env, clazz, "toolMinor", "F");
904 gPointerCoordsClassInfo.orientation = GetFieldIDOrDie(env, clazz, "orientation", "F");
905 gPointerCoordsClassInfo.relativeX = GetFieldIDOrDie(env, clazz, "relativeX", "F");
906 gPointerCoordsClassInfo.relativeY = GetFieldIDOrDie(env, clazz, "relativeY", "F");
907 gPointerCoordsClassInfo.isResampled = GetFieldIDOrDie(env, clazz, "isResampled", "Z");
908
909 clazz = FindClassOrDie(env, "android/view/MotionEvent$PointerProperties");
910
911 gPointerPropertiesClassInfo.id = GetFieldIDOrDie(env, clazz, "id", "I");
912 gPointerPropertiesClassInfo.toolType = GetFieldIDOrDie(env, clazz, "toolType", "I");
913
914 return res;
915 }
916
917 } // namespace android
918