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