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 "InputManager-JNI" 18 19 //#define LOG_NDEBUG 0 20 21 // Log debug messages about InputReaderPolicy 22 #define DEBUG_INPUT_READER_POLICY 0 23 24 // Log debug messages about InputDispatcherPolicy 25 #define DEBUG_INPUT_DISPATCHER_POLICY 0 26 27 28 #include "JNIHelp.h" 29 #include "jni.h" 30 #include <limits.h> 31 #include <android_runtime/AndroidRuntime.h> 32 #include <android_runtime/Log.h> 33 34 #include <utils/Log.h> 35 #include <utils/Looper.h> 36 #include <utils/threads.h> 37 38 #include <input/PointerController.h> 39 #include <input/SpriteController.h> 40 41 #include <inputflinger/InputManager.h> 42 43 #include <android_os_MessageQueue.h> 44 #include <android_view_InputDevice.h> 45 #include <android_view_KeyEvent.h> 46 #include <android_view_MotionEvent.h> 47 #include <android_view_InputChannel.h> 48 #include <android_view_PointerIcon.h> 49 #include <android/graphics/GraphicsJNI.h> 50 51 #include <ScopedLocalRef.h> 52 #include <ScopedPrimitiveArray.h> 53 #include <ScopedUtfChars.h> 54 55 #include "com_android_server_power_PowerManagerService.h" 56 #include "com_android_server_input_InputApplicationHandle.h" 57 #include "com_android_server_input_InputWindowHandle.h" 58 59 namespace android { 60 61 // The exponent used to calculate the pointer speed scaling factor. 62 // The scaling factor is calculated as 2 ^ (speed * exponent), 63 // where the speed ranges from -7 to + 7 and is supplied by the user. 64 static const float POINTER_SPEED_EXPONENT = 1.0f / 4; 65 66 static struct { 67 jmethodID notifyConfigurationChanged; 68 jmethodID notifyInputDevicesChanged; 69 jmethodID notifySwitch; 70 jmethodID notifyInputChannelBroken; 71 jmethodID notifyANR; 72 jmethodID filterInputEvent; 73 jmethodID interceptKeyBeforeQueueing; 74 jmethodID interceptMotionBeforeQueueingNonInteractive; 75 jmethodID interceptKeyBeforeDispatching; 76 jmethodID dispatchUnhandledKey; 77 jmethodID checkInjectEventsPermission; 78 jmethodID getVirtualKeyQuietTimeMillis; 79 jmethodID getExcludedDeviceNames; 80 jmethodID getKeyRepeatTimeout; 81 jmethodID getKeyRepeatDelay; 82 jmethodID getHoverTapTimeout; 83 jmethodID getHoverTapSlop; 84 jmethodID getDoubleTapTimeout; 85 jmethodID getLongPressTimeout; 86 jmethodID getPointerLayer; 87 jmethodID getPointerIcon; 88 jmethodID getKeyboardLayoutOverlay; 89 jmethodID getDeviceAlias; 90 jmethodID getTouchCalibrationForInputDevice; 91 } gServiceClassInfo; 92 93 static struct { 94 jclass clazz; 95 } gInputDeviceClassInfo; 96 97 static struct { 98 jclass clazz; 99 } gKeyEventClassInfo; 100 101 static struct { 102 jclass clazz; 103 } gMotionEventClassInfo; 104 105 static struct { 106 jclass clazz; 107 jmethodID constructor; 108 } gInputDeviceIdentifierInfo; 109 110 static struct { 111 jclass clazz; 112 jmethodID getAffineTransform; 113 } gTouchCalibrationClassInfo; 114 115 116 117 // --- Global functions --- 118 119 template<typename T> 120 inline static T min(const T& a, const T& b) { 121 return a < b ? a : b; 122 } 123 124 template<typename T> 125 inline static T max(const T& a, const T& b) { 126 return a > b ? a : b; 127 } 128 129 static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env, 130 const sp<InputApplicationHandle>& inputApplicationHandle) { 131 if (inputApplicationHandle == NULL) { 132 return NULL; 133 } 134 return static_cast<NativeInputApplicationHandle*>(inputApplicationHandle.get())-> 135 getInputApplicationHandleObjLocalRef(env); 136 } 137 138 static jobject getInputWindowHandleObjLocalRef(JNIEnv* env, 139 const sp<InputWindowHandle>& inputWindowHandle) { 140 if (inputWindowHandle == NULL) { 141 return NULL; 142 } 143 return static_cast<NativeInputWindowHandle*>(inputWindowHandle.get())-> 144 getInputWindowHandleObjLocalRef(env); 145 } 146 147 static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, int32_t style, 148 SpriteIcon* outSpriteIcon) { 149 PointerIcon pointerIcon; 150 status_t status = android_view_PointerIcon_loadSystemIcon(env, 151 contextObj, style, &pointerIcon); 152 if (!status) { 153 pointerIcon.bitmap.copyTo(&outSpriteIcon->bitmap, kN32_SkColorType); 154 outSpriteIcon->hotSpotX = pointerIcon.hotSpotX; 155 outSpriteIcon->hotSpotY = pointerIcon.hotSpotY; 156 } 157 } 158 159 enum { 160 WM_ACTION_PASS_TO_USER = 1, 161 }; 162 163 164 // --- NativeInputManager --- 165 166 class NativeInputManager : public virtual RefBase, 167 public virtual InputReaderPolicyInterface, 168 public virtual InputDispatcherPolicyInterface, 169 public virtual PointerControllerPolicyInterface { 170 protected: 171 virtual ~NativeInputManager(); 172 173 public: 174 NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper); 175 176 inline sp<InputManager> getInputManager() const { return mInputManager; } 177 178 void dump(String8& dump); 179 180 void setDisplayViewport(bool external, const DisplayViewport& viewport); 181 182 status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel, 183 const sp<InputWindowHandle>& inputWindowHandle, bool monitor); 184 status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel); 185 186 void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray); 187 void setFocusedApplication(JNIEnv* env, jobject applicationHandleObj); 188 void setInputDispatchMode(bool enabled, bool frozen); 189 void setSystemUiVisibility(int32_t visibility); 190 void setPointerSpeed(int32_t speed); 191 void setShowTouches(bool enabled); 192 void setInteractive(bool interactive); 193 void reloadCalibration(); 194 195 /* --- InputReaderPolicyInterface implementation --- */ 196 197 virtual void getReaderConfiguration(InputReaderConfiguration* outConfig); 198 virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId); 199 virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices); 200 virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier); 201 virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier); 202 virtual TouchAffineTransformation getTouchAffineTransformation(JNIEnv *env, 203 jfloatArray matrixArr); 204 virtual TouchAffineTransformation getTouchAffineTransformation( 205 const String8& inputDeviceDescriptor, int32_t surfaceRotation); 206 207 /* --- InputDispatcherPolicyInterface implementation --- */ 208 209 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask, 210 uint32_t policyFlags); 211 virtual void notifyConfigurationChanged(nsecs_t when); 212 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle, 213 const sp<InputWindowHandle>& inputWindowHandle, 214 const String8& reason); 215 virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle); 216 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags); 217 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig); 218 virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags); 219 virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags); 220 virtual nsecs_t interceptKeyBeforeDispatching( 221 const sp<InputWindowHandle>& inputWindowHandle, 222 const KeyEvent* keyEvent, uint32_t policyFlags); 223 virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle, 224 const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent); 225 virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType); 226 virtual bool checkInjectEventsPermissionNonReentrant( 227 int32_t injectorPid, int32_t injectorUid); 228 229 /* --- PointerControllerPolicyInterface implementation --- */ 230 231 virtual void loadPointerResources(PointerResources* outResources); 232 233 private: 234 sp<InputManager> mInputManager; 235 236 jobject mContextObj; 237 jobject mServiceObj; 238 sp<Looper> mLooper; 239 240 Mutex mLock; 241 struct Locked { 242 // Display size information. 243 DisplayViewport internalViewport; 244 DisplayViewport externalViewport; 245 246 // System UI visibility. 247 int32_t systemUiVisibility; 248 249 // Pointer speed. 250 int32_t pointerSpeed; 251 252 // True if pointer gestures are enabled. 253 bool pointerGesturesEnabled; 254 255 // Show touches feature enable/disable. 256 bool showTouches; 257 258 // Sprite controller singleton, created on first use. 259 sp<SpriteController> spriteController; 260 261 // Pointer controller singleton, created and destroyed as needed. 262 wp<PointerController> pointerController; 263 } mLocked; 264 265 volatile bool mInteractive; 266 267 void updateInactivityTimeoutLocked(const sp<PointerController>& controller); 268 void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags); 269 void ensureSpriteControllerLocked(); 270 271 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName); 272 273 static inline JNIEnv* jniEnv() { 274 return AndroidRuntime::getJNIEnv(); 275 } 276 }; 277 278 279 280 NativeInputManager::NativeInputManager(jobject contextObj, 281 jobject serviceObj, const sp<Looper>& looper) : 282 mLooper(looper), mInteractive(true) { 283 JNIEnv* env = jniEnv(); 284 285 mContextObj = env->NewGlobalRef(contextObj); 286 mServiceObj = env->NewGlobalRef(serviceObj); 287 288 { 289 AutoMutex _l(mLock); 290 mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE; 291 mLocked.pointerSpeed = 0; 292 mLocked.pointerGesturesEnabled = true; 293 mLocked.showTouches = false; 294 } 295 296 sp<EventHub> eventHub = new EventHub(); 297 mInputManager = new InputManager(eventHub, this, this); 298 } 299 300 NativeInputManager::~NativeInputManager() { 301 JNIEnv* env = jniEnv(); 302 303 env->DeleteGlobalRef(mContextObj); 304 env->DeleteGlobalRef(mServiceObj); 305 } 306 307 void NativeInputManager::dump(String8& dump) { 308 mInputManager->getReader()->dump(dump); 309 dump.append("\n"); 310 311 mInputManager->getDispatcher()->dump(dump); 312 dump.append("\n"); 313 } 314 315 bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { 316 if (env->ExceptionCheck()) { 317 ALOGE("An exception was thrown by callback '%s'.", methodName); 318 LOGE_EX(env); 319 env->ExceptionClear(); 320 return true; 321 } 322 return false; 323 } 324 325 void NativeInputManager::setDisplayViewport(bool external, const DisplayViewport& viewport) { 326 bool changed = false; 327 { 328 AutoMutex _l(mLock); 329 330 DisplayViewport& v = external ? mLocked.externalViewport : mLocked.internalViewport; 331 if (v != viewport) { 332 changed = true; 333 v = viewport; 334 335 if (!external) { 336 sp<PointerController> controller = mLocked.pointerController.promote(); 337 if (controller != NULL) { 338 controller->setDisplayViewport( 339 viewport.logicalRight - viewport.logicalLeft, 340 viewport.logicalBottom - viewport.logicalTop, 341 viewport.orientation); 342 } 343 } 344 } 345 } 346 347 if (changed) { 348 mInputManager->getReader()->requestRefreshConfiguration( 349 InputReaderConfiguration::CHANGE_DISPLAY_INFO); 350 } 351 } 352 353 status_t NativeInputManager::registerInputChannel(JNIEnv* env, 354 const sp<InputChannel>& inputChannel, 355 const sp<InputWindowHandle>& inputWindowHandle, bool monitor) { 356 return mInputManager->getDispatcher()->registerInputChannel( 357 inputChannel, inputWindowHandle, monitor); 358 } 359 360 status_t NativeInputManager::unregisterInputChannel(JNIEnv* env, 361 const sp<InputChannel>& inputChannel) { 362 return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel); 363 } 364 365 void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outConfig) { 366 JNIEnv* env = jniEnv(); 367 368 jint virtualKeyQuietTime = env->CallIntMethod(mServiceObj, 369 gServiceClassInfo.getVirtualKeyQuietTimeMillis); 370 if (!checkAndClearExceptionFromCallback(env, "getVirtualKeyQuietTimeMillis")) { 371 outConfig->virtualKeyQuietTime = milliseconds_to_nanoseconds(virtualKeyQuietTime); 372 } 373 374 outConfig->excludedDeviceNames.clear(); 375 jobjectArray excludedDeviceNames = jobjectArray(env->CallObjectMethod(mServiceObj, 376 gServiceClassInfo.getExcludedDeviceNames)); 377 if (!checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && excludedDeviceNames) { 378 jsize length = env->GetArrayLength(excludedDeviceNames); 379 for (jsize i = 0; i < length; i++) { 380 jstring item = jstring(env->GetObjectArrayElement(excludedDeviceNames, i)); 381 const char* deviceNameChars = env->GetStringUTFChars(item, NULL); 382 outConfig->excludedDeviceNames.add(String8(deviceNameChars)); 383 env->ReleaseStringUTFChars(item, deviceNameChars); 384 env->DeleteLocalRef(item); 385 } 386 env->DeleteLocalRef(excludedDeviceNames); 387 } 388 389 jint hoverTapTimeout = env->CallIntMethod(mServiceObj, 390 gServiceClassInfo.getHoverTapTimeout); 391 if (!checkAndClearExceptionFromCallback(env, "getHoverTapTimeout")) { 392 jint doubleTapTimeout = env->CallIntMethod(mServiceObj, 393 gServiceClassInfo.getDoubleTapTimeout); 394 if (!checkAndClearExceptionFromCallback(env, "getDoubleTapTimeout")) { 395 jint longPressTimeout = env->CallIntMethod(mServiceObj, 396 gServiceClassInfo.getLongPressTimeout); 397 if (!checkAndClearExceptionFromCallback(env, "getLongPressTimeout")) { 398 outConfig->pointerGestureTapInterval = milliseconds_to_nanoseconds(hoverTapTimeout); 399 400 // We must ensure that the tap-drag interval is significantly shorter than 401 // the long-press timeout because the tap is held down for the entire duration 402 // of the double-tap timeout. 403 jint tapDragInterval = max(min(longPressTimeout - 100, 404 doubleTapTimeout), hoverTapTimeout); 405 outConfig->pointerGestureTapDragInterval = 406 milliseconds_to_nanoseconds(tapDragInterval); 407 } 408 } 409 } 410 411 jint hoverTapSlop = env->CallIntMethod(mServiceObj, 412 gServiceClassInfo.getHoverTapSlop); 413 if (!checkAndClearExceptionFromCallback(env, "getHoverTapSlop")) { 414 outConfig->pointerGestureTapSlop = hoverTapSlop; 415 } 416 417 { // acquire lock 418 AutoMutex _l(mLock); 419 420 outConfig->pointerVelocityControlParameters.scale = exp2f(mLocked.pointerSpeed 421 * POINTER_SPEED_EXPONENT); 422 outConfig->pointerGesturesEnabled = mLocked.pointerGesturesEnabled; 423 424 outConfig->showTouches = mLocked.showTouches; 425 426 outConfig->setDisplayInfo(false /*external*/, mLocked.internalViewport); 427 outConfig->setDisplayInfo(true /*external*/, mLocked.externalViewport); 428 } // release lock 429 } 430 431 sp<PointerControllerInterface> NativeInputManager::obtainPointerController(int32_t deviceId) { 432 AutoMutex _l(mLock); 433 434 sp<PointerController> controller = mLocked.pointerController.promote(); 435 if (controller == NULL) { 436 ensureSpriteControllerLocked(); 437 438 controller = new PointerController(this, mLooper, mLocked.spriteController); 439 mLocked.pointerController = controller; 440 441 DisplayViewport& v = mLocked.internalViewport; 442 controller->setDisplayViewport( 443 v.logicalRight - v.logicalLeft, 444 v.logicalBottom - v.logicalTop, 445 v.orientation); 446 447 JNIEnv* env = jniEnv(); 448 jobject pointerIconObj = env->CallObjectMethod(mServiceObj, 449 gServiceClassInfo.getPointerIcon); 450 if (!checkAndClearExceptionFromCallback(env, "getPointerIcon")) { 451 PointerIcon pointerIcon; 452 status_t status = android_view_PointerIcon_load(env, pointerIconObj, 453 mContextObj, &pointerIcon); 454 if (!status && !pointerIcon.isNullIcon()) { 455 controller->setPointerIcon(SpriteIcon(pointerIcon.bitmap, 456 pointerIcon.hotSpotX, pointerIcon.hotSpotY)); 457 } else { 458 controller->setPointerIcon(SpriteIcon()); 459 } 460 env->DeleteLocalRef(pointerIconObj); 461 } 462 463 updateInactivityTimeoutLocked(controller); 464 } 465 return controller; 466 } 467 468 void NativeInputManager::ensureSpriteControllerLocked() { 469 if (mLocked.spriteController == NULL) { 470 JNIEnv* env = jniEnv(); 471 jint layer = env->CallIntMethod(mServiceObj, gServiceClassInfo.getPointerLayer); 472 if (checkAndClearExceptionFromCallback(env, "getPointerLayer")) { 473 layer = -1; 474 } 475 mLocked.spriteController = new SpriteController(mLooper, layer); 476 } 477 } 478 479 void NativeInputManager::notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) { 480 JNIEnv* env = jniEnv(); 481 482 size_t count = inputDevices.size(); 483 jobjectArray inputDevicesObjArray = env->NewObjectArray( 484 count, gInputDeviceClassInfo.clazz, NULL); 485 if (inputDevicesObjArray) { 486 bool error = false; 487 for (size_t i = 0; i < count; i++) { 488 jobject inputDeviceObj = android_view_InputDevice_create(env, inputDevices.itemAt(i)); 489 if (!inputDeviceObj) { 490 error = true; 491 break; 492 } 493 494 env->SetObjectArrayElement(inputDevicesObjArray, i, inputDeviceObj); 495 env->DeleteLocalRef(inputDeviceObj); 496 } 497 498 if (!error) { 499 env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyInputDevicesChanged, 500 inputDevicesObjArray); 501 } 502 503 env->DeleteLocalRef(inputDevicesObjArray); 504 } 505 506 checkAndClearExceptionFromCallback(env, "notifyInputDevicesChanged"); 507 } 508 509 sp<KeyCharacterMap> NativeInputManager::getKeyboardLayoutOverlay( 510 const InputDeviceIdentifier& identifier) { 511 JNIEnv* env = jniEnv(); 512 513 sp<KeyCharacterMap> result; 514 ScopedLocalRef<jstring> descriptor(env, env->NewStringUTF(identifier.descriptor.string())); 515 ScopedLocalRef<jobject> identifierObj(env, env->NewObject(gInputDeviceIdentifierInfo.clazz, 516 gInputDeviceIdentifierInfo.constructor, descriptor.get(), 517 identifier.vendor, identifier.product)); 518 ScopedLocalRef<jobjectArray> arrayObj(env, jobjectArray(env->CallObjectMethod(mServiceObj, 519 gServiceClassInfo.getKeyboardLayoutOverlay, identifierObj.get()))); 520 if (arrayObj.get()) { 521 ScopedLocalRef<jstring> filenameObj(env, 522 jstring(env->GetObjectArrayElement(arrayObj.get(), 0))); 523 ScopedLocalRef<jstring> contentsObj(env, 524 jstring(env->GetObjectArrayElement(arrayObj.get(), 1))); 525 ScopedUtfChars filenameChars(env, filenameObj.get()); 526 ScopedUtfChars contentsChars(env, contentsObj.get()); 527 528 KeyCharacterMap::loadContents(String8(filenameChars.c_str()), 529 String8(contentsChars.c_str()), KeyCharacterMap::FORMAT_OVERLAY, &result); 530 } 531 checkAndClearExceptionFromCallback(env, "getKeyboardLayoutOverlay"); 532 return result; 533 } 534 535 String8 NativeInputManager::getDeviceAlias(const InputDeviceIdentifier& identifier) { 536 JNIEnv* env = jniEnv(); 537 538 ScopedLocalRef<jstring> uniqueIdObj(env, env->NewStringUTF(identifier.uniqueId.string())); 539 ScopedLocalRef<jstring> aliasObj(env, jstring(env->CallObjectMethod(mServiceObj, 540 gServiceClassInfo.getDeviceAlias, uniqueIdObj.get()))); 541 String8 result; 542 if (aliasObj.get()) { 543 ScopedUtfChars aliasChars(env, aliasObj.get()); 544 result.setTo(aliasChars.c_str()); 545 } 546 checkAndClearExceptionFromCallback(env, "getDeviceAlias"); 547 return result; 548 } 549 550 void NativeInputManager::notifySwitch(nsecs_t when, 551 uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) { 552 #if DEBUG_INPUT_DISPATCHER_POLICY 553 ALOGD("notifySwitch - when=%lld, switchValues=0x%08x, switchMask=0x%08x, policyFlags=0x%x", 554 when, switchValues, switchMask, policyFlags); 555 #endif 556 557 JNIEnv* env = jniEnv(); 558 559 env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySwitch, 560 when, switchValues, switchMask); 561 checkAndClearExceptionFromCallback(env, "notifySwitch"); 562 } 563 564 void NativeInputManager::notifyConfigurationChanged(nsecs_t when) { 565 #if DEBUG_INPUT_DISPATCHER_POLICY 566 ALOGD("notifyConfigurationChanged - when=%lld", when); 567 #endif 568 569 JNIEnv* env = jniEnv(); 570 571 env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyConfigurationChanged, when); 572 checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged"); 573 } 574 575 nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle, 576 const sp<InputWindowHandle>& inputWindowHandle, const String8& reason) { 577 #if DEBUG_INPUT_DISPATCHER_POLICY 578 ALOGD("notifyANR"); 579 #endif 580 581 JNIEnv* env = jniEnv(); 582 583 jobject inputApplicationHandleObj = 584 getInputApplicationHandleObjLocalRef(env, inputApplicationHandle); 585 jobject inputWindowHandleObj = 586 getInputWindowHandleObjLocalRef(env, inputWindowHandle); 587 jstring reasonObj = env->NewStringUTF(reason.string()); 588 589 jlong newTimeout = env->CallLongMethod(mServiceObj, 590 gServiceClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj, 591 reasonObj); 592 if (checkAndClearExceptionFromCallback(env, "notifyANR")) { 593 newTimeout = 0; // abort dispatch 594 } else { 595 assert(newTimeout >= 0); 596 } 597 598 env->DeleteLocalRef(reasonObj); 599 env->DeleteLocalRef(inputWindowHandleObj); 600 env->DeleteLocalRef(inputApplicationHandleObj); 601 return newTimeout; 602 } 603 604 void NativeInputManager::notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) { 605 #if DEBUG_INPUT_DISPATCHER_POLICY 606 ALOGD("notifyInputChannelBroken"); 607 #endif 608 609 JNIEnv* env = jniEnv(); 610 611 jobject inputWindowHandleObj = 612 getInputWindowHandleObjLocalRef(env, inputWindowHandle); 613 if (inputWindowHandleObj) { 614 env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyInputChannelBroken, 615 inputWindowHandleObj); 616 checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken"); 617 618 env->DeleteLocalRef(inputWindowHandleObj); 619 } 620 } 621 622 void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) { 623 JNIEnv* env = jniEnv(); 624 625 jint keyRepeatTimeout = env->CallIntMethod(mServiceObj, 626 gServiceClassInfo.getKeyRepeatTimeout); 627 if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatTimeout")) { 628 outConfig->keyRepeatTimeout = milliseconds_to_nanoseconds(keyRepeatTimeout); 629 } 630 631 jint keyRepeatDelay = env->CallIntMethod(mServiceObj, 632 gServiceClassInfo.getKeyRepeatDelay); 633 if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatDelay")) { 634 outConfig->keyRepeatDelay = milliseconds_to_nanoseconds(keyRepeatDelay); 635 } 636 } 637 638 void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) { 639 Vector<sp<InputWindowHandle> > windowHandles; 640 641 if (windowHandleObjArray) { 642 jsize length = env->GetArrayLength(windowHandleObjArray); 643 for (jsize i = 0; i < length; i++) { 644 jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i); 645 if (! windowHandleObj) { 646 break; // found null element indicating end of used portion of the array 647 } 648 649 sp<InputWindowHandle> windowHandle = 650 android_server_InputWindowHandle_getHandle(env, windowHandleObj); 651 if (windowHandle != NULL) { 652 windowHandles.push(windowHandle); 653 } 654 env->DeleteLocalRef(windowHandleObj); 655 } 656 } 657 658 mInputManager->getDispatcher()->setInputWindows(windowHandles); 659 660 // Do this after the dispatcher has updated the window handle state. 661 bool newPointerGesturesEnabled = true; 662 size_t numWindows = windowHandles.size(); 663 for (size_t i = 0; i < numWindows; i++) { 664 const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i); 665 const InputWindowInfo* windowInfo = windowHandle->getInfo(); 666 if (windowInfo && windowInfo->hasFocus && (windowInfo->inputFeatures 667 & InputWindowInfo::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) { 668 newPointerGesturesEnabled = false; 669 } 670 } 671 672 uint32_t changes = 0; 673 { // acquire lock 674 AutoMutex _l(mLock); 675 676 if (mLocked.pointerGesturesEnabled != newPointerGesturesEnabled) { 677 mLocked.pointerGesturesEnabled = newPointerGesturesEnabled; 678 changes |= InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT; 679 } 680 } // release lock 681 682 if (changes) { 683 mInputManager->getReader()->requestRefreshConfiguration(changes); 684 } 685 } 686 687 void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationHandleObj) { 688 sp<InputApplicationHandle> applicationHandle = 689 android_server_InputApplicationHandle_getHandle(env, applicationHandleObj); 690 mInputManager->getDispatcher()->setFocusedApplication(applicationHandle); 691 } 692 693 void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) { 694 mInputManager->getDispatcher()->setInputDispatchMode(enabled, frozen); 695 } 696 697 void NativeInputManager::setSystemUiVisibility(int32_t visibility) { 698 AutoMutex _l(mLock); 699 700 if (mLocked.systemUiVisibility != visibility) { 701 mLocked.systemUiVisibility = visibility; 702 703 sp<PointerController> controller = mLocked.pointerController.promote(); 704 if (controller != NULL) { 705 updateInactivityTimeoutLocked(controller); 706 } 707 } 708 } 709 710 void NativeInputManager::updateInactivityTimeoutLocked(const sp<PointerController>& controller) { 711 bool lightsOut = mLocked.systemUiVisibility & ASYSTEM_UI_VISIBILITY_STATUS_BAR_HIDDEN; 712 controller->setInactivityTimeout(lightsOut 713 ? PointerController::INACTIVITY_TIMEOUT_SHORT 714 : PointerController::INACTIVITY_TIMEOUT_NORMAL); 715 } 716 717 void NativeInputManager::setPointerSpeed(int32_t speed) { 718 { // acquire lock 719 AutoMutex _l(mLock); 720 721 if (mLocked.pointerSpeed == speed) { 722 return; 723 } 724 725 ALOGI("Setting pointer speed to %d.", speed); 726 mLocked.pointerSpeed = speed; 727 } // release lock 728 729 mInputManager->getReader()->requestRefreshConfiguration( 730 InputReaderConfiguration::CHANGE_POINTER_SPEED); 731 } 732 733 void NativeInputManager::setShowTouches(bool enabled) { 734 { // acquire lock 735 AutoMutex _l(mLock); 736 737 if (mLocked.showTouches == enabled) { 738 return; 739 } 740 741 ALOGI("Setting show touches feature to %s.", enabled ? "enabled" : "disabled"); 742 mLocked.showTouches = enabled; 743 } // release lock 744 745 mInputManager->getReader()->requestRefreshConfiguration( 746 InputReaderConfiguration::CHANGE_SHOW_TOUCHES); 747 } 748 749 void NativeInputManager::setInteractive(bool interactive) { 750 mInteractive = interactive; 751 } 752 753 void NativeInputManager::reloadCalibration() { 754 mInputManager->getReader()->requestRefreshConfiguration( 755 InputReaderConfiguration::TOUCH_AFFINE_TRANSFORMATION); 756 } 757 758 TouchAffineTransformation NativeInputManager::getTouchAffineTransformation( 759 JNIEnv *env, jfloatArray matrixArr) { 760 ScopedFloatArrayRO matrix(env, matrixArr); 761 assert(matrix.size() == 6); 762 763 TouchAffineTransformation transform; 764 transform.x_scale = matrix[0]; 765 transform.x_ymix = matrix[1]; 766 transform.x_offset = matrix[2]; 767 transform.y_xmix = matrix[3]; 768 transform.y_scale = matrix[4]; 769 transform.y_offset = matrix[5]; 770 771 return transform; 772 } 773 774 TouchAffineTransformation NativeInputManager::getTouchAffineTransformation( 775 const String8& inputDeviceDescriptor, int32_t surfaceRotation) { 776 JNIEnv* env = jniEnv(); 777 778 ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.string())); 779 780 jobject cal = env->CallObjectMethod(mServiceObj, 781 gServiceClassInfo.getTouchCalibrationForInputDevice, descriptorObj.get(), 782 surfaceRotation); 783 784 jfloatArray matrixArr = jfloatArray(env->CallObjectMethod(cal, 785 gTouchCalibrationClassInfo.getAffineTransform)); 786 787 TouchAffineTransformation transform = getTouchAffineTransformation(env, matrixArr); 788 789 env->DeleteLocalRef(matrixArr); 790 env->DeleteLocalRef(cal); 791 792 return transform; 793 } 794 795 bool NativeInputManager::filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) { 796 jobject inputEventObj; 797 798 JNIEnv* env = jniEnv(); 799 switch (inputEvent->getType()) { 800 case AINPUT_EVENT_TYPE_KEY: 801 inputEventObj = android_view_KeyEvent_fromNative(env, 802 static_cast<const KeyEvent*>(inputEvent)); 803 break; 804 case AINPUT_EVENT_TYPE_MOTION: 805 inputEventObj = android_view_MotionEvent_obtainAsCopy(env, 806 static_cast<const MotionEvent*>(inputEvent)); 807 break; 808 default: 809 return true; // dispatch the event normally 810 } 811 812 if (!inputEventObj) { 813 ALOGE("Failed to obtain input event object for filterInputEvent."); 814 return true; // dispatch the event normally 815 } 816 817 // The callee is responsible for recycling the event. 818 jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent, 819 inputEventObj, policyFlags); 820 if (checkAndClearExceptionFromCallback(env, "filterInputEvent")) { 821 pass = true; 822 } 823 env->DeleteLocalRef(inputEventObj); 824 return pass; 825 } 826 827 void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent, 828 uint32_t& policyFlags) { 829 // Policy: 830 // - Ignore untrusted events and pass them along. 831 // - Ask the window manager what to do with normal events and trusted injected events. 832 // - For normal events wake and brighten the screen if currently off or dim. 833 if (mInteractive) { 834 policyFlags |= POLICY_FLAG_INTERACTIVE; 835 } 836 if ((policyFlags & POLICY_FLAG_TRUSTED)) { 837 nsecs_t when = keyEvent->getEventTime(); 838 JNIEnv* env = jniEnv(); 839 jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); 840 jint wmActions; 841 if (keyEventObj) { 842 wmActions = env->CallIntMethod(mServiceObj, 843 gServiceClassInfo.interceptKeyBeforeQueueing, 844 keyEventObj, policyFlags); 845 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { 846 wmActions = 0; 847 } 848 android_view_KeyEvent_recycle(env, keyEventObj); 849 env->DeleteLocalRef(keyEventObj); 850 } else { 851 ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing."); 852 wmActions = 0; 853 } 854 855 handleInterceptActions(wmActions, when, /*byref*/ policyFlags); 856 } else { 857 if (mInteractive) { 858 policyFlags |= POLICY_FLAG_PASS_TO_USER; 859 } 860 } 861 } 862 863 void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) { 864 // Policy: 865 // - Ignore untrusted events and pass them along. 866 // - No special filtering for injected events required at this time. 867 // - Filter normal events based on screen state. 868 // - For normal events brighten (but do not wake) the screen if currently dim. 869 if (mInteractive) { 870 policyFlags |= POLICY_FLAG_INTERACTIVE; 871 } 872 if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) { 873 if (policyFlags & POLICY_FLAG_INTERACTIVE) { 874 policyFlags |= POLICY_FLAG_PASS_TO_USER; 875 } else { 876 JNIEnv* env = jniEnv(); 877 jint wmActions = env->CallIntMethod(mServiceObj, 878 gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive, 879 when, policyFlags); 880 if (checkAndClearExceptionFromCallback(env, 881 "interceptMotionBeforeQueueingNonInteractive")) { 882 wmActions = 0; 883 } 884 885 handleInterceptActions(wmActions, when, /*byref*/ policyFlags); 886 } 887 } else { 888 if (mInteractive) { 889 policyFlags |= POLICY_FLAG_PASS_TO_USER; 890 } 891 } 892 } 893 894 void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when, 895 uint32_t& policyFlags) { 896 if (wmActions & WM_ACTION_PASS_TO_USER) { 897 policyFlags |= POLICY_FLAG_PASS_TO_USER; 898 } else { 899 #if DEBUG_INPUT_DISPATCHER_POLICY 900 ALOGD("handleInterceptActions: Not passing key to user."); 901 #endif 902 } 903 } 904 905 nsecs_t NativeInputManager::interceptKeyBeforeDispatching( 906 const sp<InputWindowHandle>& inputWindowHandle, 907 const KeyEvent* keyEvent, uint32_t policyFlags) { 908 // Policy: 909 // - Ignore untrusted events and pass them along. 910 // - Filter normal events and trusted injected events through the window manager policy to 911 // handle the HOME key and the like. 912 nsecs_t result = 0; 913 if (policyFlags & POLICY_FLAG_TRUSTED) { 914 JNIEnv* env = jniEnv(); 915 916 // Note: inputWindowHandle may be null. 917 jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle); 918 jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); 919 if (keyEventObj) { 920 jlong delayMillis = env->CallLongMethod(mServiceObj, 921 gServiceClassInfo.interceptKeyBeforeDispatching, 922 inputWindowHandleObj, keyEventObj, policyFlags); 923 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching"); 924 android_view_KeyEvent_recycle(env, keyEventObj); 925 env->DeleteLocalRef(keyEventObj); 926 if (!error) { 927 if (delayMillis < 0) { 928 result = -1; 929 } else if (delayMillis > 0) { 930 result = milliseconds_to_nanoseconds(delayMillis); 931 } 932 } 933 } else { 934 ALOGE("Failed to obtain key event object for interceptKeyBeforeDispatching."); 935 } 936 env->DeleteLocalRef(inputWindowHandleObj); 937 } 938 return result; 939 } 940 941 bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle, 942 const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) { 943 // Policy: 944 // - Ignore untrusted events and do not perform default handling. 945 bool result = false; 946 if (policyFlags & POLICY_FLAG_TRUSTED) { 947 JNIEnv* env = jniEnv(); 948 949 // Note: inputWindowHandle may be null. 950 jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle); 951 jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); 952 if (keyEventObj) { 953 jobject fallbackKeyEventObj = env->CallObjectMethod(mServiceObj, 954 gServiceClassInfo.dispatchUnhandledKey, 955 inputWindowHandleObj, keyEventObj, policyFlags); 956 if (checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey")) { 957 fallbackKeyEventObj = NULL; 958 } 959 android_view_KeyEvent_recycle(env, keyEventObj); 960 env->DeleteLocalRef(keyEventObj); 961 962 if (fallbackKeyEventObj) { 963 // Note: outFallbackKeyEvent may be the same object as keyEvent. 964 if (!android_view_KeyEvent_toNative(env, fallbackKeyEventObj, 965 outFallbackKeyEvent)) { 966 result = true; 967 } 968 android_view_KeyEvent_recycle(env, fallbackKeyEventObj); 969 env->DeleteLocalRef(fallbackKeyEventObj); 970 } 971 } else { 972 ALOGE("Failed to obtain key event object for dispatchUnhandledKey."); 973 } 974 env->DeleteLocalRef(inputWindowHandleObj); 975 } 976 return result; 977 } 978 979 void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) { 980 android_server_PowerManagerService_userActivity(eventTime, eventType); 981 } 982 983 984 bool NativeInputManager::checkInjectEventsPermissionNonReentrant( 985 int32_t injectorPid, int32_t injectorUid) { 986 JNIEnv* env = jniEnv(); 987 jboolean result = env->CallBooleanMethod(mServiceObj, 988 gServiceClassInfo.checkInjectEventsPermission, injectorPid, injectorUid); 989 if (checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission")) { 990 result = false; 991 } 992 return result; 993 } 994 995 void NativeInputManager::loadPointerResources(PointerResources* outResources) { 996 JNIEnv* env = jniEnv(); 997 998 loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_HOVER, 999 &outResources->spotHover); 1000 loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_TOUCH, 1001 &outResources->spotTouch); 1002 loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_ANCHOR, 1003 &outResources->spotAnchor); 1004 } 1005 1006 1007 // ---------------------------------------------------------------------------- 1008 1009 static jlong nativeInit(JNIEnv* env, jclass clazz, 1010 jobject serviceObj, jobject contextObj, jobject messageQueueObj) { 1011 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); 1012 if (messageQueue == NULL) { 1013 jniThrowRuntimeException(env, "MessageQueue is not initialized."); 1014 return 0; 1015 } 1016 1017 NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, 1018 messageQueue->getLooper()); 1019 im->incStrong(0); 1020 return reinterpret_cast<jlong>(im); 1021 } 1022 1023 static void nativeStart(JNIEnv* env, jclass clazz, jlong ptr) { 1024 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1025 1026 status_t result = im->getInputManager()->start(); 1027 if (result) { 1028 jniThrowRuntimeException(env, "Input manager could not be started."); 1029 } 1030 } 1031 1032 static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jlong ptr, jboolean external, 1033 jint displayId, jint orientation, 1034 jint logicalLeft, jint logicalTop, jint logicalRight, jint logicalBottom, 1035 jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom, 1036 jint deviceWidth, jint deviceHeight) { 1037 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1038 1039 DisplayViewport v; 1040 v.displayId = displayId; 1041 v.orientation = orientation; 1042 v.logicalLeft = logicalLeft; 1043 v.logicalTop = logicalTop; 1044 v.logicalRight = logicalRight; 1045 v.logicalBottom = logicalBottom; 1046 v.physicalLeft = physicalLeft; 1047 v.physicalTop = physicalTop; 1048 v.physicalRight = physicalRight; 1049 v.physicalBottom = physicalBottom; 1050 v.deviceWidth = deviceWidth; 1051 v.deviceHeight = deviceHeight; 1052 im->setDisplayViewport(external, v); 1053 } 1054 1055 static jint nativeGetScanCodeState(JNIEnv* env, jclass clazz, 1056 jlong ptr, jint deviceId, jint sourceMask, jint scanCode) { 1057 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1058 1059 return (jint) im->getInputManager()->getReader()->getScanCodeState( 1060 deviceId, uint32_t(sourceMask), scanCode); 1061 } 1062 1063 static jint nativeGetKeyCodeState(JNIEnv* env, jclass clazz, 1064 jlong ptr, jint deviceId, jint sourceMask, jint keyCode) { 1065 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1066 1067 return (jint) im->getInputManager()->getReader()->getKeyCodeState( 1068 deviceId, uint32_t(sourceMask), keyCode); 1069 } 1070 1071 static jint nativeGetSwitchState(JNIEnv* env, jclass clazz, 1072 jlong ptr, jint deviceId, jint sourceMask, jint sw) { 1073 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1074 1075 return (jint) im->getInputManager()->getReader()->getSwitchState( 1076 deviceId, uint32_t(sourceMask), sw); 1077 } 1078 1079 static jboolean nativeHasKeys(JNIEnv* env, jclass clazz, 1080 jlong ptr, jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) { 1081 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1082 1083 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL); 1084 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL); 1085 jsize numCodes = env->GetArrayLength(keyCodes); 1086 jboolean result; 1087 if (numCodes == env->GetArrayLength(keyCodes)) { 1088 if (im->getInputManager()->getReader()->hasKeys( 1089 deviceId, uint32_t(sourceMask), numCodes, codes, flags)) { 1090 result = JNI_TRUE; 1091 } else { 1092 result = JNI_FALSE; 1093 } 1094 } else { 1095 result = JNI_FALSE; 1096 } 1097 1098 env->ReleaseBooleanArrayElements(outFlags, flags, 0); 1099 env->ReleaseIntArrayElements(keyCodes, codes, 0); 1100 return result; 1101 } 1102 1103 static void throwInputChannelNotInitialized(JNIEnv* env) { 1104 jniThrowException(env, "java/lang/IllegalStateException", 1105 "inputChannel is not initialized"); 1106 } 1107 1108 static void handleInputChannelDisposed(JNIEnv* env, 1109 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) { 1110 NativeInputManager* im = static_cast<NativeInputManager*>(data); 1111 1112 ALOGW("Input channel object '%s' was disposed without first being unregistered with " 1113 "the input manager!", inputChannel->getName().string()); 1114 im->unregisterInputChannel(env, inputChannel); 1115 } 1116 1117 static void nativeRegisterInputChannel(JNIEnv* env, jclass clazz, 1118 jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) { 1119 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1120 1121 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env, 1122 inputChannelObj); 1123 if (inputChannel == NULL) { 1124 throwInputChannelNotInitialized(env); 1125 return; 1126 } 1127 1128 sp<InputWindowHandle> inputWindowHandle = 1129 android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj); 1130 1131 status_t status = im->registerInputChannel( 1132 env, inputChannel, inputWindowHandle, monitor); 1133 if (status) { 1134 String8 message; 1135 message.appendFormat("Failed to register input channel. status=%d", status); 1136 jniThrowRuntimeException(env, message.string()); 1137 return; 1138 } 1139 1140 if (! monitor) { 1141 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, 1142 handleInputChannelDisposed, im); 1143 } 1144 } 1145 1146 static void nativeUnregisterInputChannel(JNIEnv* env, jclass clazz, 1147 jlong ptr, jobject inputChannelObj) { 1148 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1149 1150 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env, 1151 inputChannelObj); 1152 if (inputChannel == NULL) { 1153 throwInputChannelNotInitialized(env); 1154 return; 1155 } 1156 1157 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL); 1158 1159 status_t status = im->unregisterInputChannel(env, inputChannel); 1160 if (status && status != BAD_VALUE) { // ignore already unregistered channel 1161 String8 message; 1162 message.appendFormat("Failed to unregister input channel. status=%d", status); 1163 jniThrowRuntimeException(env, message.string()); 1164 } 1165 } 1166 1167 static void nativeSetInputFilterEnabled(JNIEnv* env, jclass clazz, 1168 jlong ptr, jboolean enabled) { 1169 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1170 1171 im->getInputManager()->getDispatcher()->setInputFilterEnabled(enabled); 1172 } 1173 1174 static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz, 1175 jlong ptr, jobject inputEventObj, jint displayId, jint injectorPid, jint injectorUid, 1176 jint syncMode, jint timeoutMillis, jint policyFlags) { 1177 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1178 1179 if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) { 1180 KeyEvent keyEvent; 1181 status_t status = android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent); 1182 if (status) { 1183 jniThrowRuntimeException(env, "Could not read contents of KeyEvent object."); 1184 return INPUT_EVENT_INJECTION_FAILED; 1185 } 1186 1187 return (jint) im->getInputManager()->getDispatcher()->injectInputEvent( 1188 & keyEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis, 1189 uint32_t(policyFlags)); 1190 } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) { 1191 const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj); 1192 if (!motionEvent) { 1193 jniThrowRuntimeException(env, "Could not read contents of MotionEvent object."); 1194 return INPUT_EVENT_INJECTION_FAILED; 1195 } 1196 1197 return (jint) im->getInputManager()->getDispatcher()->injectInputEvent( 1198 motionEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis, 1199 uint32_t(policyFlags)); 1200 } else { 1201 jniThrowRuntimeException(env, "Invalid input event type."); 1202 return INPUT_EVENT_INJECTION_FAILED; 1203 } 1204 } 1205 1206 static void nativeSetInputWindows(JNIEnv* env, jclass clazz, 1207 jlong ptr, jobjectArray windowHandleObjArray) { 1208 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1209 1210 im->setInputWindows(env, windowHandleObjArray); 1211 } 1212 1213 static void nativeSetFocusedApplication(JNIEnv* env, jclass clazz, 1214 jlong ptr, jobject applicationHandleObj) { 1215 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1216 1217 im->setFocusedApplication(env, applicationHandleObj); 1218 } 1219 1220 static void nativeSetInputDispatchMode(JNIEnv* env, 1221 jclass clazz, jlong ptr, jboolean enabled, jboolean frozen) { 1222 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1223 1224 im->setInputDispatchMode(enabled, frozen); 1225 } 1226 1227 static void nativeSetSystemUiVisibility(JNIEnv* env, 1228 jclass clazz, jlong ptr, jint visibility) { 1229 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1230 1231 im->setSystemUiVisibility(visibility); 1232 } 1233 1234 static jboolean nativeTransferTouchFocus(JNIEnv* env, 1235 jclass clazz, jlong ptr, jobject fromChannelObj, jobject toChannelObj) { 1236 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1237 1238 sp<InputChannel> fromChannel = 1239 android_view_InputChannel_getInputChannel(env, fromChannelObj); 1240 sp<InputChannel> toChannel = 1241 android_view_InputChannel_getInputChannel(env, toChannelObj); 1242 1243 if (fromChannel == NULL || toChannel == NULL) { 1244 return JNI_FALSE; 1245 } 1246 1247 if (im->getInputManager()->getDispatcher()-> 1248 transferTouchFocus(fromChannel, toChannel)) { 1249 return JNI_TRUE; 1250 } else { 1251 return JNI_FALSE; 1252 } 1253 } 1254 1255 static void nativeSetPointerSpeed(JNIEnv* env, 1256 jclass clazz, jlong ptr, jint speed) { 1257 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1258 1259 im->setPointerSpeed(speed); 1260 } 1261 1262 static void nativeSetShowTouches(JNIEnv* env, 1263 jclass clazz, jlong ptr, jboolean enabled) { 1264 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1265 1266 im->setShowTouches(enabled); 1267 } 1268 1269 static void nativeSetInteractive(JNIEnv* env, 1270 jclass clazz, jlong ptr, jboolean interactive) { 1271 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1272 1273 im->setInteractive(interactive); 1274 } 1275 1276 static void nativeReloadCalibration(JNIEnv* env, jclass clazz, jlong ptr) { 1277 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1278 im->reloadCalibration(); 1279 } 1280 1281 static void nativeVibrate(JNIEnv* env, 1282 jclass clazz, jlong ptr, jint deviceId, jlongArray patternObj, 1283 jint repeat, jint token) { 1284 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1285 1286 size_t patternSize = env->GetArrayLength(patternObj); 1287 if (patternSize > MAX_VIBRATE_PATTERN_SIZE) { 1288 ALOGI("Skipped requested vibration because the pattern size is %zu " 1289 "which is more than the maximum supported size of %d.", 1290 patternSize, MAX_VIBRATE_PATTERN_SIZE); 1291 return; // limit to reasonable size 1292 } 1293 1294 jlong* patternMillis = static_cast<jlong*>(env->GetPrimitiveArrayCritical( 1295 patternObj, NULL)); 1296 nsecs_t pattern[patternSize]; 1297 for (size_t i = 0; i < patternSize; i++) { 1298 pattern[i] = max(jlong(0), min(patternMillis[i], 1299 (jlong)(MAX_VIBRATE_PATTERN_DELAY_NSECS / 1000000LL))) * 1000000LL; 1300 } 1301 env->ReleasePrimitiveArrayCritical(patternObj, patternMillis, JNI_ABORT); 1302 1303 im->getInputManager()->getReader()->vibrate(deviceId, pattern, patternSize, repeat, token); 1304 } 1305 1306 static void nativeCancelVibrate(JNIEnv* env, 1307 jclass clazz, jlong ptr, jint deviceId, jint token) { 1308 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1309 1310 im->getInputManager()->getReader()->cancelVibrate(deviceId, token); 1311 } 1312 1313 static void nativeReloadKeyboardLayouts(JNIEnv* env, 1314 jclass clazz, jlong ptr) { 1315 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1316 1317 im->getInputManager()->getReader()->requestRefreshConfiguration( 1318 InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS); 1319 } 1320 1321 static void nativeReloadDeviceAliases(JNIEnv* env, 1322 jclass clazz, jlong ptr) { 1323 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1324 1325 im->getInputManager()->getReader()->requestRefreshConfiguration( 1326 InputReaderConfiguration::CHANGE_DEVICE_ALIAS); 1327 } 1328 1329 static jstring nativeDump(JNIEnv* env, jclass clazz, jlong ptr) { 1330 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1331 1332 String8 dump; 1333 im->dump(dump); 1334 return env->NewStringUTF(dump.string()); 1335 } 1336 1337 static void nativeMonitor(JNIEnv* env, jclass clazz, jlong ptr) { 1338 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1339 1340 im->getInputManager()->getReader()->monitor(); 1341 im->getInputManager()->getDispatcher()->monitor(); 1342 } 1343 1344 // ---------------------------------------------------------------------------- 1345 1346 static JNINativeMethod gInputManagerMethods[] = { 1347 /* name, signature, funcPtr */ 1348 { "nativeInit", 1349 "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J", 1350 (void*) nativeInit }, 1351 { "nativeStart", "(J)V", 1352 (void*) nativeStart }, 1353 { "nativeSetDisplayViewport", "(JZIIIIIIIIIIII)V", 1354 (void*) nativeSetDisplayViewport }, 1355 { "nativeGetScanCodeState", "(JIII)I", 1356 (void*) nativeGetScanCodeState }, 1357 { "nativeGetKeyCodeState", "(JIII)I", 1358 (void*) nativeGetKeyCodeState }, 1359 { "nativeGetSwitchState", "(JIII)I", 1360 (void*) nativeGetSwitchState }, 1361 { "nativeHasKeys", "(JII[I[Z)Z", 1362 (void*) nativeHasKeys }, 1363 { "nativeRegisterInputChannel", 1364 "(JLandroid/view/InputChannel;Lcom/android/server/input/InputWindowHandle;Z)V", 1365 (void*) nativeRegisterInputChannel }, 1366 { "nativeUnregisterInputChannel", "(JLandroid/view/InputChannel;)V", 1367 (void*) nativeUnregisterInputChannel }, 1368 { "nativeSetInputFilterEnabled", "(JZ)V", 1369 (void*) nativeSetInputFilterEnabled }, 1370 { "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I", 1371 (void*) nativeInjectInputEvent }, 1372 { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V", 1373 (void*) nativeSetInputWindows }, 1374 { "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V", 1375 (void*) nativeSetFocusedApplication }, 1376 { "nativeSetInputDispatchMode", "(JZZ)V", 1377 (void*) nativeSetInputDispatchMode }, 1378 { "nativeSetSystemUiVisibility", "(JI)V", 1379 (void*) nativeSetSystemUiVisibility }, 1380 { "nativeTransferTouchFocus", "(JLandroid/view/InputChannel;Landroid/view/InputChannel;)Z", 1381 (void*) nativeTransferTouchFocus }, 1382 { "nativeSetPointerSpeed", "(JI)V", 1383 (void*) nativeSetPointerSpeed }, 1384 { "nativeSetShowTouches", "(JZ)V", 1385 (void*) nativeSetShowTouches }, 1386 { "nativeSetInteractive", "(JZ)V", 1387 (void*) nativeSetInteractive }, 1388 { "nativeReloadCalibration", "(J)V", 1389 (void*) nativeReloadCalibration }, 1390 { "nativeVibrate", "(JI[JII)V", 1391 (void*) nativeVibrate }, 1392 { "nativeCancelVibrate", "(JII)V", 1393 (void*) nativeCancelVibrate }, 1394 { "nativeReloadKeyboardLayouts", "(J)V", 1395 (void*) nativeReloadKeyboardLayouts }, 1396 { "nativeReloadDeviceAliases", "(J)V", 1397 (void*) nativeReloadDeviceAliases }, 1398 { "nativeDump", "(J)Ljava/lang/String;", 1399 (void*) nativeDump }, 1400 { "nativeMonitor", "(J)V", 1401 (void*) nativeMonitor }, 1402 }; 1403 1404 #define FIND_CLASS(var, className) \ 1405 var = env->FindClass(className); \ 1406 LOG_FATAL_IF(! var, "Unable to find class " className); 1407 1408 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 1409 var = env->GetMethodID(clazz, methodName, methodDescriptor); \ 1410 LOG_FATAL_IF(! var, "Unable to find method " methodName); 1411 1412 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 1413 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 1414 LOG_FATAL_IF(! var, "Unable to find field " fieldName); 1415 1416 int register_android_server_InputManager(JNIEnv* env) { 1417 int res = jniRegisterNativeMethods(env, "com/android/server/input/InputManagerService", 1418 gInputManagerMethods, NELEM(gInputManagerMethods)); 1419 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 1420 1421 // Callbacks 1422 1423 jclass clazz; 1424 FIND_CLASS(clazz, "com/android/server/input/InputManagerService"); 1425 1426 GET_METHOD_ID(gServiceClassInfo.notifyConfigurationChanged, clazz, 1427 "notifyConfigurationChanged", "(J)V"); 1428 1429 GET_METHOD_ID(gServiceClassInfo.notifyInputDevicesChanged, clazz, 1430 "notifyInputDevicesChanged", "([Landroid/view/InputDevice;)V"); 1431 1432 GET_METHOD_ID(gServiceClassInfo.notifySwitch, clazz, 1433 "notifySwitch", "(JII)V"); 1434 1435 GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz, 1436 "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V"); 1437 1438 GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz, 1439 "notifyANR", 1440 "(Lcom/android/server/input/InputApplicationHandle;Lcom/android/server/input/InputWindowHandle;Ljava/lang/String;)J"); 1441 1442 GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz, 1443 "filterInputEvent", "(Landroid/view/InputEvent;I)Z"); 1444 1445 GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz, 1446 "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I"); 1447 1448 GET_METHOD_ID(gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive, clazz, 1449 "interceptMotionBeforeQueueingNonInteractive", "(JI)I"); 1450 1451 GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz, 1452 "interceptKeyBeforeDispatching", 1453 "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)J"); 1454 1455 GET_METHOD_ID(gServiceClassInfo.dispatchUnhandledKey, clazz, 1456 "dispatchUnhandledKey", 1457 "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;"); 1458 1459 GET_METHOD_ID(gServiceClassInfo.checkInjectEventsPermission, clazz, 1460 "checkInjectEventsPermission", "(II)Z"); 1461 1462 GET_METHOD_ID(gServiceClassInfo.getVirtualKeyQuietTimeMillis, clazz, 1463 "getVirtualKeyQuietTimeMillis", "()I"); 1464 1465 GET_METHOD_ID(gServiceClassInfo.getExcludedDeviceNames, clazz, 1466 "getExcludedDeviceNames", "()[Ljava/lang/String;"); 1467 1468 GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz, 1469 "getKeyRepeatTimeout", "()I"); 1470 1471 GET_METHOD_ID(gServiceClassInfo.getKeyRepeatDelay, clazz, 1472 "getKeyRepeatDelay", "()I"); 1473 1474 GET_METHOD_ID(gServiceClassInfo.getHoverTapTimeout, clazz, 1475 "getHoverTapTimeout", "()I"); 1476 1477 GET_METHOD_ID(gServiceClassInfo.getHoverTapSlop, clazz, 1478 "getHoverTapSlop", "()I"); 1479 1480 GET_METHOD_ID(gServiceClassInfo.getDoubleTapTimeout, clazz, 1481 "getDoubleTapTimeout", "()I"); 1482 1483 GET_METHOD_ID(gServiceClassInfo.getLongPressTimeout, clazz, 1484 "getLongPressTimeout", "()I"); 1485 1486 GET_METHOD_ID(gServiceClassInfo.getPointerLayer, clazz, 1487 "getPointerLayer", "()I"); 1488 1489 GET_METHOD_ID(gServiceClassInfo.getPointerIcon, clazz, 1490 "getPointerIcon", "()Landroid/view/PointerIcon;"); 1491 1492 GET_METHOD_ID(gServiceClassInfo.getKeyboardLayoutOverlay, clazz, 1493 "getKeyboardLayoutOverlay", 1494 "(Landroid/hardware/input/InputDeviceIdentifier;)[Ljava/lang/String;"); 1495 1496 GET_METHOD_ID(gServiceClassInfo.getDeviceAlias, clazz, 1497 "getDeviceAlias", "(Ljava/lang/String;)Ljava/lang/String;"); 1498 1499 GET_METHOD_ID(gServiceClassInfo.getTouchCalibrationForInputDevice, clazz, 1500 "getTouchCalibrationForInputDevice", 1501 "(Ljava/lang/String;I)Landroid/hardware/input/TouchCalibration;"); 1502 1503 // InputDevice 1504 1505 FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice"); 1506 gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz)); 1507 1508 // KeyEvent 1509 1510 FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent"); 1511 gKeyEventClassInfo.clazz = jclass(env->NewGlobalRef(gKeyEventClassInfo.clazz)); 1512 1513 // MotionEvent 1514 1515 FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent"); 1516 gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz)); 1517 1518 // InputDeviceIdentifier 1519 1520 FIND_CLASS(gInputDeviceIdentifierInfo.clazz, "android/hardware/input/InputDeviceIdentifier"); 1521 gInputDeviceIdentifierInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceIdentifierInfo.clazz)); 1522 GET_METHOD_ID(gInputDeviceIdentifierInfo.constructor, gInputDeviceIdentifierInfo.clazz, 1523 "<init>", "(Ljava/lang/String;II)V"); 1524 1525 // TouchCalibration 1526 1527 FIND_CLASS(gTouchCalibrationClassInfo.clazz, "android/hardware/input/TouchCalibration"); 1528 gTouchCalibrationClassInfo.clazz = jclass(env->NewGlobalRef(gTouchCalibrationClassInfo.clazz)); 1529 1530 GET_METHOD_ID(gTouchCalibrationClassInfo.getAffineTransform, gTouchCalibrationClassInfo.clazz, 1531 "getAffineTransform", "()[F"); 1532 1533 return 0; 1534 } 1535 1536 } /* namespace android */ 1537