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