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