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 <SkMatrix.h>
22 #include <android_runtime/AndroidRuntime.h>
23 #include <android_runtime/Log.h>
24 #include <utils/Log.h>
25 #include <input/Input.h>
26 #include <nativehelper/ScopedUtfChars.h>
27 #include "android_os_Parcel.h"
28 #include "android_view_MotionEvent.h"
29 #include "android_util_Binder.h"
30 #include "android/graphics/Matrix.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,float xOffset,float yOffset,jobject outPointerCoordsObj)258 static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointerCoords,
259 float xOffset, float yOffset, jobject outPointerCoordsObj) {
260 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.x,
261 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_X) + xOffset);
262 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.y,
263 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_Y) + yOffset);
264 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.pressure,
265 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
266 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.size,
267 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_SIZE));
268 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMajor,
269 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR));
270 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMinor,
271 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR));
272 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMajor,
273 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR));
274 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMinor,
275 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR));
276 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.orientation,
277 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
278
279 uint64_t outBits = 0;
280 BitSet64 bits = BitSet64(rawPointerCoords->bits);
281 bits.clearBit(AMOTION_EVENT_AXIS_X);
282 bits.clearBit(AMOTION_EVENT_AXIS_Y);
283 bits.clearBit(AMOTION_EVENT_AXIS_PRESSURE);
284 bits.clearBit(AMOTION_EVENT_AXIS_SIZE);
285 bits.clearBit(AMOTION_EVENT_AXIS_TOUCH_MAJOR);
286 bits.clearBit(AMOTION_EVENT_AXIS_TOUCH_MINOR);
287 bits.clearBit(AMOTION_EVENT_AXIS_TOOL_MAJOR);
288 bits.clearBit(AMOTION_EVENT_AXIS_TOOL_MINOR);
289 bits.clearBit(AMOTION_EVENT_AXIS_ORIENTATION);
290 if (!bits.isEmpty()) {
291 uint32_t packedAxesCount = bits.count();
292 jfloatArray outValuesArray = obtainPackedAxisValuesArray(env, packedAxesCount,
293 outPointerCoordsObj);
294 if (!outValuesArray) {
295 return; // OOM
296 }
297
298 jfloat* outValues = static_cast<jfloat*>(env->GetPrimitiveArrayCritical(
299 outValuesArray, NULL));
300
301 uint32_t index = 0;
302 do {
303 uint32_t axis = bits.clearFirstMarkedBit();
304 outBits |= BitSet64::valueForBit(axis);
305 outValues[index++] = rawPointerCoords->getAxisValue(axis);
306 } while (!bits.isEmpty());
307
308 env->ReleasePrimitiveArrayCritical(outValuesArray, outValues, 0);
309 env->DeleteLocalRef(outValuesArray);
310 }
311 env->SetLongField(outPointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits, outBits);
312 }
313
pointerPropertiesToNative(JNIEnv * env,jobject pointerPropertiesObj,PointerProperties * outPointerProperties)314 static void pointerPropertiesToNative(JNIEnv* env, jobject pointerPropertiesObj,
315 PointerProperties* outPointerProperties) {
316 outPointerProperties->clear();
317 outPointerProperties->id = env->GetIntField(pointerPropertiesObj,
318 gPointerPropertiesClassInfo.id);
319 outPointerProperties->toolType = env->GetIntField(pointerPropertiesObj,
320 gPointerPropertiesClassInfo.toolType);
321 }
322
pointerPropertiesFromNative(JNIEnv * env,const PointerProperties * pointerProperties,jobject outPointerPropertiesObj)323 static void pointerPropertiesFromNative(JNIEnv* env, const PointerProperties* pointerProperties,
324 jobject outPointerPropertiesObj) {
325 env->SetIntField(outPointerPropertiesObj, gPointerPropertiesClassInfo.id,
326 pointerProperties->id);
327 env->SetIntField(outPointerPropertiesObj, gPointerPropertiesClassInfo.toolType,
328 pointerProperties->toolType);
329 }
330
331
332 // ----------------------------------------------------------------------------
333
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)334 static jlong android_view_MotionEvent_nativeInitialize(JNIEnv* env, jclass clazz,
335 jlong nativePtr,
336 jint deviceId, jint source, jint displayId, jint action, jint flags, jint edgeFlags,
337 jint metaState, jint buttonState, jint classification,
338 jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision,
339 jlong downTimeNanos, jlong eventTimeNanos,
340 jint pointerCount, jobjectArray pointerPropertiesObjArray,
341 jobjectArray pointerCoordsObjArray) {
342 if (!validatePointerCount(env, pointerCount)
343 || !validatePointerPropertiesArray(env, pointerPropertiesObjArray, pointerCount)
344 || !validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
345 return 0;
346 }
347
348 MotionEvent* event;
349 if (nativePtr) {
350 event = reinterpret_cast<MotionEvent*>(nativePtr);
351 } else {
352 event = new 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 goto Error;
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 goto Error;
370 }
371 pointerCoordsToNative(env, pointerCoordsObj, xOffset, yOffset, &rawPointerCoords[i]);
372 env->DeleteLocalRef(pointerCoordsObj);
373 }
374
375 event->initialize(deviceId, source, displayId, action, 0, flags, edgeFlags, metaState,
376 buttonState, static_cast<MotionClassification>(classification),
377 xOffset, yOffset, xPrecision, yPrecision,
378 downTimeNanos, eventTimeNanos, pointerCount, pointerProperties, rawPointerCoords);
379
380 return reinterpret_cast<jlong>(event);
381
382 Error:
383 if (!nativePtr) {
384 delete event;
385 }
386 return 0;
387 }
388
android_view_MotionEvent_nativeDispose(JNIEnv * env,jclass clazz,jlong nativePtr)389 static void android_view_MotionEvent_nativeDispose(JNIEnv* env, jclass clazz,
390 jlong nativePtr) {
391 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
392 delete event;
393 }
394
android_view_MotionEvent_nativeAddBatch(JNIEnv * env,jclass clazz,jlong nativePtr,jlong eventTimeNanos,jobjectArray pointerCoordsObjArray,jint metaState)395 static void android_view_MotionEvent_nativeAddBatch(JNIEnv* env, jclass clazz,
396 jlong nativePtr, jlong eventTimeNanos, jobjectArray pointerCoordsObjArray,
397 jint metaState) {
398 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
399 size_t pointerCount = event->getPointerCount();
400 if (!validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
401 return;
402 }
403
404 PointerCoords rawPointerCoords[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 pointerCoordsToNative(env, pointerCoordsObj,
413 event->getXOffset(), event->getYOffset(), &rawPointerCoords[i]);
414 env->DeleteLocalRef(pointerCoordsObj);
415 }
416
417 event->addSample(eventTimeNanos, rawPointerCoords);
418 event->setMetaState(event->getMetaState() | metaState);
419 }
420
android_view_MotionEvent_nativeGetPointerCoords(JNIEnv * env,jclass clazz,jlong nativePtr,jint pointerIndex,jint historyPos,jobject outPointerCoordsObj)421 static void android_view_MotionEvent_nativeGetPointerCoords(JNIEnv* env, jclass clazz,
422 jlong nativePtr, jint pointerIndex, jint historyPos, jobject outPointerCoordsObj) {
423 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
424 size_t pointerCount = event->getPointerCount();
425 if (!validatePointerIndex(env, pointerIndex, pointerCount)
426 || !validatePointerCoords(env, outPointerCoordsObj)) {
427 return;
428 }
429
430 const PointerCoords* rawPointerCoords;
431 if (historyPos == HISTORY_CURRENT) {
432 rawPointerCoords = event->getRawPointerCoords(pointerIndex);
433 } else {
434 size_t historySize = event->getHistorySize();
435 if (!validateHistoryPos(env, historyPos, historySize)) {
436 return;
437 }
438 rawPointerCoords = event->getHistoricalRawPointerCoords(pointerIndex, historyPos);
439 }
440 pointerCoordsFromNative(env, rawPointerCoords, event->getXOffset(), event->getYOffset(),
441 outPointerCoordsObj);
442 }
443
android_view_MotionEvent_nativeGetPointerProperties(JNIEnv * env,jclass clazz,jlong nativePtr,jint pointerIndex,jobject outPointerPropertiesObj)444 static void android_view_MotionEvent_nativeGetPointerProperties(JNIEnv* env, jclass clazz,
445 jlong nativePtr, jint pointerIndex, jobject outPointerPropertiesObj) {
446 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
447 size_t pointerCount = event->getPointerCount();
448 if (!validatePointerIndex(env, pointerIndex, pointerCount)
449 || !validatePointerProperties(env, outPointerPropertiesObj)) {
450 return;
451 }
452
453 const PointerProperties* pointerProperties = event->getPointerProperties(pointerIndex);
454 pointerPropertiesFromNative(env, pointerProperties, outPointerPropertiesObj);
455 }
456
android_view_MotionEvent_nativeReadFromParcel(JNIEnv * env,jclass clazz,jlong nativePtr,jobject parcelObj)457 static jlong android_view_MotionEvent_nativeReadFromParcel(JNIEnv* env, jclass clazz,
458 jlong nativePtr, jobject parcelObj) {
459 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
460 if (!event) {
461 event = new MotionEvent();
462 }
463
464 Parcel* parcel = parcelForJavaObject(env, parcelObj);
465
466 status_t status = event->readFromParcel(parcel);
467 if (status) {
468 if (!nativePtr) {
469 delete event;
470 }
471 jniThrowRuntimeException(env, "Failed to read MotionEvent parcel.");
472 return 0;
473 }
474 return reinterpret_cast<jlong>(event);
475 }
476
android_view_MotionEvent_nativeWriteToParcel(JNIEnv * env,jclass clazz,jlong nativePtr,jobject parcelObj)477 static void android_view_MotionEvent_nativeWriteToParcel(JNIEnv* env, jclass clazz,
478 jlong nativePtr, jobject parcelObj) {
479 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
480 Parcel* parcel = parcelForJavaObject(env, parcelObj);
481
482 status_t status = event->writeToParcel(parcel);
483 if (status) {
484 jniThrowRuntimeException(env, "Failed to write MotionEvent parcel.");
485 }
486 }
487
android_view_MotionEvent_nativeAxisToString(JNIEnv * env,jclass clazz,jint axis)488 static jstring android_view_MotionEvent_nativeAxisToString(JNIEnv* env, jclass clazz,
489 jint axis) {
490 return env->NewStringUTF(MotionEvent::getLabel(static_cast<int32_t>(axis)));
491 }
492
android_view_MotionEvent_nativeAxisFromString(JNIEnv * env,jclass clazz,jstring label)493 static jint android_view_MotionEvent_nativeAxisFromString(JNIEnv* env, jclass clazz,
494 jstring label) {
495 ScopedUtfChars axisLabel(env, label);
496 return static_cast<jint>(MotionEvent::getAxisFromLabel(axisLabel.c_str()));
497 }
498
499 // ---------------- @FastNative ----------------------------------
500
android_view_MotionEvent_nativeGetPointerId(JNIEnv * env,jclass clazz,jlong nativePtr,jint pointerIndex)501 static jint android_view_MotionEvent_nativeGetPointerId(JNIEnv* env, jclass clazz,
502 jlong nativePtr, jint pointerIndex) {
503 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
504 size_t pointerCount = event->getPointerCount();
505 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
506 return -1;
507 }
508 return event->getPointerId(pointerIndex);
509 }
510
android_view_MotionEvent_nativeGetToolType(JNIEnv * env,jclass clazz,jlong nativePtr,jint pointerIndex)511 static jint android_view_MotionEvent_nativeGetToolType(JNIEnv* env, jclass clazz,
512 jlong nativePtr, jint pointerIndex) {
513 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
514 size_t pointerCount = event->getPointerCount();
515 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
516 return -1;
517 }
518 return event->getToolType(pointerIndex);
519 }
520
android_view_MotionEvent_nativeGetEventTimeNanos(JNIEnv * env,jclass clazz,jlong nativePtr,jint historyPos)521 static jlong android_view_MotionEvent_nativeGetEventTimeNanos(JNIEnv* env, jclass clazz,
522 jlong nativePtr, jint historyPos) {
523 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
524 if (historyPos == HISTORY_CURRENT) {
525 return event->getEventTime();
526 } else {
527 size_t historySize = event->getHistorySize();
528 if (!validateHistoryPos(env, historyPos, historySize)) {
529 return 0;
530 }
531 return event->getHistoricalEventTime(historyPos);
532 }
533 }
534
android_view_MotionEvent_nativeGetRawAxisValue(JNIEnv * env,jclass clazz,jlong nativePtr,jint axis,jint pointerIndex,jint historyPos)535 static jfloat android_view_MotionEvent_nativeGetRawAxisValue(JNIEnv* env, jclass clazz,
536 jlong nativePtr, jint axis,
537 jint pointerIndex, jint historyPos) {
538 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
539 size_t pointerCount = event->getPointerCount();
540 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
541 return 0;
542 }
543
544 if (historyPos == HISTORY_CURRENT) {
545 return event->getRawAxisValue(axis, pointerIndex);
546 } else {
547 size_t historySize = event->getHistorySize();
548 if (!validateHistoryPos(env, historyPos, historySize)) {
549 return 0;
550 }
551 return event->getHistoricalRawAxisValue(axis, pointerIndex, historyPos);
552 }
553 }
554
android_view_MotionEvent_nativeGetAxisValue(JNIEnv * env,jclass clazz,jlong nativePtr,jint axis,jint pointerIndex,jint historyPos)555 static jfloat android_view_MotionEvent_nativeGetAxisValue(JNIEnv* env, jclass clazz,
556 jlong nativePtr, jint axis, jint pointerIndex, jint historyPos) {
557 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
558 size_t pointerCount = event->getPointerCount();
559 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
560 return 0;
561 }
562
563 if (historyPos == HISTORY_CURRENT) {
564 return event->getAxisValue(axis, pointerIndex);
565 } else {
566 size_t historySize = event->getHistorySize();
567 if (!validateHistoryPos(env, historyPos, historySize)) {
568 return 0;
569 }
570 return event->getHistoricalAxisValue(axis, pointerIndex, historyPos);
571 }
572 }
573
574 // ----------------- @CriticalNative ------------------------------
575
android_view_MotionEvent_nativeCopy(jlong destNativePtr,jlong sourceNativePtr,jboolean keepHistory)576 static jlong android_view_MotionEvent_nativeCopy(jlong destNativePtr, jlong sourceNativePtr,
577 jboolean keepHistory) {
578 MotionEvent* destEvent = reinterpret_cast<MotionEvent*>(destNativePtr);
579 if (!destEvent) {
580 destEvent = new MotionEvent();
581 }
582 MotionEvent* sourceEvent = reinterpret_cast<MotionEvent*>(sourceNativePtr);
583 destEvent->copyFrom(sourceEvent, keepHistory);
584 return reinterpret_cast<jlong>(destEvent);
585 }
586
android_view_MotionEvent_nativeGetDeviceId(jlong nativePtr)587 static jint android_view_MotionEvent_nativeGetDeviceId(jlong nativePtr) {
588 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
589 return event->getDeviceId();
590 }
591
android_view_MotionEvent_nativeGetSource(jlong nativePtr)592 static jint android_view_MotionEvent_nativeGetSource(jlong nativePtr) {
593 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
594 return event->getSource();
595 }
596
android_view_MotionEvent_nativeSetSource(jlong nativePtr,jint source)597 static void android_view_MotionEvent_nativeSetSource(jlong nativePtr, jint source) {
598 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
599 event->setSource(source);
600 }
601
android_view_MotionEvent_nativeGetDisplayId(jlong nativePtr)602 static jint android_view_MotionEvent_nativeGetDisplayId(jlong nativePtr) {
603 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
604 return event->getDisplayId();
605 }
606
android_view_MotionEvent_nativeSetDisplayId(jlong nativePtr,jint displayId)607 static void android_view_MotionEvent_nativeSetDisplayId(jlong nativePtr, jint displayId) {
608 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
609 return event->setDisplayId(displayId);
610 }
611
android_view_MotionEvent_nativeGetAction(jlong nativePtr)612 static jint android_view_MotionEvent_nativeGetAction(jlong nativePtr) {
613 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
614 return event->getAction();
615 }
616
android_view_MotionEvent_nativeSetAction(jlong nativePtr,jint action)617 static void android_view_MotionEvent_nativeSetAction(jlong nativePtr, jint action) {
618 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
619 event->setAction(action);
620 }
621
android_view_MotionEvent_nativeGetActionButton(jlong nativePtr)622 static int android_view_MotionEvent_nativeGetActionButton(jlong nativePtr) {
623 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
624 return event->getActionButton();
625 }
626
android_view_MotionEvent_nativeSetActionButton(jlong nativePtr,jint button)627 static void android_view_MotionEvent_nativeSetActionButton(jlong nativePtr, jint button) {
628 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
629 event->setActionButton(button);
630 }
631
android_view_MotionEvent_nativeIsTouchEvent(jlong nativePtr)632 static jboolean android_view_MotionEvent_nativeIsTouchEvent(jlong nativePtr) {
633 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
634 return event->isTouchEvent();
635 }
636
android_view_MotionEvent_nativeGetFlags(jlong nativePtr)637 static jint android_view_MotionEvent_nativeGetFlags(jlong nativePtr) {
638 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
639 return event->getFlags();
640 }
641
android_view_MotionEvent_nativeSetFlags(jlong nativePtr,jint flags)642 static void android_view_MotionEvent_nativeSetFlags(jlong nativePtr, jint flags) {
643 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
644 event->setFlags(flags);
645 }
646
android_view_MotionEvent_nativeGetEdgeFlags(jlong nativePtr)647 static jint android_view_MotionEvent_nativeGetEdgeFlags(jlong nativePtr) {
648 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
649 return event->getEdgeFlags();
650 }
651
android_view_MotionEvent_nativeSetEdgeFlags(jlong nativePtr,jint edgeFlags)652 static void android_view_MotionEvent_nativeSetEdgeFlags(jlong nativePtr, jint edgeFlags) {
653 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
654 event->setEdgeFlags(edgeFlags);
655 }
656
android_view_MotionEvent_nativeGetMetaState(jlong nativePtr)657 static jint android_view_MotionEvent_nativeGetMetaState(jlong nativePtr) {
658 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
659 return event->getMetaState();
660 }
661
android_view_MotionEvent_nativeGetButtonState(jlong nativePtr)662 static jint android_view_MotionEvent_nativeGetButtonState(jlong nativePtr) {
663 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
664 return event->getButtonState();
665 }
666
android_view_MotionEvent_nativeSetButtonState(jlong nativePtr,jint buttonState)667 static void android_view_MotionEvent_nativeSetButtonState(jlong nativePtr, jint buttonState) {
668 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
669 event->setButtonState(buttonState);
670 }
671
android_view_MotionEvent_nativeGetClassification(jlong nativePtr)672 static jint android_view_MotionEvent_nativeGetClassification(jlong nativePtr) {
673 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
674 return static_cast<jint>(event->getClassification());
675 }
676
android_view_MotionEvent_nativeOffsetLocation(jlong nativePtr,jfloat deltaX,jfloat deltaY)677 static void android_view_MotionEvent_nativeOffsetLocation(jlong nativePtr, jfloat deltaX,
678 jfloat deltaY) {
679 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
680 return event->offsetLocation(deltaX, deltaY);
681 }
682
android_view_MotionEvent_nativeGetXOffset(jlong nativePtr)683 static jfloat android_view_MotionEvent_nativeGetXOffset(jlong nativePtr) {
684 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
685 return event->getXOffset();
686 }
687
android_view_MotionEvent_nativeGetYOffset(jlong nativePtr)688 static jfloat android_view_MotionEvent_nativeGetYOffset(jlong nativePtr) {
689 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
690 return event->getYOffset();
691 }
692
android_view_MotionEvent_nativeGetXPrecision(jlong nativePtr)693 static jfloat android_view_MotionEvent_nativeGetXPrecision(jlong nativePtr) {
694 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
695 return event->getXPrecision();
696 }
697
android_view_MotionEvent_nativeGetYPrecision(jlong nativePtr)698 static jfloat android_view_MotionEvent_nativeGetYPrecision(jlong nativePtr) {
699 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
700 return event->getYPrecision();
701 }
702
android_view_MotionEvent_nativeGetDownTimeNanos(jlong nativePtr)703 static jlong android_view_MotionEvent_nativeGetDownTimeNanos(jlong nativePtr) {
704 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
705 return event->getDownTime();
706 }
707
android_view_MotionEvent_nativeSetDownTimeNanos(jlong nativePtr,jlong downTimeNanos)708 static void android_view_MotionEvent_nativeSetDownTimeNanos(jlong nativePtr, jlong downTimeNanos) {
709 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
710 event->setDownTime(downTimeNanos);
711 }
712
android_view_MotionEvent_nativeGetPointerCount(jlong nativePtr)713 static jint android_view_MotionEvent_nativeGetPointerCount(jlong nativePtr) {
714 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
715 return jint(event->getPointerCount());
716 }
717
android_view_MotionEvent_nativeFindPointerIndex(jlong nativePtr,jint pointerId)718 static jint android_view_MotionEvent_nativeFindPointerIndex(jlong nativePtr, jint pointerId) {
719 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
720 return jint(event->findPointerIndex(pointerId));
721 }
722
android_view_MotionEvent_nativeGetHistorySize(jlong nativePtr)723 static jint android_view_MotionEvent_nativeGetHistorySize(jlong nativePtr) {
724 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
725 return jint(event->getHistorySize());
726 }
727
android_view_MotionEvent_nativeScale(jlong nativePtr,jfloat scale)728 static void android_view_MotionEvent_nativeScale(jlong nativePtr, jfloat scale) {
729 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
730 event->scale(scale);
731 }
732
android_view_MotionEvent_nativeTransform(jlong nativePtr,jlong matrixPtr)733 static void android_view_MotionEvent_nativeTransform(jlong nativePtr, jlong matrixPtr) {
734 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
735 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
736
737 static_assert(SkMatrix::kMScaleX == 0, "SkMatrix unexpected index");
738 static_assert(SkMatrix::kMSkewX == 1, "SkMatrix unexpected index");
739 static_assert(SkMatrix::kMTransX == 2, "SkMatrix unexpected index");
740 static_assert(SkMatrix::kMSkewY == 3, "SkMatrix unexpected index");
741 static_assert(SkMatrix::kMScaleY == 4, "SkMatrix unexpected index");
742 static_assert(SkMatrix::kMTransY == 5, "SkMatrix unexpected index");
743 static_assert(SkMatrix::kMPersp0 == 6, "SkMatrix unexpected index");
744 static_assert(SkMatrix::kMPersp1 == 7, "SkMatrix unexpected index");
745 static_assert(SkMatrix::kMPersp2 == 8, "SkMatrix unexpected index");
746 float m[9];
747 matrix->get9(m);
748 event->transform(m);
749 }
750
751 // ----------------------------------------------------------------------------
752
753 static const JNINativeMethod gMotionEventMethods[] = {
754 /* name, signature, funcPtr */
755 { "nativeInitialize",
756 "(JIIIIIIIIIFFFFJJI[Landroid/view/MotionEvent$PointerProperties;"
757 "[Landroid/view/MotionEvent$PointerCoords;)J",
758 (void*)android_view_MotionEvent_nativeInitialize },
759 { "nativeDispose",
760 "(J)V",
761 (void*)android_view_MotionEvent_nativeDispose },
762 { "nativeAddBatch",
763 "(JJ[Landroid/view/MotionEvent$PointerCoords;I)V",
764 (void*)android_view_MotionEvent_nativeAddBatch },
765 { "nativeReadFromParcel",
766 "(JLandroid/os/Parcel;)J",
767 (void*)android_view_MotionEvent_nativeReadFromParcel },
768 { "nativeWriteToParcel",
769 "(JLandroid/os/Parcel;)V",
770 (void*)android_view_MotionEvent_nativeWriteToParcel },
771 { "nativeAxisToString", "(I)Ljava/lang/String;",
772 (void*)android_view_MotionEvent_nativeAxisToString },
773 { "nativeAxisFromString", "(Ljava/lang/String;)I",
774 (void*)android_view_MotionEvent_nativeAxisFromString },
775 { "nativeGetPointerProperties",
776 "(JILandroid/view/MotionEvent$PointerProperties;)V",
777 (void*)android_view_MotionEvent_nativeGetPointerProperties },
778 { "nativeGetPointerCoords",
779 "(JIILandroid/view/MotionEvent$PointerCoords;)V",
780 (void*)android_view_MotionEvent_nativeGetPointerCoords },
781
782 // --------------- @FastNative ----------------------
783 { "nativeGetPointerId",
784 "(JI)I",
785 (void*)android_view_MotionEvent_nativeGetPointerId },
786 { "nativeGetToolType",
787 "(JI)I",
788 (void*)android_view_MotionEvent_nativeGetToolType },
789 { "nativeGetEventTimeNanos",
790 "(JI)J",
791 (void*)android_view_MotionEvent_nativeGetEventTimeNanos },
792 { "nativeGetRawAxisValue",
793 "(JIII)F",
794 (void*)android_view_MotionEvent_nativeGetRawAxisValue },
795 { "nativeGetAxisValue",
796 "(JIII)F",
797 (void*)android_view_MotionEvent_nativeGetAxisValue },
798
799 // --------------- @CriticalNative ------------------
800
801 { "nativeCopy",
802 "(JJZ)J",
803 (void*)android_view_MotionEvent_nativeCopy },
804 { "nativeGetDeviceId",
805 "(J)I",
806 (void*)android_view_MotionEvent_nativeGetDeviceId },
807 { "nativeGetSource",
808 "(J)I",
809 (void*)android_view_MotionEvent_nativeGetSource },
810 { "nativeSetSource",
811 "(JI)V",
812 (void*)android_view_MotionEvent_nativeSetSource },
813 { "nativeGetDisplayId",
814 "(J)I",
815 (void*)android_view_MotionEvent_nativeGetDisplayId },
816 { "nativeSetDisplayId",
817 "(JI)V",
818 (void*)android_view_MotionEvent_nativeSetDisplayId },
819 { "nativeGetAction",
820 "(J)I",
821 (void*)android_view_MotionEvent_nativeGetAction },
822 { "nativeSetAction",
823 "(JI)V",
824 (void*)android_view_MotionEvent_nativeSetAction },
825 { "nativeGetActionButton",
826 "(J)I",
827 (void*)android_view_MotionEvent_nativeGetActionButton},
828 { "nativeSetActionButton",
829 "(JI)V",
830 (void*)android_view_MotionEvent_nativeSetActionButton},
831 { "nativeIsTouchEvent",
832 "(J)Z",
833 (void*)android_view_MotionEvent_nativeIsTouchEvent },
834 { "nativeGetFlags",
835 "(J)I",
836 (void*)android_view_MotionEvent_nativeGetFlags },
837 { "nativeSetFlags",
838 "(JI)V",
839 (void*)android_view_MotionEvent_nativeSetFlags },
840 { "nativeGetEdgeFlags",
841 "(J)I",
842 (void*)android_view_MotionEvent_nativeGetEdgeFlags },
843 { "nativeSetEdgeFlags",
844 "(JI)V",
845 (void*)android_view_MotionEvent_nativeSetEdgeFlags },
846 { "nativeGetMetaState",
847 "(J)I",
848 (void*)android_view_MotionEvent_nativeGetMetaState },
849 { "nativeGetButtonState",
850 "(J)I",
851 (void*)android_view_MotionEvent_nativeGetButtonState },
852 { "nativeSetButtonState",
853 "(JI)V",
854 (void*)android_view_MotionEvent_nativeSetButtonState },
855 { "nativeGetClassification",
856 "(J)I",
857 (void*)android_view_MotionEvent_nativeGetClassification },
858 { "nativeOffsetLocation",
859 "(JFF)V",
860 (void*)android_view_MotionEvent_nativeOffsetLocation },
861 { "nativeGetXOffset",
862 "(J)F",
863 (void*)android_view_MotionEvent_nativeGetXOffset },
864 { "nativeGetYOffset",
865 "(J)F",
866 (void*)android_view_MotionEvent_nativeGetYOffset },
867 { "nativeGetXPrecision",
868 "(J)F",
869 (void*)android_view_MotionEvent_nativeGetXPrecision },
870 { "nativeGetYPrecision",
871 "(J)F",
872 (void*)android_view_MotionEvent_nativeGetYPrecision },
873 { "nativeGetDownTimeNanos",
874 "(J)J",
875 (void*)android_view_MotionEvent_nativeGetDownTimeNanos },
876 { "nativeSetDownTimeNanos",
877 "(JJ)V",
878 (void*)android_view_MotionEvent_nativeSetDownTimeNanos },
879 { "nativeGetPointerCount",
880 "(J)I",
881 (void*)android_view_MotionEvent_nativeGetPointerCount },
882 { "nativeFindPointerIndex",
883 "(JI)I",
884 (void*)android_view_MotionEvent_nativeFindPointerIndex },
885 { "nativeGetHistorySize",
886 "(J)I",
887 (void*)android_view_MotionEvent_nativeGetHistorySize },
888 { "nativeScale",
889 "(JF)V",
890 (void*)android_view_MotionEvent_nativeScale },
891 { "nativeTransform",
892 "(JJ)V",
893 (void*)android_view_MotionEvent_nativeTransform },
894 };
895
register_android_view_MotionEvent(JNIEnv * env)896 int register_android_view_MotionEvent(JNIEnv* env) {
897 int res = RegisterMethodsOrDie(env, "android/view/MotionEvent", gMotionEventMethods,
898 NELEM(gMotionEventMethods));
899
900 gMotionEventClassInfo.clazz = FindClassOrDie(env, "android/view/MotionEvent");
901 gMotionEventClassInfo.clazz = MakeGlobalRefOrDie(env, gMotionEventClassInfo.clazz);
902
903 gMotionEventClassInfo.obtain = GetStaticMethodIDOrDie(env, gMotionEventClassInfo.clazz,
904 "obtain", "()Landroid/view/MotionEvent;");
905 gMotionEventClassInfo.recycle = GetMethodIDOrDie(env, gMotionEventClassInfo.clazz,
906 "recycle", "()V");
907 gMotionEventClassInfo.mNativePtr = GetFieldIDOrDie(env, gMotionEventClassInfo.clazz,
908 "mNativePtr", "J");
909
910 jclass clazz = FindClassOrDie(env, "android/view/MotionEvent$PointerCoords");
911
912 gPointerCoordsClassInfo.mPackedAxisBits = GetFieldIDOrDie(env, clazz, "mPackedAxisBits", "J");
913 gPointerCoordsClassInfo.mPackedAxisValues = GetFieldIDOrDie(env, clazz, "mPackedAxisValues",
914 "[F");
915 gPointerCoordsClassInfo.x = GetFieldIDOrDie(env, clazz, "x", "F");
916 gPointerCoordsClassInfo.y = GetFieldIDOrDie(env, clazz, "y", "F");
917 gPointerCoordsClassInfo.pressure = GetFieldIDOrDie(env, clazz, "pressure", "F");
918 gPointerCoordsClassInfo.size = GetFieldIDOrDie(env, clazz, "size", "F");
919 gPointerCoordsClassInfo.touchMajor = GetFieldIDOrDie(env, clazz, "touchMajor", "F");
920 gPointerCoordsClassInfo.touchMinor = GetFieldIDOrDie(env, clazz, "touchMinor", "F");
921 gPointerCoordsClassInfo.toolMajor = GetFieldIDOrDie(env, clazz, "toolMajor", "F");
922 gPointerCoordsClassInfo.toolMinor = GetFieldIDOrDie(env, clazz, "toolMinor", "F");
923 gPointerCoordsClassInfo.orientation = GetFieldIDOrDie(env, clazz, "orientation", "F");
924
925 clazz = FindClassOrDie(env, "android/view/MotionEvent$PointerProperties");
926
927 gPointerPropertiesClassInfo.id = GetFieldIDOrDie(env, clazz, "id", "I");
928 gPointerPropertiesClassInfo.toolType = GetFieldIDOrDie(env, clazz, "toolType", "I");
929
930 return res;
931 }
932
933 } // namespace android
934