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