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