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