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