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