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