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