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