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