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 #include "JNIHelp.h" 28 #include "jni.h" 29 #include <limits.h> 30 #include <android_runtime/AndroidRuntime.h> 31 #include <ui/InputReader.h> 32 #include <ui/InputDispatcher.h> 33 #include <ui/InputManager.h> 34 #include <ui/InputTransport.h> 35 #include <utils/Log.h> 36 #include <utils/threads.h> 37 #include "../../core/jni/android_view_KeyEvent.h" 38 #include "../../core/jni/android_view_MotionEvent.h" 39 #include "../../core/jni/android_view_InputChannel.h" 40 #include "com_android_server_PowerManagerService.h" 41 42 namespace android { 43 44 // ---------------------------------------------------------------------------- 45 46 static struct { 47 jclass clazz; 48 49 jmethodID notifyConfigurationChanged; 50 jmethodID notifyLidSwitchChanged; 51 jmethodID notifyInputChannelBroken; 52 jmethodID notifyANR; 53 jmethodID interceptKeyBeforeQueueing; 54 jmethodID interceptKeyBeforeDispatching; 55 jmethodID checkInjectEventsPermission; 56 jmethodID filterTouchEvents; 57 jmethodID filterJumpyTouchEvents; 58 jmethodID getVirtualKeyDefinitions; 59 jmethodID getInputDeviceCalibration; 60 jmethodID getExcludedDeviceNames; 61 jmethodID getMaxEventsPerSecond; 62 } gCallbacksClassInfo; 63 64 static struct { 65 jclass clazz; 66 67 jfieldID scanCode; 68 jfieldID centerX; 69 jfieldID centerY; 70 jfieldID width; 71 jfieldID height; 72 } gVirtualKeyDefinitionClassInfo; 73 74 static struct { 75 jclass clazz; 76 77 jfieldID keys; 78 jfieldID values; 79 } gInputDeviceCalibrationClassInfo; 80 81 static struct { 82 jclass clazz; 83 84 jfieldID inputChannel; 85 jfieldID name; 86 jfieldID layoutParamsFlags; 87 jfieldID layoutParamsType; 88 jfieldID dispatchingTimeoutNanos; 89 jfieldID frameLeft; 90 jfieldID frameTop; 91 jfieldID frameRight; 92 jfieldID frameBottom; 93 jfieldID visibleFrameLeft; 94 jfieldID visibleFrameTop; 95 jfieldID visibleFrameRight; 96 jfieldID visibleFrameBottom; 97 jfieldID touchableAreaLeft; 98 jfieldID touchableAreaTop; 99 jfieldID touchableAreaRight; 100 jfieldID touchableAreaBottom; 101 jfieldID visible; 102 jfieldID canReceiveKeys; 103 jfieldID hasFocus; 104 jfieldID hasWallpaper; 105 jfieldID paused; 106 jfieldID layer; 107 jfieldID ownerPid; 108 jfieldID ownerUid; 109 } gInputWindowClassInfo; 110 111 static struct { 112 jclass clazz; 113 114 jfieldID name; 115 jfieldID dispatchingTimeoutNanos; 116 jfieldID token; 117 } gInputApplicationClassInfo; 118 119 static struct { 120 jclass clazz; 121 } gKeyEventClassInfo; 122 123 static struct { 124 jclass clazz; 125 } gMotionEventClassInfo; 126 127 static struct { 128 jclass clazz; 129 130 jmethodID ctor; 131 jmethodID addMotionRange; 132 133 jfieldID mId; 134 jfieldID mName; 135 jfieldID mSources; 136 jfieldID mKeyboardType; 137 jfieldID mMotionRanges; 138 } gInputDeviceClassInfo; 139 140 static struct { 141 jclass clazz; 142 143 jfieldID touchscreen; 144 jfieldID keyboard; 145 jfieldID navigation; 146 } gConfigurationClassInfo; 147 148 // ---------------------------------------------------------------------------- 149 150 static inline nsecs_t now() { 151 return systemTime(SYSTEM_TIME_MONOTONIC); 152 } 153 154 // ---------------------------------------------------------------------------- 155 156 class NativeInputManager : public virtual RefBase, 157 public virtual InputReaderPolicyInterface, 158 public virtual InputDispatcherPolicyInterface { 159 protected: 160 virtual ~NativeInputManager(); 161 162 public: 163 NativeInputManager(jobject callbacksObj); 164 165 inline sp<InputManager> getInputManager() const { return mInputManager; } 166 167 void dump(String8& dump); 168 169 void setDisplaySize(int32_t displayId, int32_t width, int32_t height); 170 void setDisplayOrientation(int32_t displayId, int32_t orientation); 171 172 status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel, 173 jweak inputChannelObjWeak, bool monitor); 174 status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel); 175 176 void setInputWindows(JNIEnv* env, jobjectArray windowObjArray); 177 void setFocusedApplication(JNIEnv* env, jobject applicationObj); 178 void setInputDispatchMode(bool enabled, bool frozen); 179 180 /* --- InputReaderPolicyInterface implementation --- */ 181 182 virtual bool getDisplayInfo(int32_t displayId, 183 int32_t* width, int32_t* height, int32_t* orientation); 184 virtual bool filterTouchEvents(); 185 virtual bool filterJumpyTouchEvents(); 186 virtual void getVirtualKeyDefinitions(const String8& deviceName, 187 Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions); 188 virtual void getInputDeviceCalibration(const String8& deviceName, 189 InputDeviceCalibration& outCalibration); 190 virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames); 191 192 /* --- InputDispatcherPolicyInterface implementation --- */ 193 194 virtual void notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue, 195 uint32_t policyFlags); 196 virtual void notifyConfigurationChanged(nsecs_t when); 197 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle, 198 const sp<InputChannel>& inputChannel); 199 virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel); 200 virtual nsecs_t getKeyRepeatTimeout(); 201 virtual nsecs_t getKeyRepeatDelay(); 202 virtual int32_t getMaxEventsPerSecond(); 203 virtual void interceptKeyBeforeQueueing(nsecs_t when, int32_t deviceId, 204 int32_t action, int32_t& flags, int32_t keyCode, int32_t scanCode, 205 uint32_t& policyFlags); 206 virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags); 207 virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel, 208 const KeyEvent* keyEvent, uint32_t policyFlags); 209 virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType); 210 virtual bool checkInjectEventsPermissionNonReentrant( 211 int32_t injectorPid, int32_t injectorUid); 212 213 private: 214 class ApplicationToken : public InputApplicationHandle { 215 jweak mTokenObjWeak; 216 217 public: 218 ApplicationToken(jweak tokenObjWeak) : 219 mTokenObjWeak(tokenObjWeak) { } 220 221 virtual ~ApplicationToken() { 222 JNIEnv* env = NativeInputManager::jniEnv(); 223 env->DeleteWeakGlobalRef(mTokenObjWeak); 224 } 225 226 inline jweak getTokenObj() { return mTokenObjWeak; } 227 }; 228 229 sp<InputManager> mInputManager; 230 231 jobject mCallbacksObj; 232 233 // Cached filtering policies. 234 int32_t mFilterTouchEvents; 235 int32_t mFilterJumpyTouchEvents; 236 237 // Cached throttling policy. 238 int32_t mMaxEventsPerSecond; 239 240 // Cached display state. (lock mDisplayLock) 241 Mutex mDisplayLock; 242 int32_t mDisplayWidth, mDisplayHeight; 243 int32_t mDisplayOrientation; 244 245 // Power manager interactions. 246 bool isScreenOn(); 247 bool isScreenBright(); 248 249 // Weak references to all currently registered input channels by connection pointer. 250 Mutex mInputChannelRegistryLock; 251 KeyedVector<InputChannel*, jweak> mInputChannelObjWeakTable; 252 253 jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel); 254 255 static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow); 256 257 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName); 258 259 static inline JNIEnv* jniEnv() { 260 return AndroidRuntime::getJNIEnv(); 261 } 262 }; 263 264 // ---------------------------------------------------------------------------- 265 266 NativeInputManager::NativeInputManager(jobject callbacksObj) : 267 mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), 268 mMaxEventsPerSecond(-1), 269 mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0) { 270 JNIEnv* env = jniEnv(); 271 272 mCallbacksObj = env->NewGlobalRef(callbacksObj); 273 274 sp<EventHub> eventHub = new EventHub(); 275 mInputManager = new InputManager(eventHub, this, this); 276 } 277 278 NativeInputManager::~NativeInputManager() { 279 JNIEnv* env = jniEnv(); 280 281 env->DeleteGlobalRef(mCallbacksObj); 282 } 283 284 void NativeInputManager::dump(String8& dump) { 285 mInputManager->getReader()->dump(dump); 286 dump.append("\n"); 287 288 mInputManager->getDispatcher()->dump(dump); 289 dump.append("\n"); 290 } 291 292 bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { 293 if (env->ExceptionCheck()) { 294 LOGE("An exception was thrown by callback '%s'.", methodName); 295 LOGE_EX(env); 296 env->ExceptionClear(); 297 return true; 298 } 299 return false; 300 } 301 302 void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) { 303 if (displayId == 0) { 304 AutoMutex _l(mDisplayLock); 305 306 mDisplayWidth = width; 307 mDisplayHeight = height; 308 } 309 } 310 311 void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) { 312 if (displayId == 0) { 313 AutoMutex _l(mDisplayLock); 314 315 mDisplayOrientation = orientation; 316 } 317 } 318 319 status_t NativeInputManager::registerInputChannel(JNIEnv* env, 320 const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) { 321 jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj); 322 if (! inputChannelObjWeak) { 323 LOGE("Could not create weak reference for input channel."); 324 LOGE_EX(env); 325 return NO_MEMORY; 326 } 327 328 status_t status; 329 { 330 AutoMutex _l(mInputChannelRegistryLock); 331 332 ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get()); 333 if (index >= 0) { 334 LOGE("Input channel object '%s' has already been registered", 335 inputChannel->getName().string()); 336 status = INVALID_OPERATION; 337 goto DeleteWeakRef; 338 } 339 340 mInputChannelObjWeakTable.add(inputChannel.get(), inputChannelObjWeak); 341 } 342 343 status = mInputManager->getDispatcher()->registerInputChannel(inputChannel, monitor); 344 if (! status) { 345 // Success. 346 return OK; 347 } 348 349 // Failed! 350 { 351 AutoMutex _l(mInputChannelRegistryLock); 352 mInputChannelObjWeakTable.removeItem(inputChannel.get()); 353 } 354 355 DeleteWeakRef: 356 env->DeleteWeakGlobalRef(inputChannelObjWeak); 357 return status; 358 } 359 360 status_t NativeInputManager::unregisterInputChannel(JNIEnv* env, 361 const sp<InputChannel>& inputChannel) { 362 jweak inputChannelObjWeak; 363 { 364 AutoMutex _l(mInputChannelRegistryLock); 365 366 ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get()); 367 if (index < 0) { 368 LOGE("Input channel object '%s' is not currently registered", 369 inputChannel->getName().string()); 370 return INVALID_OPERATION; 371 } 372 373 inputChannelObjWeak = mInputChannelObjWeakTable.valueAt(index); 374 mInputChannelObjWeakTable.removeItemsAt(index); 375 } 376 377 env->DeleteWeakGlobalRef(inputChannelObjWeak); 378 379 return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel); 380 } 381 382 jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env, 383 const sp<InputChannel>& inputChannel) { 384 InputChannel* inputChannelPtr = inputChannel.get(); 385 if (! inputChannelPtr) { 386 return NULL; 387 } 388 389 { 390 AutoMutex _l(mInputChannelRegistryLock); 391 392 ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannelPtr); 393 if (index < 0) { 394 return NULL; 395 } 396 397 jweak inputChannelObjWeak = mInputChannelObjWeakTable.valueAt(index); 398 return env->NewLocalRef(inputChannelObjWeak); 399 } 400 } 401 402 bool NativeInputManager::getDisplayInfo(int32_t displayId, 403 int32_t* width, int32_t* height, int32_t* orientation) { 404 bool result = false; 405 if (displayId == 0) { 406 AutoMutex _l(mDisplayLock); 407 408 if (mDisplayWidth > 0) { 409 if (width) { 410 *width = mDisplayWidth; 411 } 412 if (height) { 413 *height = mDisplayHeight; 414 } 415 if (orientation) { 416 *orientation = mDisplayOrientation; 417 } 418 result = true; 419 } 420 } 421 return result; 422 } 423 424 bool NativeInputManager::filterTouchEvents() { 425 if (mFilterTouchEvents < 0) { 426 JNIEnv* env = jniEnv(); 427 428 jboolean result = env->CallBooleanMethod(mCallbacksObj, 429 gCallbacksClassInfo.filterTouchEvents); 430 if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) { 431 result = false; 432 } 433 434 mFilterTouchEvents = result ? 1 : 0; 435 } 436 return mFilterTouchEvents; 437 } 438 439 bool NativeInputManager::filterJumpyTouchEvents() { 440 if (mFilterJumpyTouchEvents < 0) { 441 JNIEnv* env = jniEnv(); 442 443 jboolean result = env->CallBooleanMethod(mCallbacksObj, 444 gCallbacksClassInfo.filterJumpyTouchEvents); 445 if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) { 446 result = false; 447 } 448 449 mFilterJumpyTouchEvents = result ? 1 : 0; 450 } 451 return mFilterJumpyTouchEvents; 452 } 453 454 void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName, 455 Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) { 456 outVirtualKeyDefinitions.clear(); 457 458 JNIEnv* env = jniEnv(); 459 460 jstring deviceNameStr = env->NewStringUTF(deviceName.string()); 461 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) { 462 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj, 463 gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr)); 464 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) { 465 jsize length = env->GetArrayLength(result); 466 for (jsize i = 0; i < length; i++) { 467 jobject item = env->GetObjectArrayElement(result, i); 468 469 outVirtualKeyDefinitions.add(); 470 outVirtualKeyDefinitions.editTop().scanCode = 471 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode)); 472 outVirtualKeyDefinitions.editTop().centerX = 473 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX)); 474 outVirtualKeyDefinitions.editTop().centerY = 475 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY)); 476 outVirtualKeyDefinitions.editTop().width = 477 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width)); 478 outVirtualKeyDefinitions.editTop().height = 479 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height)); 480 481 env->DeleteLocalRef(item); 482 } 483 env->DeleteLocalRef(result); 484 } 485 env->DeleteLocalRef(deviceNameStr); 486 } 487 } 488 489 void NativeInputManager::getInputDeviceCalibration(const String8& deviceName, 490 InputDeviceCalibration& outCalibration) { 491 outCalibration.clear(); 492 493 JNIEnv* env = jniEnv(); 494 495 jstring deviceNameStr = env->NewStringUTF(deviceName.string()); 496 if (! checkAndClearExceptionFromCallback(env, "getInputDeviceCalibration")) { 497 jobject result = env->CallObjectMethod(mCallbacksObj, 498 gCallbacksClassInfo.getInputDeviceCalibration, deviceNameStr); 499 if (! checkAndClearExceptionFromCallback(env, "getInputDeviceCalibration") && result) { 500 jobjectArray keys = jobjectArray(env->GetObjectField(result, 501 gInputDeviceCalibrationClassInfo.keys)); 502 jobjectArray values = jobjectArray(env->GetObjectField(result, 503 gInputDeviceCalibrationClassInfo.values)); 504 505 jsize length = env->GetArrayLength(keys); 506 for (jsize i = 0; i < length; i++) { 507 jstring keyStr = jstring(env->GetObjectArrayElement(keys, i)); 508 jstring valueStr = jstring(env->GetObjectArrayElement(values, i)); 509 510 const char* keyChars = env->GetStringUTFChars(keyStr, NULL); 511 String8 key(keyChars); 512 env->ReleaseStringUTFChars(keyStr, keyChars); 513 514 const char* valueChars = env->GetStringUTFChars(valueStr, NULL); 515 String8 value(valueChars); 516 env->ReleaseStringUTFChars(valueStr, valueChars); 517 518 outCalibration.addProperty(key, value); 519 520 env->DeleteLocalRef(keyStr); 521 env->DeleteLocalRef(valueStr); 522 } 523 env->DeleteLocalRef(keys); 524 env->DeleteLocalRef(values); 525 env->DeleteLocalRef(result); 526 } 527 env->DeleteLocalRef(deviceNameStr); 528 } 529 } 530 531 void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) { 532 outExcludedDeviceNames.clear(); 533 534 JNIEnv* env = jniEnv(); 535 536 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj, 537 gCallbacksClassInfo.getExcludedDeviceNames)); 538 if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) { 539 jsize length = env->GetArrayLength(result); 540 for (jsize i = 0; i < length; i++) { 541 jstring item = jstring(env->GetObjectArrayElement(result, i)); 542 543 const char* deviceNameChars = env->GetStringUTFChars(item, NULL); 544 outExcludedDeviceNames.add(String8(deviceNameChars)); 545 env->ReleaseStringUTFChars(item, deviceNameChars); 546 547 env->DeleteLocalRef(item); 548 } 549 env->DeleteLocalRef(result); 550 } 551 } 552 553 void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode, 554 int32_t switchValue, uint32_t policyFlags) { 555 #if DEBUG_INPUT_DISPATCHER_POLICY 556 LOGD("notifySwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x", 557 when, switchCode, switchValue, policyFlags); 558 #endif 559 560 JNIEnv* env = jniEnv(); 561 562 switch (switchCode) { 563 case SW_LID: 564 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged, 565 when, switchValue == 0); 566 checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged"); 567 break; 568 } 569 } 570 571 void NativeInputManager::notifyConfigurationChanged(nsecs_t when) { 572 #if DEBUG_INPUT_DISPATCHER_POLICY 573 LOGD("notifyConfigurationChanged - when=%lld", when); 574 #endif 575 576 JNIEnv* env = jniEnv(); 577 578 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged, when); 579 checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged"); 580 } 581 582 nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle, 583 const sp<InputChannel>& inputChannel) { 584 #if DEBUG_INPUT_DISPATCHER_POLICY 585 LOGD("notifyANR"); 586 #endif 587 588 JNIEnv* env = jniEnv(); 589 590 jobject tokenObjLocal; 591 if (inputApplicationHandle.get()) { 592 ApplicationToken* token = static_cast<ApplicationToken*>(inputApplicationHandle.get()); 593 jweak tokenObjWeak = token->getTokenObj(); 594 tokenObjLocal = env->NewLocalRef(tokenObjWeak); 595 } else { 596 tokenObjLocal = NULL; 597 } 598 599 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel); 600 jlong newTimeout = env->CallLongMethod(mCallbacksObj, 601 gCallbacksClassInfo.notifyANR, tokenObjLocal, inputChannelObjLocal); 602 if (checkAndClearExceptionFromCallback(env, "notifyANR")) { 603 newTimeout = 0; // abort dispatch 604 } else { 605 assert(newTimeout >= 0); 606 } 607 608 env->DeleteLocalRef(tokenObjLocal); 609 env->DeleteLocalRef(inputChannelObjLocal); 610 return newTimeout; 611 } 612 613 void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) { 614 #if DEBUG_INPUT_DISPATCHER_POLICY 615 LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string()); 616 #endif 617 618 JNIEnv* env = jniEnv(); 619 620 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel); 621 if (inputChannelObjLocal) { 622 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken, 623 inputChannelObjLocal); 624 checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken"); 625 626 env->DeleteLocalRef(inputChannelObjLocal); 627 } 628 } 629 630 nsecs_t NativeInputManager::getKeyRepeatTimeout() { 631 if (! isScreenOn()) { 632 // Disable key repeat when the screen is off. 633 return -1; 634 } else { 635 // TODO use ViewConfiguration.getLongPressTimeout() 636 return milliseconds_to_nanoseconds(500); 637 } 638 } 639 640 nsecs_t NativeInputManager::getKeyRepeatDelay() { 641 return milliseconds_to_nanoseconds(50); 642 } 643 644 int32_t NativeInputManager::getMaxEventsPerSecond() { 645 if (mMaxEventsPerSecond < 0) { 646 JNIEnv* env = jniEnv(); 647 648 jint result = env->CallIntMethod(mCallbacksObj, 649 gCallbacksClassInfo.getMaxEventsPerSecond); 650 if (checkAndClearExceptionFromCallback(env, "getMaxEventsPerSecond")) { 651 result = 60; 652 } 653 654 mMaxEventsPerSecond = result; 655 } 656 return mMaxEventsPerSecond; 657 } 658 659 void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) { 660 Vector<InputWindow> windows; 661 662 jsize length = env->GetArrayLength(windowObjArray); 663 for (jsize i = 0; i < length; i++) { 664 jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i); 665 if (! inputTargetObj) { 666 break; // found null element indicating end of used portion of the array 667 } 668 669 windows.push(); 670 InputWindow& window = windows.editTop(); 671 bool valid = populateWindow(env, inputTargetObj, window); 672 if (! valid) { 673 windows.pop(); 674 } 675 676 env->DeleteLocalRef(inputTargetObj); 677 } 678 679 mInputManager->getDispatcher()->setInputWindows(windows); 680 } 681 682 bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj, 683 InputWindow& outWindow) { 684 bool valid = false; 685 686 jobject inputChannelObj = env->GetObjectField(windowObj, 687 gInputWindowClassInfo.inputChannel); 688 if (inputChannelObj) { 689 sp<InputChannel> inputChannel = 690 android_view_InputChannel_getInputChannel(env, inputChannelObj); 691 if (inputChannel != NULL) { 692 jstring name = jstring(env->GetObjectField(windowObj, 693 gInputWindowClassInfo.name)); 694 jint layoutParamsFlags = env->GetIntField(windowObj, 695 gInputWindowClassInfo.layoutParamsFlags); 696 jint layoutParamsType = env->GetIntField(windowObj, 697 gInputWindowClassInfo.layoutParamsType); 698 jlong dispatchingTimeoutNanos = env->GetLongField(windowObj, 699 gInputWindowClassInfo.dispatchingTimeoutNanos); 700 jint frameLeft = env->GetIntField(windowObj, 701 gInputWindowClassInfo.frameLeft); 702 jint frameTop = env->GetIntField(windowObj, 703 gInputWindowClassInfo.frameTop); 704 jint frameRight = env->GetIntField(windowObj, 705 gInputWindowClassInfo.frameRight); 706 jint frameBottom = env->GetIntField(windowObj, 707 gInputWindowClassInfo.frameBottom); 708 jint visibleFrameLeft = env->GetIntField(windowObj, 709 gInputWindowClassInfo.visibleFrameLeft); 710 jint visibleFrameTop = env->GetIntField(windowObj, 711 gInputWindowClassInfo.visibleFrameTop); 712 jint visibleFrameRight = env->GetIntField(windowObj, 713 gInputWindowClassInfo.visibleFrameRight); 714 jint visibleFrameBottom = env->GetIntField(windowObj, 715 gInputWindowClassInfo.visibleFrameBottom); 716 jint touchableAreaLeft = env->GetIntField(windowObj, 717 gInputWindowClassInfo.touchableAreaLeft); 718 jint touchableAreaTop = env->GetIntField(windowObj, 719 gInputWindowClassInfo.touchableAreaTop); 720 jint touchableAreaRight = env->GetIntField(windowObj, 721 gInputWindowClassInfo.touchableAreaRight); 722 jint touchableAreaBottom = env->GetIntField(windowObj, 723 gInputWindowClassInfo.touchableAreaBottom); 724 jboolean visible = env->GetBooleanField(windowObj, 725 gInputWindowClassInfo.visible); 726 jboolean canReceiveKeys = env->GetBooleanField(windowObj, 727 gInputWindowClassInfo.canReceiveKeys); 728 jboolean hasFocus = env->GetBooleanField(windowObj, 729 gInputWindowClassInfo.hasFocus); 730 jboolean hasWallpaper = env->GetBooleanField(windowObj, 731 gInputWindowClassInfo.hasWallpaper); 732 jboolean paused = env->GetBooleanField(windowObj, 733 gInputWindowClassInfo.paused); 734 jint layer = env->GetIntField(windowObj, 735 gInputWindowClassInfo.layer); 736 jint ownerPid = env->GetIntField(windowObj, 737 gInputWindowClassInfo.ownerPid); 738 jint ownerUid = env->GetIntField(windowObj, 739 gInputWindowClassInfo.ownerUid); 740 741 const char* nameStr = env->GetStringUTFChars(name, NULL); 742 743 outWindow.inputChannel = inputChannel; 744 outWindow.name.setTo(nameStr); 745 outWindow.layoutParamsFlags = layoutParamsFlags; 746 outWindow.layoutParamsType = layoutParamsType; 747 outWindow.dispatchingTimeout = dispatchingTimeoutNanos; 748 outWindow.frameLeft = frameLeft; 749 outWindow.frameTop = frameTop; 750 outWindow.frameRight = frameRight; 751 outWindow.frameBottom = frameBottom; 752 outWindow.visibleFrameLeft = visibleFrameLeft; 753 outWindow.visibleFrameTop = visibleFrameTop; 754 outWindow.visibleFrameRight = visibleFrameRight; 755 outWindow.visibleFrameBottom = visibleFrameBottom; 756 outWindow.touchableAreaLeft = touchableAreaLeft; 757 outWindow.touchableAreaTop = touchableAreaTop; 758 outWindow.touchableAreaRight = touchableAreaRight; 759 outWindow.touchableAreaBottom = touchableAreaBottom; 760 outWindow.visible = visible; 761 outWindow.canReceiveKeys = canReceiveKeys; 762 outWindow.hasFocus = hasFocus; 763 outWindow.hasWallpaper = hasWallpaper; 764 outWindow.paused = paused; 765 outWindow.layer = layer; 766 outWindow.ownerPid = ownerPid; 767 outWindow.ownerUid = ownerUid; 768 769 env->ReleaseStringUTFChars(name, nameStr); 770 valid = true; 771 } else { 772 LOGW("Dropping input target because its input channel is not initialized."); 773 } 774 775 env->DeleteLocalRef(inputChannelObj); 776 } else { 777 LOGW("Dropping input target because the input channel object was null."); 778 } 779 return valid; 780 } 781 782 void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) { 783 if (applicationObj) { 784 jstring nameObj = jstring(env->GetObjectField(applicationObj, 785 gInputApplicationClassInfo.name)); 786 jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj, 787 gInputApplicationClassInfo.dispatchingTimeoutNanos); 788 jobject tokenObj = env->GetObjectField(applicationObj, 789 gInputApplicationClassInfo.token); 790 jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj); 791 if (! tokenObjWeak) { 792 LOGE("Could not create weak reference for application token."); 793 LOGE_EX(env); 794 env->ExceptionClear(); 795 } 796 env->DeleteLocalRef(tokenObj); 797 798 String8 name; 799 if (nameObj) { 800 const char* nameStr = env->GetStringUTFChars(nameObj, NULL); 801 name.setTo(nameStr); 802 env->ReleaseStringUTFChars(nameObj, nameStr); 803 env->DeleteLocalRef(nameObj); 804 } else { 805 LOGE("InputApplication.name should not be null."); 806 name.setTo("unknown"); 807 } 808 809 InputApplication application; 810 application.name = name; 811 application.dispatchingTimeout = dispatchingTimeoutNanos; 812 application.handle = new ApplicationToken(tokenObjWeak); 813 mInputManager->getDispatcher()->setFocusedApplication(& application); 814 } else { 815 mInputManager->getDispatcher()->setFocusedApplication(NULL); 816 } 817 } 818 819 void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) { 820 mInputManager->getDispatcher()->setInputDispatchMode(enabled, frozen); 821 } 822 823 bool NativeInputManager::isScreenOn() { 824 return android_server_PowerManagerService_isScreenOn(); 825 } 826 827 bool NativeInputManager::isScreenBright() { 828 return android_server_PowerManagerService_isScreenBright(); 829 } 830 831 void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when, 832 int32_t deviceId, int32_t action, int32_t &flags, 833 int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) { 834 #if DEBUG_INPUT_DISPATCHER_POLICY 835 LOGD("interceptKeyBeforeQueueing - when=%lld, deviceId=%d, action=%d, flags=%d, " 836 "keyCode=%d, scanCode=%d, policyFlags=0x%x", 837 when, deviceId, action, flags, keyCode, scanCode, policyFlags); 838 #endif 839 840 if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) { 841 policyFlags |= POLICY_FLAG_VIRTUAL; 842 flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; 843 } 844 845 // Policy: 846 // - Ignore untrusted events and pass them along. 847 // - Ask the window manager what to do with normal events and trusted injected events. 848 // - For normal events wake and brighten the screen if currently off or dim. 849 if ((policyFlags & POLICY_FLAG_TRUSTED)) { 850 const int32_t WM_ACTION_PASS_TO_USER = 1; 851 const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2; 852 const int32_t WM_ACTION_GO_TO_SLEEP = 4; 853 854 bool isScreenOn = this->isScreenOn(); 855 bool isScreenBright = this->isScreenBright(); 856 857 JNIEnv* env = jniEnv(); 858 jint wmActions = env->CallIntMethod(mCallbacksObj, 859 gCallbacksClassInfo.interceptKeyBeforeQueueing, 860 when, keyCode, action == AKEY_EVENT_ACTION_DOWN, policyFlags, isScreenOn); 861 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { 862 wmActions = 0; 863 } 864 865 if (!(flags & POLICY_FLAG_INJECTED)) { 866 if (!isScreenOn) { 867 policyFlags |= POLICY_FLAG_WOKE_HERE; 868 flags |= AKEY_EVENT_FLAG_WOKE_HERE; 869 } 870 871 if (!isScreenBright) { 872 policyFlags |= POLICY_FLAG_BRIGHT_HERE; 873 } 874 } 875 876 if (wmActions & WM_ACTION_GO_TO_SLEEP) { 877 android_server_PowerManagerService_goToSleep(when); 878 } 879 880 if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) { 881 android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT); 882 } 883 884 if (wmActions & WM_ACTION_PASS_TO_USER) { 885 policyFlags |= POLICY_FLAG_PASS_TO_USER; 886 } 887 } else { 888 policyFlags |= POLICY_FLAG_PASS_TO_USER; 889 } 890 } 891 892 void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) { 893 #if DEBUG_INPUT_DISPATCHER_POLICY 894 LOGD("interceptGenericBeforeQueueing - when=%lld, policyFlags=0x%x", when, policyFlags); 895 #endif 896 897 // Policy: 898 // - Ignore untrusted events and pass them along. 899 // - No special filtering for injected events required at this time. 900 // - Filter normal events based on screen state. 901 // - For normal events brighten (but do not wake) the screen if currently dim. 902 if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) { 903 if (isScreenOn()) { 904 policyFlags |= POLICY_FLAG_PASS_TO_USER; 905 906 if (!isScreenBright()) { 907 policyFlags |= POLICY_FLAG_BRIGHT_HERE; 908 } 909 } 910 } else { 911 policyFlags |= POLICY_FLAG_PASS_TO_USER; 912 } 913 } 914 915 bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel, 916 const KeyEvent* keyEvent, uint32_t policyFlags) { 917 // Policy: 918 // - Ignore untrusted events and pass them along. 919 // - Filter normal events and trusted injected events through the window manager policy to 920 // handle the HOME key and the like. 921 if (policyFlags & POLICY_FLAG_TRUSTED) { 922 JNIEnv* env = jniEnv(); 923 924 // Note: inputChannel may be null. 925 jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel); 926 jboolean consumed = env->CallBooleanMethod(mCallbacksObj, 927 gCallbacksClassInfo.interceptKeyBeforeDispatching, 928 inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(), 929 keyEvent->getKeyCode(), keyEvent->getMetaState(), 930 keyEvent->getRepeatCount(), policyFlags); 931 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching"); 932 933 env->DeleteLocalRef(inputChannelObj); 934 return consumed && ! error; 935 } else { 936 return false; 937 } 938 } 939 940 void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) { 941 android_server_PowerManagerService_userActivity(eventTime, eventType); 942 } 943 944 945 bool NativeInputManager::checkInjectEventsPermissionNonReentrant( 946 int32_t injectorPid, int32_t injectorUid) { 947 JNIEnv* env = jniEnv(); 948 jboolean result = env->CallBooleanMethod(mCallbacksObj, 949 gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid); 950 checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission"); 951 return result; 952 } 953 954 // ---------------------------------------------------------------------------- 955 956 static sp<NativeInputManager> gNativeInputManager; 957 958 static bool checkInputManagerUnitialized(JNIEnv* env) { 959 if (gNativeInputManager == NULL) { 960 LOGE("Input manager not initialized."); 961 jniThrowRuntimeException(env, "Input manager not initialized."); 962 return true; 963 } 964 return false; 965 } 966 967 static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz, 968 jobject callbacks) { 969 if (gNativeInputManager == NULL) { 970 gNativeInputManager = new NativeInputManager(callbacks); 971 } else { 972 LOGE("Input manager already initialized."); 973 jniThrowRuntimeException(env, "Input manager already initialized."); 974 } 975 } 976 977 static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) { 978 if (checkInputManagerUnitialized(env)) { 979 return; 980 } 981 982 status_t result = gNativeInputManager->getInputManager()->start(); 983 if (result) { 984 jniThrowRuntimeException(env, "Input manager could not be started."); 985 } 986 } 987 988 static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz, 989 jint displayId, jint width, jint height) { 990 if (checkInputManagerUnitialized(env)) { 991 return; 992 } 993 994 // XXX we could get this from the SurfaceFlinger directly instead of requiring it 995 // to be passed in like this, not sure which is better but leaving it like this 996 // keeps the window manager in direct control of when display transitions propagate down 997 // to the input dispatcher 998 gNativeInputManager->setDisplaySize(displayId, width, height); 999 } 1000 1001 static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz, 1002 jint displayId, jint orientation) { 1003 if (checkInputManagerUnitialized(env)) { 1004 return; 1005 } 1006 1007 gNativeInputManager->setDisplayOrientation(displayId, orientation); 1008 } 1009 1010 static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz, 1011 jint deviceId, jint sourceMask, jint scanCode) { 1012 if (checkInputManagerUnitialized(env)) { 1013 return AKEY_STATE_UNKNOWN; 1014 } 1015 1016 return gNativeInputManager->getInputManager()->getReader()->getScanCodeState( 1017 deviceId, uint32_t(sourceMask), scanCode); 1018 } 1019 1020 static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz, 1021 jint deviceId, jint sourceMask, jint keyCode) { 1022 if (checkInputManagerUnitialized(env)) { 1023 return AKEY_STATE_UNKNOWN; 1024 } 1025 1026 return gNativeInputManager->getInputManager()->getReader()->getKeyCodeState( 1027 deviceId, uint32_t(sourceMask), keyCode); 1028 } 1029 1030 static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz, 1031 jint deviceId, jint sourceMask, jint sw) { 1032 if (checkInputManagerUnitialized(env)) { 1033 return AKEY_STATE_UNKNOWN; 1034 } 1035 1036 return gNativeInputManager->getInputManager()->getReader()->getSwitchState( 1037 deviceId, uint32_t(sourceMask), sw); 1038 } 1039 1040 static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz, 1041 jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) { 1042 if (checkInputManagerUnitialized(env)) { 1043 return JNI_FALSE; 1044 } 1045 1046 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL); 1047 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL); 1048 jsize numCodes = env->GetArrayLength(keyCodes); 1049 jboolean result; 1050 if (numCodes == env->GetArrayLength(keyCodes)) { 1051 result = gNativeInputManager->getInputManager()->getReader()->hasKeys( 1052 deviceId, uint32_t(sourceMask), numCodes, codes, flags); 1053 } else { 1054 result = JNI_FALSE; 1055 } 1056 1057 env->ReleaseBooleanArrayElements(outFlags, flags, 0); 1058 env->ReleaseIntArrayElements(keyCodes, codes, 0); 1059 return result; 1060 } 1061 1062 static void throwInputChannelNotInitialized(JNIEnv* env) { 1063 jniThrowException(env, "java/lang/IllegalStateException", 1064 "inputChannel is not initialized"); 1065 } 1066 1067 static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env, 1068 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) { 1069 LOGW("Input channel object '%s' was disposed without first being unregistered with " 1070 "the input manager!", inputChannel->getName().string()); 1071 1072 if (gNativeInputManager != NULL) { 1073 gNativeInputManager->unregisterInputChannel(env, inputChannel); 1074 } 1075 } 1076 1077 static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz, 1078 jobject inputChannelObj, jboolean monitor) { 1079 if (checkInputManagerUnitialized(env)) { 1080 return; 1081 } 1082 1083 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env, 1084 inputChannelObj); 1085 if (inputChannel == NULL) { 1086 throwInputChannelNotInitialized(env); 1087 return; 1088 } 1089 1090 1091 status_t status = gNativeInputManager->registerInputChannel( 1092 env, inputChannel, inputChannelObj, monitor); 1093 if (status) { 1094 jniThrowRuntimeException(env, "Failed to register input channel. " 1095 "Check logs for details."); 1096 return; 1097 } 1098 1099 if (! monitor) { 1100 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, 1101 android_server_InputManager_handleInputChannelDisposed, NULL); 1102 } 1103 } 1104 1105 static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz, 1106 jobject inputChannelObj) { 1107 if (checkInputManagerUnitialized(env)) { 1108 return; 1109 } 1110 1111 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env, 1112 inputChannelObj); 1113 if (inputChannel == NULL) { 1114 throwInputChannelNotInitialized(env); 1115 return; 1116 } 1117 1118 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL); 1119 1120 status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel); 1121 if (status) { 1122 jniThrowRuntimeException(env, "Failed to unregister input channel. " 1123 "Check logs for details."); 1124 } 1125 } 1126 1127 static jint android_server_InputManager_nativeInjectInputEvent(JNIEnv* env, jclass clazz, 1128 jobject inputEventObj, jint injectorPid, jint injectorUid, 1129 jint syncMode, jint timeoutMillis) { 1130 if (checkInputManagerUnitialized(env)) { 1131 return INPUT_EVENT_INJECTION_FAILED; 1132 } 1133 1134 if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) { 1135 KeyEvent keyEvent; 1136 android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent); 1137 1138 return gNativeInputManager->getInputManager()->getDispatcher()->injectInputEvent( 1139 & keyEvent, injectorPid, injectorUid, syncMode, timeoutMillis); 1140 } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) { 1141 MotionEvent motionEvent; 1142 android_view_MotionEvent_toNative(env, inputEventObj, & motionEvent); 1143 1144 return gNativeInputManager->getInputManager()->getDispatcher()->injectInputEvent( 1145 & motionEvent, injectorPid, injectorUid, syncMode, timeoutMillis); 1146 } else { 1147 jniThrowRuntimeException(env, "Invalid input event type."); 1148 return INPUT_EVENT_INJECTION_FAILED; 1149 } 1150 } 1151 1152 static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz, 1153 jobjectArray windowObjArray) { 1154 if (checkInputManagerUnitialized(env)) { 1155 return; 1156 } 1157 1158 gNativeInputManager->setInputWindows(env, windowObjArray); 1159 } 1160 1161 static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz, 1162 jobject applicationObj) { 1163 if (checkInputManagerUnitialized(env)) { 1164 return; 1165 } 1166 1167 gNativeInputManager->setFocusedApplication(env, applicationObj); 1168 } 1169 1170 static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env, 1171 jclass clazz, jboolean enabled, jboolean frozen) { 1172 if (checkInputManagerUnitialized(env)) { 1173 return; 1174 } 1175 1176 gNativeInputManager->setInputDispatchMode(enabled, frozen); 1177 } 1178 1179 static jobject android_server_InputManager_nativeGetInputDevice(JNIEnv* env, 1180 jclass clazz, jint deviceId) { 1181 if (checkInputManagerUnitialized(env)) { 1182 return NULL; 1183 } 1184 1185 InputDeviceInfo deviceInfo; 1186 status_t status = gNativeInputManager->getInputManager()->getReader()->getInputDeviceInfo( 1187 deviceId, & deviceInfo); 1188 if (status) { 1189 return NULL; 1190 } 1191 1192 jobject deviceObj = env->NewObject(gInputDeviceClassInfo.clazz, gInputDeviceClassInfo.ctor); 1193 if (! deviceObj) { 1194 return NULL; 1195 } 1196 1197 jstring deviceNameObj = env->NewStringUTF(deviceInfo.getName().string()); 1198 if (! deviceNameObj) { 1199 return NULL; 1200 } 1201 1202 env->SetIntField(deviceObj, gInputDeviceClassInfo.mId, deviceInfo.getId()); 1203 env->SetObjectField(deviceObj, gInputDeviceClassInfo.mName, deviceNameObj); 1204 env->SetIntField(deviceObj, gInputDeviceClassInfo.mSources, deviceInfo.getSources()); 1205 env->SetIntField(deviceObj, gInputDeviceClassInfo.mKeyboardType, deviceInfo.getKeyboardType()); 1206 1207 const KeyedVector<int, InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); 1208 for (size_t i = 0; i < ranges.size(); i++) { 1209 int rangeType = ranges.keyAt(i); 1210 const InputDeviceInfo::MotionRange& range = ranges.valueAt(i); 1211 env->CallVoidMethod(deviceObj, gInputDeviceClassInfo.addMotionRange, 1212 rangeType, range.min, range.max, range.flat, range.fuzz); 1213 if (env->ExceptionCheck()) { 1214 return NULL; 1215 } 1216 } 1217 1218 return deviceObj; 1219 } 1220 1221 static jintArray android_server_InputManager_nativeGetInputDeviceIds(JNIEnv* env, 1222 jclass clazz) { 1223 if (checkInputManagerUnitialized(env)) { 1224 return NULL; 1225 } 1226 1227 Vector<int> deviceIds; 1228 gNativeInputManager->getInputManager()->getReader()->getInputDeviceIds(deviceIds); 1229 1230 jintArray deviceIdsObj = env->NewIntArray(deviceIds.size()); 1231 if (! deviceIdsObj) { 1232 return NULL; 1233 } 1234 1235 env->SetIntArrayRegion(deviceIdsObj, 0, deviceIds.size(), deviceIds.array()); 1236 return deviceIdsObj; 1237 } 1238 1239 static void android_server_InputManager_nativeGetInputConfiguration(JNIEnv* env, 1240 jclass clazz, jobject configObj) { 1241 if (checkInputManagerUnitialized(env)) { 1242 return; 1243 } 1244 1245 InputConfiguration config; 1246 gNativeInputManager->getInputManager()->getReader()->getInputConfiguration(& config); 1247 1248 env->SetIntField(configObj, gConfigurationClassInfo.touchscreen, config.touchScreen); 1249 env->SetIntField(configObj, gConfigurationClassInfo.keyboard, config.keyboard); 1250 env->SetIntField(configObj, gConfigurationClassInfo.navigation, config.navigation); 1251 } 1252 1253 static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) { 1254 if (checkInputManagerUnitialized(env)) { 1255 return NULL; 1256 } 1257 1258 String8 dump; 1259 gNativeInputManager->dump(dump); 1260 return env->NewStringUTF(dump.string()); 1261 } 1262 1263 // ---------------------------------------------------------------------------- 1264 1265 static JNINativeMethod gInputManagerMethods[] = { 1266 /* name, signature, funcPtr */ 1267 { "nativeInit", "(Lcom/android/server/InputManager$Callbacks;)V", 1268 (void*) android_server_InputManager_nativeInit }, 1269 { "nativeStart", "()V", 1270 (void*) android_server_InputManager_nativeStart }, 1271 { "nativeSetDisplaySize", "(III)V", 1272 (void*) android_server_InputManager_nativeSetDisplaySize }, 1273 { "nativeSetDisplayOrientation", "(II)V", 1274 (void*) android_server_InputManager_nativeSetDisplayOrientation }, 1275 { "nativeGetScanCodeState", "(III)I", 1276 (void*) android_server_InputManager_nativeGetScanCodeState }, 1277 { "nativeGetKeyCodeState", "(III)I", 1278 (void*) android_server_InputManager_nativeGetKeyCodeState }, 1279 { "nativeGetSwitchState", "(III)I", 1280 (void*) android_server_InputManager_nativeGetSwitchState }, 1281 { "nativeHasKeys", "(II[I[Z)Z", 1282 (void*) android_server_InputManager_nativeHasKeys }, 1283 { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;Z)V", 1284 (void*) android_server_InputManager_nativeRegisterInputChannel }, 1285 { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V", 1286 (void*) android_server_InputManager_nativeUnregisterInputChannel }, 1287 { "nativeInjectInputEvent", "(Landroid/view/InputEvent;IIII)I", 1288 (void*) android_server_InputManager_nativeInjectInputEvent }, 1289 { "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V", 1290 (void*) android_server_InputManager_nativeSetInputWindows }, 1291 { "nativeSetFocusedApplication", "(Lcom/android/server/InputApplication;)V", 1292 (void*) android_server_InputManager_nativeSetFocusedApplication }, 1293 { "nativeSetInputDispatchMode", "(ZZ)V", 1294 (void*) android_server_InputManager_nativeSetInputDispatchMode }, 1295 { "nativeGetInputDevice", "(I)Landroid/view/InputDevice;", 1296 (void*) android_server_InputManager_nativeGetInputDevice }, 1297 { "nativeGetInputDeviceIds", "()[I", 1298 (void*) android_server_InputManager_nativeGetInputDeviceIds }, 1299 { "nativeGetInputConfiguration", "(Landroid/content/res/Configuration;)V", 1300 (void*) android_server_InputManager_nativeGetInputConfiguration }, 1301 { "nativeDump", "()Ljava/lang/String;", 1302 (void*) android_server_InputManager_nativeDump }, 1303 }; 1304 1305 #define FIND_CLASS(var, className) \ 1306 var = env->FindClass(className); \ 1307 LOG_FATAL_IF(! var, "Unable to find class " className); \ 1308 var = jclass(env->NewGlobalRef(var)); 1309 1310 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 1311 var = env->GetMethodID(clazz, methodName, methodDescriptor); \ 1312 LOG_FATAL_IF(! var, "Unable to find method " methodName); 1313 1314 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 1315 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 1316 LOG_FATAL_IF(! var, "Unable to find field " fieldName); 1317 1318 int register_android_server_InputManager(JNIEnv* env) { 1319 int res = jniRegisterNativeMethods(env, "com/android/server/InputManager", 1320 gInputManagerMethods, NELEM(gInputManagerMethods)); 1321 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 1322 1323 // Callbacks 1324 1325 FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks"); 1326 1327 GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz, 1328 "notifyConfigurationChanged", "(J)V"); 1329 1330 GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz, 1331 "notifyLidSwitchChanged", "(JZ)V"); 1332 1333 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz, 1334 "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V"); 1335 1336 GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz, 1337 "notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J"); 1338 1339 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz, 1340 "interceptKeyBeforeQueueing", "(JIZIZ)I"); 1341 1342 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz, 1343 "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z"); 1344 1345 GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz, 1346 "checkInjectEventsPermission", "(II)Z"); 1347 1348 GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz, 1349 "filterTouchEvents", "()Z"); 1350 1351 GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz, 1352 "filterJumpyTouchEvents", "()Z"); 1353 1354 GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz, 1355 "getVirtualKeyDefinitions", 1356 "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;"); 1357 1358 GET_METHOD_ID(gCallbacksClassInfo.getInputDeviceCalibration, gCallbacksClassInfo.clazz, 1359 "getInputDeviceCalibration", 1360 "(Ljava/lang/String;)Lcom/android/server/InputManager$InputDeviceCalibration;"); 1361 1362 GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz, 1363 "getExcludedDeviceNames", "()[Ljava/lang/String;"); 1364 1365 GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz, 1366 "getMaxEventsPerSecond", "()I"); 1367 1368 // VirtualKeyDefinition 1369 1370 FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz, 1371 "com/android/server/InputManager$VirtualKeyDefinition"); 1372 1373 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz, 1374 "scanCode", "I"); 1375 1376 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz, 1377 "centerX", "I"); 1378 1379 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz, 1380 "centerY", "I"); 1381 1382 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz, 1383 "width", "I"); 1384 1385 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz, 1386 "height", "I"); 1387 1388 // InputDeviceCalibration 1389 1390 FIND_CLASS(gInputDeviceCalibrationClassInfo.clazz, 1391 "com/android/server/InputManager$InputDeviceCalibration"); 1392 1393 GET_FIELD_ID(gInputDeviceCalibrationClassInfo.keys, gInputDeviceCalibrationClassInfo.clazz, 1394 "keys", "[Ljava/lang/String;"); 1395 1396 GET_FIELD_ID(gInputDeviceCalibrationClassInfo.values, gInputDeviceCalibrationClassInfo.clazz, 1397 "values", "[Ljava/lang/String;"); 1398 1399 // InputWindow 1400 1401 FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow"); 1402 1403 GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz, 1404 "inputChannel", "Landroid/view/InputChannel;"); 1405 1406 GET_FIELD_ID(gInputWindowClassInfo.name, gInputWindowClassInfo.clazz, 1407 "name", "Ljava/lang/String;"); 1408 1409 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz, 1410 "layoutParamsFlags", "I"); 1411 1412 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz, 1413 "layoutParamsType", "I"); 1414 1415 GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz, 1416 "dispatchingTimeoutNanos", "J"); 1417 1418 GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz, 1419 "frameLeft", "I"); 1420 1421 GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz, 1422 "frameTop", "I"); 1423 1424 GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz, 1425 "frameRight", "I"); 1426 1427 GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz, 1428 "frameBottom", "I"); 1429 1430 GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz, 1431 "visibleFrameLeft", "I"); 1432 1433 GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz, 1434 "visibleFrameTop", "I"); 1435 1436 GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz, 1437 "visibleFrameRight", "I"); 1438 1439 GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz, 1440 "visibleFrameBottom", "I"); 1441 1442 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz, 1443 "touchableAreaLeft", "I"); 1444 1445 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz, 1446 "touchableAreaTop", "I"); 1447 1448 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz, 1449 "touchableAreaRight", "I"); 1450 1451 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz, 1452 "touchableAreaBottom", "I"); 1453 1454 GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz, 1455 "visible", "Z"); 1456 1457 GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, gInputWindowClassInfo.clazz, 1458 "canReceiveKeys", "Z"); 1459 1460 GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz, 1461 "hasFocus", "Z"); 1462 1463 GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz, 1464 "hasWallpaper", "Z"); 1465 1466 GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz, 1467 "paused", "Z"); 1468 1469 GET_FIELD_ID(gInputWindowClassInfo.layer, gInputWindowClassInfo.clazz, 1470 "layer", "I"); 1471 1472 GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz, 1473 "ownerPid", "I"); 1474 1475 GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz, 1476 "ownerUid", "I"); 1477 1478 // InputApplication 1479 1480 FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication"); 1481 1482 GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz, 1483 "name", "Ljava/lang/String;"); 1484 1485 GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos, 1486 gInputApplicationClassInfo.clazz, 1487 "dispatchingTimeoutNanos", "J"); 1488 1489 GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz, 1490 "token", "Ljava/lang/Object;"); 1491 1492 // KeyEvent 1493 1494 FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent"); 1495 1496 // MotionEvent 1497 1498 FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent"); 1499 1500 // InputDevice 1501 1502 FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice"); 1503 1504 GET_METHOD_ID(gInputDeviceClassInfo.ctor, gInputDeviceClassInfo.clazz, 1505 "<init>", "()V"); 1506 1507 GET_METHOD_ID(gInputDeviceClassInfo.addMotionRange, gInputDeviceClassInfo.clazz, 1508 "addMotionRange", "(IFFFF)V"); 1509 1510 GET_FIELD_ID(gInputDeviceClassInfo.mId, gInputDeviceClassInfo.clazz, 1511 "mId", "I"); 1512 1513 GET_FIELD_ID(gInputDeviceClassInfo.mName, gInputDeviceClassInfo.clazz, 1514 "mName", "Ljava/lang/String;"); 1515 1516 GET_FIELD_ID(gInputDeviceClassInfo.mSources, gInputDeviceClassInfo.clazz, 1517 "mSources", "I"); 1518 1519 GET_FIELD_ID(gInputDeviceClassInfo.mKeyboardType, gInputDeviceClassInfo.clazz, 1520 "mKeyboardType", "I"); 1521 1522 GET_FIELD_ID(gInputDeviceClassInfo.mMotionRanges, gInputDeviceClassInfo.clazz, 1523 "mMotionRanges", "[Landroid/view/InputDevice$MotionRange;"); 1524 1525 // Configuration 1526 1527 FIND_CLASS(gConfigurationClassInfo.clazz, "android/content/res/Configuration"); 1528 1529 GET_FIELD_ID(gConfigurationClassInfo.touchscreen, gConfigurationClassInfo.clazz, 1530 "touchscreen", "I"); 1531 1532 GET_FIELD_ID(gConfigurationClassInfo.keyboard, gConfigurationClassInfo.clazz, 1533 "keyboard", "I"); 1534 1535 GET_FIELD_ID(gConfigurationClassInfo.navigation, gConfigurationClassInfo.clazz, 1536 "navigation", "I"); 1537 1538 return 0; 1539 } 1540 1541 } /* namespace android */ 1542