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