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