blob: 2ede7ec3c2fbb32930aa42931e8e74f482f9c3ed [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 Brown2ed24622011-03-14 19:39:54 -070060MotionEvent* android_view_MotionEvent_getNativePtr(JNIEnv* env, jobject eventObj) {
61 if (!eventObj) {
62 return NULL;
63 }
Jeff Brown91c69ab2011-02-14 17:03:18 -080064 return reinterpret_cast<MotionEvent*>(
65 env->GetIntField(eventObj, gMotionEventClassInfo.mNativePtr));
66}
Jeff Brown46b9ac02010-04-22 18:58:52 -070067
Jeff Brown91c69ab2011-02-14 17:03:18 -080068static void android_view_MotionEvent_setNativePtr(JNIEnv* env, jobject eventObj,
69 MotionEvent* event) {
70 env->SetIntField(eventObj, gMotionEventClassInfo.mNativePtr,
71 reinterpret_cast<int>(event));
72}
73
Jeff Brown2ed24622011-03-14 19:39:54 -070074jobject android_view_MotionEvent_obtainAsCopy(JNIEnv* env, const MotionEvent* event) {
Jeff Brown46b9ac02010-04-22 18:58:52 -070075 jobject eventObj = env->CallStaticObjectMethod(gMotionEventClassInfo.clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -080076 gMotionEventClassInfo.obtain);
Jeff Brown2ed24622011-03-14 19:39:54 -070077 if (env->ExceptionCheck() || !eventObj) {
Jeff Brown46b9ac02010-04-22 18:58:52 -070078 LOGE("An exception occurred while obtaining a motion event.");
79 LOGE_EX(env);
80 env->ExceptionClear();
81 return NULL;
82 }
83
Jeff Brown91c69ab2011-02-14 17:03:18 -080084 MotionEvent* destEvent = android_view_MotionEvent_getNativePtr(env, eventObj);
85 if (!destEvent) {
86 destEvent = new MotionEvent();
87 android_view_MotionEvent_setNativePtr(env, eventObj, destEvent);
Jeff Brown46b9ac02010-04-22 18:58:52 -070088 }
89
Jeff Brown91c69ab2011-02-14 17:03:18 -080090 destEvent->copyFrom(event, true);
Jeff Brown46b9ac02010-04-22 18:58:52 -070091 return eventObj;
92}
93
Jeff Brown1f245102010-11-18 20:53:46 -080094status_t android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj) {
Jeff Brown46b9ac02010-04-22 18:58:52 -070095 env->CallVoidMethod(eventObj, gMotionEventClassInfo.recycle);
96 if (env->ExceptionCheck()) {
97 LOGW("An exception occurred while recycling a motion event.");
98 LOGW_EX(env);
99 env->ExceptionClear();
Jeff Brown1f245102010-11-18 20:53:46 -0800100 return UNKNOWN_ERROR;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700101 }
Jeff Brown1f245102010-11-18 20:53:46 -0800102 return OK;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700103}
104
Jeff Brown91c69ab2011-02-14 17:03:18 -0800105// ----------------------------------------------------------------------------
Jeff Brown20e987b2010-08-23 12:01:02 -0700106
Jeff Brown91c69ab2011-02-14 17:03:18 -0800107static const jint HISTORY_CURRENT = -0x80000000;
108
109static bool validatePointerCount(JNIEnv* env, jint pointerCount) {
110 if (pointerCount < 1) {
111 jniThrowException(env, "java/lang/IllegalArgumentException",
112 "pointerCount must be at least 1");
113 return false;
Jeff Brown20e987b2010-08-23 12:01:02 -0700114 }
Jeff Brown91c69ab2011-02-14 17:03:18 -0800115 return true;
Jeff Brown20e987b2010-08-23 12:01:02 -0700116}
117
Jeff Brown91c69ab2011-02-14 17:03:18 -0800118static bool validatePointerIdsArray(JNIEnv* env, jintArray pointerIdsArray,
119 size_t pointerCount) {
120 if (!pointerIdsArray) {
121 jniThrowException(env, "java/lang/IllegalArgumentException",
122 "pointerIds array must not be null");
123 return false;
124 }
125 size_t length = size_t(env->GetArrayLength(pointerIdsArray));
126 if (length < pointerCount) {
127 jniThrowException(env, "java/lang/IllegalArgumentException",
128 "pointerIds array must be large enough to hold all pointers");
129 return false;
130 }
131 return true;
132}
Jeff Brown20e987b2010-08-23 12:01:02 -0700133
Jeff Brown91c69ab2011-02-14 17:03:18 -0800134static bool validatePointerCoordsObjArray(JNIEnv* env, jobjectArray pointerCoordsObjArray,
135 size_t pointerCount) {
136 if (!pointerCoordsObjArray) {
137 jniThrowException(env, "java/lang/IllegalArgumentException",
138 "pointerCoords array must not be null");
139 return false;
140 }
141 size_t length = size_t(env->GetArrayLength(pointerCoordsObjArray));
142 if (length < pointerCount) {
143 jniThrowException(env, "java/lang/IllegalArgumentException",
144 "pointerCoords array must be large enough to hold all pointers");
145 return false;
146 }
147 return true;
148}
Jeff Brown20e987b2010-08-23 12:01:02 -0700149
Jeff Brown91c69ab2011-02-14 17:03:18 -0800150static bool validatePointerIndex(JNIEnv* env, jint pointerIndex, size_t pointerCount) {
151 if (pointerIndex < 0 || size_t(pointerIndex) >= pointerCount) {
152 jniThrowException(env, "java/lang/IllegalArgumentException",
153 "pointerIndex out of range");
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 validateHistoryPos(JNIEnv* env, jint historyPos, size_t historySize) {
160 if (historyPos < 0 || size_t(historyPos) >= historySize) {
161 jniThrowException(env, "java/lang/IllegalArgumentException",
162 "historyPos 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 validatePointerCoords(JNIEnv* env, jobject pointerCoordsObj) {
169 if (!pointerCoordsObj) {
170 jniThrowException(env, "java/lang/IllegalArgumentException",
171 "pointerCoords must not be null");
172 return false;
173 }
174 return true;
175}
176
177static void pointerCoordsToNative(JNIEnv* env, jobject pointerCoordsObj,
178 float xOffset, float yOffset, PointerCoords* outRawPointerCoords) {
179 outRawPointerCoords->clear();
Jeff Brownebbd5d12011-02-17 13:01:34 -0800180 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_X,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800181 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.x) - xOffset);
Jeff Brownebbd5d12011-02-17 13:01:34 -0800182 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_Y,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800183 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.y) - yOffset);
Jeff Brownebbd5d12011-02-17 13:01:34 -0800184 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800185 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.pressure));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800186 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_SIZE,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800187 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.size));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800188 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800189 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMajor));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800190 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800191 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMinor));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800192 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800193 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMajor));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800194 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800195 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMinor));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800196 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800197 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.orientation));
198
Jeff Brown6f2fba42011-02-19 01:08:02 -0800199 uint64_t bits = env->GetLongField(pointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800200 if (bits) {
201 jfloatArray valuesArray = jfloatArray(env->GetObjectField(pointerCoordsObj,
202 gPointerCoordsClassInfo.mPackedAxisValues));
203 if (valuesArray) {
204 jfloat* values = static_cast<jfloat*>(
205 env->GetPrimitiveArrayCritical(valuesArray, NULL));
206
207 uint32_t index = 0;
208 do {
Jeff Browncc0c1592011-02-19 05:07:28 -0800209 uint32_t axis = __builtin_ctzll(bits);
Jeff Brown6f2fba42011-02-19 01:08:02 -0800210 uint64_t axisBit = 1LL << axis;
Jeff Brown91c69ab2011-02-14 17:03:18 -0800211 bits &= ~axisBit;
212 outRawPointerCoords->setAxisValue(axis, values[index++]);
213 } while (bits);
214
215 env->ReleasePrimitiveArrayCritical(valuesArray, values, JNI_ABORT);
216 env->DeleteLocalRef(valuesArray);
217 }
218 }
219}
220
221static jfloatArray obtainPackedAxisValuesArray(JNIEnv* env, uint32_t minSize,
222 jobject outPointerCoordsObj) {
223 jfloatArray outValuesArray = jfloatArray(env->GetObjectField(outPointerCoordsObj,
224 gPointerCoordsClassInfo.mPackedAxisValues));
225 if (outValuesArray) {
226 uint32_t size = env->GetArrayLength(outValuesArray);
227 if (minSize <= size) {
228 return outValuesArray;
229 }
230 env->DeleteLocalRef(outValuesArray);
231 }
232 uint32_t size = 8;
233 while (size < minSize) {
234 size *= 2;
235 }
236 outValuesArray = env->NewFloatArray(size);
237 env->SetObjectField(outPointerCoordsObj,
238 gPointerCoordsClassInfo.mPackedAxisValues, outValuesArray);
239 return outValuesArray;
240}
241
242static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointerCoords,
243 float xOffset, float yOffset, jobject outPointerCoordsObj) {
244 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.x,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800245 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_X) + xOffset);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800246 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.y,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800247 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_Y) + yOffset);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800248 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.pressure,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800249 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800250 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.size,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800251 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_SIZE));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800252 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMajor,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800253 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800254 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMinor,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800255 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800256 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMajor,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800257 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800258 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMinor,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800259 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800260 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.orientation,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800261 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800262
Jeff Brown6f2fba42011-02-19 01:08:02 -0800263 const uint64_t unpackedAxisBits = 0
264 | (1LL << AMOTION_EVENT_AXIS_X)
265 | (1LL << AMOTION_EVENT_AXIS_Y)
266 | (1LL << AMOTION_EVENT_AXIS_PRESSURE)
267 | (1LL << AMOTION_EVENT_AXIS_SIZE)
268 | (1LL << AMOTION_EVENT_AXIS_TOUCH_MAJOR)
269 | (1LL << AMOTION_EVENT_AXIS_TOUCH_MINOR)
270 | (1LL << AMOTION_EVENT_AXIS_TOOL_MAJOR)
271 | (1LL << AMOTION_EVENT_AXIS_TOOL_MINOR)
272 | (1LL << AMOTION_EVENT_AXIS_ORIENTATION);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800273
Jeff Brown6f2fba42011-02-19 01:08:02 -0800274 uint64_t outBits = 0;
275 uint64_t remainingBits = rawPointerCoords->bits & ~unpackedAxisBits;
Jeff Brown91c69ab2011-02-14 17:03:18 -0800276 if (remainingBits) {
Jeff Brown6f2fba42011-02-19 01:08:02 -0800277 uint32_t packedAxesCount = __builtin_popcountll(remainingBits);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800278 jfloatArray outValuesArray = obtainPackedAxisValuesArray(env, packedAxesCount,
279 outPointerCoordsObj);
280 if (!outValuesArray) {
281 return; // OOM
Jeff Brown20e987b2010-08-23 12:01:02 -0700282 }
283
Jeff Brown91c69ab2011-02-14 17:03:18 -0800284 jfloat* outValues = static_cast<jfloat*>(env->GetPrimitiveArrayCritical(
285 outValuesArray, NULL));
Jeff Brown20e987b2010-08-23 12:01:02 -0700286
Jeff Brown91c69ab2011-02-14 17:03:18 -0800287 const float* values = rawPointerCoords->values;
288 uint32_t index = 0;
289 do {
Jeff Browncc0c1592011-02-19 05:07:28 -0800290 uint32_t axis = __builtin_ctzll(remainingBits);
Jeff Brown6f2fba42011-02-19 01:08:02 -0800291 uint64_t axisBit = 1LL << axis;
Jeff Brown91c69ab2011-02-14 17:03:18 -0800292 remainingBits &= ~axisBit;
293 outBits |= axisBit;
294 outValues[index++] = rawPointerCoords->getAxisValue(axis);
295 } while (remainingBits);
296
297 env->ReleasePrimitiveArrayCritical(outValuesArray, outValues, 0);
298 env->DeleteLocalRef(outValuesArray);
299 }
Jeff Brown6f2fba42011-02-19 01:08:02 -0800300 env->SetLongField(outPointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits, outBits);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800301}
302
303
304// ----------------------------------------------------------------------------
305
306static jint android_view_MotionEvent_nativeInitialize(JNIEnv* env, jclass clazz,
307 jint nativePtr,
308 jint deviceId, jint source, jint action, jint flags, jint edgeFlags, jint metaState,
309 jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision,
310 jlong downTimeNanos, jlong eventTimeNanos,
311 jint pointerCount, jintArray pointerIdsArray, jobjectArray pointerCoordsObjArray) {
312 if (!validatePointerCount(env, pointerCount)
313 || !validatePointerIdsArray(env, pointerIdsArray, pointerCount)
314 || !validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
315 return 0;
Jeff Brown20e987b2010-08-23 12:01:02 -0700316 }
317
Jeff Brown91c69ab2011-02-14 17:03:18 -0800318 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
319 if (!event) {
320 event = new MotionEvent();
321 }
Jeff Brown20e987b2010-08-23 12:01:02 -0700322
Jeff Brown91c69ab2011-02-14 17:03:18 -0800323 PointerCoords rawPointerCoords[pointerCount];
Jeff Brown20e987b2010-08-23 12:01:02 -0700324
Jeff Brown91c69ab2011-02-14 17:03:18 -0800325 for (jint i = 0; i < pointerCount; i++) {
326 jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
327 if (!pointerCoordsObj) {
328 jniThrowNullPointerException(env, "pointerCoords");
329 if (!nativePtr) {
330 delete event;
331 }
332 return 0;
333 }
334 pointerCoordsToNative(env, pointerCoordsObj, xOffset, yOffset, &rawPointerCoords[i]);
335 env->DeleteLocalRef(pointerCoordsObj);
336 }
337
338 int* pointerIds = static_cast<int*>(env->GetPrimitiveArrayCritical(pointerIdsArray, NULL));
339
340 event->initialize(deviceId, source, action, flags, edgeFlags, metaState,
341 xOffset, yOffset, xPrecision, yPrecision,
342 downTimeNanos, eventTimeNanos, pointerCount, pointerIds, rawPointerCoords);
343
344 env->ReleasePrimitiveArrayCritical(pointerIdsArray, pointerIds, JNI_ABORT);
345 return reinterpret_cast<jint>(event);
346}
347
348static jint android_view_MotionEvent_nativeCopy(JNIEnv* env, jclass clazz,
349 jint destNativePtr, jint sourceNativePtr, jboolean keepHistory) {
350 MotionEvent* destEvent = reinterpret_cast<MotionEvent*>(destNativePtr);
351 if (!destEvent) {
352 destEvent = new MotionEvent();
353 }
354 MotionEvent* sourceEvent = reinterpret_cast<MotionEvent*>(sourceNativePtr);
355 destEvent->copyFrom(sourceEvent, keepHistory);
356 return reinterpret_cast<jint>(destEvent);
357}
358
359static void android_view_MotionEvent_nativeDispose(JNIEnv* env, jclass clazz,
360 jint nativePtr) {
361 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
362 delete event;
363}
364
365static void android_view_MotionEvent_nativeAddBatch(JNIEnv* env, jclass clazz,
366 jint nativePtr, jlong eventTimeNanos, jobjectArray pointerCoordsObjArray,
367 jint metaState) {
368 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
369 size_t pointerCount = event->getPointerCount();
370 if (!validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
371 return;
372 }
373
374 PointerCoords rawPointerCoords[pointerCount];
375
376 for (size_t i = 0; i < pointerCount; i++) {
377 jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
378 if (!pointerCoordsObj) {
379 jniThrowNullPointerException(env, "pointerCoords");
380 return;
381 }
382 pointerCoordsToNative(env, pointerCoordsObj,
383 event->getXOffset(), event->getYOffset(), &rawPointerCoords[i]);
384 env->DeleteLocalRef(pointerCoordsObj);
385 }
386
387 event->addSample(eventTimeNanos, rawPointerCoords);
388 event->setMetaState(event->getMetaState() | metaState);
389}
390
391static jint android_view_MotionEvent_nativeGetDeviceId(JNIEnv* env, jclass clazz,
392 jint nativePtr) {
393 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
394 return event->getDeviceId();
395}
396
397static jint android_view_MotionEvent_nativeGetSource(JNIEnv* env, jclass clazz,
398 jint nativePtr) {
399 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
400 return event->getSource();
401}
402
403static void android_view_MotionEvent_nativeSetSource(JNIEnv* env, jclass clazz,
404 jint nativePtr, jint source) {
405 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
406 event->setSource(source);
407}
408
409static jint android_view_MotionEvent_nativeGetAction(JNIEnv* env, jclass clazz,
410 jint nativePtr) {
411 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
412 return event->getAction();
413}
414
415static void android_view_MotionEvent_nativeSetAction(JNIEnv* env, jclass clazz,
416 jint nativePtr, jint action) {
417 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
418 event->setAction(action);
419}
420
Jeff Brown56194eb2011-03-02 19:23:13 -0800421static jboolean android_view_MotionEvent_nativeIsTouchEvent(JNIEnv* env, jclass clazz,
422 jint nativePtr) {
423 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
424 return event->isTouchEvent();
425}
426
Jeff Brown91c69ab2011-02-14 17:03:18 -0800427static jint android_view_MotionEvent_nativeGetFlags(JNIEnv* env, jclass clazz,
428 jint nativePtr) {
429 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
430 return event->getFlags();
431}
432
Jeff Brown21bc5c92011-02-28 18:27:14 -0800433static void android_view_MotionEvent_nativeSetFlags(JNIEnv* env, jclass clazz,
434 jint nativePtr, jint flags) {
435 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
436 event->setFlags(flags);
437}
438
Jeff Brown91c69ab2011-02-14 17:03:18 -0800439static jint android_view_MotionEvent_nativeGetEdgeFlags(JNIEnv* env, jclass clazz,
440 jint nativePtr) {
441 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
442 return event->getEdgeFlags();
443}
444
445static void android_view_MotionEvent_nativeSetEdgeFlags(JNIEnv* env, jclass clazz,
446 jint nativePtr, jint edgeFlags) {
447 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
448 event->setEdgeFlags(edgeFlags);
449}
450
451static jint android_view_MotionEvent_nativeGetMetaState(JNIEnv* env, jclass clazz,
452 jint nativePtr) {
453 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
454 return event->getMetaState();
455}
456
457static void android_view_MotionEvent_nativeOffsetLocation(JNIEnv* env, jclass clazz,
458 jint nativePtr, jfloat deltaX, jfloat deltaY) {
459 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
460 return event->offsetLocation(deltaX, deltaY);
461}
462
463static jfloat android_view_MotionEvent_nativeGetXPrecision(JNIEnv* env, jclass clazz,
464 jint nativePtr) {
465 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
466 return event->getXPrecision();
467}
468
469static jfloat android_view_MotionEvent_nativeGetYPrecision(JNIEnv* env, jclass clazz,
470 jint nativePtr) {
471 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
472 return event->getYPrecision();
473}
474
475static jlong android_view_MotionEvent_nativeGetDownTimeNanos(JNIEnv* env, jclass clazz,
476 jint nativePtr) {
477 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
478 return event->getDownTime();
479}
480
481static jint android_view_MotionEvent_nativeGetPointerCount(JNIEnv* env, jclass clazz,
482 jint nativePtr) {
483 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
484 return jint(event->getPointerCount());
485}
486
487static jint android_view_MotionEvent_nativeGetPointerId(JNIEnv* env, jclass clazz,
488 jint nativePtr, jint pointerIndex) {
489 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
490 size_t pointerCount = event->getPointerCount();
491 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
492 return -1;
493 }
494 return event->getPointerId(pointerIndex);
495}
496
497static jint android_view_MotionEvent_nativeFindPointerIndex(JNIEnv* env, jclass clazz,
498 jint nativePtr, jint pointerId) {
499 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
Jeff Brown2ed24622011-03-14 19:39:54 -0700500 return jint(event->findPointerIndex(pointerId));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800501}
502
503static jint android_view_MotionEvent_nativeGetHistorySize(JNIEnv* env, jclass clazz,
504 jint nativePtr) {
505 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
506 return jint(event->getHistorySize());
507}
508
509static jlong android_view_MotionEvent_nativeGetEventTimeNanos(JNIEnv* env, jclass clazz,
510 jint nativePtr, jint historyPos) {
511 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
512 if (historyPos == HISTORY_CURRENT) {
513 return event->getEventTime();
514 } else {
515 size_t historySize = event->getHistorySize();
516 if (!validateHistoryPos(env, historyPos, historySize)) {
517 return 0;
518 }
519 return event->getHistoricalEventTime(historyPos);
520 }
521}
522
523static jfloat android_view_MotionEvent_nativeGetRawAxisValue(JNIEnv* env, jclass clazz,
524 jint nativePtr, jint axis, jint pointerIndex, jint historyPos) {
525 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
526 size_t pointerCount = event->getPointerCount();
527 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
528 return 0;
529 }
530
531 if (historyPos == HISTORY_CURRENT) {
532 return event->getRawAxisValue(axis, pointerIndex);
533 } else {
534 size_t historySize = event->getHistorySize();
535 if (!validateHistoryPos(env, historyPos, historySize)) {
536 return 0;
537 }
538 return event->getHistoricalRawAxisValue(axis, pointerIndex, historyPos);
539 }
540}
541
542static jfloat android_view_MotionEvent_nativeGetAxisValue(JNIEnv* env, jclass clazz,
543 jint nativePtr, jint axis, jint pointerIndex, jint historyPos) {
544 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
545 size_t pointerCount = event->getPointerCount();
546 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
547 return 0;
548 }
549
550 if (historyPos == HISTORY_CURRENT) {
551 return event->getAxisValue(axis, pointerIndex);
552 } else {
553 size_t historySize = event->getHistorySize();
554 if (!validateHistoryPos(env, historyPos, historySize)) {
555 return 0;
556 }
557 return event->getHistoricalAxisValue(axis, pointerIndex, historyPos);
558 }
559}
560
561static void android_view_MotionEvent_nativeGetPointerCoords(JNIEnv* env, jclass clazz,
562 jint nativePtr, jint pointerIndex, jint historyPos, jobject outPointerCoordsObj) {
563 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
564 size_t pointerCount = event->getPointerCount();
565 if (!validatePointerIndex(env, pointerIndex, pointerCount)
566 || !validatePointerCoords(env, outPointerCoordsObj)) {
567 return;
568 }
569
570 const PointerCoords* rawPointerCoords;
571 if (historyPos == HISTORY_CURRENT) {
572 rawPointerCoords = event->getRawPointerCoords(pointerIndex);
573 } else {
574 size_t historySize = event->getHistorySize();
575 if (!validateHistoryPos(env, historyPos, historySize)) {
576 return;
577 }
578 rawPointerCoords = event->getHistoricalRawPointerCoords(pointerIndex, historyPos);
579 }
580 pointerCoordsFromNative(env, rawPointerCoords, event->getXOffset(), event->getYOffset(),
581 outPointerCoordsObj);
582}
583
584static void android_view_MotionEvent_nativeScale(JNIEnv* env, jclass clazz,
585 jint nativePtr, jfloat scale) {
586 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
587 event->scale(scale);
588}
589
590static void android_view_MotionEvent_nativeTransform(JNIEnv* env, jclass clazz,
591 jint nativePtr, jobject matrixObj) {
592 SkMatrix* matrix = android_graphics_Matrix_getSkMatrix(env, matrixObj);
593 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
594 event->transform(matrix);
595}
596
597static jint android_view_MotionEvent_nativeReadFromParcel(JNIEnv* env, jclass clazz,
598 jint nativePtr, jobject parcelObj) {
599 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
600 if (!event) {
601 event = new MotionEvent();
602 }
603
604 Parcel* parcel = parcelForJavaObject(env, parcelObj);
605
606 status_t status = event->readFromParcel(parcel);
Jeff Brownebbd5d12011-02-17 13:01:34 -0800607 if (status) {
Jeff Brown91c69ab2011-02-14 17:03:18 -0800608 if (!nativePtr) {
609 delete event;
610 }
611 jniThrowRuntimeException(env, "Failed to read MotionEvent parcel.");
612 return 0;
613 }
614 return reinterpret_cast<jint>(event);
615}
616
617static void android_view_MotionEvent_nativeWriteToParcel(JNIEnv* env, jclass clazz,
618 jint nativePtr, jobject parcelObj) {
619 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
620 Parcel* parcel = parcelForJavaObject(env, parcelObj);
621
622 status_t status = event->writeToParcel(parcel);
Jeff Brownebbd5d12011-02-17 13:01:34 -0800623 if (status) {
Jeff Brown91c69ab2011-02-14 17:03:18 -0800624 jniThrowRuntimeException(env, "Failed to write MotionEvent parcel.");
625 }
Jeff Brown20e987b2010-08-23 12:01:02 -0700626}
627
Jeff Brown46b9ac02010-04-22 18:58:52 -0700628// ----------------------------------------------------------------------------
629
Jeff Brown20e987b2010-08-23 12:01:02 -0700630static JNINativeMethod gMotionEventMethods[] = {
631 /* name, signature, funcPtr */
Jeff Brown91c69ab2011-02-14 17:03:18 -0800632 { "nativeInitialize",
633 "(IIIIIIIFFFFJJI[I[Landroid/view/MotionEvent$PointerCoords;)I",
634 (void*)android_view_MotionEvent_nativeInitialize },
635 { "nativeCopy",
636 "(IIZ)I",
637 (void*)android_view_MotionEvent_nativeCopy },
638 { "nativeDispose",
639 "(I)V",
640 (void*)android_view_MotionEvent_nativeDispose },
641 { "nativeAddBatch",
642 "(IJ[Landroid/view/MotionEvent$PointerCoords;I)V",
643 (void*)android_view_MotionEvent_nativeAddBatch },
644 { "nativeGetDeviceId",
645 "(I)I",
646 (void*)android_view_MotionEvent_nativeGetDeviceId },
647 { "nativeGetSource",
648 "(I)I",
649 (void*)android_view_MotionEvent_nativeGetSource },
650 { "nativeSetSource",
651 "(II)I",
652 (void*)android_view_MotionEvent_nativeSetSource },
653 { "nativeGetAction",
654 "(I)I",
655 (void*)android_view_MotionEvent_nativeGetAction },
656 { "nativeSetAction",
657 "(II)V",
658 (void*)android_view_MotionEvent_nativeSetAction },
Jeff Brown56194eb2011-03-02 19:23:13 -0800659 { "nativeIsTouchEvent",
660 "(I)Z",
661 (void*)android_view_MotionEvent_nativeIsTouchEvent },
Jeff Brown91c69ab2011-02-14 17:03:18 -0800662 { "nativeGetFlags",
663 "(I)I",
664 (void*)android_view_MotionEvent_nativeGetFlags },
Jeff Brown21bc5c92011-02-28 18:27:14 -0800665 { "nativeSetFlags",
666 "(II)V",
667 (void*)android_view_MotionEvent_nativeSetFlags },
Jeff Brown91c69ab2011-02-14 17:03:18 -0800668 { "nativeGetEdgeFlags",
669 "(I)I",
670 (void*)android_view_MotionEvent_nativeGetEdgeFlags },
671 { "nativeSetEdgeFlags",
672 "(II)V",
673 (void*)android_view_MotionEvent_nativeSetEdgeFlags },
674 { "nativeGetMetaState",
675 "(I)I",
676 (void*)android_view_MotionEvent_nativeGetMetaState },
677 { "nativeOffsetLocation",
678 "(IFF)V",
679 (void*)android_view_MotionEvent_nativeOffsetLocation },
680 { "nativeGetXPrecision",
681 "(I)F",
682 (void*)android_view_MotionEvent_nativeGetXPrecision },
683 { "nativeGetYPrecision",
684 "(I)F",
685 (void*)android_view_MotionEvent_nativeGetYPrecision },
686 { "nativeGetDownTimeNanos",
687 "(I)J",
688 (void*)android_view_MotionEvent_nativeGetDownTimeNanos },
689 { "nativeGetPointerCount",
690 "(I)I",
691 (void*)android_view_MotionEvent_nativeGetPointerCount },
692 { "nativeGetPointerId",
693 "(II)I",
694 (void*)android_view_MotionEvent_nativeGetPointerId },
695 { "nativeFindPointerIndex",
696 "(II)I",
697 (void*)android_view_MotionEvent_nativeFindPointerIndex },
698 { "nativeGetHistorySize",
699 "(I)I",
700 (void*)android_view_MotionEvent_nativeGetHistorySize },
701 { "nativeGetEventTimeNanos",
702 "(II)J",
703 (void*)android_view_MotionEvent_nativeGetEventTimeNanos },
704 { "nativeGetRawAxisValue",
705 "(IIII)F",
706 (void*)android_view_MotionEvent_nativeGetRawAxisValue },
707 { "nativeGetAxisValue",
708 "(IIII)F",
709 (void*)android_view_MotionEvent_nativeGetAxisValue },
710 { "nativeGetPointerCoords",
711 "(IIILandroid/view/MotionEvent$PointerCoords;)V",
712 (void*)android_view_MotionEvent_nativeGetPointerCoords },
713 { "nativeScale",
714 "(IF)V",
715 (void*)android_view_MotionEvent_nativeScale },
Jeff Brown20e987b2010-08-23 12:01:02 -0700716 { "nativeTransform",
Jeff Brown91c69ab2011-02-14 17:03:18 -0800717 "(ILandroid/graphics/Matrix;)V",
Jeff Brown20e987b2010-08-23 12:01:02 -0700718 (void*)android_view_MotionEvent_nativeTransform },
Jeff Brown91c69ab2011-02-14 17:03:18 -0800719 { "nativeReadFromParcel",
720 "(ILandroid/os/Parcel;)I",
721 (void*)android_view_MotionEvent_nativeReadFromParcel },
722 { "nativeWriteToParcel",
723 "(ILandroid/os/Parcel;)V",
724 (void*)android_view_MotionEvent_nativeWriteToParcel },
Jeff Brown20e987b2010-08-23 12:01:02 -0700725};
726
Jeff Brown46b9ac02010-04-22 18:58:52 -0700727#define FIND_CLASS(var, className) \
728 var = env->FindClass(className); \
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800729 LOG_FATAL_IF(! var, "Unable to find class " className);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700730
731#define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
732 var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
733 LOG_FATAL_IF(! var, "Unable to find static method" methodName);
734
735#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
736 var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
737 LOG_FATAL_IF(! var, "Unable to find method" methodName);
738
739#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
740 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
741 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
742
743int register_android_view_MotionEvent(JNIEnv* env) {
Jeff Brown20e987b2010-08-23 12:01:02 -0700744 int res = jniRegisterNativeMethods(env, "android/view/MotionEvent",
745 gMotionEventMethods, NELEM(gMotionEventMethods));
746 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
747
Jeff Brown46b9ac02010-04-22 18:58:52 -0700748 FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800749 gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz));
Jeff Brown46b9ac02010-04-22 18:58:52 -0700750
751 GET_STATIC_METHOD_ID(gMotionEventClassInfo.obtain, gMotionEventClassInfo.clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800752 "obtain", "()Landroid/view/MotionEvent;");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700753 GET_METHOD_ID(gMotionEventClassInfo.recycle, gMotionEventClassInfo.clazz,
754 "recycle", "()V");
Jeff Brown91c69ab2011-02-14 17:03:18 -0800755 GET_FIELD_ID(gMotionEventClassInfo.mNativePtr, gMotionEventClassInfo.clazz,
756 "mNativePtr", "I");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700757
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800758 jclass clazz;
759 FIND_CLASS(clazz, "android/view/MotionEvent$PointerCoords");
Jeff Brown91c69ab2011-02-14 17:03:18 -0800760
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800761 GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisBits, clazz,
Jeff Brown6f2fba42011-02-19 01:08:02 -0800762 "mPackedAxisBits", "J");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800763 GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisValues, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800764 "mPackedAxisValues", "[F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800765 GET_FIELD_ID(gPointerCoordsClassInfo.x, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800766 "x", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800767 GET_FIELD_ID(gPointerCoordsClassInfo.y, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800768 "y", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800769 GET_FIELD_ID(gPointerCoordsClassInfo.pressure, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800770 "pressure", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800771 GET_FIELD_ID(gPointerCoordsClassInfo.size, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800772 "size", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800773 GET_FIELD_ID(gPointerCoordsClassInfo.touchMajor, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800774 "touchMajor", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800775 GET_FIELD_ID(gPointerCoordsClassInfo.touchMinor, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800776 "touchMinor", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800777 GET_FIELD_ID(gPointerCoordsClassInfo.toolMajor, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800778 "toolMajor", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800779 GET_FIELD_ID(gPointerCoordsClassInfo.toolMinor, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800780 "toolMinor", "F");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800781 GET_FIELD_ID(gPointerCoordsClassInfo.orientation, clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800782 "orientation", "F");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700783
784 return 0;
785}
786
787} // namespace android