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