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 ATRACE_TAG ATRACE_TAG_INPUT
     20 
     21 //#define LOG_NDEBUG 0
     22 
     23 // Log debug messages about InputReaderPolicy
     24 #define DEBUG_INPUT_READER_POLICY 0
     25 
     26 // Log debug messages about InputDispatcherPolicy
     27 #define DEBUG_INPUT_DISPATCHER_POLICY 0
     28 
     29 
     30 #include <nativehelper/JNIHelp.h>
     31 #include "jni.h"
     32 #include <atomic>
     33 #include <cinttypes>
     34 #include <limits.h>
     35 #include <android_runtime/AndroidRuntime.h>
     36 #include <android_runtime/Log.h>
     37 
     38 #include <utils/Log.h>
     39 #include <utils/Looper.h>
     40 #include <utils/threads.h>
     41 #include <utils/Trace.h>
     42 #include <utils/SortedVector.h>
     43 
     44 #include <input/PointerController.h>
     45 #include <input/SpriteController.h>
     46 
     47 #include <inputflinger/InputManager.h>
     48 
     49 #include <android_os_MessageQueue.h>
     50 #include <android_view_InputDevice.h>
     51 #include <android_view_KeyEvent.h>
     52 #include <android_view_MotionEvent.h>
     53 #include <android_view_InputChannel.h>
     54 #include <android_view_PointerIcon.h>
     55 #include <android/graphics/GraphicsJNI.h>
     56 
     57 #include <nativehelper/ScopedLocalRef.h>
     58 #include <nativehelper/ScopedPrimitiveArray.h>
     59 #include <nativehelper/ScopedUtfChars.h>
     60 
     61 #include "com_android_server_power_PowerManagerService.h"
     62 #include "com_android_server_input_InputApplicationHandle.h"
     63 #include "com_android_server_input_InputWindowHandle.h"
     64 #include "android_hardware_display_DisplayViewport.h"
     65 
     66 #define INDENT "  "
     67 
     68 namespace android {
     69 
     70 // The exponent used to calculate the pointer speed scaling factor.
     71 // The scaling factor is calculated as 2 ^ (speed * exponent),
     72 // where the speed ranges from -7 to + 7 and is supplied by the user.
     73 static const float POINTER_SPEED_EXPONENT = 1.0f / 4;
     74 
     75 static struct {
     76     jmethodID notifyConfigurationChanged;
     77     jmethodID notifyInputDevicesChanged;
     78     jmethodID notifySwitch;
     79     jmethodID notifyInputChannelBroken;
     80     jmethodID notifyANR;
     81     jmethodID filterInputEvent;
     82     jmethodID interceptKeyBeforeQueueing;
     83     jmethodID interceptMotionBeforeQueueingNonInteractive;
     84     jmethodID interceptKeyBeforeDispatching;
     85     jmethodID dispatchUnhandledKey;
     86     jmethodID checkInjectEventsPermission;
     87     jmethodID getVirtualKeyQuietTimeMillis;
     88     jmethodID getExcludedDeviceNames;
     89     jmethodID getKeyRepeatTimeout;
     90     jmethodID getKeyRepeatDelay;
     91     jmethodID getHoverTapTimeout;
     92     jmethodID getHoverTapSlop;
     93     jmethodID getDoubleTapTimeout;
     94     jmethodID getLongPressTimeout;
     95     jmethodID getPointerLayer;
     96     jmethodID getPointerIcon;
     97     jmethodID getKeyboardLayoutOverlay;
     98     jmethodID getDeviceAlias;
     99     jmethodID getTouchCalibrationForInputDevice;
    100 } gServiceClassInfo;
    101 
    102 static struct {
    103     jclass clazz;
    104 } gInputDeviceClassInfo;
    105 
    106 static struct {
    107     jclass clazz;
    108 } gKeyEventClassInfo;
    109 
    110 static struct {
    111     jclass clazz;
    112 } gMotionEventClassInfo;
    113 
    114 static struct {
    115     jclass clazz;
    116     jmethodID constructor;
    117 } gInputDeviceIdentifierInfo;
    118 
    119 static struct {
    120     jclass clazz;
    121     jmethodID getAffineTransform;
    122 } gTouchCalibrationClassInfo;
    123 
    124 
    125 
    126 // --- Global functions ---
    127 
    128 template<typename T>
    129 inline static T min(const T& a, const T& b) {
    130     return a < b ? a : b;
    131 }
    132 
    133 template<typename T>
    134 inline static T max(const T& a, const T& b) {
    135     return a > b ? a : b;
    136 }
    137 
    138 static inline const char* toString(bool value) {
    139     return value ? "true" : "false";
    140 }
    141 
    142 static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
    143         const sp<InputApplicationHandle>& inputApplicationHandle) {
    144     if (inputApplicationHandle == NULL) {
    145         return NULL;
    146     }
    147     return static_cast<NativeInputApplicationHandle*>(inputApplicationHandle.get())->
    148             getInputApplicationHandleObjLocalRef(env);
    149 }
    150 
    151 static jobject getInputWindowHandleObjLocalRef(JNIEnv* env,
    152         const sp<InputWindowHandle>& inputWindowHandle) {
    153     if (inputWindowHandle == NULL) {
    154         return NULL;
    155     }
    156     return static_cast<NativeInputWindowHandle*>(inputWindowHandle.get())->
    157             getInputWindowHandleObjLocalRef(env);
    158 }
    159 
    160 static void loadSystemIconAsSpriteWithPointerIcon(JNIEnv* env, jobject contextObj, int32_t style,
    161         PointerIcon* outPointerIcon, SpriteIcon* outSpriteIcon) {
    162     status_t status = android_view_PointerIcon_loadSystemIcon(env,
    163             contextObj, style, outPointerIcon);
    164     if (!status) {
    165         SkBitmap* bitmapCopy = &outSpriteIcon->bitmap;
    166         SkImageInfo bitmapCopyInfo = outPointerIcon->bitmap.info().makeColorType(kN32_SkColorType);
    167         if (bitmapCopy->tryAllocPixels(bitmapCopyInfo)) {
    168             outPointerIcon->bitmap.readPixels(bitmapCopy->info(), bitmapCopy->getPixels(),
    169                     bitmapCopy->rowBytes(), 0, 0);
    170         }
    171         outSpriteIcon->hotSpotX = outPointerIcon->hotSpotX;
    172         outSpriteIcon->hotSpotY = outPointerIcon->hotSpotY;
    173     }
    174 }
    175 
    176 static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, int32_t style,
    177                                    SpriteIcon* outSpriteIcon) {
    178     PointerIcon pointerIcon;
    179     loadSystemIconAsSpriteWithPointerIcon(env, contextObj, style, &pointerIcon, outSpriteIcon);
    180 }
    181 
    182 enum {
    183     WM_ACTION_PASS_TO_USER = 1,
    184 };
    185 
    186 
    187 // --- NativeInputManager ---
    188 
    189 class NativeInputManager : public virtual RefBase,
    190     public virtual InputReaderPolicyInterface,
    191     public virtual InputDispatcherPolicyInterface,
    192     public virtual PointerControllerPolicyInterface {
    193 protected:
    194     virtual ~NativeInputManager();
    195 
    196 public:
    197     NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper);
    198 
    199     inline sp<InputManager> getInputManager() const { return mInputManager; }
    200 
    201     void dump(String8& dump);
    202 
    203     void setVirtualDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray);
    204     void setDisplayViewport(int32_t viewportType, const DisplayViewport& viewport);
    205 
    206     status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
    207             const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
    208     status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
    209 
    210     void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray);
    211     void setFocusedApplication(JNIEnv* env, jobject applicationHandleObj);
    212     void setInputDispatchMode(bool enabled, bool frozen);
    213     void setSystemUiVisibility(int32_t visibility);
    214     void setPointerSpeed(int32_t speed);
    215     void setInputDeviceEnabled(uint32_t deviceId, bool enabled);
    216     void setShowTouches(bool enabled);
    217     void setInteractive(bool interactive);
    218     void reloadCalibration();
    219     void setPointerIconType(int32_t iconId);
    220     void reloadPointerIcons();
    221     void setCustomPointerIcon(const SpriteIcon& icon);
    222     void setPointerCapture(bool enabled);
    223 
    224     /* --- InputReaderPolicyInterface implementation --- */
    225 
    226     virtual void getReaderConfiguration(InputReaderConfiguration* outConfig);
    227     virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
    228     virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices);
    229     virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier);
    230     virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier);
    231     virtual TouchAffineTransformation getTouchAffineTransformation(JNIEnv *env,
    232             jfloatArray matrixArr);
    233     virtual TouchAffineTransformation getTouchAffineTransformation(
    234             const String8& inputDeviceDescriptor, int32_t surfaceRotation);
    235 
    236     /* --- InputDispatcherPolicyInterface implementation --- */
    237 
    238     virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
    239             uint32_t policyFlags);
    240     virtual void notifyConfigurationChanged(nsecs_t when);
    241     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
    242             const sp<InputWindowHandle>& inputWindowHandle,
    243             const String8& reason);
    244     virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
    245     virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags);
    246     virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig);
    247     virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
    248     virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
    249     virtual nsecs_t interceptKeyBeforeDispatching(
    250             const sp<InputWindowHandle>& inputWindowHandle,
    251             const KeyEvent* keyEvent, uint32_t policyFlags);
    252     virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
    253             const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
    254     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
    255     virtual bool checkInjectEventsPermissionNonReentrant(
    256             int32_t injectorPid, int32_t injectorUid);
    257 
    258     /* --- PointerControllerPolicyInterface implementation --- */
    259 
    260     virtual void loadPointerIcon(SpriteIcon* icon);
    261     virtual void loadPointerResources(PointerResources* outResources);
    262     virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
    263             std::map<int32_t, PointerAnimation>* outAnimationResources);
    264     virtual int32_t getDefaultPointerIconId();
    265     virtual int32_t getCustomPointerIconId();
    266 
    267 private:
    268     sp<InputManager> mInputManager;
    269 
    270     jobject mContextObj;
    271     jobject mServiceObj;
    272     sp<Looper> mLooper;
    273 
    274     Mutex mLock;
    275     struct Locked {
    276         // Display size information.
    277         DisplayViewport internalViewport;
    278         DisplayViewport externalViewport;
    279         Vector<DisplayViewport> virtualViewports;
    280 
    281         // System UI visibility.
    282         int32_t systemUiVisibility;
    283 
    284         // Pointer speed.
    285         int32_t pointerSpeed;
    286 
    287         // True if pointer gestures are enabled.
    288         bool pointerGesturesEnabled;
    289 
    290         // Show touches feature enable/disable.
    291         bool showTouches;
    292 
    293         // Pointer capture feature enable/disable.
    294         bool pointerCapture;
    295 
    296         // Sprite controller singleton, created on first use.
    297         sp<SpriteController> spriteController;
    298 
    299         // Pointer controller singleton, created and destroyed as needed.
    300         wp<PointerController> pointerController;
    301 
    302         // Input devices to be disabled
    303         SortedVector<int32_t> disabledInputDevices;
    304     } mLocked;
    305 
    306     std::atomic<bool> mInteractive;
    307 
    308     void updateInactivityTimeoutLocked(const sp<PointerController>& controller);
    309     void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
    310     void ensureSpriteControllerLocked();
    311 
    312     static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
    313 
    314     static inline JNIEnv* jniEnv() {
    315         return AndroidRuntime::getJNIEnv();
    316     }
    317 };
    318 
    319 
    320 
    321 NativeInputManager::NativeInputManager(jobject contextObj,
    322         jobject serviceObj, const sp<Looper>& looper) :
    323         mLooper(looper), mInteractive(true) {
    324     JNIEnv* env = jniEnv();
    325 
    326     mContextObj = env->NewGlobalRef(contextObj);
    327     mServiceObj = env->NewGlobalRef(serviceObj);
    328 
    329     {
    330         AutoMutex _l(mLock);
    331         mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
    332         mLocked.pointerSpeed = 0;
    333         mLocked.pointerGesturesEnabled = true;
    334         mLocked.showTouches = false;
    335         mLocked.pointerCapture = false;
    336     }
    337     mInteractive = true;
    338 
    339     sp<EventHub> eventHub = new EventHub();
    340     mInputManager = new InputManager(eventHub, this, this);
    341 }
    342 
    343 NativeInputManager::~NativeInputManager() {
    344     JNIEnv* env = jniEnv();
    345 
    346     env->DeleteGlobalRef(mContextObj);
    347     env->DeleteGlobalRef(mServiceObj);
    348 }
    349 
    350 void NativeInputManager::dump(String8& dump) {
    351     dump.append("Input Manager State:\n");
    352     {
    353         dump.appendFormat(INDENT "Interactive: %s\n", toString(mInteractive.load()));
    354     }
    355     {
    356         AutoMutex _l(mLock);
    357         dump.appendFormat(INDENT "System UI Visibility: 0x%0" PRIx32 "\n",
    358                 mLocked.systemUiVisibility);
    359         dump.appendFormat(INDENT "Pointer Speed: %" PRId32 "\n", mLocked.pointerSpeed);
    360         dump.appendFormat(INDENT "Pointer Gestures Enabled: %s\n",
    361                 toString(mLocked.pointerGesturesEnabled));
    362         dump.appendFormat(INDENT "Show Touches: %s\n", toString(mLocked.showTouches));
    363         dump.appendFormat(INDENT "Pointer Capture Enabled: %s\n", toString(mLocked.pointerCapture));
    364     }
    365     dump.append("\n");
    366 
    367     mInputManager->getReader()->dump(dump);
    368     dump.append("\n");
    369 
    370     mInputManager->getDispatcher()->dump(dump);
    371     dump.append("\n");
    372 }
    373 
    374 bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
    375     if (env->ExceptionCheck()) {
    376         ALOGE("An exception was thrown by callback '%s'.", methodName);
    377         LOGE_EX(env);
    378         env->ExceptionClear();
    379         return true;
    380     }
    381     return false;
    382 }
    383 
    384 void NativeInputManager::setVirtualDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray) {
    385     Vector<DisplayViewport> viewports;
    386 
    387     if (viewportObjArray) {
    388         jsize length = env->GetArrayLength(viewportObjArray);
    389         for (jsize i = 0; i < length; i++) {
    390             jobject viewportObj = env->GetObjectArrayElement(viewportObjArray, i);
    391             if (! viewportObj) {
    392                 break; // found null element indicating end of used portion of the array
    393             }
    394 
    395             DisplayViewport viewport;
    396             android_hardware_display_DisplayViewport_toNative(env, viewportObj, &viewport);
    397             ALOGI("Viewport [%d] to add: %s", (int) length, viewport.uniqueId.c_str());
    398             viewports.push(viewport);
    399 
    400             env->DeleteLocalRef(viewportObj);
    401         }
    402     }
    403 
    404     {
    405         AutoMutex _l(mLock);
    406         mLocked.virtualViewports = viewports;
    407     }
    408 
    409     mInputManager->getReader()->requestRefreshConfiguration(
    410             InputReaderConfiguration::CHANGE_DISPLAY_INFO);
    411 }
    412 
    413 void NativeInputManager::setDisplayViewport(int32_t type, const DisplayViewport& viewport) {
    414     bool changed = false;
    415     {
    416         AutoMutex _l(mLock);
    417 
    418         ViewportType viewportType = static_cast<ViewportType>(type);
    419         DisplayViewport* v = NULL;
    420         if (viewportType == ViewportType::VIEWPORT_EXTERNAL) {
    421             v = &mLocked.externalViewport;
    422         } else if (viewportType == ViewportType::VIEWPORT_INTERNAL) {
    423             v = &mLocked.internalViewport;
    424         }
    425 
    426         if (v != NULL && *v != viewport) {
    427             changed = true;
    428             *v = viewport;
    429 
    430             if (viewportType == ViewportType::VIEWPORT_INTERNAL) {
    431                 sp<PointerController> controller = mLocked.pointerController.promote();
    432                 if (controller != NULL) {
    433                     controller->setDisplayViewport(
    434                             viewport.logicalRight - viewport.logicalLeft,
    435                             viewport.logicalBottom - viewport.logicalTop,
    436                             viewport.orientation);
    437                 }
    438             }
    439         }
    440     }
    441 
    442     if (changed) {
    443         mInputManager->getReader()->requestRefreshConfiguration(
    444                 InputReaderConfiguration::CHANGE_DISPLAY_INFO);
    445     }
    446 }
    447 
    448 status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
    449         const sp<InputChannel>& inputChannel,
    450         const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
    451     ATRACE_CALL();
    452     return mInputManager->getDispatcher()->registerInputChannel(
    453             inputChannel, inputWindowHandle, monitor);
    454 }
    455 
    456 status_t NativeInputManager::unregisterInputChannel(JNIEnv* /* env */,
    457         const sp<InputChannel>& inputChannel) {
    458     ATRACE_CALL();
    459     return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel);
    460 }
    461 
    462 void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outConfig) {
    463     ATRACE_CALL();
    464     JNIEnv* env = jniEnv();
    465 
    466     jint virtualKeyQuietTime = env->CallIntMethod(mServiceObj,
    467             gServiceClassInfo.getVirtualKeyQuietTimeMillis);
    468     if (!checkAndClearExceptionFromCallback(env, "getVirtualKeyQuietTimeMillis")) {
    469         outConfig->virtualKeyQuietTime = milliseconds_to_nanoseconds(virtualKeyQuietTime);
    470     }
    471 
    472     outConfig->excludedDeviceNames.clear();
    473     jobjectArray excludedDeviceNames = jobjectArray(env->CallObjectMethod(mServiceObj,
    474             gServiceClassInfo.getExcludedDeviceNames));
    475     if (!checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && excludedDeviceNames) {
    476         jsize length = env->GetArrayLength(excludedDeviceNames);
    477         for (jsize i = 0; i < length; i++) {
    478             jstring item = jstring(env->GetObjectArrayElement(excludedDeviceNames, i));
    479             const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
    480             outConfig->excludedDeviceNames.add(String8(deviceNameChars));
    481             env->ReleaseStringUTFChars(item, deviceNameChars);
    482             env->DeleteLocalRef(item);
    483         }
    484         env->DeleteLocalRef(excludedDeviceNames);
    485     }
    486 
    487     jint hoverTapTimeout = env->CallIntMethod(mServiceObj,
    488             gServiceClassInfo.getHoverTapTimeout);
    489     if (!checkAndClearExceptionFromCallback(env, "getHoverTapTimeout")) {
    490         jint doubleTapTimeout = env->CallIntMethod(mServiceObj,
    491                 gServiceClassInfo.getDoubleTapTimeout);
    492         if (!checkAndClearExceptionFromCallback(env, "getDoubleTapTimeout")) {
    493             jint longPressTimeout = env->CallIntMethod(mServiceObj,
    494                     gServiceClassInfo.getLongPressTimeout);
    495             if (!checkAndClearExceptionFromCallback(env, "getLongPressTimeout")) {
    496                 outConfig->pointerGestureTapInterval = milliseconds_to_nanoseconds(hoverTapTimeout);
    497 
    498                 // We must ensure that the tap-drag interval is significantly shorter than
    499                 // the long-press timeout because the tap is held down for the entire duration
    500                 // of the double-tap timeout.
    501                 jint tapDragInterval = max(min(longPressTimeout - 100,
    502                         doubleTapTimeout), hoverTapTimeout);
    503                 outConfig->pointerGestureTapDragInterval =
    504                         milliseconds_to_nanoseconds(tapDragInterval);
    505             }
    506         }
    507     }
    508 
    509     jint hoverTapSlop = env->CallIntMethod(mServiceObj,
    510             gServiceClassInfo.getHoverTapSlop);
    511     if (!checkAndClearExceptionFromCallback(env, "getHoverTapSlop")) {
    512         outConfig->pointerGestureTapSlop = hoverTapSlop;
    513     }
    514 
    515     { // acquire lock
    516         AutoMutex _l(mLock);
    517 
    518         outConfig->pointerVelocityControlParameters.scale = exp2f(mLocked.pointerSpeed
    519                 * POINTER_SPEED_EXPONENT);
    520         outConfig->pointerGesturesEnabled = mLocked.pointerGesturesEnabled;
    521 
    522         outConfig->showTouches = mLocked.showTouches;
    523 
    524         outConfig->pointerCapture = mLocked.pointerCapture;
    525 
    526         outConfig->setPhysicalDisplayViewport(ViewportType::VIEWPORT_INTERNAL,
    527                 mLocked.internalViewport);
    528         outConfig->setPhysicalDisplayViewport(ViewportType::VIEWPORT_EXTERNAL,
    529                 mLocked.externalViewport);
    530         outConfig->setVirtualDisplayViewports(mLocked.virtualViewports);
    531 
    532         outConfig->disabledDevices = mLocked.disabledInputDevices;
    533     } // release lock
    534 }
    535 
    536 sp<PointerControllerInterface> NativeInputManager::obtainPointerController(int32_t /* deviceId */) {
    537     ATRACE_CALL();
    538     AutoMutex _l(mLock);
    539 
    540     sp<PointerController> controller = mLocked.pointerController.promote();
    541     if (controller == NULL) {
    542         ensureSpriteControllerLocked();
    543 
    544         controller = new PointerController(this, mLooper, mLocked.spriteController);
    545         mLocked.pointerController = controller;
    546 
    547         DisplayViewport& v = mLocked.internalViewport;
    548         controller->setDisplayViewport(
    549                 v.logicalRight - v.logicalLeft,
    550                 v.logicalBottom - v.logicalTop,
    551                 v.orientation);
    552 
    553         updateInactivityTimeoutLocked(controller);
    554     }
    555     return controller;
    556 }
    557 
    558 void NativeInputManager::ensureSpriteControllerLocked() {
    559     if (mLocked.spriteController == NULL) {
    560         JNIEnv* env = jniEnv();
    561         jint layer = env->CallIntMethod(mServiceObj, gServiceClassInfo.getPointerLayer);
    562         if (checkAndClearExceptionFromCallback(env, "getPointerLayer")) {
    563             layer = -1;
    564         }
    565         mLocked.spriteController = new SpriteController(mLooper, layer);
    566     }
    567 }
    568 
    569 void NativeInputManager::notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) {
    570     ATRACE_CALL();
    571     JNIEnv* env = jniEnv();
    572 
    573     size_t count = inputDevices.size();
    574     jobjectArray inputDevicesObjArray = env->NewObjectArray(
    575             count, gInputDeviceClassInfo.clazz, NULL);
    576     if (inputDevicesObjArray) {
    577         bool error = false;
    578         for (size_t i = 0; i < count; i++) {
    579             jobject inputDeviceObj = android_view_InputDevice_create(env, inputDevices.itemAt(i));
    580             if (!inputDeviceObj) {
    581                 error = true;
    582                 break;
    583             }
    584 
    585             env->SetObjectArrayElement(inputDevicesObjArray, i, inputDeviceObj);
    586             env->DeleteLocalRef(inputDeviceObj);
    587         }
    588 
    589         if (!error) {
    590             env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyInputDevicesChanged,
    591                     inputDevicesObjArray);
    592         }
    593 
    594         env->DeleteLocalRef(inputDevicesObjArray);
    595     }
    596 
    597     checkAndClearExceptionFromCallback(env, "notifyInputDevicesChanged");
    598 }
    599 
    600 sp<KeyCharacterMap> NativeInputManager::getKeyboardLayoutOverlay(
    601         const InputDeviceIdentifier& identifier) {
    602     ATRACE_CALL();
    603     JNIEnv* env = jniEnv();
    604 
    605     sp<KeyCharacterMap> result;
    606     ScopedLocalRef<jstring> descriptor(env, env->NewStringUTF(identifier.descriptor.string()));
    607     ScopedLocalRef<jobject> identifierObj(env, env->NewObject(gInputDeviceIdentifierInfo.clazz,
    608             gInputDeviceIdentifierInfo.constructor, descriptor.get(),
    609             identifier.vendor, identifier.product));
    610     ScopedLocalRef<jobjectArray> arrayObj(env, jobjectArray(env->CallObjectMethod(mServiceObj,
    611                 gServiceClassInfo.getKeyboardLayoutOverlay, identifierObj.get())));
    612     if (arrayObj.get()) {
    613         ScopedLocalRef<jstring> filenameObj(env,
    614                 jstring(env->GetObjectArrayElement(arrayObj.get(), 0)));
    615         ScopedLocalRef<jstring> contentsObj(env,
    616                 jstring(env->GetObjectArrayElement(arrayObj.get(), 1)));
    617         ScopedUtfChars filenameChars(env, filenameObj.get());
    618         ScopedUtfChars contentsChars(env, contentsObj.get());
    619 
    620         KeyCharacterMap::loadContents(String8(filenameChars.c_str()),
    621                 String8(contentsChars.c_str()), KeyCharacterMap::FORMAT_OVERLAY, &result);
    622     }
    623     checkAndClearExceptionFromCallback(env, "getKeyboardLayoutOverlay");
    624     return result;
    625 }
    626 
    627 String8 NativeInputManager::getDeviceAlias(const InputDeviceIdentifier& identifier) {
    628     ATRACE_CALL();
    629     JNIEnv* env = jniEnv();
    630 
    631     ScopedLocalRef<jstring> uniqueIdObj(env, env->NewStringUTF(identifier.uniqueId.string()));
    632     ScopedLocalRef<jstring> aliasObj(env, jstring(env->CallObjectMethod(mServiceObj,
    633             gServiceClassInfo.getDeviceAlias, uniqueIdObj.get())));
    634     String8 result;
    635     if (aliasObj.get()) {
    636         ScopedUtfChars aliasChars(env, aliasObj.get());
    637         result.setTo(aliasChars.c_str());
    638     }
    639     checkAndClearExceptionFromCallback(env, "getDeviceAlias");
    640     return result;
    641 }
    642 
    643 void NativeInputManager::notifySwitch(nsecs_t when,
    644         uint32_t switchValues, uint32_t switchMask, uint32_t /* policyFlags */) {
    645 #if DEBUG_INPUT_DISPATCHER_POLICY
    646     ALOGD("notifySwitch - when=%lld, switchValues=0x%08x, switchMask=0x%08x, policyFlags=0x%x",
    647             when, switchValues, switchMask, policyFlags);
    648 #endif
    649     ATRACE_CALL();
    650 
    651     JNIEnv* env = jniEnv();
    652 
    653     env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySwitch,
    654             when, switchValues, switchMask);
    655     checkAndClearExceptionFromCallback(env, "notifySwitch");
    656 }
    657 
    658 void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
    659 #if DEBUG_INPUT_DISPATCHER_POLICY
    660     ALOGD("notifyConfigurationChanged - when=%lld", when);
    661 #endif
    662     ATRACE_CALL();
    663 
    664     JNIEnv* env = jniEnv();
    665 
    666     env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyConfigurationChanged, when);
    667     checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
    668 }
    669 
    670 nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
    671         const sp<InputWindowHandle>& inputWindowHandle, const String8& reason) {
    672 #if DEBUG_INPUT_DISPATCHER_POLICY
    673     ALOGD("notifyANR");
    674 #endif
    675     ATRACE_CALL();
    676 
    677     JNIEnv* env = jniEnv();
    678 
    679     jobject inputApplicationHandleObj =
    680             getInputApplicationHandleObjLocalRef(env, inputApplicationHandle);
    681     jobject inputWindowHandleObj =
    682             getInputWindowHandleObjLocalRef(env, inputWindowHandle);
    683     jstring reasonObj = env->NewStringUTF(reason.string());
    684 
    685     jlong newTimeout = env->CallLongMethod(mServiceObj,
    686                 gServiceClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj,
    687                 reasonObj);
    688     if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
    689         newTimeout = 0; // abort dispatch
    690     } else {
    691         assert(newTimeout >= 0);
    692     }
    693 
    694     env->DeleteLocalRef(reasonObj);
    695     env->DeleteLocalRef(inputWindowHandleObj);
    696     env->DeleteLocalRef(inputApplicationHandleObj);
    697     return newTimeout;
    698 }
    699 
    700 void NativeInputManager::notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
    701 #if DEBUG_INPUT_DISPATCHER_POLICY
    702     ALOGD("notifyInputChannelBroken");
    703 #endif
    704     ATRACE_CALL();
    705 
    706     JNIEnv* env = jniEnv();
    707 
    708     jobject inputWindowHandleObj =
    709             getInputWindowHandleObjLocalRef(env, inputWindowHandle);
    710     if (inputWindowHandleObj) {
    711         env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyInputChannelBroken,
    712                 inputWindowHandleObj);
    713         checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
    714 
    715         env->DeleteLocalRef(inputWindowHandleObj);
    716     }
    717 }
    718 
    719 void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
    720     ATRACE_CALL();
    721     JNIEnv* env = jniEnv();
    722 
    723     jint keyRepeatTimeout = env->CallIntMethod(mServiceObj,
    724             gServiceClassInfo.getKeyRepeatTimeout);
    725     if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatTimeout")) {
    726         outConfig->keyRepeatTimeout = milliseconds_to_nanoseconds(keyRepeatTimeout);
    727     }
    728 
    729     jint keyRepeatDelay = env->CallIntMethod(mServiceObj,
    730             gServiceClassInfo.getKeyRepeatDelay);
    731     if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatDelay")) {
    732         outConfig->keyRepeatDelay = milliseconds_to_nanoseconds(keyRepeatDelay);
    733     }
    734 }
    735 
    736 void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) {
    737     Vector<sp<InputWindowHandle> > windowHandles;
    738 
    739     if (windowHandleObjArray) {
    740         jsize length = env->GetArrayLength(windowHandleObjArray);
    741         for (jsize i = 0; i < length; i++) {
    742             jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i);
    743             if (! windowHandleObj) {
    744                 break; // found null element indicating end of used portion of the array
    745             }
    746 
    747             sp<InputWindowHandle> windowHandle =
    748                     android_server_InputWindowHandle_getHandle(env, windowHandleObj);
    749             if (windowHandle != NULL) {
    750                 windowHandles.push(windowHandle);
    751             }
    752             env->DeleteLocalRef(windowHandleObj);
    753         }
    754     }
    755 
    756     mInputManager->getDispatcher()->setInputWindows(windowHandles);
    757 
    758     // Do this after the dispatcher has updated the window handle state.
    759     bool newPointerGesturesEnabled = true;
    760     size_t numWindows = windowHandles.size();
    761     for (size_t i = 0; i < numWindows; i++) {
    762         const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
    763         const InputWindowInfo* windowInfo = windowHandle->getInfo();
    764         if (windowInfo && windowInfo->hasFocus && (windowInfo->inputFeatures
    765                 & InputWindowInfo::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) {
    766             newPointerGesturesEnabled = false;
    767         }
    768     }
    769 
    770     uint32_t changes = 0;
    771     { // acquire lock
    772         AutoMutex _l(mLock);
    773 
    774         if (mLocked.pointerGesturesEnabled != newPointerGesturesEnabled) {
    775             mLocked.pointerGesturesEnabled = newPointerGesturesEnabled;
    776             changes |= InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT;
    777         }
    778     } // release lock
    779 
    780     if (changes) {
    781         mInputManager->getReader()->requestRefreshConfiguration(changes);
    782     }
    783 }
    784 
    785 void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationHandleObj) {
    786     sp<InputApplicationHandle> applicationHandle =
    787             android_server_InputApplicationHandle_getHandle(env, applicationHandleObj);
    788     mInputManager->getDispatcher()->setFocusedApplication(applicationHandle);
    789 }
    790 
    791 void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
    792     mInputManager->getDispatcher()->setInputDispatchMode(enabled, frozen);
    793 }
    794 
    795 void NativeInputManager::setSystemUiVisibility(int32_t visibility) {
    796     AutoMutex _l(mLock);
    797 
    798     if (mLocked.systemUiVisibility != visibility) {
    799         mLocked.systemUiVisibility = visibility;
    800 
    801         sp<PointerController> controller = mLocked.pointerController.promote();
    802         if (controller != NULL) {
    803             updateInactivityTimeoutLocked(controller);
    804         }
    805     }
    806 }
    807 
    808 void NativeInputManager::updateInactivityTimeoutLocked(const sp<PointerController>& controller) {
    809     bool lightsOut = mLocked.systemUiVisibility & ASYSTEM_UI_VISIBILITY_STATUS_BAR_HIDDEN;
    810     controller->setInactivityTimeout(lightsOut
    811             ? PointerController::INACTIVITY_TIMEOUT_SHORT
    812             : PointerController::INACTIVITY_TIMEOUT_NORMAL);
    813 }
    814 
    815 void NativeInputManager::setPointerSpeed(int32_t speed) {
    816     { // acquire lock
    817         AutoMutex _l(mLock);
    818 
    819         if (mLocked.pointerSpeed == speed) {
    820             return;
    821         }
    822 
    823         ALOGI("Setting pointer speed to %d.", speed);
    824         mLocked.pointerSpeed = speed;
    825     } // release lock
    826 
    827     mInputManager->getReader()->requestRefreshConfiguration(
    828             InputReaderConfiguration::CHANGE_POINTER_SPEED);
    829 }
    830 
    831 void NativeInputManager::setInputDeviceEnabled(uint32_t deviceId, bool enabled) {
    832     { // acquire lock
    833         AutoMutex _l(mLock);
    834 
    835         ssize_t index = mLocked.disabledInputDevices.indexOf(deviceId);
    836         bool currentlyEnabled = index < 0;
    837         if (!enabled && currentlyEnabled) {
    838             mLocked.disabledInputDevices.add(deviceId);
    839         }
    840         if (enabled && !currentlyEnabled) {
    841             mLocked.disabledInputDevices.remove(deviceId);
    842         }
    843     } // release lock
    844 
    845     mInputManager->getReader()->requestRefreshConfiguration(
    846             InputReaderConfiguration::CHANGE_ENABLED_STATE);
    847 }
    848 
    849 void NativeInputManager::setShowTouches(bool enabled) {
    850     { // acquire lock
    851         AutoMutex _l(mLock);
    852 
    853         if (mLocked.showTouches == enabled) {
    854             return;
    855         }
    856 
    857         ALOGI("Setting show touches feature to %s.", enabled ? "enabled" : "disabled");
    858         mLocked.showTouches = enabled;
    859     } // release lock
    860 
    861     mInputManager->getReader()->requestRefreshConfiguration(
    862             InputReaderConfiguration::CHANGE_SHOW_TOUCHES);
    863 }
    864 
    865 void NativeInputManager::setPointerCapture(bool enabled) {
    866     { // acquire lock
    867         AutoMutex _l(mLock);
    868 
    869         if (mLocked.pointerCapture == enabled) {
    870             return;
    871         }
    872 
    873         ALOGI("Setting pointer capture to %s.", enabled ? "enabled" : "disabled");
    874         mLocked.pointerCapture = enabled;
    875     } // release lock
    876 
    877     mInputManager->getReader()->requestRefreshConfiguration(
    878             InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
    879 }
    880 
    881 void NativeInputManager::setInteractive(bool interactive) {
    882     mInteractive = interactive;
    883 }
    884 
    885 void NativeInputManager::reloadCalibration() {
    886     mInputManager->getReader()->requestRefreshConfiguration(
    887             InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION);
    888 }
    889 
    890 void NativeInputManager::setPointerIconType(int32_t iconId) {
    891     AutoMutex _l(mLock);
    892     sp<PointerController> controller = mLocked.pointerController.promote();
    893     if (controller != NULL) {
    894         controller->updatePointerIcon(iconId);
    895     }
    896 }
    897 
    898 void NativeInputManager::reloadPointerIcons() {
    899     AutoMutex _l(mLock);
    900     sp<PointerController> controller = mLocked.pointerController.promote();
    901     if (controller != NULL) {
    902         controller->reloadPointerResources();
    903     }
    904 }
    905 
    906 void NativeInputManager::setCustomPointerIcon(const SpriteIcon& icon) {
    907     AutoMutex _l(mLock);
    908     sp<PointerController> controller = mLocked.pointerController.promote();
    909     if (controller != NULL) {
    910         controller->setCustomPointerIcon(icon);
    911     }
    912 }
    913 
    914 TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
    915         JNIEnv *env, jfloatArray matrixArr) {
    916     ATRACE_CALL();
    917     ScopedFloatArrayRO matrix(env, matrixArr);
    918     assert(matrix.size() == 6);
    919 
    920     TouchAffineTransformation transform;
    921     transform.x_scale  = matrix[0];
    922     transform.x_ymix   = matrix[1];
    923     transform.x_offset = matrix[2];
    924     transform.y_xmix   = matrix[3];
    925     transform.y_scale  = matrix[4];
    926     transform.y_offset = matrix[5];
    927 
    928     return transform;
    929 }
    930 
    931 TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
    932         const String8& inputDeviceDescriptor, int32_t surfaceRotation) {
    933     JNIEnv* env = jniEnv();
    934 
    935     ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.string()));
    936 
    937     jobject cal = env->CallObjectMethod(mServiceObj,
    938             gServiceClassInfo.getTouchCalibrationForInputDevice, descriptorObj.get(),
    939             surfaceRotation);
    940 
    941     jfloatArray matrixArr = jfloatArray(env->CallObjectMethod(cal,
    942             gTouchCalibrationClassInfo.getAffineTransform));
    943 
    944     TouchAffineTransformation transform = getTouchAffineTransformation(env, matrixArr);
    945 
    946     env->DeleteLocalRef(matrixArr);
    947     env->DeleteLocalRef(cal);
    948 
    949     return transform;
    950 }
    951 
    952 bool NativeInputManager::filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
    953     ATRACE_CALL();
    954     jobject inputEventObj;
    955 
    956     JNIEnv* env = jniEnv();
    957     switch (inputEvent->getType()) {
    958     case AINPUT_EVENT_TYPE_KEY:
    959         inputEventObj = android_view_KeyEvent_fromNative(env,
    960                 static_cast<const KeyEvent*>(inputEvent));
    961         break;
    962     case AINPUT_EVENT_TYPE_MOTION:
    963         inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
    964                 static_cast<const MotionEvent*>(inputEvent));
    965         break;
    966     default:
    967         return true; // dispatch the event normally
    968     }
    969 
    970     if (!inputEventObj) {
    971         ALOGE("Failed to obtain input event object for filterInputEvent.");
    972         return true; // dispatch the event normally
    973     }
    974 
    975     // The callee is responsible for recycling the event.
    976     jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,
    977             inputEventObj, policyFlags);
    978     if (checkAndClearExceptionFromCallback(env, "filterInputEvent")) {
    979         pass = true;
    980     }
    981     env->DeleteLocalRef(inputEventObj);
    982     return pass;
    983 }
    984 
    985 void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
    986         uint32_t& policyFlags) {
    987     ATRACE_CALL();
    988     // Policy:
    989     // - Ignore untrusted events and pass them along.
    990     // - Ask the window manager what to do with normal events and trusted injected events.
    991     // - For normal events wake and brighten the screen if currently off or dim.
    992     bool interactive = mInteractive.load();
    993     if (interactive) {
    994         policyFlags |= POLICY_FLAG_INTERACTIVE;
    995     }
    996     if ((policyFlags & POLICY_FLAG_TRUSTED)) {
    997         nsecs_t when = keyEvent->getEventTime();
    998         JNIEnv* env = jniEnv();
    999         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
   1000         jint wmActions;
   1001         if (keyEventObj) {
   1002             wmActions = env->CallIntMethod(mServiceObj,
   1003                     gServiceClassInfo.interceptKeyBeforeQueueing,
   1004                     keyEventObj, policyFlags);
   1005             if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
   1006                 wmActions = 0;
   1007             }
   1008             android_view_KeyEvent_recycle(env, keyEventObj);
   1009             env->DeleteLocalRef(keyEventObj);
   1010         } else {
   1011             ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing.");
   1012             wmActions = 0;
   1013         }
   1014 
   1015         handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
   1016     } else {
   1017         if (interactive) {
   1018             policyFlags |= POLICY_FLAG_PASS_TO_USER;
   1019         }
   1020     }
   1021 }
   1022 
   1023 void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
   1024     ATRACE_CALL();
   1025     // Policy:
   1026     // - Ignore untrusted events and pass them along.
   1027     // - No special filtering for injected events required at this time.
   1028     // - Filter normal events based on screen state.
   1029     // - For normal events brighten (but do not wake) the screen if currently dim.
   1030     bool interactive = mInteractive.load();
   1031     if (interactive) {
   1032         policyFlags |= POLICY_FLAG_INTERACTIVE;
   1033     }
   1034     if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {
   1035         if (policyFlags & POLICY_FLAG_INTERACTIVE) {
   1036             policyFlags |= POLICY_FLAG_PASS_TO_USER;
   1037         } else {
   1038             JNIEnv* env = jniEnv();
   1039             jint wmActions = env->CallIntMethod(mServiceObj,
   1040                         gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive,
   1041                         when, policyFlags);
   1042             if (checkAndClearExceptionFromCallback(env,
   1043                     "interceptMotionBeforeQueueingNonInteractive")) {
   1044                 wmActions = 0;
   1045             }
   1046 
   1047             handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
   1048         }
   1049     } else {
   1050         if (interactive) {
   1051             policyFlags |= POLICY_FLAG_PASS_TO_USER;
   1052         }
   1053     }
   1054 }
   1055 
   1056 void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
   1057         uint32_t& policyFlags) {
   1058     if (wmActions & WM_ACTION_PASS_TO_USER) {
   1059         policyFlags |= POLICY_FLAG_PASS_TO_USER;
   1060     } else {
   1061 #if DEBUG_INPUT_DISPATCHER_POLICY
   1062         ALOGD("handleInterceptActions: Not passing key to user.");
   1063 #endif
   1064     }
   1065 }
   1066 
   1067 nsecs_t NativeInputManager::interceptKeyBeforeDispatching(
   1068         const sp<InputWindowHandle>& inputWindowHandle,
   1069         const KeyEvent* keyEvent, uint32_t policyFlags) {
   1070     ATRACE_CALL();
   1071     // Policy:
   1072     // - Ignore untrusted events and pass them along.
   1073     // - Filter normal events and trusted injected events through the window manager policy to
   1074     //   handle the HOME key and the like.
   1075     nsecs_t result = 0;
   1076     if (policyFlags & POLICY_FLAG_TRUSTED) {
   1077         JNIEnv* env = jniEnv();
   1078 
   1079         // Note: inputWindowHandle may be null.
   1080         jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
   1081         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
   1082         if (keyEventObj) {
   1083             jlong delayMillis = env->CallLongMethod(mServiceObj,
   1084                     gServiceClassInfo.interceptKeyBeforeDispatching,
   1085                     inputWindowHandleObj, keyEventObj, policyFlags);
   1086             bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
   1087             android_view_KeyEvent_recycle(env, keyEventObj);
   1088             env->DeleteLocalRef(keyEventObj);
   1089             if (!error) {
   1090                 if (delayMillis < 0) {
   1091                     result = -1;
   1092                 } else if (delayMillis > 0) {
   1093                     result = milliseconds_to_nanoseconds(delayMillis);
   1094                 }
   1095             }
   1096         } else {
   1097             ALOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
   1098         }
   1099         env->DeleteLocalRef(inputWindowHandleObj);
   1100     }
   1101     return result;
   1102 }
   1103 
   1104 bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
   1105         const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
   1106     ATRACE_CALL();
   1107     // Policy:
   1108     // - Ignore untrusted events and do not perform default handling.
   1109     bool result = false;
   1110     if (policyFlags & POLICY_FLAG_TRUSTED) {
   1111         JNIEnv* env = jniEnv();
   1112 
   1113         // Note: inputWindowHandle may be null.
   1114         jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
   1115         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
   1116         if (keyEventObj) {
   1117             jobject fallbackKeyEventObj = env->CallObjectMethod(mServiceObj,
   1118                     gServiceClassInfo.dispatchUnhandledKey,
   1119                     inputWindowHandleObj, keyEventObj, policyFlags);
   1120             if (checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey")) {
   1121                 fallbackKeyEventObj = NULL;
   1122             }
   1123             android_view_KeyEvent_recycle(env, keyEventObj);
   1124             env->DeleteLocalRef(keyEventObj);
   1125 
   1126             if (fallbackKeyEventObj) {
   1127                 // Note: outFallbackKeyEvent may be the same object as keyEvent.
   1128                 if (!android_view_KeyEvent_toNative(env, fallbackKeyEventObj,
   1129                         outFallbackKeyEvent)) {
   1130                     result = true;
   1131                 }
   1132                 android_view_KeyEvent_recycle(env, fallbackKeyEventObj);
   1133                 env->DeleteLocalRef(fallbackKeyEventObj);
   1134             }
   1135         } else {
   1136             ALOGE("Failed to obtain key event object for dispatchUnhandledKey.");
   1137         }
   1138         env->DeleteLocalRef(inputWindowHandleObj);
   1139     }
   1140     return result;
   1141 }
   1142 
   1143 void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
   1144     ATRACE_CALL();
   1145     android_server_PowerManagerService_userActivity(eventTime, eventType);
   1146 }
   1147 
   1148 
   1149 bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
   1150         int32_t injectorPid, int32_t injectorUid) {
   1151     ATRACE_CALL();
   1152     JNIEnv* env = jniEnv();
   1153     jboolean result = env->CallBooleanMethod(mServiceObj,
   1154             gServiceClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
   1155     if (checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission")) {
   1156         result = false;
   1157     }
   1158     return result;
   1159 }
   1160 
   1161 void NativeInputManager::loadPointerIcon(SpriteIcon* icon) {
   1162     ATRACE_CALL();
   1163     JNIEnv* env = jniEnv();
   1164 
   1165     ScopedLocalRef<jobject> pointerIconObj(env, env->CallObjectMethod(
   1166             mServiceObj, gServiceClassInfo.getPointerIcon));
   1167     if (checkAndClearExceptionFromCallback(env, "getPointerIcon")) {
   1168         return;
   1169     }
   1170 
   1171     PointerIcon pointerIcon;
   1172     status_t status = android_view_PointerIcon_load(env, pointerIconObj.get(),
   1173                                                     mContextObj, &pointerIcon);
   1174     if (!status && !pointerIcon.isNullIcon()) {
   1175         *icon = SpriteIcon(pointerIcon.bitmap, pointerIcon.hotSpotX, pointerIcon.hotSpotY);
   1176     } else {
   1177         *icon = SpriteIcon();
   1178     }
   1179 }
   1180 
   1181 void NativeInputManager::loadPointerResources(PointerResources* outResources) {
   1182     ATRACE_CALL();
   1183     JNIEnv* env = jniEnv();
   1184 
   1185     loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_HOVER,
   1186             &outResources->spotHover);
   1187     loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_TOUCH,
   1188             &outResources->spotTouch);
   1189     loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_ANCHOR,
   1190             &outResources->spotAnchor);
   1191 }
   1192 
   1193 void NativeInputManager::loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
   1194         std::map<int32_t, PointerAnimation>* outAnimationResources) {
   1195     ATRACE_CALL();
   1196     JNIEnv* env = jniEnv();
   1197 
   1198     for (int iconId = POINTER_ICON_STYLE_CONTEXT_MENU; iconId <= POINTER_ICON_STYLE_GRABBING;
   1199              ++iconId) {
   1200         PointerIcon pointerIcon;
   1201         loadSystemIconAsSpriteWithPointerIcon(
   1202                 env, mContextObj, iconId, &pointerIcon, &((*outResources)[iconId]));
   1203         if (!pointerIcon.bitmapFrames.empty()) {
   1204             PointerAnimation& animationData = (*outAnimationResources)[iconId];
   1205             size_t numFrames = pointerIcon.bitmapFrames.size() + 1;
   1206             animationData.durationPerFrame =
   1207                     milliseconds_to_nanoseconds(pointerIcon.durationPerFrame);
   1208             animationData.animationFrames.reserve(numFrames);
   1209             animationData.animationFrames.push_back(SpriteIcon(
   1210                     pointerIcon.bitmap, pointerIcon.hotSpotX, pointerIcon.hotSpotY));
   1211             for (size_t i = 0; i < numFrames - 1; ++i) {
   1212               animationData.animationFrames.push_back(SpriteIcon(
   1213                       pointerIcon.bitmapFrames[i], pointerIcon.hotSpotX, pointerIcon.hotSpotY));
   1214             }
   1215         }
   1216     }
   1217     loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_NULL,
   1218             &((*outResources)[POINTER_ICON_STYLE_NULL]));
   1219 }
   1220 
   1221 int32_t NativeInputManager::getDefaultPointerIconId() {
   1222     return POINTER_ICON_STYLE_ARROW;
   1223 }
   1224 
   1225 int32_t NativeInputManager::getCustomPointerIconId() {
   1226     return POINTER_ICON_STYLE_CUSTOM;
   1227 }
   1228 
   1229 // ----------------------------------------------------------------------------
   1230 
   1231 static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
   1232         jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
   1233     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
   1234     if (messageQueue == NULL) {
   1235         jniThrowRuntimeException(env, "MessageQueue is not initialized.");
   1236         return 0;
   1237     }
   1238 
   1239     NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
   1240             messageQueue->getLooper());
   1241     im->incStrong(0);
   1242     return reinterpret_cast<jlong>(im);
   1243 }
   1244 
   1245 static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
   1246     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1247 
   1248     status_t result = im->getInputManager()->start();
   1249     if (result) {
   1250         jniThrowRuntimeException(env, "Input manager could not be started.");
   1251     }
   1252 }
   1253 
   1254 static void nativeSetVirtualDisplayViewports(JNIEnv* env, jclass /* clazz */, jlong ptr,
   1255         jobjectArray viewportObjArray) {
   1256     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1257     im->setVirtualDisplayViewports(env, viewportObjArray);
   1258 }
   1259 
   1260 static void nativeSetDisplayViewport(JNIEnv* env, jclass /* clazz */, jlong ptr,
   1261         jint viewportType, jint displayId, jint orientation,
   1262         jint logicalLeft, jint logicalTop, jint logicalRight, jint logicalBottom,
   1263         jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom,
   1264         jint deviceWidth, jint deviceHeight, jstring uniqueId) {
   1265     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1266 
   1267     DisplayViewport v;
   1268     v.displayId = displayId;
   1269     v.orientation = orientation;
   1270     v.logicalLeft = logicalLeft;
   1271     v.logicalTop = logicalTop;
   1272     v.logicalRight = logicalRight;
   1273     v.logicalBottom = logicalBottom;
   1274     v.physicalLeft = physicalLeft;
   1275     v.physicalTop = physicalTop;
   1276     v.physicalRight = physicalRight;
   1277     v.physicalBottom = physicalBottom;
   1278     v.deviceWidth = deviceWidth;
   1279     v.deviceHeight = deviceHeight;
   1280     if (uniqueId != nullptr) {
   1281         v.uniqueId.setTo(ScopedUtfChars(env, uniqueId).c_str());
   1282     }
   1283 
   1284     im->setDisplayViewport(viewportType, v);
   1285 }
   1286 
   1287 static jint nativeGetScanCodeState(JNIEnv* /* env */, jclass /* clazz */,
   1288         jlong ptr, jint deviceId, jint sourceMask, jint scanCode) {
   1289     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1290 
   1291     return (jint) im->getInputManager()->getReader()->getScanCodeState(
   1292             deviceId, uint32_t(sourceMask), scanCode);
   1293 }
   1294 
   1295 static jint nativeGetKeyCodeState(JNIEnv* /* env */, jclass /* clazz */,
   1296         jlong ptr, jint deviceId, jint sourceMask, jint keyCode) {
   1297     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1298 
   1299     return (jint) im->getInputManager()->getReader()->getKeyCodeState(
   1300             deviceId, uint32_t(sourceMask), keyCode);
   1301 }
   1302 
   1303 static jint nativeGetSwitchState(JNIEnv* /* env */, jclass /* clazz */,
   1304         jlong ptr, jint deviceId, jint sourceMask, jint sw) {
   1305     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1306 
   1307     return (jint) im->getInputManager()->getReader()->getSwitchState(
   1308             deviceId, uint32_t(sourceMask), sw);
   1309 }
   1310 
   1311 static jboolean nativeHasKeys(JNIEnv* env, jclass /* clazz */,
   1312         jlong ptr, jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
   1313     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1314 
   1315     int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
   1316     uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
   1317     jsize numCodes = env->GetArrayLength(keyCodes);
   1318     jboolean result;
   1319     if (numCodes == env->GetArrayLength(keyCodes)) {
   1320         if (im->getInputManager()->getReader()->hasKeys(
   1321                 deviceId, uint32_t(sourceMask), numCodes, codes, flags)) {
   1322             result = JNI_TRUE;
   1323         } else {
   1324             result = JNI_FALSE;
   1325         }
   1326     } else {
   1327         result = JNI_FALSE;
   1328     }
   1329 
   1330     env->ReleaseBooleanArrayElements(outFlags, flags, 0);
   1331     env->ReleaseIntArrayElements(keyCodes, codes, 0);
   1332     return result;
   1333 }
   1334 
   1335 static void throwInputChannelNotInitialized(JNIEnv* env) {
   1336     jniThrowException(env, "java/lang/IllegalStateException",
   1337              "inputChannel is not initialized");
   1338 }
   1339 
   1340 static void handleInputChannelDisposed(JNIEnv* env,
   1341         jobject /* inputChannelObj */, const sp<InputChannel>& inputChannel, void* data) {
   1342     NativeInputManager* im = static_cast<NativeInputManager*>(data);
   1343 
   1344     ALOGW("Input channel object '%s' was disposed without first being unregistered with "
   1345             "the input manager!", inputChannel->getName().string());
   1346     im->unregisterInputChannel(env, inputChannel);
   1347 }
   1348 
   1349 static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
   1350         jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
   1351     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1352 
   1353     sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
   1354             inputChannelObj);
   1355     if (inputChannel == NULL) {
   1356         throwInputChannelNotInitialized(env);
   1357         return;
   1358     }
   1359 
   1360     sp<InputWindowHandle> inputWindowHandle =
   1361             android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
   1362 
   1363     status_t status = im->registerInputChannel(
   1364             env, inputChannel, inputWindowHandle, monitor);
   1365     if (status) {
   1366         String8 message;
   1367         message.appendFormat("Failed to register input channel.  status=%d", status);
   1368         jniThrowRuntimeException(env, message.string());
   1369         return;
   1370     }
   1371 
   1372     if (! monitor) {
   1373         android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
   1374                 handleInputChannelDisposed, im);
   1375     }
   1376 }
   1377 
   1378 static void nativeUnregisterInputChannel(JNIEnv* env, jclass /* clazz */,
   1379         jlong ptr, jobject inputChannelObj) {
   1380     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1381 
   1382     sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
   1383             inputChannelObj);
   1384     if (inputChannel == NULL) {
   1385         throwInputChannelNotInitialized(env);
   1386         return;
   1387     }
   1388 
   1389     android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
   1390 
   1391     status_t status = im->unregisterInputChannel(env, inputChannel);
   1392     if (status && status != BAD_VALUE) { // ignore already unregistered channel
   1393         String8 message;
   1394         message.appendFormat("Failed to unregister input channel.  status=%d", status);
   1395         jniThrowRuntimeException(env, message.string());
   1396     }
   1397 }
   1398 
   1399 static void nativeSetInputFilterEnabled(JNIEnv* /* env */, jclass /* clazz */,
   1400         jlong ptr, jboolean enabled) {
   1401     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1402 
   1403     im->getInputManager()->getDispatcher()->setInputFilterEnabled(enabled);
   1404 }
   1405 
   1406 static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */,
   1407         jlong ptr, jobject inputEventObj, jint displayId, jint injectorPid, jint injectorUid,
   1408         jint syncMode, jint timeoutMillis, jint policyFlags) {
   1409     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1410 
   1411     if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
   1412         KeyEvent keyEvent;
   1413         status_t status = android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent);
   1414         if (status) {
   1415             jniThrowRuntimeException(env, "Could not read contents of KeyEvent object.");
   1416             return INPUT_EVENT_INJECTION_FAILED;
   1417         }
   1418 
   1419         return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
   1420                 & keyEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,
   1421                 uint32_t(policyFlags));
   1422     } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
   1423         const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj);
   1424         if (!motionEvent) {
   1425             jniThrowRuntimeException(env, "Could not read contents of MotionEvent object.");
   1426             return INPUT_EVENT_INJECTION_FAILED;
   1427         }
   1428 
   1429         return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
   1430                 motionEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,
   1431                 uint32_t(policyFlags));
   1432     } else {
   1433         jniThrowRuntimeException(env, "Invalid input event type.");
   1434         return INPUT_EVENT_INJECTION_FAILED;
   1435     }
   1436 }
   1437 
   1438 static void nativeToggleCapsLock(JNIEnv* env, jclass /* clazz */,
   1439          jlong ptr, jint deviceId) {
   1440     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1441 
   1442     im->getInputManager()->getReader()->toggleCapsLockState(deviceId);
   1443 }
   1444 
   1445 static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */,
   1446         jlong ptr, jobjectArray windowHandleObjArray) {
   1447     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1448 
   1449     im->setInputWindows(env, windowHandleObjArray);
   1450 }
   1451 
   1452 static void nativeSetFocusedApplication(JNIEnv* env, jclass /* clazz */,
   1453         jlong ptr, jobject applicationHandleObj) {
   1454     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1455 
   1456     im->setFocusedApplication(env, applicationHandleObj);
   1457 }
   1458 
   1459 static void nativeSetPointerCapture(JNIEnv* env, jclass /* clazz */, jlong ptr,
   1460         jboolean enabled) {
   1461     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1462 
   1463     im->setPointerCapture(enabled);
   1464 }
   1465 
   1466 static void nativeSetInputDispatchMode(JNIEnv* /* env */,
   1467         jclass /* clazz */, jlong ptr, jboolean enabled, jboolean frozen) {
   1468     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1469 
   1470     im->setInputDispatchMode(enabled, frozen);
   1471 }
   1472 
   1473 static void nativeSetSystemUiVisibility(JNIEnv* /* env */,
   1474         jclass /* clazz */, jlong ptr, jint visibility) {
   1475     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1476 
   1477     im->setSystemUiVisibility(visibility);
   1478 }
   1479 
   1480 static jboolean nativeTransferTouchFocus(JNIEnv* env,
   1481         jclass /* clazz */, jlong ptr, jobject fromChannelObj, jobject toChannelObj) {
   1482     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1483 
   1484     sp<InputChannel> fromChannel =
   1485             android_view_InputChannel_getInputChannel(env, fromChannelObj);
   1486     sp<InputChannel> toChannel =
   1487             android_view_InputChannel_getInputChannel(env, toChannelObj);
   1488 
   1489     if (fromChannel == NULL || toChannel == NULL) {
   1490         return JNI_FALSE;
   1491     }
   1492 
   1493     if (im->getInputManager()->getDispatcher()->
   1494             transferTouchFocus(fromChannel, toChannel)) {
   1495         return JNI_TRUE;
   1496     } else {
   1497         return JNI_FALSE;
   1498     }
   1499 }
   1500 
   1501 static void nativeSetPointerSpeed(JNIEnv* /* env */,
   1502         jclass /* clazz */, jlong ptr, jint speed) {
   1503     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1504 
   1505     im->setPointerSpeed(speed);
   1506 }
   1507 
   1508 static void nativeSetShowTouches(JNIEnv* /* env */,
   1509         jclass /* clazz */, jlong ptr, jboolean enabled) {
   1510     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1511 
   1512     im->setShowTouches(enabled);
   1513 }
   1514 
   1515 static void nativeSetInteractive(JNIEnv* env,
   1516         jclass clazz, jlong ptr, jboolean interactive) {
   1517     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1518 
   1519     im->setInteractive(interactive);
   1520 }
   1521 
   1522 static void nativeReloadCalibration(JNIEnv* env, jclass clazz, jlong ptr) {
   1523     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1524 
   1525     im->reloadCalibration();
   1526 }
   1527 
   1528 static void nativeVibrate(JNIEnv* env,
   1529         jclass /* clazz */, jlong ptr, jint deviceId, jlongArray patternObj,
   1530         jint repeat, jint token) {
   1531     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1532 
   1533     size_t patternSize = env->GetArrayLength(patternObj);
   1534     if (patternSize > MAX_VIBRATE_PATTERN_SIZE) {
   1535         ALOGI("Skipped requested vibration because the pattern size is %zu "
   1536                 "which is more than the maximum supported size of %d.",
   1537                 patternSize, MAX_VIBRATE_PATTERN_SIZE);
   1538         return; // limit to reasonable size
   1539     }
   1540 
   1541     jlong* patternMillis = static_cast<jlong*>(env->GetPrimitiveArrayCritical(
   1542             patternObj, NULL));
   1543     nsecs_t pattern[patternSize];
   1544     for (size_t i = 0; i < patternSize; i++) {
   1545         pattern[i] = max(jlong(0), min(patternMillis[i],
   1546                 (jlong)(MAX_VIBRATE_PATTERN_DELAY_NSECS / 1000000LL))) * 1000000LL;
   1547     }
   1548     env->ReleasePrimitiveArrayCritical(patternObj, patternMillis, JNI_ABORT);
   1549 
   1550     im->getInputManager()->getReader()->vibrate(deviceId, pattern, patternSize, repeat, token);
   1551 }
   1552 
   1553 static void nativeCancelVibrate(JNIEnv* /* env */,
   1554         jclass /* clazz */, jlong ptr, jint deviceId, jint token) {
   1555     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1556 
   1557     im->getInputManager()->getReader()->cancelVibrate(deviceId, token);
   1558 }
   1559 
   1560 static void nativeReloadKeyboardLayouts(JNIEnv* /* env */,
   1561         jclass /* clazz */, jlong ptr) {
   1562     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1563 
   1564     im->getInputManager()->getReader()->requestRefreshConfiguration(
   1565             InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS);
   1566 }
   1567 
   1568 static void nativeReloadDeviceAliases(JNIEnv* /* env */,
   1569         jclass /* clazz */, jlong ptr) {
   1570     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1571 
   1572     im->getInputManager()->getReader()->requestRefreshConfiguration(
   1573             InputReaderConfiguration::CHANGE_DEVICE_ALIAS);
   1574 }
   1575 
   1576 static jstring nativeDump(JNIEnv* env, jclass /* clazz */, jlong ptr) {
   1577     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1578 
   1579     String8 dump;
   1580     im->dump(dump);
   1581     return env->NewStringUTF(dump.string());
   1582 }
   1583 
   1584 static void nativeMonitor(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) {
   1585     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1586 
   1587     im->getInputManager()->getReader()->monitor();
   1588     im->getInputManager()->getDispatcher()->monitor();
   1589 }
   1590 
   1591 static jboolean nativeIsInputDeviceEnabled(JNIEnv* env /* env */,
   1592         jclass /* clazz */, jlong ptr, jint deviceId) {
   1593     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1594 
   1595     return im->getInputManager()->getReader()->isInputDeviceEnabled(deviceId);
   1596 }
   1597 
   1598 static void nativeEnableInputDevice(JNIEnv* /* env */,
   1599         jclass /* clazz */, jlong ptr, jint deviceId) {
   1600     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1601 
   1602     im->setInputDeviceEnabled(deviceId, true);
   1603 }
   1604 
   1605 static void nativeDisableInputDevice(JNIEnv* /* env */,
   1606         jclass /* clazz */, jlong ptr, jint deviceId) {
   1607     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1608 
   1609     im->setInputDeviceEnabled(deviceId, false);
   1610 }
   1611 
   1612 static void nativeSetPointerIconType(JNIEnv* /* env */, jclass /* clazz */, jlong ptr, jint iconId) {
   1613     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1614 
   1615     im->setPointerIconType(iconId);
   1616 }
   1617 
   1618 static void nativeReloadPointerIcons(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) {
   1619     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1620 
   1621     im->reloadPointerIcons();
   1622 }
   1623 
   1624 static void nativeSetCustomPointerIcon(JNIEnv* env, jclass /* clazz */,
   1625                                        jlong ptr, jobject iconObj) {
   1626     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   1627 
   1628     PointerIcon pointerIcon;
   1629     status_t result = android_view_PointerIcon_getLoadedIcon(env, iconObj, &pointerIcon);
   1630     if (result) {
   1631         jniThrowRuntimeException(env, "Failed to load custom pointer icon.");
   1632         return;
   1633     }
   1634 
   1635     SpriteIcon spriteIcon;
   1636     SkImageInfo spriteInfo = pointerIcon.bitmap.info().makeColorType(kN32_SkColorType);
   1637     if (spriteIcon.bitmap.tryAllocPixels(spriteInfo)) {
   1638         pointerIcon.bitmap.readPixels(spriteInfo, spriteIcon.bitmap.getPixels(),
   1639                 spriteIcon.bitmap.rowBytes(), 0, 0);
   1640     }
   1641     spriteIcon.hotSpotX = pointerIcon.hotSpotX;
   1642     spriteIcon.hotSpotY = pointerIcon.hotSpotY;
   1643     im->setCustomPointerIcon(spriteIcon);
   1644 }
   1645 
   1646 // ----------------------------------------------------------------------------
   1647 
   1648 static const JNINativeMethod gInputManagerMethods[] = {
   1649     /* name, signature, funcPtr */
   1650     { "nativeInit",
   1651             "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J",
   1652             (void*) nativeInit },
   1653     { "nativeStart", "(J)V",
   1654             (void*) nativeStart },
   1655     { "nativeSetVirtualDisplayViewports", "(J[Landroid/hardware/display/DisplayViewport;)V",
   1656             (void*) nativeSetVirtualDisplayViewports },
   1657     { "nativeSetDisplayViewport", "(JIIIIIIIIIIIIILjava/lang/String;)V",
   1658             (void*) nativeSetDisplayViewport },
   1659     { "nativeGetScanCodeState", "(JIII)I",
   1660             (void*) nativeGetScanCodeState },
   1661     { "nativeGetKeyCodeState", "(JIII)I",
   1662             (void*) nativeGetKeyCodeState },
   1663     { "nativeGetSwitchState", "(JIII)I",
   1664             (void*) nativeGetSwitchState },
   1665     { "nativeHasKeys", "(JII[I[Z)Z",
   1666             (void*) nativeHasKeys },
   1667     { "nativeRegisterInputChannel",
   1668             "(JLandroid/view/InputChannel;Lcom/android/server/input/InputWindowHandle;Z)V",
   1669             (void*) nativeRegisterInputChannel },
   1670     { "nativeUnregisterInputChannel", "(JLandroid/view/InputChannel;)V",
   1671             (void*) nativeUnregisterInputChannel },
   1672     { "nativeSetInputFilterEnabled", "(JZ)V",
   1673             (void*) nativeSetInputFilterEnabled },
   1674     { "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I",
   1675             (void*) nativeInjectInputEvent },
   1676     { "nativeToggleCapsLock", "(JI)V",
   1677             (void*) nativeToggleCapsLock },
   1678     { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V",
   1679             (void*) nativeSetInputWindows },
   1680     { "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V",
   1681             (void*) nativeSetFocusedApplication },
   1682     { "nativeSetPointerCapture", "(JZ)V",
   1683             (void*) nativeSetPointerCapture },
   1684     { "nativeSetInputDispatchMode", "(JZZ)V",
   1685             (void*) nativeSetInputDispatchMode },
   1686     { "nativeSetSystemUiVisibility", "(JI)V",
   1687             (void*) nativeSetSystemUiVisibility },
   1688     { "nativeTransferTouchFocus", "(JLandroid/view/InputChannel;Landroid/view/InputChannel;)Z",
   1689             (void*) nativeTransferTouchFocus },
   1690     { "nativeSetPointerSpeed", "(JI)V",
   1691             (void*) nativeSetPointerSpeed },
   1692     { "nativeSetShowTouches", "(JZ)V",
   1693             (void*) nativeSetShowTouches },
   1694     { "nativeSetInteractive", "(JZ)V",
   1695             (void*) nativeSetInteractive },
   1696     { "nativeReloadCalibration", "(J)V",
   1697             (void*) nativeReloadCalibration },
   1698     { "nativeVibrate", "(JI[JII)V",
   1699             (void*) nativeVibrate },
   1700     { "nativeCancelVibrate", "(JII)V",
   1701             (void*) nativeCancelVibrate },
   1702     { "nativeReloadKeyboardLayouts", "(J)V",
   1703             (void*) nativeReloadKeyboardLayouts },
   1704     { "nativeReloadDeviceAliases", "(J)V",
   1705             (void*) nativeReloadDeviceAliases },
   1706     { "nativeDump", "(J)Ljava/lang/String;",
   1707             (void*) nativeDump },
   1708     { "nativeMonitor", "(J)V",
   1709             (void*) nativeMonitor },
   1710     { "nativeIsInputDeviceEnabled", "(JI)Z",
   1711             (void*) nativeIsInputDeviceEnabled },
   1712     { "nativeEnableInputDevice", "(JI)V",
   1713             (void*) nativeEnableInputDevice },
   1714     { "nativeDisableInputDevice", "(JI)V",
   1715             (void*) nativeDisableInputDevice },
   1716     { "nativeSetPointerIconType", "(JI)V",
   1717             (void*) nativeSetPointerIconType },
   1718     { "nativeReloadPointerIcons", "(J)V",
   1719             (void*) nativeReloadPointerIcons },
   1720     { "nativeSetCustomPointerIcon", "(JLandroid/view/PointerIcon;)V",
   1721             (void*) nativeSetCustomPointerIcon },
   1722 };
   1723 
   1724 #define FIND_CLASS(var, className) \
   1725         var = env->FindClass(className); \
   1726         LOG_FATAL_IF(! (var), "Unable to find class " className);
   1727 
   1728 #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
   1729         var = env->GetMethodID(clazz, methodName, methodDescriptor); \
   1730         LOG_FATAL_IF(! (var), "Unable to find method " methodName);
   1731 
   1732 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
   1733         var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
   1734         LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
   1735 
   1736 int register_android_server_InputManager(JNIEnv* env) {
   1737     int res = jniRegisterNativeMethods(env, "com/android/server/input/InputManagerService",
   1738             gInputManagerMethods, NELEM(gInputManagerMethods));
   1739     (void) res;  // Faked use when LOG_NDEBUG.
   1740     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
   1741 
   1742     // Callbacks
   1743 
   1744     jclass clazz;
   1745     FIND_CLASS(clazz, "com/android/server/input/InputManagerService");
   1746 
   1747     GET_METHOD_ID(gServiceClassInfo.notifyConfigurationChanged, clazz,
   1748             "notifyConfigurationChanged", "(J)V");
   1749 
   1750     GET_METHOD_ID(gServiceClassInfo.notifyInputDevicesChanged, clazz,
   1751             "notifyInputDevicesChanged", "([Landroid/view/InputDevice;)V");
   1752 
   1753     GET_METHOD_ID(gServiceClassInfo.notifySwitch, clazz,
   1754             "notifySwitch", "(JII)V");
   1755 
   1756     GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz,
   1757             "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V");
   1758 
   1759     GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
   1760             "notifyANR",
   1761             "(Lcom/android/server/input/InputApplicationHandle;Lcom/android/server/input/InputWindowHandle;Ljava/lang/String;)J");
   1762 
   1763     GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
   1764             "filterInputEvent", "(Landroid/view/InputEvent;I)Z");
   1765 
   1766     GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
   1767             "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I");
   1768 
   1769     GET_METHOD_ID(gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive, clazz,
   1770             "interceptMotionBeforeQueueingNonInteractive", "(JI)I");
   1771 
   1772     GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
   1773             "interceptKeyBeforeDispatching",
   1774             "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)J");
   1775 
   1776     GET_METHOD_ID(gServiceClassInfo.dispatchUnhandledKey, clazz,
   1777             "dispatchUnhandledKey",
   1778             "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
   1779 
   1780     GET_METHOD_ID(gServiceClassInfo.checkInjectEventsPermission, clazz,
   1781             "checkInjectEventsPermission", "(II)Z");
   1782 
   1783     GET_METHOD_ID(gServiceClassInfo.getVirtualKeyQuietTimeMillis, clazz,
   1784             "getVirtualKeyQuietTimeMillis", "()I");
   1785 
   1786     GET_METHOD_ID(gServiceClassInfo.getExcludedDeviceNames, clazz,
   1787             "getExcludedDeviceNames", "()[Ljava/lang/String;");
   1788 
   1789     GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz,
   1790             "getKeyRepeatTimeout", "()I");
   1791 
   1792     GET_METHOD_ID(gServiceClassInfo.getKeyRepeatDelay, clazz,
   1793             "getKeyRepeatDelay", "()I");
   1794 
   1795     GET_METHOD_ID(gServiceClassInfo.getHoverTapTimeout, clazz,
   1796             "getHoverTapTimeout", "()I");
   1797 
   1798     GET_METHOD_ID(gServiceClassInfo.getHoverTapSlop, clazz,
   1799             "getHoverTapSlop", "()I");
   1800 
   1801     GET_METHOD_ID(gServiceClassInfo.getDoubleTapTimeout, clazz,
   1802             "getDoubleTapTimeout", "()I");
   1803 
   1804     GET_METHOD_ID(gServiceClassInfo.getLongPressTimeout, clazz,
   1805             "getLongPressTimeout", "()I");
   1806 
   1807     GET_METHOD_ID(gServiceClassInfo.getPointerLayer, clazz,
   1808             "getPointerLayer", "()I");
   1809 
   1810     GET_METHOD_ID(gServiceClassInfo.getPointerIcon, clazz,
   1811             "getPointerIcon", "()Landroid/view/PointerIcon;");
   1812 
   1813     GET_METHOD_ID(gServiceClassInfo.getKeyboardLayoutOverlay, clazz,
   1814             "getKeyboardLayoutOverlay",
   1815             "(Landroid/hardware/input/InputDeviceIdentifier;)[Ljava/lang/String;");
   1816 
   1817     GET_METHOD_ID(gServiceClassInfo.getDeviceAlias, clazz,
   1818             "getDeviceAlias", "(Ljava/lang/String;)Ljava/lang/String;");
   1819 
   1820     GET_METHOD_ID(gServiceClassInfo.getTouchCalibrationForInputDevice, clazz,
   1821             "getTouchCalibrationForInputDevice",
   1822             "(Ljava/lang/String;I)Landroid/hardware/input/TouchCalibration;");
   1823 
   1824     // InputDevice
   1825 
   1826     FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");
   1827     gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz));
   1828 
   1829     // KeyEvent
   1830 
   1831     FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
   1832     gKeyEventClassInfo.clazz = jclass(env->NewGlobalRef(gKeyEventClassInfo.clazz));
   1833 
   1834     // MotionEvent
   1835 
   1836     FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
   1837     gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz));
   1838 
   1839     // InputDeviceIdentifier
   1840 
   1841     FIND_CLASS(gInputDeviceIdentifierInfo.clazz, "android/hardware/input/InputDeviceIdentifier");
   1842     gInputDeviceIdentifierInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceIdentifierInfo.clazz));
   1843     GET_METHOD_ID(gInputDeviceIdentifierInfo.constructor, gInputDeviceIdentifierInfo.clazz,
   1844             "<init>", "(Ljava/lang/String;II)V");
   1845 
   1846     // TouchCalibration
   1847 
   1848     FIND_CLASS(gTouchCalibrationClassInfo.clazz, "android/hardware/input/TouchCalibration");
   1849     gTouchCalibrationClassInfo.clazz = jclass(env->NewGlobalRef(gTouchCalibrationClassInfo.clazz));
   1850 
   1851     GET_METHOD_ID(gTouchCalibrationClassInfo.getAffineTransform, gTouchCalibrationClassInfo.clazz,
   1852             "getAffineTransform", "()[F");
   1853 
   1854     return 0;
   1855 }
   1856 
   1857 } /* namespace android */
   1858