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