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