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     if (messageQueue == NULL) {
    979         jniThrowRuntimeException(env, "MessageQueue is not initialized.");
    980         return 0;
    981     }
    982 
    983     NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
    984             messageQueue->getLooper());
    985     im->incStrong(0);
    986     return reinterpret_cast<jint>(im);
    987 }
    988 
    989 static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) {
    990     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
    991 
    992     status_t result = im->getInputManager()->start();
    993     if (result) {
    994         jniThrowRuntimeException(env, "Input manager could not be started.");
    995     }
    996 }
    997 
    998 static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jint ptr, jboolean external,
    999         jint displayId, jint orientation,
   1000         jint logicalLeft, jint logicalTop, jint logicalRight, jint logicalBottom,
   1001         jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom,
   1002         jint deviceWidth, jint deviceHeight) {
   1003     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1004 
   1005     DisplayViewport v;
   1006     v.displayId = displayId;
   1007     v.orientation = orientation;
   1008     v.logicalLeft = logicalLeft;
   1009     v.logicalTop = logicalTop;
   1010     v.logicalRight = logicalRight;
   1011     v.logicalBottom = logicalBottom;
   1012     v.physicalLeft = physicalLeft;
   1013     v.physicalTop = physicalTop;
   1014     v.physicalRight = physicalRight;
   1015     v.physicalBottom = physicalBottom;
   1016     v.deviceWidth = deviceWidth;
   1017     v.deviceHeight = deviceHeight;
   1018     im->setDisplayViewport(external, v);
   1019 }
   1020 
   1021 static jint nativeGetScanCodeState(JNIEnv* env, jclass clazz,
   1022         jint ptr, jint deviceId, jint sourceMask, jint scanCode) {
   1023     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1024 
   1025     return im->getInputManager()->getReader()->getScanCodeState(
   1026             deviceId, uint32_t(sourceMask), scanCode);
   1027 }
   1028 
   1029 static jint nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
   1030         jint ptr, jint deviceId, jint sourceMask, jint keyCode) {
   1031     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1032 
   1033     return im->getInputManager()->getReader()->getKeyCodeState(
   1034             deviceId, uint32_t(sourceMask), keyCode);
   1035 }
   1036 
   1037 static jint nativeGetSwitchState(JNIEnv* env, jclass clazz,
   1038         jint ptr, jint deviceId, jint sourceMask, jint sw) {
   1039     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1040 
   1041     return im->getInputManager()->getReader()->getSwitchState(
   1042             deviceId, uint32_t(sourceMask), sw);
   1043 }
   1044 
   1045 static jboolean nativeHasKeys(JNIEnv* env, jclass clazz,
   1046         jint ptr, jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
   1047     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1048 
   1049     int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
   1050     uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
   1051     jsize numCodes = env->GetArrayLength(keyCodes);
   1052     jboolean result;
   1053     if (numCodes == env->GetArrayLength(keyCodes)) {
   1054         result = im->getInputManager()->getReader()->hasKeys(
   1055                 deviceId, uint32_t(sourceMask), numCodes, codes, flags);
   1056     } else {
   1057         result = JNI_FALSE;
   1058     }
   1059 
   1060     env->ReleaseBooleanArrayElements(outFlags, flags, 0);
   1061     env->ReleaseIntArrayElements(keyCodes, codes, 0);
   1062     return result;
   1063 }
   1064 
   1065 static void throwInputChannelNotInitialized(JNIEnv* env) {
   1066     jniThrowException(env, "java/lang/IllegalStateException",
   1067              "inputChannel is not initialized");
   1068 }
   1069 
   1070 static void handleInputChannelDisposed(JNIEnv* env,
   1071         jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
   1072     NativeInputManager* im = static_cast<NativeInputManager*>(data);
   1073 
   1074     ALOGW("Input channel object '%s' was disposed without first being unregistered with "
   1075             "the input manager!", inputChannel->getName().string());
   1076     im->unregisterInputChannel(env, inputChannel);
   1077 }
   1078 
   1079 static void nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
   1080         jint ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
   1081     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1082 
   1083     sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
   1084             inputChannelObj);
   1085     if (inputChannel == NULL) {
   1086         throwInputChannelNotInitialized(env);
   1087         return;
   1088     }
   1089 
   1090     sp<InputWindowHandle> inputWindowHandle =
   1091             android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
   1092 
   1093     status_t status = im->registerInputChannel(
   1094             env, inputChannel, inputWindowHandle, monitor);
   1095     if (status) {
   1096         String8 message;
   1097         message.appendFormat("Failed to register input channel.  status=%d", status);
   1098         jniThrowRuntimeException(env, message.string());
   1099         return;
   1100     }
   1101 
   1102     if (! monitor) {
   1103         android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
   1104                 handleInputChannelDisposed, im);
   1105     }
   1106 }
   1107 
   1108 static void nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
   1109         jint ptr, jobject inputChannelObj) {
   1110     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1111 
   1112     sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
   1113             inputChannelObj);
   1114     if (inputChannel == NULL) {
   1115         throwInputChannelNotInitialized(env);
   1116         return;
   1117     }
   1118 
   1119     android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
   1120 
   1121     status_t status = im->unregisterInputChannel(env, inputChannel);
   1122     if (status && status != BAD_VALUE) { // ignore already unregistered channel
   1123         String8 message;
   1124         message.appendFormat("Failed to unregister input channel.  status=%d", status);
   1125         jniThrowRuntimeException(env, message.string());
   1126     }
   1127 }
   1128 
   1129 static void nativeSetInputFilterEnabled(JNIEnv* env, jclass clazz,
   1130         jint ptr, jboolean enabled) {
   1131     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1132 
   1133     im->getInputManager()->getDispatcher()->setInputFilterEnabled(enabled);
   1134 }
   1135 
   1136 static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz,
   1137         jint ptr, jobject inputEventObj, jint injectorPid, jint injectorUid,
   1138         jint syncMode, jint timeoutMillis, jint policyFlags) {
   1139     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1140 
   1141     if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
   1142         KeyEvent keyEvent;
   1143         status_t status = android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent);
   1144         if (status) {
   1145             jniThrowRuntimeException(env, "Could not read contents of KeyEvent object.");
   1146             return INPUT_EVENT_INJECTION_FAILED;
   1147         }
   1148 
   1149         return im->getInputManager()->getDispatcher()->injectInputEvent(
   1150                 & keyEvent, injectorPid, injectorUid, syncMode, timeoutMillis,
   1151                 uint32_t(policyFlags));
   1152     } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
   1153         const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj);
   1154         if (!motionEvent) {
   1155             jniThrowRuntimeException(env, "Could not read contents of MotionEvent object.");
   1156             return INPUT_EVENT_INJECTION_FAILED;
   1157         }
   1158 
   1159         return im->getInputManager()->getDispatcher()->injectInputEvent(
   1160                 motionEvent, injectorPid, injectorUid, syncMode, timeoutMillis,
   1161                 uint32_t(policyFlags));
   1162     } else {
   1163         jniThrowRuntimeException(env, "Invalid input event type.");
   1164         return INPUT_EVENT_INJECTION_FAILED;
   1165     }
   1166 }
   1167 
   1168 static void nativeSetInputWindows(JNIEnv* env, jclass clazz,
   1169         jint ptr, jobjectArray windowHandleObjArray) {
   1170     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1171 
   1172     im->setInputWindows(env, windowHandleObjArray);
   1173 }
   1174 
   1175 static void nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
   1176         jint ptr, jobject applicationHandleObj) {
   1177     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1178 
   1179     im->setFocusedApplication(env, applicationHandleObj);
   1180 }
   1181 
   1182 static void nativeSetInputDispatchMode(JNIEnv* env,
   1183         jclass clazz, jint ptr, jboolean enabled, jboolean frozen) {
   1184     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1185 
   1186     im->setInputDispatchMode(enabled, frozen);
   1187 }
   1188 
   1189 static void nativeSetSystemUiVisibility(JNIEnv* env,
   1190         jclass clazz, jint ptr, jint visibility) {
   1191     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1192 
   1193     im->setSystemUiVisibility(visibility);
   1194 }
   1195 
   1196 static jboolean nativeTransferTouchFocus(JNIEnv* env,
   1197         jclass clazz, jint ptr, jobject fromChannelObj, jobject toChannelObj) {
   1198     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1199 
   1200     sp<InputChannel> fromChannel =
   1201             android_view_InputChannel_getInputChannel(env, fromChannelObj);
   1202     sp<InputChannel> toChannel =
   1203             android_view_InputChannel_getInputChannel(env, toChannelObj);
   1204 
   1205     if (fromChannel == NULL || toChannel == NULL) {
   1206         return false;
   1207     }
   1208 
   1209     return im->getInputManager()->getDispatcher()->
   1210             transferTouchFocus(fromChannel, toChannel);
   1211 }
   1212 
   1213 static void nativeSetPointerSpeed(JNIEnv* env,
   1214         jclass clazz, jint ptr, jint speed) {
   1215     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1216 
   1217     im->setPointerSpeed(speed);
   1218 }
   1219 
   1220 static void nativeSetShowTouches(JNIEnv* env,
   1221         jclass clazz, jint ptr, jboolean enabled) {
   1222     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1223 
   1224     im->setShowTouches(enabled);
   1225 }
   1226 
   1227 static void nativeVibrate(JNIEnv* env,
   1228         jclass clazz, jint ptr, jint deviceId, jlongArray patternObj,
   1229         jint repeat, jint token) {
   1230     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1231 
   1232     size_t patternSize = env->GetArrayLength(patternObj);
   1233     if (patternSize > MAX_VIBRATE_PATTERN_SIZE) {
   1234         ALOGI("Skipped requested vibration because the pattern size is %d "
   1235                 "which is more than the maximum supported size of %d.",
   1236                 patternSize, MAX_VIBRATE_PATTERN_SIZE);
   1237         return; // limit to reasonable size
   1238     }
   1239 
   1240     jlong* patternMillis = static_cast<jlong*>(env->GetPrimitiveArrayCritical(
   1241             patternObj, NULL));
   1242     nsecs_t pattern[patternSize];
   1243     for (size_t i = 0; i < patternSize; i++) {
   1244         pattern[i] = max(jlong(0), min(patternMillis[i],
   1245                 MAX_VIBRATE_PATTERN_DELAY_NSECS / 1000000LL)) * 1000000LL;
   1246     }
   1247     env->ReleasePrimitiveArrayCritical(patternObj, patternMillis, JNI_ABORT);
   1248 
   1249     im->getInputManager()->getReader()->vibrate(deviceId, pattern, patternSize, repeat, token);
   1250 }
   1251 
   1252 static void nativeCancelVibrate(JNIEnv* env,
   1253         jclass clazz, jint ptr, jint deviceId, jint token) {
   1254     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1255 
   1256     im->getInputManager()->getReader()->cancelVibrate(deviceId, token);
   1257 }
   1258 
   1259 static void nativeReloadKeyboardLayouts(JNIEnv* env,
   1260         jclass clazz, jint ptr) {
   1261     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1262 
   1263     im->getInputManager()->getReader()->requestRefreshConfiguration(
   1264             InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS);
   1265 }
   1266 
   1267 static void nativeReloadDeviceAliases(JNIEnv* env,
   1268         jclass clazz, jint ptr) {
   1269     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1270 
   1271     im->getInputManager()->getReader()->requestRefreshConfiguration(
   1272             InputReaderConfiguration::CHANGE_DEVICE_ALIAS);
   1273 }
   1274 
   1275 static jstring nativeDump(JNIEnv* env, jclass clazz, jint ptr) {
   1276     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1277 
   1278     String8 dump;
   1279     im->dump(dump);
   1280     return env->NewStringUTF(dump.string());
   1281 }
   1282 
   1283 static void nativeMonitor(JNIEnv* env, jclass clazz, jint ptr) {
   1284     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1285 
   1286     im->getInputManager()->getReader()->monitor();
   1287     im->getInputManager()->getDispatcher()->monitor();
   1288 }
   1289 
   1290 // ----------------------------------------------------------------------------
   1291 
   1292 static JNINativeMethod gInputManagerMethods[] = {
   1293     /* name, signature, funcPtr */
   1294     { "nativeInit",
   1295             "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)I",
   1296             (void*) nativeInit },
   1297     { "nativeStart", "(I)V",
   1298             (void*) nativeStart },
   1299     { "nativeSetDisplayViewport", "(IZIIIIIIIIIIII)V",
   1300             (void*) nativeSetDisplayViewport },
   1301     { "nativeGetScanCodeState", "(IIII)I",
   1302             (void*) nativeGetScanCodeState },
   1303     { "nativeGetKeyCodeState", "(IIII)I",
   1304             (void*) nativeGetKeyCodeState },
   1305     { "nativeGetSwitchState", "(IIII)I",
   1306             (void*) nativeGetSwitchState },
   1307     { "nativeHasKeys", "(III[I[Z)Z",
   1308             (void*) nativeHasKeys },
   1309     { "nativeRegisterInputChannel",
   1310             "(ILandroid/view/InputChannel;Lcom/android/server/input/InputWindowHandle;Z)V",
   1311             (void*) nativeRegisterInputChannel },
   1312     { "nativeUnregisterInputChannel", "(ILandroid/view/InputChannel;)V",
   1313             (void*) nativeUnregisterInputChannel },
   1314     { "nativeSetInputFilterEnabled", "(IZ)V",
   1315             (void*) nativeSetInputFilterEnabled },
   1316     { "nativeInjectInputEvent", "(ILandroid/view/InputEvent;IIIII)I",
   1317             (void*) nativeInjectInputEvent },
   1318     { "nativeSetInputWindows", "(I[Lcom/android/server/input/InputWindowHandle;)V",
   1319             (void*) nativeSetInputWindows },
   1320     { "nativeSetFocusedApplication", "(ILcom/android/server/input/InputApplicationHandle;)V",
   1321             (void*) nativeSetFocusedApplication },
   1322     { "nativeSetInputDispatchMode", "(IZZ)V",
   1323             (void*) nativeSetInputDispatchMode },
   1324     { "nativeSetSystemUiVisibility", "(II)V",
   1325             (void*) nativeSetSystemUiVisibility },
   1326     { "nativeTransferTouchFocus", "(ILandroid/view/InputChannel;Landroid/view/InputChannel;)Z",
   1327             (void*) nativeTransferTouchFocus },
   1328     { "nativeSetPointerSpeed", "(II)V",
   1329             (void*) nativeSetPointerSpeed },
   1330     { "nativeSetShowTouches", "(IZ)V",
   1331             (void*) nativeSetShowTouches },
   1332     { "nativeVibrate", "(II[JII)V",
   1333             (void*) nativeVibrate },
   1334     { "nativeCancelVibrate", "(III)V",
   1335             (void*) nativeCancelVibrate },
   1336     { "nativeReloadKeyboardLayouts", "(I)V",
   1337             (void*) nativeReloadKeyboardLayouts },
   1338     { "nativeReloadDeviceAliases", "(I)V",
   1339             (void*) nativeReloadDeviceAliases },
   1340     { "nativeDump", "(I)Ljava/lang/String;",
   1341             (void*) nativeDump },
   1342     { "nativeMonitor", "(I)V",
   1343             (void*) nativeMonitor },
   1344 };
   1345 
   1346 #define FIND_CLASS(var, className) \
   1347         var = env->FindClass(className); \
   1348         LOG_FATAL_IF(! var, "Unable to find class " className);
   1349 
   1350 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
   1351         var = env->GetMethodID(clazz, methodName, methodDescriptor); \
   1352         LOG_FATAL_IF(! var, "Unable to find method " methodName);
   1353 
   1354 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
   1355         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
   1356         LOG_FATAL_IF(! var, "Unable to find field " fieldName);
   1357 
   1358 int register_android_server_InputManager(JNIEnv* env) {
   1359     int res = jniRegisterNativeMethods(env, "com/android/server/input/InputManagerService",
   1360             gInputManagerMethods, NELEM(gInputManagerMethods));
   1361     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
   1362 
   1363     // Callbacks
   1364 
   1365     jclass clazz;
   1366     FIND_CLASS(clazz, "com/android/server/input/InputManagerService");
   1367 
   1368     GET_METHOD_ID(gServiceClassInfo.notifyConfigurationChanged, clazz,
   1369             "notifyConfigurationChanged", "(J)V");
   1370 
   1371     GET_METHOD_ID(gServiceClassInfo.notifyInputDevicesChanged, clazz,
   1372             "notifyInputDevicesChanged", "([Landroid/view/InputDevice;)V");
   1373 
   1374     GET_METHOD_ID(gServiceClassInfo.notifySwitch, clazz,
   1375             "notifySwitch", "(JII)V");
   1376 
   1377     GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz,
   1378             "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V");
   1379 
   1380     GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
   1381             "notifyANR",
   1382             "(Lcom/android/server/input/InputApplicationHandle;Lcom/android/server/input/InputWindowHandle;)J");
   1383 
   1384     GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
   1385             "filterInputEvent", "(Landroid/view/InputEvent;I)Z");
   1386 
   1387     GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
   1388             "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
   1389 
   1390     GET_METHOD_ID(gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
   1391             clazz,
   1392             "interceptMotionBeforeQueueingWhenScreenOff", "(I)I");
   1393 
   1394     GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
   1395             "interceptKeyBeforeDispatching",
   1396             "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)J");
   1397 
   1398     GET_METHOD_ID(gServiceClassInfo.dispatchUnhandledKey, clazz,
   1399             "dispatchUnhandledKey",
   1400             "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
   1401 
   1402     GET_METHOD_ID(gServiceClassInfo.checkInjectEventsPermission, clazz,
   1403             "checkInjectEventsPermission", "(II)Z");
   1404 
   1405     GET_METHOD_ID(gServiceClassInfo.getVirtualKeyQuietTimeMillis, clazz,
   1406             "getVirtualKeyQuietTimeMillis", "()I");
   1407 
   1408     GET_METHOD_ID(gServiceClassInfo.getExcludedDeviceNames, clazz,
   1409             "getExcludedDeviceNames", "()[Ljava/lang/String;");
   1410 
   1411     GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz,
   1412             "getKeyRepeatTimeout", "()I");
   1413 
   1414     GET_METHOD_ID(gServiceClassInfo.getKeyRepeatDelay, clazz,
   1415             "getKeyRepeatDelay", "()I");
   1416 
   1417     GET_METHOD_ID(gServiceClassInfo.getHoverTapTimeout, clazz,
   1418             "getHoverTapTimeout", "()I");
   1419 
   1420     GET_METHOD_ID(gServiceClassInfo.getHoverTapSlop, clazz,
   1421             "getHoverTapSlop", "()I");
   1422 
   1423     GET_METHOD_ID(gServiceClassInfo.getDoubleTapTimeout, clazz,
   1424             "getDoubleTapTimeout", "()I");
   1425 
   1426     GET_METHOD_ID(gServiceClassInfo.getLongPressTimeout, clazz,
   1427             "getLongPressTimeout", "()I");
   1428 
   1429     GET_METHOD_ID(gServiceClassInfo.getPointerLayer, clazz,
   1430             "getPointerLayer", "()I");
   1431 
   1432     GET_METHOD_ID(gServiceClassInfo.getPointerIcon, clazz,
   1433             "getPointerIcon", "()Landroid/view/PointerIcon;");
   1434 
   1435     GET_METHOD_ID(gServiceClassInfo.getKeyboardLayoutOverlay, clazz,
   1436             "getKeyboardLayoutOverlay", "(Ljava/lang/String;)[Ljava/lang/String;");
   1437 
   1438     GET_METHOD_ID(gServiceClassInfo.getDeviceAlias, clazz,
   1439             "getDeviceAlias", "(Ljava/lang/String;)Ljava/lang/String;");
   1440 
   1441     // InputDevice
   1442 
   1443     FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");
   1444     gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz));
   1445 
   1446     // KeyEvent
   1447 
   1448     FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
   1449     gKeyEventClassInfo.clazz = jclass(env->NewGlobalRef(gKeyEventClassInfo.clazz));
   1450 
   1451     // MotionEvent
   1452 
   1453     FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
   1454     gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz));
   1455 
   1456     return 0;
   1457 }
   1458 
   1459 } /* namespace android */
   1460