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