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