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