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