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