2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "MotionEvent-JNI"
22 #include <android_runtime/AndroidRuntime.h>
23 #include <utils/Log.h>
24 #include <input/Input.h>
25 #include "android_os_Parcel.h"
26 #include "android_view_MotionEvent.h"
27 #include "android_util_Binder.h"
28 #include "android/graphics/Matrix.h"
32 // ----------------------------------------------------------------------------
41 } gMotionEventClassInfo;
44 jfieldID mPackedAxisBits;
45 jfieldID mPackedAxisValues;
55 } gPointerCoordsClassInfo;
60 } gPointerPropertiesClassInfo;
62 // ----------------------------------------------------------------------------
64 MotionEvent* android_view_MotionEvent_getNativePtr(JNIEnv* env, jobject eventObj) {
68 return reinterpret_cast<MotionEvent*>(
69 env->GetIntField(eventObj, gMotionEventClassInfo.mNativePtr));
72 static void android_view_MotionEvent_setNativePtr(JNIEnv* env, jobject eventObj,
74 env->SetIntField(eventObj, gMotionEventClassInfo.mNativePtr,
75 reinterpret_cast<int>(event));
78 jobject android_view_MotionEvent_obtainAsCopy(JNIEnv* env, const MotionEvent* event) {
79 jobject eventObj = env->CallStaticObjectMethod(gMotionEventClassInfo.clazz,
80 gMotionEventClassInfo.obtain);
81 if (env->ExceptionCheck() || !eventObj) {
82 ALOGE("An exception occurred while obtaining a motion event.");
84 env->ExceptionClear();
88 MotionEvent* destEvent = android_view_MotionEvent_getNativePtr(env, eventObj);
90 destEvent = new MotionEvent();
91 android_view_MotionEvent_setNativePtr(env, eventObj, destEvent);
94 destEvent->copyFrom(event, true);
98 status_t android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj) {
99 env->CallVoidMethod(eventObj, gMotionEventClassInfo.recycle);
100 if (env->ExceptionCheck()) {
101 ALOGW("An exception occurred while recycling a motion event.");
103 env->ExceptionClear();
104 return UNKNOWN_ERROR;
109 // ----------------------------------------------------------------------------
111 static const jint HISTORY_CURRENT = -0x80000000;
113 static bool validatePointerCount(JNIEnv* env, jint pointerCount) {
114 if (pointerCount < 1) {
115 jniThrowException(env, "java/lang/IllegalArgumentException",
116 "pointerCount must be at least 1");
122 static bool validatePointerPropertiesArray(JNIEnv* env, jobjectArray pointerPropertiesObjArray,
123 size_t pointerCount) {
124 if (!pointerPropertiesObjArray) {
125 jniThrowException(env, "java/lang/IllegalArgumentException",
126 "pointerProperties array must not be null");
129 size_t length = size_t(env->GetArrayLength(pointerPropertiesObjArray));
130 if (length < pointerCount) {
131 jniThrowException(env, "java/lang/IllegalArgumentException",
132 "pointerProperties array must be large enough to hold all pointers");
138 static bool validatePointerCoordsObjArray(JNIEnv* env, jobjectArray pointerCoordsObjArray,
139 size_t pointerCount) {
140 if (!pointerCoordsObjArray) {
141 jniThrowException(env, "java/lang/IllegalArgumentException",
142 "pointerCoords array must not be null");
145 size_t length = size_t(env->GetArrayLength(pointerCoordsObjArray));
146 if (length < pointerCount) {
147 jniThrowException(env, "java/lang/IllegalArgumentException",
148 "pointerCoords array must be large enough to hold all pointers");
154 static bool validatePointerIndex(JNIEnv* env, jint pointerIndex, size_t pointerCount) {
155 if (pointerIndex < 0 || size_t(pointerIndex) >= pointerCount) {
156 jniThrowException(env, "java/lang/IllegalArgumentException",
157 "pointerIndex out of range");
163 static bool validateHistoryPos(JNIEnv* env, jint historyPos, size_t historySize) {
164 if (historyPos < 0 || size_t(historyPos) >= historySize) {
165 jniThrowException(env, "java/lang/IllegalArgumentException",
166 "historyPos out of range");
172 static bool validatePointerCoords(JNIEnv* env, jobject pointerCoordsObj) {
173 if (!pointerCoordsObj) {
174 jniThrowException(env, "java/lang/IllegalArgumentException",
175 "pointerCoords must not be null");
181 static bool validatePointerProperties(JNIEnv* env, jobject pointerPropertiesObj) {
182 if (!pointerPropertiesObj) {
183 jniThrowException(env, "java/lang/IllegalArgumentException",
184 "pointerProperties must not be null");
190 static void pointerCoordsToNative(JNIEnv* env, jobject pointerCoordsObj,
191 float xOffset, float yOffset, PointerCoords* outRawPointerCoords) {
192 outRawPointerCoords->clear();
193 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_X,
194 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.x) - xOffset);
195 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_Y,
196 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.y) - yOffset);
197 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
198 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.pressure));
199 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_SIZE,
200 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.size));
201 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
202 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMajor));
203 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR,
204 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMinor));
205 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR,
206 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMajor));
207 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR,
208 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMinor));
209 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
210 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.orientation));
212 uint64_t bits = env->GetLongField(pointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits);
214 jfloatArray valuesArray = jfloatArray(env->GetObjectField(pointerCoordsObj,
215 gPointerCoordsClassInfo.mPackedAxisValues));
217 jfloat* values = static_cast<jfloat*>(
218 env->GetPrimitiveArrayCritical(valuesArray, NULL));
222 uint32_t axis = __builtin_ctzll(bits);
223 uint64_t axisBit = 1LL << axis;
225 outRawPointerCoords->setAxisValue(axis, values[index++]);
228 env->ReleasePrimitiveArrayCritical(valuesArray, values, JNI_ABORT);
229 env->DeleteLocalRef(valuesArray);
234 static jfloatArray obtainPackedAxisValuesArray(JNIEnv* env, uint32_t minSize,
235 jobject outPointerCoordsObj) {
236 jfloatArray outValuesArray = jfloatArray(env->GetObjectField(outPointerCoordsObj,
237 gPointerCoordsClassInfo.mPackedAxisValues));
238 if (outValuesArray) {
239 uint32_t size = env->GetArrayLength(outValuesArray);
240 if (minSize <= size) {
241 return outValuesArray;
243 env->DeleteLocalRef(outValuesArray);
246 while (size < minSize) {
249 outValuesArray = env->NewFloatArray(size);
250 env->SetObjectField(outPointerCoordsObj,
251 gPointerCoordsClassInfo.mPackedAxisValues, outValuesArray);
252 return outValuesArray;
255 static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointerCoords,
256 float xOffset, float yOffset, jobject outPointerCoordsObj) {
257 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.x,
258 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_X) + xOffset);
259 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.y,
260 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_Y) + yOffset);
261 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.pressure,
262 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
263 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.size,
264 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_SIZE));
265 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMajor,
266 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR));
267 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMinor,
268 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR));
269 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMajor,
270 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR));
271 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMinor,
272 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR));
273 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.orientation,
274 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
276 const uint64_t unpackedAxisBits = 0
277 | (1LL << AMOTION_EVENT_AXIS_X)
278 | (1LL << AMOTION_EVENT_AXIS_Y)
279 | (1LL << AMOTION_EVENT_AXIS_PRESSURE)
280 | (1LL << AMOTION_EVENT_AXIS_SIZE)
281 | (1LL << AMOTION_EVENT_AXIS_TOUCH_MAJOR)
282 | (1LL << AMOTION_EVENT_AXIS_TOUCH_MINOR)
283 | (1LL << AMOTION_EVENT_AXIS_TOOL_MAJOR)
284 | (1LL << AMOTION_EVENT_AXIS_TOOL_MINOR)
285 | (1LL << AMOTION_EVENT_AXIS_ORIENTATION);
287 uint64_t outBits = 0;
288 uint64_t remainingBits = rawPointerCoords->bits & ~unpackedAxisBits;
290 uint32_t packedAxesCount = __builtin_popcountll(remainingBits);
291 jfloatArray outValuesArray = obtainPackedAxisValuesArray(env, packedAxesCount,
292 outPointerCoordsObj);
293 if (!outValuesArray) {
297 jfloat* outValues = static_cast<jfloat*>(env->GetPrimitiveArrayCritical(
298 outValuesArray, NULL));
300 const float* values = rawPointerCoords->values;
303 uint32_t axis = __builtin_ctzll(remainingBits);
304 uint64_t axisBit = 1LL << axis;
305 remainingBits &= ~axisBit;
307 outValues[index++] = rawPointerCoords->getAxisValue(axis);
308 } while (remainingBits);
310 env->ReleasePrimitiveArrayCritical(outValuesArray, outValues, 0);
311 env->DeleteLocalRef(outValuesArray);
313 env->SetLongField(outPointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits, outBits);
316 static void pointerPropertiesToNative(JNIEnv* env, jobject pointerPropertiesObj,
317 PointerProperties* outPointerProperties) {
318 outPointerProperties->clear();
319 outPointerProperties->id = env->GetIntField(pointerPropertiesObj,
320 gPointerPropertiesClassInfo.id);
321 outPointerProperties->toolType = env->GetIntField(pointerPropertiesObj,
322 gPointerPropertiesClassInfo.toolType);
325 static void pointerPropertiesFromNative(JNIEnv* env, const PointerProperties* pointerProperties,
326 jobject outPointerPropertiesObj) {
327 env->SetIntField(outPointerPropertiesObj, gPointerPropertiesClassInfo.id,
328 pointerProperties->id);
329 env->SetIntField(outPointerPropertiesObj, gPointerPropertiesClassInfo.toolType,
330 pointerProperties->toolType);
334 // ----------------------------------------------------------------------------
336 static jint android_view_MotionEvent_nativeInitialize(JNIEnv* env, jclass clazz,
338 jint deviceId, jint source, jint action, jint flags, jint edgeFlags,
339 jint metaState, jint buttonState,
340 jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision,
341 jlong downTimeNanos, jlong eventTimeNanos,
342 jint pointerCount, jobjectArray pointerPropertiesObjArray,
343 jobjectArray pointerCoordsObjArray) {
344 if (!validatePointerCount(env, pointerCount)
345 || !validatePointerPropertiesArray(env, pointerPropertiesObjArray, pointerCount)
346 || !validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
350 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
352 event = new MotionEvent();
355 PointerProperties pointerProperties[pointerCount];
356 PointerCoords rawPointerCoords[pointerCount];
358 for (jint i = 0; i < pointerCount; i++) {
359 jobject pointerPropertiesObj = env->GetObjectArrayElement(pointerPropertiesObjArray, i);
360 if (!pointerPropertiesObj) {
363 pointerPropertiesToNative(env, pointerPropertiesObj, &pointerProperties[i]);
364 env->DeleteLocalRef(pointerPropertiesObj);
366 jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
367 if (!pointerCoordsObj) {
368 jniThrowNullPointerException(env, "pointerCoords");
371 pointerCoordsToNative(env, pointerCoordsObj, xOffset, yOffset, &rawPointerCoords[i]);
372 env->DeleteLocalRef(pointerCoordsObj);
375 event->initialize(deviceId, source, action, flags, edgeFlags, metaState, buttonState,
376 xOffset, yOffset, xPrecision, yPrecision,
377 downTimeNanos, eventTimeNanos, pointerCount, pointerProperties, rawPointerCoords);
379 return reinterpret_cast<jint>(event);
388 static jint android_view_MotionEvent_nativeCopy(JNIEnv* env, jclass clazz,
389 jint destNativePtr, jint sourceNativePtr, jboolean keepHistory) {
390 MotionEvent* destEvent = reinterpret_cast<MotionEvent*>(destNativePtr);
392 destEvent = new MotionEvent();
394 MotionEvent* sourceEvent = reinterpret_cast<MotionEvent*>(sourceNativePtr);
395 destEvent->copyFrom(sourceEvent, keepHistory);
396 return reinterpret_cast<jint>(destEvent);
399 static void android_view_MotionEvent_nativeDispose(JNIEnv* env, jclass clazz,
401 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
405 static void android_view_MotionEvent_nativeAddBatch(JNIEnv* env, jclass clazz,
406 jint nativePtr, jlong eventTimeNanos, jobjectArray pointerCoordsObjArray,
408 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
409 size_t pointerCount = event->getPointerCount();
410 if (!validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
414 PointerCoords rawPointerCoords[pointerCount];
416 for (size_t i = 0; i < pointerCount; i++) {
417 jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
418 if (!pointerCoordsObj) {
419 jniThrowNullPointerException(env, "pointerCoords");
422 pointerCoordsToNative(env, pointerCoordsObj,
423 event->getXOffset(), event->getYOffset(), &rawPointerCoords[i]);
424 env->DeleteLocalRef(pointerCoordsObj);
427 event->addSample(eventTimeNanos, rawPointerCoords);
428 event->setMetaState(event->getMetaState() | metaState);
431 static jint android_view_MotionEvent_nativeGetDeviceId(JNIEnv* env, jclass clazz,
433 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
434 return event->getDeviceId();
437 static jint android_view_MotionEvent_nativeGetSource(JNIEnv* env, jclass clazz,
439 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
440 return event->getSource();
443 static void android_view_MotionEvent_nativeSetSource(JNIEnv* env, jclass clazz,
444 jint nativePtr, jint source) {
445 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
446 event->setSource(source);
449 static jint android_view_MotionEvent_nativeGetAction(JNIEnv* env, jclass clazz,
451 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
452 return event->getAction();
455 static void android_view_MotionEvent_nativeSetAction(JNIEnv* env, jclass clazz,
456 jint nativePtr, jint action) {
457 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
458 event->setAction(action);
461 static jboolean android_view_MotionEvent_nativeIsTouchEvent(JNIEnv* env, jclass clazz,
463 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
464 return event->isTouchEvent();
467 static jint android_view_MotionEvent_nativeGetFlags(JNIEnv* env, jclass clazz,
469 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
470 return event->getFlags();
473 static void android_view_MotionEvent_nativeSetFlags(JNIEnv* env, jclass clazz,
474 jint nativePtr, jint flags) {
475 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
476 event->setFlags(flags);
479 static jint android_view_MotionEvent_nativeGetEdgeFlags(JNIEnv* env, jclass clazz,
481 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
482 return event->getEdgeFlags();
485 static void android_view_MotionEvent_nativeSetEdgeFlags(JNIEnv* env, jclass clazz,
486 jint nativePtr, jint edgeFlags) {
487 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
488 event->setEdgeFlags(edgeFlags);
491 static jint android_view_MotionEvent_nativeGetMetaState(JNIEnv* env, jclass clazz,
493 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
494 return event->getMetaState();
497 static jint android_view_MotionEvent_nativeGetButtonState(JNIEnv* env, jclass clazz,
499 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
500 return event->getButtonState();
503 static void android_view_MotionEvent_nativeOffsetLocation(JNIEnv* env, jclass clazz,
504 jint nativePtr, jfloat deltaX, jfloat deltaY) {
505 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
506 return event->offsetLocation(deltaX, deltaY);
509 static jfloat android_view_MotionEvent_nativeGetXOffset(JNIEnv* env, jclass clazz,
511 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
512 return event->getXOffset();
515 static jfloat android_view_MotionEvent_nativeGetYOffset(JNIEnv* env, jclass clazz,
517 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
518 return event->getYOffset();
521 static jfloat android_view_MotionEvent_nativeGetXPrecision(JNIEnv* env, jclass clazz,
523 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
524 return event->getXPrecision();
527 static jfloat android_view_MotionEvent_nativeGetYPrecision(JNIEnv* env, jclass clazz,
529 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
530 return event->getYPrecision();
533 static jlong android_view_MotionEvent_nativeGetDownTimeNanos(JNIEnv* env, jclass clazz,
535 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
536 return event->getDownTime();
539 static void android_view_MotionEvent_nativeSetDownTimeNanos(JNIEnv* env, jclass clazz,
540 jint nativePtr, jlong downTimeNanos) {
541 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
542 event->setDownTime(downTimeNanos);
545 static jint android_view_MotionEvent_nativeGetPointerCount(JNIEnv* env, jclass clazz,
547 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
548 return jint(event->getPointerCount());
551 static jint android_view_MotionEvent_nativeGetPointerId(JNIEnv* env, jclass clazz,
552 jint nativePtr, jint pointerIndex) {
553 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
554 size_t pointerCount = event->getPointerCount();
555 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
558 return event->getPointerId(pointerIndex);
561 static jint android_view_MotionEvent_nativeGetToolType(JNIEnv* env, jclass clazz,
562 jint nativePtr, jint pointerIndex) {
563 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
564 size_t pointerCount = event->getPointerCount();
565 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
568 return event->getToolType(pointerIndex);
571 static jint android_view_MotionEvent_nativeFindPointerIndex(JNIEnv* env, jclass clazz,
572 jint nativePtr, jint pointerId) {
573 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
574 return jint(event->findPointerIndex(pointerId));
577 static jint android_view_MotionEvent_nativeGetHistorySize(JNIEnv* env, jclass clazz,
579 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
580 return jint(event->getHistorySize());
583 static jlong android_view_MotionEvent_nativeGetEventTimeNanos(JNIEnv* env, jclass clazz,
584 jint nativePtr, jint historyPos) {
585 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
586 if (historyPos == HISTORY_CURRENT) {
587 return event->getEventTime();
589 size_t historySize = event->getHistorySize();
590 if (!validateHistoryPos(env, historyPos, historySize)) {
593 return event->getHistoricalEventTime(historyPos);
597 static jfloat android_view_MotionEvent_nativeGetRawAxisValue(JNIEnv* env, jclass clazz,
598 jint nativePtr, jint axis, jint pointerIndex, jint historyPos) {
599 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
600 size_t pointerCount = event->getPointerCount();
601 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
605 if (historyPos == HISTORY_CURRENT) {
606 return event->getRawAxisValue(axis, pointerIndex);
608 size_t historySize = event->getHistorySize();
609 if (!validateHistoryPos(env, historyPos, historySize)) {
612 return event->getHistoricalRawAxisValue(axis, pointerIndex, historyPos);
616 static jfloat android_view_MotionEvent_nativeGetAxisValue(JNIEnv* env, jclass clazz,
617 jint nativePtr, jint axis, jint pointerIndex, jint historyPos) {
618 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
619 size_t pointerCount = event->getPointerCount();
620 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
624 if (historyPos == HISTORY_CURRENT) {
625 return event->getAxisValue(axis, pointerIndex);
627 size_t historySize = event->getHistorySize();
628 if (!validateHistoryPos(env, historyPos, historySize)) {
631 return event->getHistoricalAxisValue(axis, pointerIndex, historyPos);
635 static void android_view_MotionEvent_nativeGetPointerCoords(JNIEnv* env, jclass clazz,
636 jint nativePtr, jint pointerIndex, jint historyPos, jobject outPointerCoordsObj) {
637 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
638 size_t pointerCount = event->getPointerCount();
639 if (!validatePointerIndex(env, pointerIndex, pointerCount)
640 || !validatePointerCoords(env, outPointerCoordsObj)) {
644 const PointerCoords* rawPointerCoords;
645 if (historyPos == HISTORY_CURRENT) {
646 rawPointerCoords = event->getRawPointerCoords(pointerIndex);
648 size_t historySize = event->getHistorySize();
649 if (!validateHistoryPos(env, historyPos, historySize)) {
652 rawPointerCoords = event->getHistoricalRawPointerCoords(pointerIndex, historyPos);
654 pointerCoordsFromNative(env, rawPointerCoords, event->getXOffset(), event->getYOffset(),
655 outPointerCoordsObj);
658 static void android_view_MotionEvent_nativeGetPointerProperties(JNIEnv* env, jclass clazz,
659 jint nativePtr, jint pointerIndex, jobject outPointerPropertiesObj) {
660 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
661 size_t pointerCount = event->getPointerCount();
662 if (!validatePointerIndex(env, pointerIndex, pointerCount)
663 || !validatePointerProperties(env, outPointerPropertiesObj)) {
667 const PointerProperties* pointerProperties = event->getPointerProperties(pointerIndex);
668 pointerPropertiesFromNative(env, pointerProperties, outPointerPropertiesObj);
671 static void android_view_MotionEvent_nativeScale(JNIEnv* env, jclass clazz,
672 jint nativePtr, jfloat scale) {
673 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
677 static void android_view_MotionEvent_nativeTransform(JNIEnv* env, jclass clazz,
678 jint nativePtr, jobject matrixObj) {
679 SkMatrix* matrix = android_graphics_Matrix_getSkMatrix(env, matrixObj);
680 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
683 m[0] = SkScalarToFloat(matrix->get(SkMatrix::kMScaleX));
684 m[1] = SkScalarToFloat(matrix->get(SkMatrix::kMSkewX));
685 m[2] = SkScalarToFloat(matrix->get(SkMatrix::kMTransX));
686 m[3] = SkScalarToFloat(matrix->get(SkMatrix::kMSkewY));
687 m[4] = SkScalarToFloat(matrix->get(SkMatrix::kMScaleY));
688 m[5] = SkScalarToFloat(matrix->get(SkMatrix::kMTransY));
689 m[6] = SkScalarToFloat(matrix->get(SkMatrix::kMPersp0));
690 m[7] = SkScalarToFloat(matrix->get(SkMatrix::kMPersp1));
691 m[8] = SkScalarToFloat(matrix->get(SkMatrix::kMPersp2));
695 static jint android_view_MotionEvent_nativeReadFromParcel(JNIEnv* env, jclass clazz,
696 jint nativePtr, jobject parcelObj) {
697 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
699 event = new MotionEvent();
702 Parcel* parcel = parcelForJavaObject(env, parcelObj);
704 status_t status = event->readFromParcel(parcel);
709 jniThrowRuntimeException(env, "Failed to read MotionEvent parcel.");
712 return reinterpret_cast<jint>(event);
715 static void android_view_MotionEvent_nativeWriteToParcel(JNIEnv* env, jclass clazz,
716 jint nativePtr, jobject parcelObj) {
717 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
718 Parcel* parcel = parcelForJavaObject(env, parcelObj);
720 status_t status = event->writeToParcel(parcel);
722 jniThrowRuntimeException(env, "Failed to write MotionEvent parcel.");
726 // ----------------------------------------------------------------------------
728 static JNINativeMethod gMotionEventMethods[] = {
729 /* name, signature, funcPtr */
730 { "nativeInitialize",
731 "(IIIIIIIIFFFFJJI[Landroid/view/MotionEvent$PointerProperties;"
732 "[Landroid/view/MotionEvent$PointerCoords;)I",
733 (void*)android_view_MotionEvent_nativeInitialize },
736 (void*)android_view_MotionEvent_nativeCopy },
739 (void*)android_view_MotionEvent_nativeDispose },
741 "(IJ[Landroid/view/MotionEvent$PointerCoords;I)V",
742 (void*)android_view_MotionEvent_nativeAddBatch },
743 { "nativeGetDeviceId",
745 (void*)android_view_MotionEvent_nativeGetDeviceId },
748 (void*)android_view_MotionEvent_nativeGetSource },
751 (void*)android_view_MotionEvent_nativeSetSource },
754 (void*)android_view_MotionEvent_nativeGetAction },
757 (void*)android_view_MotionEvent_nativeSetAction },
758 { "nativeIsTouchEvent",
760 (void*)android_view_MotionEvent_nativeIsTouchEvent },
763 (void*)android_view_MotionEvent_nativeGetFlags },
766 (void*)android_view_MotionEvent_nativeSetFlags },
767 { "nativeGetEdgeFlags",
769 (void*)android_view_MotionEvent_nativeGetEdgeFlags },
770 { "nativeSetEdgeFlags",
772 (void*)android_view_MotionEvent_nativeSetEdgeFlags },
773 { "nativeGetMetaState",
775 (void*)android_view_MotionEvent_nativeGetMetaState },
776 { "nativeGetButtonState",
778 (void*)android_view_MotionEvent_nativeGetButtonState },
779 { "nativeOffsetLocation",
781 (void*)android_view_MotionEvent_nativeOffsetLocation },
782 { "nativeGetXOffset",
784 (void*)android_view_MotionEvent_nativeGetXOffset },
785 { "nativeGetYOffset",
787 (void*)android_view_MotionEvent_nativeGetYOffset },
788 { "nativeGetXPrecision",
790 (void*)android_view_MotionEvent_nativeGetXPrecision },
791 { "nativeGetYPrecision",
793 (void*)android_view_MotionEvent_nativeGetYPrecision },
794 { "nativeGetDownTimeNanos",
796 (void*)android_view_MotionEvent_nativeGetDownTimeNanos },
797 { "nativeSetDownTimeNanos",
799 (void*)android_view_MotionEvent_nativeSetDownTimeNanos },
800 { "nativeGetPointerCount",
802 (void*)android_view_MotionEvent_nativeGetPointerCount },
803 { "nativeGetPointerId",
805 (void*)android_view_MotionEvent_nativeGetPointerId },
806 { "nativeGetToolType",
808 (void*)android_view_MotionEvent_nativeGetToolType },
809 { "nativeFindPointerIndex",
811 (void*)android_view_MotionEvent_nativeFindPointerIndex },
812 { "nativeGetHistorySize",
814 (void*)android_view_MotionEvent_nativeGetHistorySize },
815 { "nativeGetEventTimeNanos",
817 (void*)android_view_MotionEvent_nativeGetEventTimeNanos },
818 { "nativeGetRawAxisValue",
820 (void*)android_view_MotionEvent_nativeGetRawAxisValue },
821 { "nativeGetAxisValue",
823 (void*)android_view_MotionEvent_nativeGetAxisValue },
824 { "nativeGetPointerCoords",
825 "(IIILandroid/view/MotionEvent$PointerCoords;)V",
826 (void*)android_view_MotionEvent_nativeGetPointerCoords },
827 { "nativeGetPointerProperties",
828 "(IILandroid/view/MotionEvent$PointerProperties;)V",
829 (void*)android_view_MotionEvent_nativeGetPointerProperties },
832 (void*)android_view_MotionEvent_nativeScale },
834 "(ILandroid/graphics/Matrix;)V",
835 (void*)android_view_MotionEvent_nativeTransform },
836 { "nativeReadFromParcel",
837 "(ILandroid/os/Parcel;)I",
838 (void*)android_view_MotionEvent_nativeReadFromParcel },
839 { "nativeWriteToParcel",
840 "(ILandroid/os/Parcel;)V",
841 (void*)android_view_MotionEvent_nativeWriteToParcel },
844 #define FIND_CLASS(var, className) \
845 var = env->FindClass(className); \
846 LOG_FATAL_IF(! var, "Unable to find class " className);
848 #define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
849 var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
850 LOG_FATAL_IF(! var, "Unable to find static method" methodName);
852 #define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
853 var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
854 LOG_FATAL_IF(! var, "Unable to find method" methodName);
856 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
857 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
858 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
860 int register_android_view_MotionEvent(JNIEnv* env) {
861 int res = jniRegisterNativeMethods(env, "android/view/MotionEvent",
862 gMotionEventMethods, NELEM(gMotionEventMethods));
863 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
865 FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
866 gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz));
868 GET_STATIC_METHOD_ID(gMotionEventClassInfo.obtain, gMotionEventClassInfo.clazz,
869 "obtain", "()Landroid/view/MotionEvent;");
870 GET_METHOD_ID(gMotionEventClassInfo.recycle, gMotionEventClassInfo.clazz,
872 GET_FIELD_ID(gMotionEventClassInfo.mNativePtr, gMotionEventClassInfo.clazz,
876 FIND_CLASS(clazz, "android/view/MotionEvent$PointerCoords");
878 GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisBits, clazz,
879 "mPackedAxisBits", "J");
880 GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisValues, clazz,
881 "mPackedAxisValues", "[F");
882 GET_FIELD_ID(gPointerCoordsClassInfo.x, clazz,
884 GET_FIELD_ID(gPointerCoordsClassInfo.y, clazz,
886 GET_FIELD_ID(gPointerCoordsClassInfo.pressure, clazz,
888 GET_FIELD_ID(gPointerCoordsClassInfo.size, clazz,
890 GET_FIELD_ID(gPointerCoordsClassInfo.touchMajor, clazz,
892 GET_FIELD_ID(gPointerCoordsClassInfo.touchMinor, clazz,
894 GET_FIELD_ID(gPointerCoordsClassInfo.toolMajor, clazz,
896 GET_FIELD_ID(gPointerCoordsClassInfo.toolMinor, clazz,
898 GET_FIELD_ID(gPointerCoordsClassInfo.orientation, clazz,
901 FIND_CLASS(clazz, "android/view/MotionEvent$PointerProperties");
903 GET_FIELD_ID(gPointerPropertiesClassInfo.id, clazz,
905 GET_FIELD_ID(gPointerPropertiesClassInfo.toolType, clazz,
911 } // namespace android