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