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