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