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