com_android_server_input_InputManagerService.cpp revision 4a9c3891d4f890109e02bc83fecf9bcdf56a9395
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 interceptWakeMotionBeforeQueueing; 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, kN32_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 setInteractive(bool interactive); 193 void reloadCalibration(); 194 195 /* --- InputReaderPolicyInterface implementation --- */ 196 197 virtual void getReaderConfiguration(InputReaderConfiguration* outConfig); 198 virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId); 199 virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices); 200 virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier); 201 virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier); 202 virtual TouchAffineTransformation getTouchAffineTransformation(JNIEnv *env, 203 jfloatArray matrixArr); 204 virtual TouchAffineTransformation getTouchAffineTransformation( 205 const String8& inputDeviceDescriptor, int32_t surfaceRotation); 206 207 /* --- InputDispatcherPolicyInterface implementation --- */ 208 209 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask, 210 uint32_t policyFlags); 211 virtual void notifyConfigurationChanged(nsecs_t when); 212 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle, 213 const sp<InputWindowHandle>& inputWindowHandle, 214 const String8& reason); 215 virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle); 216 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags); 217 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig); 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 volatile bool mInteractive; 266 267 void updateInactivityTimeoutLocked(const sp<PointerController>& controller); 268 void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags); 269 void ensureSpriteControllerLocked(); 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), mInteractive(true) { 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 638void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) { 639 Vector<sp<InputWindowHandle> > windowHandles; 640 641 if (windowHandleObjArray) { 642 jsize length = env->GetArrayLength(windowHandleObjArray); 643 for (jsize i = 0; i < length; i++) { 644 jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i); 645 if (! windowHandleObj) { 646 break; // found null element indicating end of used portion of the array 647 } 648 649 sp<InputWindowHandle> windowHandle = 650 android_server_InputWindowHandle_getHandle(env, windowHandleObj); 651 if (windowHandle != NULL) { 652 windowHandles.push(windowHandle); 653 } 654 env->DeleteLocalRef(windowHandleObj); 655 } 656 } 657 658 mInputManager->getDispatcher()->setInputWindows(windowHandles); 659 660 // Do this after the dispatcher has updated the window handle state. 661 bool newPointerGesturesEnabled = true; 662 size_t numWindows = windowHandles.size(); 663 for (size_t i = 0; i < numWindows; i++) { 664 const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i); 665 const InputWindowInfo* windowInfo = windowHandle->getInfo(); 666 if (windowInfo && windowInfo->hasFocus && (windowInfo->inputFeatures 667 & InputWindowInfo::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) { 668 newPointerGesturesEnabled = false; 669 } 670 } 671 672 uint32_t changes = 0; 673 { // acquire lock 674 AutoMutex _l(mLock); 675 676 if (mLocked.pointerGesturesEnabled != newPointerGesturesEnabled) { 677 mLocked.pointerGesturesEnabled = newPointerGesturesEnabled; 678 changes |= InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT; 679 } 680 } // release lock 681 682 if (changes) { 683 mInputManager->getReader()->requestRefreshConfiguration(changes); 684 } 685} 686 687void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationHandleObj) { 688 sp<InputApplicationHandle> applicationHandle = 689 android_server_InputApplicationHandle_getHandle(env, applicationHandleObj); 690 mInputManager->getDispatcher()->setFocusedApplication(applicationHandle); 691} 692 693void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) { 694 mInputManager->getDispatcher()->setInputDispatchMode(enabled, frozen); 695} 696 697void NativeInputManager::setSystemUiVisibility(int32_t visibility) { 698 AutoMutex _l(mLock); 699 700 if (mLocked.systemUiVisibility != visibility) { 701 mLocked.systemUiVisibility = visibility; 702 703 sp<PointerController> controller = mLocked.pointerController.promote(); 704 if (controller != NULL) { 705 updateInactivityTimeoutLocked(controller); 706 } 707 } 708} 709 710void NativeInputManager::updateInactivityTimeoutLocked(const sp<PointerController>& controller) { 711 bool lightsOut = mLocked.systemUiVisibility & ASYSTEM_UI_VISIBILITY_STATUS_BAR_HIDDEN; 712 controller->setInactivityTimeout(lightsOut 713 ? PointerController::INACTIVITY_TIMEOUT_SHORT 714 : PointerController::INACTIVITY_TIMEOUT_NORMAL); 715} 716 717void NativeInputManager::setPointerSpeed(int32_t speed) { 718 { // acquire lock 719 AutoMutex _l(mLock); 720 721 if (mLocked.pointerSpeed == speed) { 722 return; 723 } 724 725 ALOGI("Setting pointer speed to %d.", speed); 726 mLocked.pointerSpeed = speed; 727 } // release lock 728 729 mInputManager->getReader()->requestRefreshConfiguration( 730 InputReaderConfiguration::CHANGE_POINTER_SPEED); 731} 732 733void NativeInputManager::setShowTouches(bool enabled) { 734 { // acquire lock 735 AutoMutex _l(mLock); 736 737 if (mLocked.showTouches == enabled) { 738 return; 739 } 740 741 ALOGI("Setting show touches feature to %s.", enabled ? "enabled" : "disabled"); 742 mLocked.showTouches = enabled; 743 } // release lock 744 745 mInputManager->getReader()->requestRefreshConfiguration( 746 InputReaderConfiguration::CHANGE_SHOW_TOUCHES); 747} 748 749void NativeInputManager::setInteractive(bool interactive) { 750 mInteractive = interactive; 751} 752 753void NativeInputManager::reloadCalibration() { 754 mInputManager->getReader()->requestRefreshConfiguration( 755 InputReaderConfiguration::TOUCH_AFFINE_TRANSFORMATION); 756} 757 758TouchAffineTransformation NativeInputManager::getTouchAffineTransformation( 759 JNIEnv *env, jfloatArray matrixArr) { 760 ScopedFloatArrayRO matrix(env, matrixArr); 761 assert(matrix.size() == 6); 762 763 TouchAffineTransformation transform; 764 transform.x_scale = matrix[0]; 765 transform.x_ymix = matrix[1]; 766 transform.x_offset = matrix[2]; 767 transform.y_xmix = matrix[3]; 768 transform.y_scale = matrix[4]; 769 transform.y_offset = matrix[5]; 770 771 return transform; 772} 773 774TouchAffineTransformation NativeInputManager::getTouchAffineTransformation( 775 const String8& inputDeviceDescriptor, int32_t surfaceRotation) { 776 JNIEnv* env = jniEnv(); 777 778 ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.string())); 779 780 jobject cal = env->CallObjectMethod(mServiceObj, 781 gServiceClassInfo.getTouchCalibrationForInputDevice, descriptorObj.get(), 782 surfaceRotation); 783 784 jfloatArray matrixArr = jfloatArray(env->CallObjectMethod(cal, 785 gTouchCalibrationClassInfo.getAffineTransform)); 786 787 TouchAffineTransformation transform = getTouchAffineTransformation(env, matrixArr); 788 789 env->DeleteLocalRef(matrixArr); 790 env->DeleteLocalRef(cal); 791 792 return transform; 793} 794 795bool NativeInputManager::filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) { 796 jobject inputEventObj; 797 798 JNIEnv* env = jniEnv(); 799 switch (inputEvent->getType()) { 800 case AINPUT_EVENT_TYPE_KEY: 801 inputEventObj = android_view_KeyEvent_fromNative(env, 802 static_cast<const KeyEvent*>(inputEvent)); 803 break; 804 case AINPUT_EVENT_TYPE_MOTION: 805 inputEventObj = android_view_MotionEvent_obtainAsCopy(env, 806 static_cast<const MotionEvent*>(inputEvent)); 807 break; 808 default: 809 return true; // dispatch the event normally 810 } 811 812 if (!inputEventObj) { 813 ALOGE("Failed to obtain input event object for filterInputEvent."); 814 return true; // dispatch the event normally 815 } 816 817 // The callee is responsible for recycling the event. 818 jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent, 819 inputEventObj, policyFlags); 820 if (checkAndClearExceptionFromCallback(env, "filterInputEvent")) { 821 pass = true; 822 } 823 env->DeleteLocalRef(inputEventObj); 824 return pass; 825} 826 827void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent, 828 uint32_t& policyFlags) { 829 // Policy: 830 // - Ignore untrusted events and pass them along. 831 // - Ask the window manager what to do with normal events and trusted injected events. 832 // - For normal events wake and brighten the screen if currently off or dim. 833 if (mInteractive) { 834 policyFlags |= POLICY_FLAG_INTERACTIVE; 835 } 836 if ((policyFlags & POLICY_FLAG_TRUSTED)) { 837 nsecs_t when = keyEvent->getEventTime(); 838 JNIEnv* env = jniEnv(); 839 jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); 840 jint wmActions; 841 if (keyEventObj) { 842 wmActions = env->CallIntMethod(mServiceObj, 843 gServiceClassInfo.interceptKeyBeforeQueueing, 844 keyEventObj, policyFlags); 845 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { 846 wmActions = 0; 847 } 848 android_view_KeyEvent_recycle(env, keyEventObj); 849 env->DeleteLocalRef(keyEventObj); 850 } else { 851 ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing."); 852 wmActions = 0; 853 } 854 855 handleInterceptActions(wmActions, when, /*byref*/ policyFlags); 856 } else { 857 policyFlags |= POLICY_FLAG_PASS_TO_USER; 858 } 859} 860 861void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) { 862 // Policy: 863 // - Ignore untrusted events and pass them along. 864 // - No special filtering for injected events required at this time. 865 // - Filter normal events based on screen state. 866 // - For normal events brighten (but do not wake) the screen if currently dim. 867 if (mInteractive) { 868 policyFlags |= POLICY_FLAG_INTERACTIVE; 869 } 870 if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) { 871 if (policyFlags & POLICY_FLAG_INTERACTIVE) { 872 policyFlags |= POLICY_FLAG_PASS_TO_USER; 873 } else if (policyFlags & POLICY_FLAG_WAKE) { 874 JNIEnv* env = jniEnv(); 875 jint wmActions = env->CallIntMethod(mServiceObj, 876 gServiceClassInfo.interceptWakeMotionBeforeQueueing, 877 when, policyFlags); 878 if (checkAndClearExceptionFromCallback(env, 879 "interceptWakeMotionBeforeQueueing")) { 880 wmActions = 0; 881 } 882 883 handleInterceptActions(wmActions, when, /*byref*/ policyFlags); 884 } 885 } else { 886 policyFlags |= POLICY_FLAG_PASS_TO_USER; 887 } 888} 889 890void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when, 891 uint32_t& policyFlags) { 892 if (wmActions & WM_ACTION_PASS_TO_USER) { 893 policyFlags |= POLICY_FLAG_PASS_TO_USER; 894 } else { 895#if DEBUG_INPUT_DISPATCHER_POLICY 896 ALOGD("handleInterceptActions: Not passing key to user."); 897#endif 898 } 899} 900 901nsecs_t NativeInputManager::interceptKeyBeforeDispatching( 902 const sp<InputWindowHandle>& inputWindowHandle, 903 const KeyEvent* keyEvent, uint32_t policyFlags) { 904 // Policy: 905 // - Ignore untrusted events and pass them along. 906 // - Filter normal events and trusted injected events through the window manager policy to 907 // handle the HOME key and the like. 908 nsecs_t result = 0; 909 if (policyFlags & POLICY_FLAG_TRUSTED) { 910 JNIEnv* env = jniEnv(); 911 912 // Note: inputWindowHandle may be null. 913 jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle); 914 jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); 915 if (keyEventObj) { 916 jlong delayMillis = env->CallLongMethod(mServiceObj, 917 gServiceClassInfo.interceptKeyBeforeDispatching, 918 inputWindowHandleObj, keyEventObj, policyFlags); 919 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching"); 920 android_view_KeyEvent_recycle(env, keyEventObj); 921 env->DeleteLocalRef(keyEventObj); 922 if (!error) { 923 if (delayMillis < 0) { 924 result = -1; 925 } else if (delayMillis > 0) { 926 result = milliseconds_to_nanoseconds(delayMillis); 927 } 928 } 929 } else { 930 ALOGE("Failed to obtain key event object for interceptKeyBeforeDispatching."); 931 } 932 env->DeleteLocalRef(inputWindowHandleObj); 933 } 934 return result; 935} 936 937bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle, 938 const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) { 939 // Policy: 940 // - Ignore untrusted events and do not perform default handling. 941 bool result = false; 942 if (policyFlags & POLICY_FLAG_TRUSTED) { 943 JNIEnv* env = jniEnv(); 944 945 // Note: inputWindowHandle may be null. 946 jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle); 947 jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); 948 if (keyEventObj) { 949 jobject fallbackKeyEventObj = env->CallObjectMethod(mServiceObj, 950 gServiceClassInfo.dispatchUnhandledKey, 951 inputWindowHandleObj, keyEventObj, policyFlags); 952 if (checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey")) { 953 fallbackKeyEventObj = NULL; 954 } 955 android_view_KeyEvent_recycle(env, keyEventObj); 956 env->DeleteLocalRef(keyEventObj); 957 958 if (fallbackKeyEventObj) { 959 // Note: outFallbackKeyEvent may be the same object as keyEvent. 960 if (!android_view_KeyEvent_toNative(env, fallbackKeyEventObj, 961 outFallbackKeyEvent)) { 962 result = true; 963 } 964 android_view_KeyEvent_recycle(env, fallbackKeyEventObj); 965 env->DeleteLocalRef(fallbackKeyEventObj); 966 } 967 } else { 968 ALOGE("Failed to obtain key event object for dispatchUnhandledKey."); 969 } 970 env->DeleteLocalRef(inputWindowHandleObj); 971 } 972 return result; 973} 974 975void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) { 976 android_server_PowerManagerService_userActivity(eventTime, eventType); 977} 978 979 980bool NativeInputManager::checkInjectEventsPermissionNonReentrant( 981 int32_t injectorPid, int32_t injectorUid) { 982 JNIEnv* env = jniEnv(); 983 jboolean result = env->CallBooleanMethod(mServiceObj, 984 gServiceClassInfo.checkInjectEventsPermission, injectorPid, injectorUid); 985 if (checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission")) { 986 result = false; 987 } 988 return result; 989} 990 991void NativeInputManager::loadPointerResources(PointerResources* outResources) { 992 JNIEnv* env = jniEnv(); 993 994 loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_HOVER, 995 &outResources->spotHover); 996 loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_TOUCH, 997 &outResources->spotTouch); 998 loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_ANCHOR, 999 &outResources->spotAnchor); 1000} 1001 1002 1003// ---------------------------------------------------------------------------- 1004 1005static jlong nativeInit(JNIEnv* env, jclass clazz, 1006 jobject serviceObj, jobject contextObj, jobject messageQueueObj) { 1007 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); 1008 if (messageQueue == NULL) { 1009 jniThrowRuntimeException(env, "MessageQueue is not initialized."); 1010 return 0; 1011 } 1012 1013 NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, 1014 messageQueue->getLooper()); 1015 im->incStrong(0); 1016 return reinterpret_cast<jlong>(im); 1017} 1018 1019static void nativeStart(JNIEnv* env, jclass clazz, jlong ptr) { 1020 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1021 1022 status_t result = im->getInputManager()->start(); 1023 if (result) { 1024 jniThrowRuntimeException(env, "Input manager could not be started."); 1025 } 1026} 1027 1028static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jlong ptr, jboolean external, 1029 jint displayId, jint orientation, 1030 jint logicalLeft, jint logicalTop, jint logicalRight, jint logicalBottom, 1031 jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom, 1032 jint deviceWidth, jint deviceHeight) { 1033 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1034 1035 DisplayViewport v; 1036 v.displayId = displayId; 1037 v.orientation = orientation; 1038 v.logicalLeft = logicalLeft; 1039 v.logicalTop = logicalTop; 1040 v.logicalRight = logicalRight; 1041 v.logicalBottom = logicalBottom; 1042 v.physicalLeft = physicalLeft; 1043 v.physicalTop = physicalTop; 1044 v.physicalRight = physicalRight; 1045 v.physicalBottom = physicalBottom; 1046 v.deviceWidth = deviceWidth; 1047 v.deviceHeight = deviceHeight; 1048 im->setDisplayViewport(external, v); 1049} 1050 1051static jint nativeGetScanCodeState(JNIEnv* env, jclass clazz, 1052 jlong ptr, jint deviceId, jint sourceMask, jint scanCode) { 1053 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1054 1055 return (jint) im->getInputManager()->getReader()->getScanCodeState( 1056 deviceId, uint32_t(sourceMask), scanCode); 1057} 1058 1059static jint nativeGetKeyCodeState(JNIEnv* env, jclass clazz, 1060 jlong ptr, jint deviceId, jint sourceMask, jint keyCode) { 1061 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1062 1063 return (jint) im->getInputManager()->getReader()->getKeyCodeState( 1064 deviceId, uint32_t(sourceMask), keyCode); 1065} 1066 1067static jint nativeGetSwitchState(JNIEnv* env, jclass clazz, 1068 jlong ptr, jint deviceId, jint sourceMask, jint sw) { 1069 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1070 1071 return (jint) im->getInputManager()->getReader()->getSwitchState( 1072 deviceId, uint32_t(sourceMask), sw); 1073} 1074 1075static jboolean nativeHasKeys(JNIEnv* env, jclass clazz, 1076 jlong ptr, jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) { 1077 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1078 1079 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL); 1080 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL); 1081 jsize numCodes = env->GetArrayLength(keyCodes); 1082 jboolean result; 1083 if (numCodes == env->GetArrayLength(keyCodes)) { 1084 if (im->getInputManager()->getReader()->hasKeys( 1085 deviceId, uint32_t(sourceMask), numCodes, codes, flags)) { 1086 result = JNI_TRUE; 1087 } else { 1088 result = JNI_FALSE; 1089 } 1090 } else { 1091 result = JNI_FALSE; 1092 } 1093 1094 env->ReleaseBooleanArrayElements(outFlags, flags, 0); 1095 env->ReleaseIntArrayElements(keyCodes, codes, 0); 1096 return result; 1097} 1098 1099static void throwInputChannelNotInitialized(JNIEnv* env) { 1100 jniThrowException(env, "java/lang/IllegalStateException", 1101 "inputChannel is not initialized"); 1102} 1103 1104static void handleInputChannelDisposed(JNIEnv* env, 1105 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) { 1106 NativeInputManager* im = static_cast<NativeInputManager*>(data); 1107 1108 ALOGW("Input channel object '%s' was disposed without first being unregistered with " 1109 "the input manager!", inputChannel->getName().string()); 1110 im->unregisterInputChannel(env, inputChannel); 1111} 1112 1113static void nativeRegisterInputChannel(JNIEnv* env, jclass clazz, 1114 jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) { 1115 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1116 1117 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env, 1118 inputChannelObj); 1119 if (inputChannel == NULL) { 1120 throwInputChannelNotInitialized(env); 1121 return; 1122 } 1123 1124 sp<InputWindowHandle> inputWindowHandle = 1125 android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj); 1126 1127 status_t status = im->registerInputChannel( 1128 env, inputChannel, inputWindowHandle, monitor); 1129 if (status) { 1130 String8 message; 1131 message.appendFormat("Failed to register input channel. status=%d", status); 1132 jniThrowRuntimeException(env, message.string()); 1133 return; 1134 } 1135 1136 if (! monitor) { 1137 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, 1138 handleInputChannelDisposed, im); 1139 } 1140} 1141 1142static void nativeUnregisterInputChannel(JNIEnv* env, jclass clazz, 1143 jlong ptr, jobject inputChannelObj) { 1144 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1145 1146 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env, 1147 inputChannelObj); 1148 if (inputChannel == NULL) { 1149 throwInputChannelNotInitialized(env); 1150 return; 1151 } 1152 1153 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL); 1154 1155 status_t status = im->unregisterInputChannel(env, inputChannel); 1156 if (status && status != BAD_VALUE) { // ignore already unregistered channel 1157 String8 message; 1158 message.appendFormat("Failed to unregister input channel. status=%d", status); 1159 jniThrowRuntimeException(env, message.string()); 1160 } 1161} 1162 1163static void nativeSetInputFilterEnabled(JNIEnv* env, jclass clazz, 1164 jlong ptr, jboolean enabled) { 1165 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1166 1167 im->getInputManager()->getDispatcher()->setInputFilterEnabled(enabled); 1168} 1169 1170static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz, 1171 jlong ptr, jobject inputEventObj, jint displayId, jint injectorPid, jint injectorUid, 1172 jint syncMode, jint timeoutMillis, jint policyFlags) { 1173 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1174 1175 if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) { 1176 KeyEvent keyEvent; 1177 status_t status = android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent); 1178 if (status) { 1179 jniThrowRuntimeException(env, "Could not read contents of KeyEvent object."); 1180 return INPUT_EVENT_INJECTION_FAILED; 1181 } 1182 1183 return (jint) im->getInputManager()->getDispatcher()->injectInputEvent( 1184 & keyEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis, 1185 uint32_t(policyFlags)); 1186 } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) { 1187 const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj); 1188 if (!motionEvent) { 1189 jniThrowRuntimeException(env, "Could not read contents of MotionEvent object."); 1190 return INPUT_EVENT_INJECTION_FAILED; 1191 } 1192 1193 return (jint) im->getInputManager()->getDispatcher()->injectInputEvent( 1194 motionEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis, 1195 uint32_t(policyFlags)); 1196 } else { 1197 jniThrowRuntimeException(env, "Invalid input event type."); 1198 return INPUT_EVENT_INJECTION_FAILED; 1199 } 1200} 1201 1202static void nativeSetInputWindows(JNIEnv* env, jclass clazz, 1203 jlong ptr, jobjectArray windowHandleObjArray) { 1204 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1205 1206 im->setInputWindows(env, windowHandleObjArray); 1207} 1208 1209static void nativeSetFocusedApplication(JNIEnv* env, jclass clazz, 1210 jlong ptr, jobject applicationHandleObj) { 1211 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1212 1213 im->setFocusedApplication(env, applicationHandleObj); 1214} 1215 1216static void nativeSetInputDispatchMode(JNIEnv* env, 1217 jclass clazz, jlong ptr, jboolean enabled, jboolean frozen) { 1218 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1219 1220 im->setInputDispatchMode(enabled, frozen); 1221} 1222 1223static void nativeSetSystemUiVisibility(JNIEnv* env, 1224 jclass clazz, jlong ptr, jint visibility) { 1225 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1226 1227 im->setSystemUiVisibility(visibility); 1228} 1229 1230static jboolean nativeTransferTouchFocus(JNIEnv* env, 1231 jclass clazz, jlong ptr, jobject fromChannelObj, jobject toChannelObj) { 1232 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1233 1234 sp<InputChannel> fromChannel = 1235 android_view_InputChannel_getInputChannel(env, fromChannelObj); 1236 sp<InputChannel> toChannel = 1237 android_view_InputChannel_getInputChannel(env, toChannelObj); 1238 1239 if (fromChannel == NULL || toChannel == NULL) { 1240 return JNI_FALSE; 1241 } 1242 1243 if (im->getInputManager()->getDispatcher()-> 1244 transferTouchFocus(fromChannel, toChannel)) { 1245 return JNI_TRUE; 1246 } else { 1247 return JNI_FALSE; 1248 } 1249} 1250 1251static void nativeSetPointerSpeed(JNIEnv* env, 1252 jclass clazz, jlong ptr, jint speed) { 1253 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1254 1255 im->setPointerSpeed(speed); 1256} 1257 1258static void nativeSetShowTouches(JNIEnv* env, 1259 jclass clazz, jlong ptr, jboolean enabled) { 1260 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1261 1262 im->setShowTouches(enabled); 1263} 1264 1265static void nativeSetInteractive(JNIEnv* env, 1266 jclass clazz, jlong ptr, jboolean interactive) { 1267 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1268 1269 im->setInteractive(interactive); 1270} 1271 1272static void nativeReloadCalibration(JNIEnv* env, jclass clazz, jlong ptr) { 1273 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1274 im->reloadCalibration(); 1275} 1276 1277static void nativeVibrate(JNIEnv* env, 1278 jclass clazz, jlong ptr, jint deviceId, jlongArray patternObj, 1279 jint repeat, jint token) { 1280 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1281 1282 size_t patternSize = env->GetArrayLength(patternObj); 1283 if (patternSize > MAX_VIBRATE_PATTERN_SIZE) { 1284 ALOGI("Skipped requested vibration because the pattern size is %zu " 1285 "which is more than the maximum supported size of %d.", 1286 patternSize, MAX_VIBRATE_PATTERN_SIZE); 1287 return; // limit to reasonable size 1288 } 1289 1290 jlong* patternMillis = static_cast<jlong*>(env->GetPrimitiveArrayCritical( 1291 patternObj, NULL)); 1292 nsecs_t pattern[patternSize]; 1293 for (size_t i = 0; i < patternSize; i++) { 1294 pattern[i] = max(jlong(0), min(patternMillis[i], 1295 (jlong)(MAX_VIBRATE_PATTERN_DELAY_NSECS / 1000000LL))) * 1000000LL; 1296 } 1297 env->ReleasePrimitiveArrayCritical(patternObj, patternMillis, JNI_ABORT); 1298 1299 im->getInputManager()->getReader()->vibrate(deviceId, pattern, patternSize, repeat, token); 1300} 1301 1302static void nativeCancelVibrate(JNIEnv* env, 1303 jclass clazz, jlong ptr, jint deviceId, jint token) { 1304 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1305 1306 im->getInputManager()->getReader()->cancelVibrate(deviceId, token); 1307} 1308 1309static void nativeReloadKeyboardLayouts(JNIEnv* env, 1310 jclass clazz, jlong ptr) { 1311 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1312 1313 im->getInputManager()->getReader()->requestRefreshConfiguration( 1314 InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS); 1315} 1316 1317static void nativeReloadDeviceAliases(JNIEnv* env, 1318 jclass clazz, jlong ptr) { 1319 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1320 1321 im->getInputManager()->getReader()->requestRefreshConfiguration( 1322 InputReaderConfiguration::CHANGE_DEVICE_ALIAS); 1323} 1324 1325static jstring nativeDump(JNIEnv* env, jclass clazz, jlong ptr) { 1326 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1327 1328 String8 dump; 1329 im->dump(dump); 1330 return env->NewStringUTF(dump.string()); 1331} 1332 1333static void nativeMonitor(JNIEnv* env, jclass clazz, jlong ptr) { 1334 NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); 1335 1336 im->getInputManager()->getReader()->monitor(); 1337 im->getInputManager()->getDispatcher()->monitor(); 1338} 1339 1340// ---------------------------------------------------------------------------- 1341 1342static JNINativeMethod gInputManagerMethods[] = { 1343 /* name, signature, funcPtr */ 1344 { "nativeInit", 1345 "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J", 1346 (void*) nativeInit }, 1347 { "nativeStart", "(J)V", 1348 (void*) nativeStart }, 1349 { "nativeSetDisplayViewport", "(JZIIIIIIIIIIII)V", 1350 (void*) nativeSetDisplayViewport }, 1351 { "nativeGetScanCodeState", "(JIII)I", 1352 (void*) nativeGetScanCodeState }, 1353 { "nativeGetKeyCodeState", "(JIII)I", 1354 (void*) nativeGetKeyCodeState }, 1355 { "nativeGetSwitchState", "(JIII)I", 1356 (void*) nativeGetSwitchState }, 1357 { "nativeHasKeys", "(JII[I[Z)Z", 1358 (void*) nativeHasKeys }, 1359 { "nativeRegisterInputChannel", 1360 "(JLandroid/view/InputChannel;Lcom/android/server/input/InputWindowHandle;Z)V", 1361 (void*) nativeRegisterInputChannel }, 1362 { "nativeUnregisterInputChannel", "(JLandroid/view/InputChannel;)V", 1363 (void*) nativeUnregisterInputChannel }, 1364 { "nativeSetInputFilterEnabled", "(JZ)V", 1365 (void*) nativeSetInputFilterEnabled }, 1366 { "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I", 1367 (void*) nativeInjectInputEvent }, 1368 { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V", 1369 (void*) nativeSetInputWindows }, 1370 { "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V", 1371 (void*) nativeSetFocusedApplication }, 1372 { "nativeSetInputDispatchMode", "(JZZ)V", 1373 (void*) nativeSetInputDispatchMode }, 1374 { "nativeSetSystemUiVisibility", "(JI)V", 1375 (void*) nativeSetSystemUiVisibility }, 1376 { "nativeTransferTouchFocus", "(JLandroid/view/InputChannel;Landroid/view/InputChannel;)Z", 1377 (void*) nativeTransferTouchFocus }, 1378 { "nativeSetPointerSpeed", "(JI)V", 1379 (void*) nativeSetPointerSpeed }, 1380 { "nativeSetShowTouches", "(JZ)V", 1381 (void*) nativeSetShowTouches }, 1382 { "nativeSetInteractive", "(JZ)V", 1383 (void*) nativeSetInteractive }, 1384 { "nativeReloadCalibration", "(J)V", 1385 (void*) nativeReloadCalibration }, 1386 { "nativeVibrate", "(JI[JII)V", 1387 (void*) nativeVibrate }, 1388 { "nativeCancelVibrate", "(JII)V", 1389 (void*) nativeCancelVibrate }, 1390 { "nativeReloadKeyboardLayouts", "(J)V", 1391 (void*) nativeReloadKeyboardLayouts }, 1392 { "nativeReloadDeviceAliases", "(J)V", 1393 (void*) nativeReloadDeviceAliases }, 1394 { "nativeDump", "(J)Ljava/lang/String;", 1395 (void*) nativeDump }, 1396 { "nativeMonitor", "(J)V", 1397 (void*) nativeMonitor }, 1398}; 1399 1400#define FIND_CLASS(var, className) \ 1401 var = env->FindClass(className); \ 1402 LOG_FATAL_IF(! var, "Unable to find class " className); 1403 1404#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 1405 var = env->GetMethodID(clazz, methodName, methodDescriptor); \ 1406 LOG_FATAL_IF(! var, "Unable to find method " methodName); 1407 1408#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 1409 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 1410 LOG_FATAL_IF(! var, "Unable to find field " fieldName); 1411 1412int register_android_server_InputManager(JNIEnv* env) { 1413 int res = jniRegisterNativeMethods(env, "com/android/server/input/InputManagerService", 1414 gInputManagerMethods, NELEM(gInputManagerMethods)); 1415 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 1416 1417 // Callbacks 1418 1419 jclass clazz; 1420 FIND_CLASS(clazz, "com/android/server/input/InputManagerService"); 1421 1422 GET_METHOD_ID(gServiceClassInfo.notifyConfigurationChanged, clazz, 1423 "notifyConfigurationChanged", "(J)V"); 1424 1425 GET_METHOD_ID(gServiceClassInfo.notifyInputDevicesChanged, clazz, 1426 "notifyInputDevicesChanged", "([Landroid/view/InputDevice;)V"); 1427 1428 GET_METHOD_ID(gServiceClassInfo.notifySwitch, clazz, 1429 "notifySwitch", "(JII)V"); 1430 1431 GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz, 1432 "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V"); 1433 1434 GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz, 1435 "notifyANR", 1436 "(Lcom/android/server/input/InputApplicationHandle;Lcom/android/server/input/InputWindowHandle;Ljava/lang/String;)J"); 1437 1438 GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz, 1439 "filterInputEvent", "(Landroid/view/InputEvent;I)Z"); 1440 1441 GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz, 1442 "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I"); 1443 1444 GET_METHOD_ID(gServiceClassInfo.interceptWakeMotionBeforeQueueing, clazz, 1445 "interceptWakeMotionBeforeQueueing", "(JI)I"); 1446 1447 GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz, 1448 "interceptKeyBeforeDispatching", 1449 "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)J"); 1450 1451 GET_METHOD_ID(gServiceClassInfo.dispatchUnhandledKey, clazz, 1452 "dispatchUnhandledKey", 1453 "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;"); 1454 1455 GET_METHOD_ID(gServiceClassInfo.checkInjectEventsPermission, clazz, 1456 "checkInjectEventsPermission", "(II)Z"); 1457 1458 GET_METHOD_ID(gServiceClassInfo.getVirtualKeyQuietTimeMillis, clazz, 1459 "getVirtualKeyQuietTimeMillis", "()I"); 1460 1461 GET_METHOD_ID(gServiceClassInfo.getExcludedDeviceNames, clazz, 1462 "getExcludedDeviceNames", "()[Ljava/lang/String;"); 1463 1464 GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz, 1465 "getKeyRepeatTimeout", "()I"); 1466 1467 GET_METHOD_ID(gServiceClassInfo.getKeyRepeatDelay, clazz, 1468 "getKeyRepeatDelay", "()I"); 1469 1470 GET_METHOD_ID(gServiceClassInfo.getHoverTapTimeout, clazz, 1471 "getHoverTapTimeout", "()I"); 1472 1473 GET_METHOD_ID(gServiceClassInfo.getHoverTapSlop, clazz, 1474 "getHoverTapSlop", "()I"); 1475 1476 GET_METHOD_ID(gServiceClassInfo.getDoubleTapTimeout, clazz, 1477 "getDoubleTapTimeout", "()I"); 1478 1479 GET_METHOD_ID(gServiceClassInfo.getLongPressTimeout, clazz, 1480 "getLongPressTimeout", "()I"); 1481 1482 GET_METHOD_ID(gServiceClassInfo.getPointerLayer, clazz, 1483 "getPointerLayer", "()I"); 1484 1485 GET_METHOD_ID(gServiceClassInfo.getPointerIcon, clazz, 1486 "getPointerIcon", "()Landroid/view/PointerIcon;"); 1487 1488 GET_METHOD_ID(gServiceClassInfo.getKeyboardLayoutOverlay, clazz, 1489 "getKeyboardLayoutOverlay", 1490 "(Landroid/hardware/input/InputDeviceIdentifier;)[Ljava/lang/String;"); 1491 1492 GET_METHOD_ID(gServiceClassInfo.getDeviceAlias, clazz, 1493 "getDeviceAlias", "(Ljava/lang/String;)Ljava/lang/String;"); 1494 1495 GET_METHOD_ID(gServiceClassInfo.getTouchCalibrationForInputDevice, clazz, 1496 "getTouchCalibrationForInputDevice", 1497 "(Ljava/lang/String;I)Landroid/hardware/input/TouchCalibration;"); 1498 1499 // InputDevice 1500 1501 FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice"); 1502 gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz)); 1503 1504 // KeyEvent 1505 1506 FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent"); 1507 gKeyEventClassInfo.clazz = jclass(env->NewGlobalRef(gKeyEventClassInfo.clazz)); 1508 1509 // MotionEvent 1510 1511 FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent"); 1512 gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz)); 1513 1514 // InputDeviceIdentifier 1515 1516 FIND_CLASS(gInputDeviceIdentifierInfo.clazz, "android/hardware/input/InputDeviceIdentifier"); 1517 gInputDeviceIdentifierInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceIdentifierInfo.clazz)); 1518 GET_METHOD_ID(gInputDeviceIdentifierInfo.constructor, gInputDeviceIdentifierInfo.clazz, 1519 "<init>", "(Ljava/lang/String;II)V"); 1520 1521 // TouchCalibration 1522 1523 FIND_CLASS(gTouchCalibrationClassInfo.clazz, "android/hardware/input/TouchCalibration"); 1524 gTouchCalibrationClassInfo.clazz = jclass(env->NewGlobalRef(gTouchCalibrationClassInfo.clazz)); 1525 1526 GET_METHOD_ID(gTouchCalibrationClassInfo.getAffineTransform, gTouchCalibrationClassInfo.clazz, 1527 "getAffineTransform", "()[F"); 1528 1529 return 0; 1530} 1531 1532} /* namespace android */ 1533