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