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