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