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