blob: 97cba23f84eac7028627052e3401b25851e836e8 [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 {
45 jclass clazz;
46
47 jfieldID mPackedAxisBits;
48 jfieldID mPackedAxisValues;
49 jfieldID x;
50 jfieldID y;
51 jfieldID pressure;
52 jfieldID size;
53 jfieldID touchMajor;
54 jfieldID touchMinor;
55 jfieldID toolMajor;
56 jfieldID toolMinor;
57 jfieldID orientation;
58} gPointerCoordsClassInfo;
59
Jeff Brown46b9ac02010-04-22 18:58:52 -070060// ----------------------------------------------------------------------------
61
Jeff Brown91c69ab2011-02-14 17:03:18 -080062static MotionEvent* android_view_MotionEvent_getNativePtr(JNIEnv* env, jobject eventObj) {
63 return reinterpret_cast<MotionEvent*>(
64 env->GetIntField(eventObj, gMotionEventClassInfo.mNativePtr));
65}
Jeff Brown46b9ac02010-04-22 18:58:52 -070066
Jeff Brown91c69ab2011-02-14 17:03:18 -080067static void android_view_MotionEvent_setNativePtr(JNIEnv* env, jobject eventObj,
68 MotionEvent* event) {
69 env->SetIntField(eventObj, gMotionEventClassInfo.mNativePtr,
70 reinterpret_cast<int>(event));
71}
72
73jobject android_view_MotionEvent_fromNative(JNIEnv* env, const MotionEvent* event) {
Jeff Brown46b9ac02010-04-22 18:58:52 -070074 jobject eventObj = env->CallStaticObjectMethod(gMotionEventClassInfo.clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -080075 gMotionEventClassInfo.obtain);
Jeff Brown46b9ac02010-04-22 18:58:52 -070076 if (env->ExceptionCheck()) {
77 LOGE("An exception occurred while obtaining a motion event.");
78 LOGE_EX(env);
79 env->ExceptionClear();
80 return NULL;
81 }
82
Jeff Brown91c69ab2011-02-14 17:03:18 -080083 MotionEvent* destEvent = android_view_MotionEvent_getNativePtr(env, eventObj);
84 if (!destEvent) {
85 destEvent = new MotionEvent();
86 android_view_MotionEvent_setNativePtr(env, eventObj, destEvent);
Jeff Brown46b9ac02010-04-22 18:58:52 -070087 }
88
Jeff Brown91c69ab2011-02-14 17:03:18 -080089 destEvent->copyFrom(event, true);
Jeff Brown46b9ac02010-04-22 18:58:52 -070090 return eventObj;
91}
92
Jeff Brown1f245102010-11-18 20:53:46 -080093status_t android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj,
Jeff Brown46b9ac02010-04-22 18:58:52 -070094 MotionEvent* event) {
Jeff Brown91c69ab2011-02-14 17:03:18 -080095 MotionEvent* srcEvent = android_view_MotionEvent_getNativePtr(env, eventObj);
96 if (!srcEvent) {
97 LOGE("MotionEvent was finalized");
Jeff Brown1f245102010-11-18 20:53:46 -080098 return BAD_VALUE;
99 }
100
Jeff Brown91c69ab2011-02-14 17:03:18 -0800101 event->copyFrom(srcEvent, true);
Jeff Brown1f245102010-11-18 20:53:46 -0800102 return OK;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700103}
104
Jeff Brown1f245102010-11-18 20:53:46 -0800105status_t android_view_MotionEvent_recycle(JNIEnv* env, jobject eventObj) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700106 env->CallVoidMethod(eventObj, gMotionEventClassInfo.recycle);
107 if (env->ExceptionCheck()) {
108 LOGW("An exception occurred while recycling a motion event.");
109 LOGW_EX(env);
110 env->ExceptionClear();
Jeff Brown1f245102010-11-18 20:53:46 -0800111 return UNKNOWN_ERROR;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700112 }
Jeff Brown1f245102010-11-18 20:53:46 -0800113 return OK;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700114}
115
Jeff Brown91c69ab2011-02-14 17:03:18 -0800116// ----------------------------------------------------------------------------
Jeff Brown20e987b2010-08-23 12:01:02 -0700117
Jeff Brown91c69ab2011-02-14 17:03:18 -0800118static const jint HISTORY_CURRENT = -0x80000000;
119
120static bool validatePointerCount(JNIEnv* env, jint pointerCount) {
121 if (pointerCount < 1) {
122 jniThrowException(env, "java/lang/IllegalArgumentException",
123 "pointerCount must be at least 1");
124 return false;
Jeff Brown20e987b2010-08-23 12:01:02 -0700125 }
Jeff Brown91c69ab2011-02-14 17:03:18 -0800126 return true;
Jeff Brown20e987b2010-08-23 12:01:02 -0700127}
128
Jeff Brown91c69ab2011-02-14 17:03:18 -0800129static bool validatePointerIdsArray(JNIEnv* env, jintArray pointerIdsArray,
130 size_t pointerCount) {
131 if (!pointerIdsArray) {
132 jniThrowException(env, "java/lang/IllegalArgumentException",
133 "pointerIds array must not be null");
134 return false;
135 }
136 size_t length = size_t(env->GetArrayLength(pointerIdsArray));
137 if (length < pointerCount) {
138 jniThrowException(env, "java/lang/IllegalArgumentException",
139 "pointerIds array must be large enough to hold all pointers");
140 return false;
141 }
142 return true;
143}
Jeff Brown20e987b2010-08-23 12:01:02 -0700144
Jeff Brown91c69ab2011-02-14 17:03:18 -0800145static bool validatePointerCoordsObjArray(JNIEnv* env, jobjectArray pointerCoordsObjArray,
146 size_t pointerCount) {
147 if (!pointerCoordsObjArray) {
148 jniThrowException(env, "java/lang/IllegalArgumentException",
149 "pointerCoords array must not be null");
150 return false;
151 }
152 size_t length = size_t(env->GetArrayLength(pointerCoordsObjArray));
153 if (length < pointerCount) {
154 jniThrowException(env, "java/lang/IllegalArgumentException",
155 "pointerCoords array must be large enough to hold all pointers");
156 return false;
157 }
158 return true;
159}
Jeff Brown20e987b2010-08-23 12:01:02 -0700160
Jeff Brown91c69ab2011-02-14 17:03:18 -0800161static bool validatePointerIndex(JNIEnv* env, jint pointerIndex, size_t pointerCount) {
162 if (pointerIndex < 0 || size_t(pointerIndex) >= pointerCount) {
163 jniThrowException(env, "java/lang/IllegalArgumentException",
164 "pointerIndex out of range");
165 return false;
166 }
167 return true;
168}
Jeff Brown20e987b2010-08-23 12:01:02 -0700169
Jeff Brown91c69ab2011-02-14 17:03:18 -0800170static bool validateHistoryPos(JNIEnv* env, jint historyPos, size_t historySize) {
171 if (historyPos < 0 || size_t(historyPos) >= historySize) {
172 jniThrowException(env, "java/lang/IllegalArgumentException",
173 "historyPos out of range");
174 return false;
175 }
176 return true;
177}
Jeff Brown20e987b2010-08-23 12:01:02 -0700178
Jeff Brown91c69ab2011-02-14 17:03:18 -0800179static bool validatePointerCoords(JNIEnv* env, jobject pointerCoordsObj) {
180 if (!pointerCoordsObj) {
181 jniThrowException(env, "java/lang/IllegalArgumentException",
182 "pointerCoords must not be null");
183 return false;
184 }
185 return true;
186}
187
188static void pointerCoordsToNative(JNIEnv* env, jobject pointerCoordsObj,
189 float xOffset, float yOffset, PointerCoords* outRawPointerCoords) {
190 outRawPointerCoords->clear();
Jeff Brownebbd5d12011-02-17 13:01:34 -0800191 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_X,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800192 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.x) - xOffset);
Jeff Brownebbd5d12011-02-17 13:01:34 -0800193 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_Y,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800194 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.y) - yOffset);
Jeff Brownebbd5d12011-02-17 13:01:34 -0800195 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800196 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.pressure));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800197 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_SIZE,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800198 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.size));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800199 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800200 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMajor));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800201 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800202 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.touchMinor));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800203 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800204 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMajor));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800205 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800206 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.toolMinor));
Jeff Brownebbd5d12011-02-17 13:01:34 -0800207 outRawPointerCoords->setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800208 env->GetFloatField(pointerCoordsObj, gPointerCoordsClassInfo.orientation));
209
Jeff Brown6f2fba42011-02-19 01:08:02 -0800210 uint64_t bits = env->GetLongField(pointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800211 if (bits) {
212 jfloatArray valuesArray = jfloatArray(env->GetObjectField(pointerCoordsObj,
213 gPointerCoordsClassInfo.mPackedAxisValues));
214 if (valuesArray) {
215 jfloat* values = static_cast<jfloat*>(
216 env->GetPrimitiveArrayCritical(valuesArray, NULL));
217
218 uint32_t index = 0;
219 do {
Jeff Browncc0c1592011-02-19 05:07:28 -0800220 uint32_t axis = __builtin_ctzll(bits);
Jeff Brown6f2fba42011-02-19 01:08:02 -0800221 uint64_t axisBit = 1LL << axis;
Jeff Brown91c69ab2011-02-14 17:03:18 -0800222 bits &= ~axisBit;
223 outRawPointerCoords->setAxisValue(axis, values[index++]);
224 } while (bits);
225
226 env->ReleasePrimitiveArrayCritical(valuesArray, values, JNI_ABORT);
227 env->DeleteLocalRef(valuesArray);
228 }
229 }
230}
231
232static jfloatArray obtainPackedAxisValuesArray(JNIEnv* env, uint32_t minSize,
233 jobject outPointerCoordsObj) {
234 jfloatArray outValuesArray = jfloatArray(env->GetObjectField(outPointerCoordsObj,
235 gPointerCoordsClassInfo.mPackedAxisValues));
236 if (outValuesArray) {
237 uint32_t size = env->GetArrayLength(outValuesArray);
238 if (minSize <= size) {
239 return outValuesArray;
240 }
241 env->DeleteLocalRef(outValuesArray);
242 }
243 uint32_t size = 8;
244 while (size < minSize) {
245 size *= 2;
246 }
247 outValuesArray = env->NewFloatArray(size);
248 env->SetObjectField(outPointerCoordsObj,
249 gPointerCoordsClassInfo.mPackedAxisValues, outValuesArray);
250 return outValuesArray;
251}
252
253static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointerCoords,
254 float xOffset, float yOffset, jobject outPointerCoordsObj) {
255 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.x,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800256 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_X) + xOffset);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800257 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.y,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800258 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_Y) + yOffset);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800259 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.pressure,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800260 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800261 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.size,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800262 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_SIZE));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800263 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMajor,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800264 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800265 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.touchMinor,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800266 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800267 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMajor,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800268 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800269 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.toolMinor,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800270 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800271 env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.orientation,
Jeff Brownebbd5d12011-02-17 13:01:34 -0800272 rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
Jeff Brown91c69ab2011-02-14 17:03:18 -0800273
Jeff Brown6f2fba42011-02-19 01:08:02 -0800274 const uint64_t unpackedAxisBits = 0
275 | (1LL << AMOTION_EVENT_AXIS_X)
276 | (1LL << AMOTION_EVENT_AXIS_Y)
277 | (1LL << AMOTION_EVENT_AXIS_PRESSURE)
278 | (1LL << AMOTION_EVENT_AXIS_SIZE)
279 | (1LL << AMOTION_EVENT_AXIS_TOUCH_MAJOR)
280 | (1LL << AMOTION_EVENT_AXIS_TOUCH_MINOR)
281 | (1LL << AMOTION_EVENT_AXIS_TOOL_MAJOR)
282 | (1LL << AMOTION_EVENT_AXIS_TOOL_MINOR)
283 | (1LL << AMOTION_EVENT_AXIS_ORIENTATION);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800284
Jeff Brown6f2fba42011-02-19 01:08:02 -0800285 uint64_t outBits = 0;
286 uint64_t remainingBits = rawPointerCoords->bits & ~unpackedAxisBits;
Jeff Brown91c69ab2011-02-14 17:03:18 -0800287 if (remainingBits) {
Jeff Brown6f2fba42011-02-19 01:08:02 -0800288 uint32_t packedAxesCount = __builtin_popcountll(remainingBits);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800289 jfloatArray outValuesArray = obtainPackedAxisValuesArray(env, packedAxesCount,
290 outPointerCoordsObj);
291 if (!outValuesArray) {
292 return; // OOM
Jeff Brown20e987b2010-08-23 12:01:02 -0700293 }
294
Jeff Brown91c69ab2011-02-14 17:03:18 -0800295 jfloat* outValues = static_cast<jfloat*>(env->GetPrimitiveArrayCritical(
296 outValuesArray, NULL));
Jeff Brown20e987b2010-08-23 12:01:02 -0700297
Jeff Brown91c69ab2011-02-14 17:03:18 -0800298 const float* values = rawPointerCoords->values;
299 uint32_t index = 0;
300 do {
Jeff Browncc0c1592011-02-19 05:07:28 -0800301 uint32_t axis = __builtin_ctzll(remainingBits);
Jeff Brown6f2fba42011-02-19 01:08:02 -0800302 uint64_t axisBit = 1LL << axis;
Jeff Brown91c69ab2011-02-14 17:03:18 -0800303 remainingBits &= ~axisBit;
304 outBits |= axisBit;
305 outValues[index++] = rawPointerCoords->getAxisValue(axis);
306 } while (remainingBits);
307
308 env->ReleasePrimitiveArrayCritical(outValuesArray, outValues, 0);
309 env->DeleteLocalRef(outValuesArray);
310 }
Jeff Brown6f2fba42011-02-19 01:08:02 -0800311 env->SetLongField(outPointerCoordsObj, gPointerCoordsClassInfo.mPackedAxisBits, outBits);
Jeff Brown91c69ab2011-02-14 17:03:18 -0800312}
313
314
315// ----------------------------------------------------------------------------
316
317static jint android_view_MotionEvent_nativeInitialize(JNIEnv* env, jclass clazz,
318 jint nativePtr,
319 jint deviceId, jint source, jint action, jint flags, jint edgeFlags, jint metaState,
320 jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision,
321 jlong downTimeNanos, jlong eventTimeNanos,
322 jint pointerCount, jintArray pointerIdsArray, jobjectArray pointerCoordsObjArray) {
323 if (!validatePointerCount(env, pointerCount)
324 || !validatePointerIdsArray(env, pointerIdsArray, pointerCount)
325 || !validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
326 return 0;
Jeff Brown20e987b2010-08-23 12:01:02 -0700327 }
328
Jeff Brown91c69ab2011-02-14 17:03:18 -0800329 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
330 if (!event) {
331 event = new MotionEvent();
332 }
Jeff Brown20e987b2010-08-23 12:01:02 -0700333
Jeff Brown91c69ab2011-02-14 17:03:18 -0800334 PointerCoords rawPointerCoords[pointerCount];
Jeff Brown20e987b2010-08-23 12:01:02 -0700335
Jeff Brown91c69ab2011-02-14 17:03:18 -0800336 for (jint i = 0; i < pointerCount; i++) {
337 jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
338 if (!pointerCoordsObj) {
339 jniThrowNullPointerException(env, "pointerCoords");
340 if (!nativePtr) {
341 delete event;
342 }
343 return 0;
344 }
345 pointerCoordsToNative(env, pointerCoordsObj, xOffset, yOffset, &rawPointerCoords[i]);
346 env->DeleteLocalRef(pointerCoordsObj);
347 }
348
349 int* pointerIds = static_cast<int*>(env->GetPrimitiveArrayCritical(pointerIdsArray, NULL));
350
351 event->initialize(deviceId, source, action, flags, edgeFlags, metaState,
352 xOffset, yOffset, xPrecision, yPrecision,
353 downTimeNanos, eventTimeNanos, pointerCount, pointerIds, rawPointerCoords);
354
355 env->ReleasePrimitiveArrayCritical(pointerIdsArray, pointerIds, JNI_ABORT);
356 return reinterpret_cast<jint>(event);
357}
358
359static jint android_view_MotionEvent_nativeCopy(JNIEnv* env, jclass clazz,
360 jint destNativePtr, jint sourceNativePtr, jboolean keepHistory) {
361 MotionEvent* destEvent = reinterpret_cast<MotionEvent*>(destNativePtr);
362 if (!destEvent) {
363 destEvent = new MotionEvent();
364 }
365 MotionEvent* sourceEvent = reinterpret_cast<MotionEvent*>(sourceNativePtr);
366 destEvent->copyFrom(sourceEvent, keepHistory);
367 return reinterpret_cast<jint>(destEvent);
368}
369
370static void android_view_MotionEvent_nativeDispose(JNIEnv* env, jclass clazz,
371 jint nativePtr) {
372 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
373 delete event;
374}
375
376static void android_view_MotionEvent_nativeAddBatch(JNIEnv* env, jclass clazz,
377 jint nativePtr, jlong eventTimeNanos, jobjectArray pointerCoordsObjArray,
378 jint metaState) {
379 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
380 size_t pointerCount = event->getPointerCount();
381 if (!validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
382 return;
383 }
384
385 PointerCoords rawPointerCoords[pointerCount];
386
387 for (size_t i = 0; i < pointerCount; i++) {
388 jobject pointerCoordsObj = env->GetObjectArrayElement(pointerCoordsObjArray, i);
389 if (!pointerCoordsObj) {
390 jniThrowNullPointerException(env, "pointerCoords");
391 return;
392 }
393 pointerCoordsToNative(env, pointerCoordsObj,
394 event->getXOffset(), event->getYOffset(), &rawPointerCoords[i]);
395 env->DeleteLocalRef(pointerCoordsObj);
396 }
397
398 event->addSample(eventTimeNanos, rawPointerCoords);
399 event->setMetaState(event->getMetaState() | metaState);
400}
401
402static jint android_view_MotionEvent_nativeGetDeviceId(JNIEnv* env, jclass clazz,
403 jint nativePtr) {
404 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
405 return event->getDeviceId();
406}
407
408static jint android_view_MotionEvent_nativeGetSource(JNIEnv* env, jclass clazz,
409 jint nativePtr) {
410 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
411 return event->getSource();
412}
413
414static void android_view_MotionEvent_nativeSetSource(JNIEnv* env, jclass clazz,
415 jint nativePtr, jint source) {
416 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
417 event->setSource(source);
418}
419
420static jint android_view_MotionEvent_nativeGetAction(JNIEnv* env, jclass clazz,
421 jint nativePtr) {
422 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
423 return event->getAction();
424}
425
426static void android_view_MotionEvent_nativeSetAction(JNIEnv* env, jclass clazz,
427 jint nativePtr, jint action) {
428 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
429 event->setAction(action);
430}
431
Jeff Brown56194eb2011-03-02 19:23:13 -0800432static jboolean android_view_MotionEvent_nativeIsTouchEvent(JNIEnv* env, jclass clazz,
433 jint nativePtr) {
434 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
435 return event->isTouchEvent();
436}
437
Jeff Brown91c69ab2011-02-14 17:03:18 -0800438static jint android_view_MotionEvent_nativeGetFlags(JNIEnv* env, jclass clazz,
439 jint nativePtr) {
440 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
441 return event->getFlags();
442}
443
444static jint android_view_MotionEvent_nativeGetEdgeFlags(JNIEnv* env, jclass clazz,
445 jint nativePtr) {
446 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
447 return event->getEdgeFlags();
448}
449
450static void android_view_MotionEvent_nativeSetEdgeFlags(JNIEnv* env, jclass clazz,
451 jint nativePtr, jint edgeFlags) {
452 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
453 event->setEdgeFlags(edgeFlags);
454}
455
456static jint android_view_MotionEvent_nativeGetMetaState(JNIEnv* env, jclass clazz,
457 jint nativePtr) {
458 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
459 return event->getMetaState();
460}
461
462static void android_view_MotionEvent_nativeOffsetLocation(JNIEnv* env, jclass clazz,
463 jint nativePtr, jfloat deltaX, jfloat deltaY) {
464 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
465 return event->offsetLocation(deltaX, deltaY);
466}
467
468static jfloat android_view_MotionEvent_nativeGetXPrecision(JNIEnv* env, jclass clazz,
469 jint nativePtr) {
470 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
471 return event->getXPrecision();
472}
473
474static jfloat android_view_MotionEvent_nativeGetYPrecision(JNIEnv* env, jclass clazz,
475 jint nativePtr) {
476 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
477 return event->getYPrecision();
478}
479
480static jlong android_view_MotionEvent_nativeGetDownTimeNanos(JNIEnv* env, jclass clazz,
481 jint nativePtr) {
482 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
483 return event->getDownTime();
484}
485
486static jint android_view_MotionEvent_nativeGetPointerCount(JNIEnv* env, jclass clazz,
487 jint nativePtr) {
488 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
489 return jint(event->getPointerCount());
490}
491
492static jint android_view_MotionEvent_nativeGetPointerId(JNIEnv* env, jclass clazz,
493 jint nativePtr, jint pointerIndex) {
494 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
495 size_t pointerCount = event->getPointerCount();
496 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
497 return -1;
498 }
499 return event->getPointerId(pointerIndex);
500}
501
502static jint android_view_MotionEvent_nativeFindPointerIndex(JNIEnv* env, jclass clazz,
503 jint nativePtr, jint pointerId) {
504 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
505 size_t pointerCount = event->getPointerCount();
506 for (size_t i = 0; i < pointerCount; i++) {
507 if (event->getPointerId(i) == pointerId) {
508 return i;
509 }
510 }
511 return -1;
512}
513
514static jint android_view_MotionEvent_nativeGetHistorySize(JNIEnv* env, jclass clazz,
515 jint nativePtr) {
516 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
517 return jint(event->getHistorySize());
518}
519
520static jlong android_view_MotionEvent_nativeGetEventTimeNanos(JNIEnv* env, jclass clazz,
521 jint nativePtr, jint historyPos) {
522 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
523 if (historyPos == HISTORY_CURRENT) {
524 return event->getEventTime();
525 } else {
526 size_t historySize = event->getHistorySize();
527 if (!validateHistoryPos(env, historyPos, historySize)) {
528 return 0;
529 }
530 return event->getHistoricalEventTime(historyPos);
531 }
532}
533
534static jfloat android_view_MotionEvent_nativeGetRawAxisValue(JNIEnv* env, jclass clazz,
535 jint nativePtr, jint axis, jint pointerIndex, jint historyPos) {
536 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
537 size_t pointerCount = event->getPointerCount();
538 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
539 return 0;
540 }
541
542 if (historyPos == HISTORY_CURRENT) {
543 return event->getRawAxisValue(axis, pointerIndex);
544 } else {
545 size_t historySize = event->getHistorySize();
546 if (!validateHistoryPos(env, historyPos, historySize)) {
547 return 0;
548 }
549 return event->getHistoricalRawAxisValue(axis, pointerIndex, historyPos);
550 }
551}
552
553static jfloat android_view_MotionEvent_nativeGetAxisValue(JNIEnv* env, jclass clazz,
554 jint nativePtr, jint axis, jint pointerIndex, jint historyPos) {
555 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
556 size_t pointerCount = event->getPointerCount();
557 if (!validatePointerIndex(env, pointerIndex, pointerCount)) {
558 return 0;
559 }
560
561 if (historyPos == HISTORY_CURRENT) {
562 return event->getAxisValue(axis, pointerIndex);
563 } else {
564 size_t historySize = event->getHistorySize();
565 if (!validateHistoryPos(env, historyPos, historySize)) {
566 return 0;
567 }
568 return event->getHistoricalAxisValue(axis, pointerIndex, historyPos);
569 }
570}
571
572static void android_view_MotionEvent_nativeGetPointerCoords(JNIEnv* env, jclass clazz,
573 jint nativePtr, jint pointerIndex, jint historyPos, jobject outPointerCoordsObj) {
574 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
575 size_t pointerCount = event->getPointerCount();
576 if (!validatePointerIndex(env, pointerIndex, pointerCount)
577 || !validatePointerCoords(env, outPointerCoordsObj)) {
578 return;
579 }
580
581 const PointerCoords* rawPointerCoords;
582 if (historyPos == HISTORY_CURRENT) {
583 rawPointerCoords = event->getRawPointerCoords(pointerIndex);
584 } else {
585 size_t historySize = event->getHistorySize();
586 if (!validateHistoryPos(env, historyPos, historySize)) {
587 return;
588 }
589 rawPointerCoords = event->getHistoricalRawPointerCoords(pointerIndex, historyPos);
590 }
591 pointerCoordsFromNative(env, rawPointerCoords, event->getXOffset(), event->getYOffset(),
592 outPointerCoordsObj);
593}
594
595static void android_view_MotionEvent_nativeScale(JNIEnv* env, jclass clazz,
596 jint nativePtr, jfloat scale) {
597 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
598 event->scale(scale);
599}
600
601static void android_view_MotionEvent_nativeTransform(JNIEnv* env, jclass clazz,
602 jint nativePtr, jobject matrixObj) {
603 SkMatrix* matrix = android_graphics_Matrix_getSkMatrix(env, matrixObj);
604 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
605 event->transform(matrix);
606}
607
608static jint android_view_MotionEvent_nativeReadFromParcel(JNIEnv* env, jclass clazz,
609 jint nativePtr, jobject parcelObj) {
610 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
611 if (!event) {
612 event = new MotionEvent();
613 }
614
615 Parcel* parcel = parcelForJavaObject(env, parcelObj);
616
617 status_t status = event->readFromParcel(parcel);
Jeff Brownebbd5d12011-02-17 13:01:34 -0800618 if (status) {
Jeff Brown91c69ab2011-02-14 17:03:18 -0800619 if (!nativePtr) {
620 delete event;
621 }
622 jniThrowRuntimeException(env, "Failed to read MotionEvent parcel.");
623 return 0;
624 }
625 return reinterpret_cast<jint>(event);
626}
627
628static void android_view_MotionEvent_nativeWriteToParcel(JNIEnv* env, jclass clazz,
629 jint nativePtr, jobject parcelObj) {
630 MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
631 Parcel* parcel = parcelForJavaObject(env, parcelObj);
632
633 status_t status = event->writeToParcel(parcel);
Jeff Brownebbd5d12011-02-17 13:01:34 -0800634 if (status) {
Jeff Brown91c69ab2011-02-14 17:03:18 -0800635 jniThrowRuntimeException(env, "Failed to write MotionEvent parcel.");
636 }
Jeff Brown20e987b2010-08-23 12:01:02 -0700637}
638
Jeff Brown46b9ac02010-04-22 18:58:52 -0700639// ----------------------------------------------------------------------------
640
Jeff Brown20e987b2010-08-23 12:01:02 -0700641static JNINativeMethod gMotionEventMethods[] = {
642 /* name, signature, funcPtr */
Jeff Brown91c69ab2011-02-14 17:03:18 -0800643 { "nativeInitialize",
644 "(IIIIIIIFFFFJJI[I[Landroid/view/MotionEvent$PointerCoords;)I",
645 (void*)android_view_MotionEvent_nativeInitialize },
646 { "nativeCopy",
647 "(IIZ)I",
648 (void*)android_view_MotionEvent_nativeCopy },
649 { "nativeDispose",
650 "(I)V",
651 (void*)android_view_MotionEvent_nativeDispose },
652 { "nativeAddBatch",
653 "(IJ[Landroid/view/MotionEvent$PointerCoords;I)V",
654 (void*)android_view_MotionEvent_nativeAddBatch },
655 { "nativeGetDeviceId",
656 "(I)I",
657 (void*)android_view_MotionEvent_nativeGetDeviceId },
658 { "nativeGetSource",
659 "(I)I",
660 (void*)android_view_MotionEvent_nativeGetSource },
661 { "nativeSetSource",
662 "(II)I",
663 (void*)android_view_MotionEvent_nativeSetSource },
664 { "nativeGetAction",
665 "(I)I",
666 (void*)android_view_MotionEvent_nativeGetAction },
667 { "nativeSetAction",
668 "(II)V",
669 (void*)android_view_MotionEvent_nativeSetAction },
Jeff Brown56194eb2011-03-02 19:23:13 -0800670 { "nativeIsTouchEvent",
671 "(I)Z",
672 (void*)android_view_MotionEvent_nativeIsTouchEvent },
Jeff Brown91c69ab2011-02-14 17:03:18 -0800673 { "nativeGetFlags",
674 "(I)I",
675 (void*)android_view_MotionEvent_nativeGetFlags },
676 { "nativeGetEdgeFlags",
677 "(I)I",
678 (void*)android_view_MotionEvent_nativeGetEdgeFlags },
679 { "nativeSetEdgeFlags",
680 "(II)V",
681 (void*)android_view_MotionEvent_nativeSetEdgeFlags },
682 { "nativeGetMetaState",
683 "(I)I",
684 (void*)android_view_MotionEvent_nativeGetMetaState },
685 { "nativeOffsetLocation",
686 "(IFF)V",
687 (void*)android_view_MotionEvent_nativeOffsetLocation },
688 { "nativeGetXPrecision",
689 "(I)F",
690 (void*)android_view_MotionEvent_nativeGetXPrecision },
691 { "nativeGetYPrecision",
692 "(I)F",
693 (void*)android_view_MotionEvent_nativeGetYPrecision },
694 { "nativeGetDownTimeNanos",
695 "(I)J",
696 (void*)android_view_MotionEvent_nativeGetDownTimeNanos },
697 { "nativeGetPointerCount",
698 "(I)I",
699 (void*)android_view_MotionEvent_nativeGetPointerCount },
700 { "nativeGetPointerId",
701 "(II)I",
702 (void*)android_view_MotionEvent_nativeGetPointerId },
703 { "nativeFindPointerIndex",
704 "(II)I",
705 (void*)android_view_MotionEvent_nativeFindPointerIndex },
706 { "nativeGetHistorySize",
707 "(I)I",
708 (void*)android_view_MotionEvent_nativeGetHistorySize },
709 { "nativeGetEventTimeNanos",
710 "(II)J",
711 (void*)android_view_MotionEvent_nativeGetEventTimeNanos },
712 { "nativeGetRawAxisValue",
713 "(IIII)F",
714 (void*)android_view_MotionEvent_nativeGetRawAxisValue },
715 { "nativeGetAxisValue",
716 "(IIII)F",
717 (void*)android_view_MotionEvent_nativeGetAxisValue },
718 { "nativeGetPointerCoords",
719 "(IIILandroid/view/MotionEvent$PointerCoords;)V",
720 (void*)android_view_MotionEvent_nativeGetPointerCoords },
721 { "nativeScale",
722 "(IF)V",
723 (void*)android_view_MotionEvent_nativeScale },
Jeff Brown20e987b2010-08-23 12:01:02 -0700724 { "nativeTransform",
Jeff Brown91c69ab2011-02-14 17:03:18 -0800725 "(ILandroid/graphics/Matrix;)V",
Jeff Brown20e987b2010-08-23 12:01:02 -0700726 (void*)android_view_MotionEvent_nativeTransform },
Jeff Brown91c69ab2011-02-14 17:03:18 -0800727 { "nativeReadFromParcel",
728 "(ILandroid/os/Parcel;)I",
729 (void*)android_view_MotionEvent_nativeReadFromParcel },
730 { "nativeWriteToParcel",
731 "(ILandroid/os/Parcel;)V",
732 (void*)android_view_MotionEvent_nativeWriteToParcel },
Jeff Brown20e987b2010-08-23 12:01:02 -0700733};
734
Jeff Brown46b9ac02010-04-22 18:58:52 -0700735#define FIND_CLASS(var, className) \
736 var = env->FindClass(className); \
737 LOG_FATAL_IF(! var, "Unable to find class " className); \
738 var = jclass(env->NewGlobalRef(var));
739
740#define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
741 var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
742 LOG_FATAL_IF(! var, "Unable to find static method" methodName);
743
744#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
745 var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
746 LOG_FATAL_IF(! var, "Unable to find method" methodName);
747
748#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
749 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
750 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
751
752int register_android_view_MotionEvent(JNIEnv* env) {
Jeff Brown20e987b2010-08-23 12:01:02 -0700753 int res = jniRegisterNativeMethods(env, "android/view/MotionEvent",
754 gMotionEventMethods, NELEM(gMotionEventMethods));
755 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
756
Jeff Brown46b9ac02010-04-22 18:58:52 -0700757 FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
758
759 GET_STATIC_METHOD_ID(gMotionEventClassInfo.obtain, gMotionEventClassInfo.clazz,
Jeff Brown91c69ab2011-02-14 17:03:18 -0800760 "obtain", "()Landroid/view/MotionEvent;");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700761 GET_METHOD_ID(gMotionEventClassInfo.recycle, gMotionEventClassInfo.clazz,
762 "recycle", "()V");
Jeff Brown91c69ab2011-02-14 17:03:18 -0800763 GET_FIELD_ID(gMotionEventClassInfo.mNativePtr, gMotionEventClassInfo.clazz,
764 "mNativePtr", "I");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700765
Jeff Brown91c69ab2011-02-14 17:03:18 -0800766 FIND_CLASS(gPointerCoordsClassInfo.clazz, "android/view/MotionEvent$PointerCoords");
767
768 GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisBits, gPointerCoordsClassInfo.clazz,
Jeff Brown6f2fba42011-02-19 01:08:02 -0800769 "mPackedAxisBits", "J");
Jeff Brown91c69ab2011-02-14 17:03:18 -0800770 GET_FIELD_ID(gPointerCoordsClassInfo.mPackedAxisValues, gPointerCoordsClassInfo.clazz,
771 "mPackedAxisValues", "[F");
772 GET_FIELD_ID(gPointerCoordsClassInfo.x, gPointerCoordsClassInfo.clazz,
773 "x", "F");
774 GET_FIELD_ID(gPointerCoordsClassInfo.y, gPointerCoordsClassInfo.clazz,
775 "y", "F");
776 GET_FIELD_ID(gPointerCoordsClassInfo.pressure, gPointerCoordsClassInfo.clazz,
777 "pressure", "F");
778 GET_FIELD_ID(gPointerCoordsClassInfo.size, gPointerCoordsClassInfo.clazz,
779 "size", "F");
780 GET_FIELD_ID(gPointerCoordsClassInfo.touchMajor, gPointerCoordsClassInfo.clazz,
781 "touchMajor", "F");
782 GET_FIELD_ID(gPointerCoordsClassInfo.touchMinor, gPointerCoordsClassInfo.clazz,
783 "touchMinor", "F");
784 GET_FIELD_ID(gPointerCoordsClassInfo.toolMajor, gPointerCoordsClassInfo.clazz,
785 "toolMajor", "F");
786 GET_FIELD_ID(gPointerCoordsClassInfo.toolMinor, gPointerCoordsClassInfo.clazz,
787 "toolMinor", "F");
788 GET_FIELD_ID(gPointerCoordsClassInfo.orientation, gPointerCoordsClassInfo.clazz,
789 "orientation", "F");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700790
791 return 0;
792}
793
794} // namespace android