blob: 68ebfe738009990eb186a1e9950a67a5dd8a5b3f [file] [log] [blame]
Jeff Brown46b9ac02010-04-22 18:58:52 -07001/*
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 <ui/Input.h>
24#include "android_view_MotionEvent.h"
Jeff Brown91c69ab2011-02-14 17:03:18 -080025#include "android_util_Binder.h"
Jeff Brown20e987b2010-08-23 12:01:02 -070026#include "android/graphics/Matrix.h"
27
Jeff Brown20e987b2010-08-23 12:01:02 -070028#include "SkMatrix.h"
Jeff Brown20e987b2010-08-23 12:01:02 -070029
30
Jeff Brown46b9ac02010-04-22 18:58:52 -070031namespace android {
32
33// ----------------------------------------------------------------------------
34
35static struct {
36 jclass clazz;
37
38 jmethodID obtain;
39 jmethodID recycle;
40
Jeff Brown91c69ab2011-02-14 17:03:18 -080041 jfieldID mNativePtr;
Jeff Brown46b9ac02010-04-22 18:58:52 -070042} gMotionEventClassInfo;
43
Jeff Brown91c69ab2011-02-14 17:03:18 -080044static struct {
Jeff Brown91c69ab2011-02-14 17:03:18 -080045 jfieldID mPackedAxisBits;
46 jfieldID mPackedAxisValues;
47 jfieldID x;
48 jfieldID y;
49 jfieldID pressure;
50 jfieldID size;
51 jfieldID touchMajor;
52 jfieldID touchMinor;
53 jfieldID toolMajor;
54 jfieldID toolMinor;
55 jfieldID orientation;
56} gPointerCoordsClassInfo;
57
Jeff Brown46b9ac02010-04-22 18:58:52 -070058// ----------------------------------------------------------------------------
59
Jeff Brown91c69ab2011-02-14 17:03:18 -080060static MotionEvent* android_view_MotionEvent_getNativePtr(JNIEnv* env, jobject eventObj) {
61 return reinterpret_cast<MotionEvent*>(
62 env->GetIntField(eventObj, gMotionEventClassInfo.mNativePtr));
63}
Jeff Brown46b9ac02010-04-22 18:58:52 -070064
Jeff Brown91c69ab2011-02-14 17:03:18 -080065static void android_view_MotionEvent_setNativePtr(JNIEnv* env, jobject eventObj,
66 MotionEvent* event) {
67 env->SetIntField(eventObj, gMotionEventClassInfo.mNativePtr,
68 reinterpret_cast<int>(event));
69}
70
71jobject android_view_MotionEvent_fromNative(JNIEnv* env, const MotionEvent* event) {
Jeff Brown46b9ac02010-04-22 18:58:52 -070072 jobject eventObj = env->CallStaticObjectMethod(gMotionEventClassInfo.clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -080073 gMotionEventClassInfo.obtain);
Jeff Brown46b9ac02010-04-22 18:58:52 -070074 if (env->ExceptionCheck()) {
75 LOGE("An exception occurred while obtaining a motion event.");
76 LOGE_EX(env);
77 env->ExceptionClear();
78 return NULL;
79 }
80
Jeff Brown91c69ab2011-02-14 17:03:18 -080081 MotionEvent* destEvent = android_view_MotionEvent_getNativePtr(env, eventObj);
82 if (!destEvent) {
83 destEvent = new MotionEvent();
84 android_view_MotionEvent_setNativePtr(env, eventObj, destEvent);
Jeff Brown46b9ac02010-04-22 18:58:52 -070085 }
86
Jeff Brown91c69ab2011-02-14 17:03:18 -080087 destEvent->copyFrom(event, true);
Jeff Brown46b9ac02010-04-22 18:58:52 -070088 return eventObj;
89}
90
Jeff Brown1f245102010-11-18 20:53:46 -080091status_t android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj,
Jeff Brown46b9ac02010-04-22 18:58:52 -070092 MotionEvent* event) {
Jeff Brown91c69ab2011-02-14 17:03:18 -080093 MotionEvent* srcEvent = android_view_MotionEvent_getNativePtr(env, eventObj);
94 if (!srcEvent) {
95 LOGE("MotionEvent was finalized");
Jeff Brown1f245102010-11-18 20:53:46 -080096 return BAD_VALUE;
97 }
98
Jeff Brown91c69ab2011-02-14 17:03:18 -080099 event->copyFrom(srcEvent, true);
Jeff Brown1f245102010-11-18 20:53:46 -0800100 return OK;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700101}
102
Jeff Brown1f245102010-11-18 20:53:46 -0800103status_t android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700104 env->CallVoidMethod(eventObj, gMotionEventClassInfo.recycle);
105 if (env->ExceptionCheck()) {
106 LOGW("An exception occurred while recycling a motion event.");
107 LOGW_EX(env);
108 env->ExceptionClear();
Jeff Brown1f245102010-11-18 20:53:46 -0800109 return UNKNOWN_ERROR;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700110 }
Jeff Brown1f245102010-11-18 20:53:46 -0800111 return OK;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700112}
113
Jeff Brown91c69ab2011-02-14 17:03:18 -0800114// ----------------------------------------------------------------------------
Jeff Brown20e987b2010-08-23 12:01:02 -0700115
Jeff Brown91c69ab2011-02-14 17:03:18 -0800116static const jint HISTORY_CURRENT = -0x80000000;
117
118static bool validatePointerCount(JNIEnv* env, jint pointerCount) {
119 if (pointerCount < 1) {
120 jniThrowException(env, "java/lang/IllegalArgumentException",
121 "pointerCount must be at least 1");
122 return false;
Jeff Brown20e987b2010-08-23 12:01:02 -0700123 }
Jeff Brown91c69ab2011-02-14 17:03:18 -0800124 return true;
Jeff Brown20e987b2010-08-23 12:01:02 -0700125}
126
Jeff Brown91c69ab2011-02-14 17:03:18 -0800127static bool validatePointerIdsArray(JNIEnv* env, jintArray pointerIdsArray,
128 size_t pointerCount) {
129 if (!pointerIdsArray) {
130 jniThrowException(env, "java/lang/IllegalArgumentException",
131 "pointerIds array must not be null");
132 return false;
133 }
134 size_t length = size_t(env->GetArrayLength(pointerIdsArray));
135 if (length < pointerCount) {
136 jniThrowException(env, "java/lang/IllegalArgumentException",
137 "pointerIds array must be large enough to hold all pointers");
138 return false;
139 }
140 return true;
141}
Jeff Brown20e987b2010-08-23 12:01:02 -0700142
Jeff Brown91c69ab2011-02-14 17:03:18 -0800143static bool validatePointerCoordsObjArray(JNIEnv* env, jobjectArray pointerCoordsObjArray,
144 size_t pointerCount) {
145 if (!pointerCoordsObjArray) {
146 jniThrowException(env, "java/lang/IllegalArgumentException",
147 "pointerCoords array must not be null");
148 return false;
149 }
150 size_t length = size_t(env->GetArrayLength(pointerCoordsObjArray));
151 if (length < pointerCount) {
152 jniThrowException(env, "java/lang/IllegalArgumentException",
153 "pointerCoords array must be large enough to hold all pointers");
154 return false;
155 }
156 return true;
157}
Jeff Brown20e987b2010-08-23 12:01:02 -0700158
Jeff Brown91c69ab2011-02-14 17:03:18 -0800159static bool validatePointerIndex(JNIEnv* env, jint pointerIndex, size_t pointerCount) {
160 if (pointerIndex < 0 || size_t(pointerIndex) >= pointerCount) {
161 jniThrowException(env, "java/lang/IllegalArgumentException",
162 "pointerIndex out of range");
163 return false;
164 }
165 return true;
166}
Jeff Brown20e987b2010-08-23 12:01:02 -0700167
Jeff Brown91c69ab2011-02-14 17:03:18 -0800168static bool validateHistoryPos(JNIEnv* env, jint historyPos, size_t historySize) {
169 if (historyPos < 0 || size_t(historyPos) >= historySize) {
170 jniThrowException(env, "java/lang/IllegalArgumentException",
171 "historyPos out of range");
172 return false;
173 }
174 return true;
175}
Jeff Brown20e987b2010-08-23 12:01:02 -0700176
Jeff Brown91c69ab2011-02-14 17:03:18 -0800177static bool validatePointerCoords(JNIEnv* env, jobject pointerCoordsObj) {
178 if (!pointerCoordsObj) {
179 jniThrowException(env, "java/lang/IllegalArgumentException",
180 "pointerCoords must not be null");
181 return false;
182 }
183 return true;
184}
185
186static void pointerCoordsToNative(JNIEnv* env, jobject pointerCoordsObj,
187 float xOffset, float yOffset, PointerCoords* outRawPointerCoords) {
188 outRawPointerCoords->clear();
Jeff Brownebbd5d12011-02-17 13:01:34 -0800189 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_X,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800190 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.x) - xOffset);
Jeff Brownebbd5d12011-02-17 13:01:34 -0800191 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_Y,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800192 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.y) - yOffset);
Jeff Brownebbd5d12011-02-17 13:01:34 -0800193 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800194 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.pressure));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800195 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_SIZE,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800196 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.size));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800197 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800198 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMajor));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800199 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800200 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMinor));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800201 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800202 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMajor));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800203 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800204 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMinor));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800205 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800206 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.orientation));
207
Jeff Brown6f2fba42011-02-19 01:08:02 -0800208 uint64_t bits = env->GetLongField(pointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800209 if (bits) {
210 jfloatArray valuesArray = jfloatArray(env->GetObjectField(pointerCoordsObj,
211 gPointerCoordsClassInfo.mPackedAxisValues));
212 if (valuesArray) {
213 jfloat* values = static_cast<jfloat*>(
214 env->GetPrimitiveArrayCritical(valuesArray, NULL));
215
216 uint32_t index = 0;
217 do {
Jeff Browncc0c1592011-02-19 05:07:28 -0800218 uint32_t axis = __builtin_ctzll(bits);
Jeff Brown6f2fba42011-02-19 01:08:02 -0800219 uint64_t axisBit = 1LL << axis;
Jeff Brown91c69ab2011-02-14 17:03:18 -0800220 bits &= ~axisBit;
221 outRawPointerCoords->setAxisValue(axis, values[index++]);
222 } while (bits);
223
224 env->ReleasePrimitiveArrayCritical(valuesArray, values, JNI_ABORT);
225 env->DeleteLocalRef(valuesArray);
226 }
227 }
228}
229
230static jfloatArray obtainPackedAxisValuesArray(JNIEnv* env, uint32_t minSize,
231 jobject outPointerCoordsObj) {
232 jfloatArray outValuesArray = jfloatArray(env->GetObjectField(outPointerCoordsObj,
233 gPointerCoordsClassInfo.mPackedAxisValues));
234 if (outValuesArray) {
235 uint32_t size = env->GetArrayLength(outValuesArray);
236 if (minSize <= size) {
237 return outValuesArray;
238 }
239 env->DeleteLocalRef(outValuesArray);
240 }
241 uint32_t size = 8;
242 while (size < minSize) {
243 size *= 2;
244 }
245 outValuesArray = env->NewFloatArray(size);
246 env->SetObjectField(outPointerCoordsObj,
247 gPointerCoordsClassInfo.mPackedAxisValues, outValuesArray);
248 return outValuesArray;
249}
250
251static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointerCoords,
252 float xOffset, float yOffset, jobject outPointerCoordsObj) {
253 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.x,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800254 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_X) + xOffset);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800255 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.y,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800256 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_Y) + yOffset);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800257 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.pressure,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800258 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800259 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.size,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800260 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_SIZE));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800261 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMajor,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800262 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800263 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMinor,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800264 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800265 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMajor,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800266 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800267 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMinor,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800268 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800269 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.orientation,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800270 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800271
Jeff Brown6f2fba42011-02-19 01:08:02 -0800272 const uint64_t unpackedAxisBits = 0
273 | (1LL << AMOTION_EVENT_AXIS_X)
274 | (1LL << AMOTION_EVENT_AXIS_Y)
275 | (1LL << AMOTION_EVENT_AXIS_PRESSURE)
276 | (1LL << AMOTION_EVENT_AXIS_SIZE)
277 | (1LL << AMOTION_EVENT_AXIS_TOUCH_MAJOR)
278 | (1LL << AMOTION_EVENT_AXIS_TOUCH_MINOR)
279 | (1LL << AMOTION_EVENT_AXIS_TOOL_MAJOR)
280 | (1LL << AMOTION_EVENT_AXIS_TOOL_MINOR)
281 | (1LL << AMOTION_EVENT_AXIS_ORIENTATION);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800282
Jeff Brown6f2fba42011-02-19 01:08:02 -0800283 uint64_t outBits = 0;
284 uint64_t remainingBits = rawPointerCoords->bits & ~unpackedAxisBits;
Jeff Brown91c69ab2011-02-14 17:03:18 -0800285 if (remainingBits) {
Jeff Brown6f2fba42011-02-19 01:08:02 -0800286 uint32_t packedAxesCount = __builtin_popcountll(remainingBits);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800287 jfloatArray outValuesArray = obtainPackedAxisValuesArray(env, packedAxesCount,
288 outPointerCoordsObj);
289 if (!outValuesArray) {
290 return; // OOM
Jeff Brown20e987b2010-08-23 12:01:02 -0700291 }
292
Jeff Brown91c69ab2011-02-14 17:03:18 -0800293 jfloat* outValues = static_cast<jfloat*>(env->GetPrimitiveArrayCritical(
294 outValuesArray, NULL));
Jeff Brown20e987b2010-08-23 12:01:02 -0700295
Jeff Brown91c69ab2011-02-14 17:03:18 -0800296 const float* values = rawPointerCoords->values;
297 uint32_t index = 0;
298 do {
Jeff Browncc0c1592011-02-19 05:07:28 -0800299 uint32_t axis = __builtin_ctzll(remainingBits);
Jeff Brown6f2fba42011-02-19 01:08:02 -0800300 uint64_t axisBit = 1LL << axis;
Jeff Brown91c69ab2011-02-14 17:03:18 -0800301 remainingBits &= ~axisBit;
302 outBits |= axisBit;
303 outValues[index++] = rawPointerCoords->getAxisValue(axis);
304 } while (remainingBits);
305
306 env->ReleasePrimitiveArrayCritical(outValuesArray, outValues, 0);
307 env->DeleteLocalRef(outValuesArray);
308 }
Jeff Brown6f2fba42011-02-19 01:08:02 -0800309 env->SetLongField(outPointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits, outBits);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800310}
311
312
313// ----------------------------------------------------------------------------
314
315static jint android_view_MotionEvent_nativeInitialize(JNIEnv* env, jclass clazz,
316 jint nativePtr,
317 jint deviceId, jint source, jint action, jint flags, jint edgeFlags, jint metaState,
318 jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision,
319 jlong downTimeNanos, jlong eventTimeNanos,
320 jint pointerCount, jintArray pointerIdsArray, jobjectArray pointerCoordsObjArray) {
321 if (!validatePointerCount(env, pointerCount)
322 || !validatePointerIdsArray(env, pointerIdsArray, pointerCount)
323 || !validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
324 return 0;
Jeff Brown20e987b2010-08-23 12:01:02 -0700325 }
326
Jeff Brown91c69ab2011-02-14 17:03:18 -0800327 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
328 if (!event) {
329 event = new MotionEvent();
330 }
Jeff Brown20e987b2010-08-23 12:01:02 -0700331
Jeff Brown91c69ab2011-02-14 17:03:18 -0800332 PointerCoords rawPointerCoords[pointerCount];
Jeff Brown20e987b2010-08-23 12:01:02 -0700333
Jeff Brown91c69ab2011-02-14 17:03:18 -0800334 for (jint i = 0; i < pointerCount; i++) {
335 jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
336 if (!pointerCoordsObj) {
337 jniThrowNullPointerException(env, "pointerCoords");
338 if (!nativePtr) {
339 delete event;
340 }
341 return 0;
342 }
343 pointerCoordsToNative(env, pointerCoordsObj, xOffset, yOffset, &rawPointerCoords[i]);
344 env->DeleteLocalRef(pointerCoordsObj);
345 }
346
347 int* pointerIds = static_cast<int*>(env->GetPrimitiveArrayCritical(pointerIdsArray, NULL));
348
349 event->initialize(deviceId, source, action, flags, edgeFlags, metaState,
350 xOffset, yOffset, xPrecision, yPrecision,
351 downTimeNanos, eventTimeNanos, pointerCount, pointerIds, rawPointerCoords);
352
353 env->ReleasePrimitiveArrayCritical(pointerIdsArray, pointerIds, JNI_ABORT);
354 return reinterpret_cast<jint>(event);
355}
356
357static jint android_view_MotionEvent_nativeCopy(JNIEnv* env, jclass clazz,
358 jint destNativePtr, jint sourceNativePtr, jboolean keepHistory) {
359 MotionEvent* destEvent = reinterpret_cast<MotionEvent*>(destNativePtr);
360 if (!destEvent) {
361 destEvent = new MotionEvent();
362 }
363 MotionEvent* sourceEvent = reinterpret_cast<MotionEvent*>(sourceNativePtr);
364 destEvent->copyFrom(sourceEvent, keepHistory);
365 return reinterpret_cast<jint>(destEvent);
366}
367
368static void android_view_MotionEvent_nativeDispose(JNIEnv* env, jclass clazz,
369 jint nativePtr) {
370 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
371 delete event;
372}
373
374static void android_view_MotionEvent_nativeAddBatch(JNIEnv* env, jclass clazz,
375 jint nativePtr, jlong eventTimeNanos, jobjectArray pointerCoordsObjArray,
376 jint metaState) {
377 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
378 size_t pointerCount = event->getPointerCount();
379 if (!validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
380 return;
381 }
382
383 PointerCoords rawPointerCoords[pointerCount];
384
385 for (size_t i = 0; i < pointerCount; i++) {
386 jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
387 if (!pointerCoordsObj) {
388 jniThrowNullPointerException(env, "pointerCoords");
389 return;
390 }
391 pointerCoordsToNative(env, pointerCoordsObj,
392 event->getXOffset(), event->getYOffset(), &rawPointerCoords[i]);
393 env->DeleteLocalRef(pointerCoordsObj);
394 }
395
396 event->addSample(eventTimeNanos, rawPointerCoords);
397 event->setMetaState(event->getMetaState() | metaState);
398}
399
400static jint android_view_MotionEvent_nativeGetDeviceId(JNIEnv* env, jclass clazz,
401 jint nativePtr) {
402 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
403 return event->getDeviceId();
404}
405
406static jint android_view_MotionEvent_nativeGetSource(JNIEnv* env, jclass clazz,
407 jint nativePtr) {
408 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
409 return event->getSource();
410}
411
412static void android_view_MotionEvent_nativeSetSource(JNIEnv* env, jclass clazz,
413 jint nativePtr, jint source) {
414 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
415 event->setSource(source);
416}
417
418static jint android_view_MotionEvent_nativeGetAction(JNIEnv* env, jclass clazz,
419 jint nativePtr) {
420 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
421 return event->getAction();
422}
423
424static void android_view_MotionEvent_nativeSetAction(JNIEnv* env, jclass clazz,
425 jint nativePtr, jint action) {
426 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
427 event->setAction(action);
428}
429
Jeff Brown56194eb2011-03-02 19:23:13 -0800430static jboolean android_view_MotionEvent_nativeIsTouchEvent(JNIEnv* env, jclass clazz,
431 jint nativePtr) {
432 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
433 return event->isTouchEvent();
434}
435
Jeff Brown91c69ab2011-02-14 17:03:18 -0800436static jint android_view_MotionEvent_nativeGetFlags(JNIEnv* env, jclass clazz,
437 jint nativePtr) {
438 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
439 return event->getFlags();
440}
441
442static jint android_view_MotionEvent_nativeGetEdgeFlags(JNIEnv* env, jclass clazz,
443 jint nativePtr) {
444 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
445 return event->getEdgeFlags();
446}
447
448static void android_view_MotionEvent_nativeSetEdgeFlags(JNIEnv* env, jclass clazz,
449 jint nativePtr, jint edgeFlags) {
450 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
451 event->setEdgeFlags(edgeFlags);
452}
453
454static jint android_view_MotionEvent_nativeGetMetaState(JNIEnv* env, jclass clazz,
455 jint nativePtr) {
456 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
457 return event->getMetaState();
458}
459
460static void android_view_MotionEvent_nativeOffsetLocation(JNIEnv* env, jclass clazz,
461 jint nativePtr, jfloat deltaX, jfloat deltaY) {
462 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
463 return event->offsetLocation(deltaX, deltaY);
464}
465
466static jfloat android_view_MotionEvent_nativeGetXPrecision(JNIEnv* env, jclass clazz,
467 jint nativePtr) {
468 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
469 return event->getXPrecision();
470}
471
472static jfloat android_view_MotionEvent_nativeGetYPrecision(JNIEnv* env, jclass clazz,
473 jint nativePtr) {
474 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
475 return event->getYPrecision();
476}
477
478static jlong android_view_MotionEvent_nativeGetDownTimeNanos(JNIEnv* env, jclass clazz,
479 jint nativePtr) {
480 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
481 return event->getDownTime();
482}
483
484static jint android_view_MotionEvent_nativeGetPointerCount(JNIEnv* env, jclass clazz,
485 jint nativePtr) {
486 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
487 return jint(event->getPointerCount());
488}
489
490static jint android_view_MotionEvent_nativeGetPointerId(JNIEnv* env, jclass clazz,
491 jint nativePtr, jint pointerIndex) {
492 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
493 size_t pointerCount = event->getPointerCount();
494 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
495 return -1;
496 }
497 return event->getPointerId(pointerIndex);
498}
499
500static jint android_view_MotionEvent_nativeFindPointerIndex(JNIEnv* env, jclass clazz,
501 jint nativePtr, jint pointerId) {
502 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
503 size_t pointerCount = event->getPointerCount();
504 for (size_t i = 0; i < pointerCount; i++) {
505 if (event->getPointerId(i) == pointerId) {
506 return i;
507 }
508 }
509 return -1;
510}
511
512static jint android_view_MotionEvent_nativeGetHistorySize(JNIEnv* env, jclass clazz,
513 jint nativePtr) {
514 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
515 return jint(event->getHistorySize());
516}
517
518static jlong android_view_MotionEvent_nativeGetEventTimeNanos(JNIEnv* env, jclass clazz,
519 jint nativePtr, jint historyPos) {
520 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
521 if (historyPos == HISTORY_CURRENT) {
522 return event->getEventTime();
523 } else {
524 size_t historySize = event->getHistorySize();
525 if (!validateHistoryPos(env, historyPos, historySize)) {
526 return 0;
527 }
528 return event->getHistoricalEventTime(historyPos);
529 }
530}
531
532static jfloat android_view_MotionEvent_nativeGetRawAxisValue(JNIEnv* env, jclass clazz,
533 jint nativePtr, jint axis, jint pointerIndex, jint historyPos) {
534 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
535 size_t pointerCount = event->getPointerCount();
536 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
537 return 0;
538 }
539
540 if (historyPos == HISTORY_CURRENT) {
541 return event->getRawAxisValue(axis, pointerIndex);
542 } else {
543 size_t historySize = event->getHistorySize();
544 if (!validateHistoryPos(env, historyPos, historySize)) {
545 return 0;
546 }
547 return event->getHistoricalRawAxisValue(axis, pointerIndex, historyPos);
548 }
549}
550
551static jfloat android_view_MotionEvent_nativeGetAxisValue(JNIEnv* env, jclass clazz,
552 jint nativePtr, jint axis, jint pointerIndex, jint historyPos) {
553 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
554 size_t pointerCount = event->getPointerCount();
555 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
556 return 0;
557 }
558
559 if (historyPos == HISTORY_CURRENT) {
560 return event->getAxisValue(axis, pointerIndex);
561 } else {
562 size_t historySize = event->getHistorySize();
563 if (!validateHistoryPos(env, historyPos, historySize)) {
564 return 0;
565 }
566 return event->getHistoricalAxisValue(axis, pointerIndex, historyPos);
567 }
568}
569
570static void android_view_MotionEvent_nativeGetPointerCoords(JNIEnv* env, jclass clazz,
571 jint nativePtr, jint pointerIndex, jint historyPos, jobject outPointerCoordsObj) {
572 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
573 size_t pointerCount = event->getPointerCount();
574 if (!validatePointerIndex(env, pointerIndex, pointerCount)
575 || !validatePointerCoords(env, outPointerCoordsObj)) {
576 return;
577 }
578
579 const PointerCoords* rawPointerCoords;
580 if (historyPos == HISTORY_CURRENT) {
581 rawPointerCoords = event->getRawPointerCoords(pointerIndex);
582 } else {
583 size_t historySize = event->getHistorySize();
584 if (!validateHistoryPos(env, historyPos, historySize)) {
585 return;
586 }
587 rawPointerCoords = event->getHistoricalRawPointerCoords(pointerIndex, historyPos);
588 }
589 pointerCoordsFromNative(env, rawPointerCoords, event->getXOffset(), event->getYOffset(),
590 outPointerCoordsObj);
591}
592
593static void android_view_MotionEvent_nativeScale(JNIEnv* env, jclass clazz,
594 jint nativePtr, jfloat scale) {
595 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
596 event->scale(scale);
597}
598
599static void android_view_MotionEvent_nativeTransform(JNIEnv* env, jclass clazz,
600 jint nativePtr, jobject matrixObj) {
601 SkMatrix* matrix = android_graphics_Matrix_getSkMatrix(env, matrixObj);
602 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
603 event->transform(matrix);
604}
605
606static jint android_view_MotionEvent_nativeReadFromParcel(JNIEnv* env, jclass clazz,
607 jint nativePtr, jobject parcelObj) {
608 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
609 if (!event) {
610 event = new MotionEvent();
611 }
612
613 Parcel* parcel = parcelForJavaObject(env, parcelObj);
614
615 status_t status = event->readFromParcel(parcel);
Jeff Brownebbd5d12011-02-17 13:01:34 -0800616 if (status) {
Jeff Brown91c69ab2011-02-14 17:03:18 -0800617 if (!nativePtr) {
618 delete event;
619 }
620 jniThrowRuntimeException(env, "Failed to read MotionEvent parcel.");
621 return 0;
622 }
623 return reinterpret_cast<jint>(event);
624}
625
626static void android_view_MotionEvent_nativeWriteToParcel(JNIEnv* env, jclass clazz,
627 jint nativePtr, jobject parcelObj) {
628 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
629 Parcel* parcel = parcelForJavaObject(env, parcelObj);
630
631 status_t status = event->writeToParcel(parcel);
Jeff Brownebbd5d12011-02-17 13:01:34 -0800632 if (status) {
Jeff Brown91c69ab2011-02-14 17:03:18 -0800633 jniThrowRuntimeException(env, "Failed to write MotionEvent parcel.");
634 }
Jeff Brown20e987b2010-08-23 12:01:02 -0700635}
636
Jeff Brown46b9ac02010-04-22 18:58:52 -0700637// ----------------------------------------------------------------------------
638
Jeff Brown20e987b2010-08-23 12:01:02 -0700639static JNINativeMethod gMotionEventMethods[] = {
640 /* name, signature, funcPtr */
Jeff Brown91c69ab2011-02-14 17:03:18 -0800641 { "nativeInitialize",
642 "(IIIIIIIFFFFJJI[I[Landroid/view/MotionEvent$PointerCoords;)I",
643 (void*)android_view_MotionEvent_nativeInitialize },
644 { "nativeCopy",
645 "(IIZ)I",
646 (void*)android_view_MotionEvent_nativeCopy },
647 { "nativeDispose",
648 "(I)V",
649 (void*)android_view_MotionEvent_nativeDispose },
650 { "nativeAddBatch",
651 "(IJ[Landroid/view/MotionEvent$PointerCoords;I)V",
652 (void*)android_view_MotionEvent_nativeAddBatch },
653 { "nativeGetDeviceId",
654 "(I)I",
655 (void*)android_view_MotionEvent_nativeGetDeviceId },
656 { "nativeGetSource",
657 "(I)I",
658 (void*)android_view_MotionEvent_nativeGetSource },
659 { "nativeSetSource",
660 "(II)I",
661 (void*)android_view_MotionEvent_nativeSetSource },
662 { "nativeGetAction",
663 "(I)I",
664 (void*)android_view_MotionEvent_nativeGetAction },
665 { "nativeSetAction",
666 "(II)V",
667 (void*)android_view_MotionEvent_nativeSetAction },
Jeff Brown56194eb2011-03-02 19:23:13 -0800668 { "nativeIsTouchEvent",
669 "(I)Z",
670 (void*)android_view_MotionEvent_nativeIsTouchEvent },
Jeff Brown91c69ab2011-02-14 17:03:18 -0800671 { "nativeGetFlags",
672 "(I)I",
673 (void*)android_view_MotionEvent_nativeGetFlags },
674 { "nativeGetEdgeFlags",
675 "(I)I",
676 (void*)android_view_MotionEvent_nativeGetEdgeFlags },
677 { "nativeSetEdgeFlags",
678 "(II)V",
679 (void*)android_view_MotionEvent_nativeSetEdgeFlags },
680 { "nativeGetMetaState",
681 "(I)I",
682 (void*)android_view_MotionEvent_nativeGetMetaState },
683 { "nativeOffsetLocation",
684 "(IFF)V",
685 (void*)android_view_MotionEvent_nativeOffsetLocation },
686 { "nativeGetXPrecision",
687 "(I)F",
688 (void*)android_view_MotionEvent_nativeGetXPrecision },
689 { "nativeGetYPrecision",
690 "(I)F",
691 (void*)android_view_MotionEvent_nativeGetYPrecision },
692 { "nativeGetDownTimeNanos",
693 "(I)J",
694 (void*)android_view_MotionEvent_nativeGetDownTimeNanos },
695 { "nativeGetPointerCount",
696 "(I)I",
697 (void*)android_view_MotionEvent_nativeGetPointerCount },
698 { "nativeGetPointerId",
699 "(II)I",
700 (void*)android_view_MotionEvent_nativeGetPointerId },
701 { "nativeFindPointerIndex",
702 "(II)I",
703 (void*)android_view_MotionEvent_nativeFindPointerIndex },
704 { "nativeGetHistorySize",
705 "(I)I",
706 (void*)android_view_MotionEvent_nativeGetHistorySize },
707 { "nativeGetEventTimeNanos",
708 "(II)J",
709 (void*)android_view_MotionEvent_nativeGetEventTimeNanos },
710 { "nativeGetRawAxisValue",
711 "(IIII)F",
712 (void*)android_view_MotionEvent_nativeGetRawAxisValue },
713 { "nativeGetAxisValue",
714 "(IIII)F",
715 (void*)android_view_MotionEvent_nativeGetAxisValue },
716 { "nativeGetPointerCoords",
717 "(IIILandroid/view/MotionEvent$PointerCoords;)V",
718 (void*)android_view_MotionEvent_nativeGetPointerCoords },
719 { "nativeScale",
720 "(IF)V",
721 (void*)android_view_MotionEvent_nativeScale },
Jeff Brown20e987b2010-08-23 12:01:02 -0700722 { "nativeTransform",
Jeff Brown91c69ab2011-02-14 17:03:18 -0800723 "(ILandroid/graphics/Matrix;)V",
Jeff Brown20e987b2010-08-23 12:01:02 -0700724 (void*)android_view_MotionEvent_nativeTransform },
Jeff Brown91c69ab2011-02-14 17:03:18 -0800725 { "nativeReadFromParcel",
726 "(ILandroid/os/Parcel;)I",
727 (void*)android_view_MotionEvent_nativeReadFromParcel },
728 { "nativeWriteToParcel",
729 "(ILandroid/os/Parcel;)V",
730 (void*)android_view_MotionEvent_nativeWriteToParcel },
Jeff Brown20e987b2010-08-23 12:01:02 -0700731};
732
Jeff Brown46b9ac02010-04-22 18:58:52 -0700733#define FIND_CLASS(var, className) \
734 var = env->FindClass(className); \
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800735 LOG_FATAL_IF(! var, "Unable to find class " className);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700736
737#define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
738 var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
739 LOG_FATAL_IF(! var, "Unable to find static method" methodName);
740
741#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
742 var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
743 LOG_FATAL_IF(! var, "Unable to find method" methodName);
744
745#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
746 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
747 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
748
749int register_android_view_MotionEvent(JNIEnv* env) {
Jeff Brown20e987b2010-08-23 12:01:02 -0700750 int res = jniRegisterNativeMethods(env, "android/view/MotionEvent",
751 gMotionEventMethods, NELEM(gMotionEventMethods));
752 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
753
Jeff Brown46b9ac02010-04-22 18:58:52 -0700754 FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800755 gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz));
Jeff Brown46b9ac02010-04-22 18:58:52 -0700756
757 GET_STATIC_METHOD_ID(gMotionEventClassInfo.obtain, gMotionEventClassInfo.clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800758 "obtain", "()Landroid/view/MotionEvent;");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700759 GET_METHOD_ID(gMotionEventClassInfo.recycle, gMotionEventClassInfo.clazz,
760 "recycle", "()V");
Jeff Brown91c69ab2011-02-14 17:03:18 -0800761 GET_FIELD_ID(gMotionEventClassInfo.mNativePtr, gMotionEventClassInfo.clazz,
762 "mNativePtr", "I");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700763
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800764 jclass clazz;
765 FIND_CLASS(clazz, "android/view/MotionEvent$PointerCoords");
Jeff Brown91c69ab2011-02-14 17:03:18 -0800766
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800767 GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisBits, clazz,
Jeff Brown6f2fba42011-02-19 01:08:02 -0800768 "mPackedAxisBits", "J");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800769 GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisValues, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800770 "mPackedAxisValues", "[F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800771 GET_FIELD_ID(gPointerCoordsClassInfo.x, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800772 "x", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800773 GET_FIELD_ID(gPointerCoordsClassInfo.y, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800774 "y", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800775 GET_FIELD_ID(gPointerCoordsClassInfo.pressure, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800776 "pressure", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800777 GET_FIELD_ID(gPointerCoordsClassInfo.size, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800778 "size", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800779 GET_FIELD_ID(gPointerCoordsClassInfo.touchMajor, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800780 "touchMajor", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800781 GET_FIELD_ID(gPointerCoordsClassInfo.touchMinor, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800782 "touchMinor", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800783 GET_FIELD_ID(gPointerCoordsClassInfo.toolMajor, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800784 "toolMajor", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800785 GET_FIELD_ID(gPointerCoordsClassInfo.toolMinor, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800786 "toolMinor", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800787 GET_FIELD_ID(gPointerCoordsClassInfo.orientation, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800788 "orientation", "F");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700789
790 return 0;
791}
792
793} // namespace android