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