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