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