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