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