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