com_android_server_input_InputManagerService.cpp revision 4a9c3891d4f890109e02bc83fecf9bcdf56a9395
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 interceptWakeMotionBeforeQueueing;
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        policyFlags |= POLICY_FLAG_PASS_TO_USER;
858    }
859}
860
861void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
862    // Policy:
863    // - Ignore untrusted events and pass them along.
864    // - No special filtering for injected events required at this time.
865    // - Filter normal events based on screen state.
866    // - For normal events brighten (but do not wake) the screen if currently dim.
867    if (mInteractive) {
868        policyFlags |= POLICY_FLAG_INTERACTIVE;
869    }
870    if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {
871        if (policyFlags & POLICY_FLAG_INTERACTIVE) {
872            policyFlags |= POLICY_FLAG_PASS_TO_USER;
873        } else if (policyFlags & POLICY_FLAG_WAKE) {
874            JNIEnv* env = jniEnv();
875            jint wmActions = env->CallIntMethod(mServiceObj,
876                        gServiceClassInfo.interceptWakeMotionBeforeQueueing,
877                        when, policyFlags);
878            if (checkAndClearExceptionFromCallback(env,
879                    "interceptWakeMotionBeforeQueueing")) {
880                wmActions = 0;
881            }
882
883            handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
884        }
885    } else {
886        policyFlags |= POLICY_FLAG_PASS_TO_USER;
887    }
888}
889
890void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
891        uint32_t& policyFlags) {
892    if (wmActions & WM_ACTION_PASS_TO_USER) {
893        policyFlags |= POLICY_FLAG_PASS_TO_USER;
894    } else {
895#if DEBUG_INPUT_DISPATCHER_POLICY
896        ALOGD("handleInterceptActions: Not passing key to user.");
897#endif
898    }
899}
900
901nsecs_t NativeInputManager::interceptKeyBeforeDispatching(
902        const sp<InputWindowHandle>& inputWindowHandle,
903        const KeyEvent* keyEvent, uint32_t policyFlags) {
904    // Policy:
905    // - Ignore untrusted events and pass them along.
906    // - Filter normal events and trusted injected events through the window manager policy to
907    //   handle the HOME key and the like.
908    nsecs_t result = 0;
909    if (policyFlags & POLICY_FLAG_TRUSTED) {
910        JNIEnv* env = jniEnv();
911
912        // Note: inputWindowHandle may be null.
913        jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
914        jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
915        if (keyEventObj) {
916            jlong delayMillis = env->CallLongMethod(mServiceObj,
917                    gServiceClassInfo.interceptKeyBeforeDispatching,
918                    inputWindowHandleObj, keyEventObj, policyFlags);
919            bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
920            android_view_KeyEvent_recycle(env, keyEventObj);
921            env->DeleteLocalRef(keyEventObj);
922            if (!error) {
923                if (delayMillis < 0) {
924                    result = -1;
925                } else if (delayMillis > 0) {
926                    result = milliseconds_to_nanoseconds(delayMillis);
927                }
928            }
929        } else {
930            ALOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
931        }
932        env->DeleteLocalRef(inputWindowHandleObj);
933    }
934    return result;
935}
936
937bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
938        const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
939    // Policy:
940    // - Ignore untrusted events and do not perform default handling.
941    bool result = false;
942    if (policyFlags & POLICY_FLAG_TRUSTED) {
943        JNIEnv* env = jniEnv();
944
945        // Note: inputWindowHandle may be null.
946        jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
947        jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
948        if (keyEventObj) {
949            jobject fallbackKeyEventObj = env->CallObjectMethod(mServiceObj,
950                    gServiceClassInfo.dispatchUnhandledKey,
951                    inputWindowHandleObj, keyEventObj, policyFlags);
952            if (checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey")) {
953                fallbackKeyEventObj = NULL;
954            }
955            android_view_KeyEvent_recycle(env, keyEventObj);
956            env->DeleteLocalRef(keyEventObj);
957
958            if (fallbackKeyEventObj) {
959                // Note: outFallbackKeyEvent may be the same object as keyEvent.
960                if (!android_view_KeyEvent_toNative(env, fallbackKeyEventObj,
961                        outFallbackKeyEvent)) {
962                    result = true;
963                }
964                android_view_KeyEvent_recycle(env, fallbackKeyEventObj);
965                env->DeleteLocalRef(fallbackKeyEventObj);
966            }
967        } else {
968            ALOGE("Failed to obtain key event object for dispatchUnhandledKey.");
969        }
970        env->DeleteLocalRef(inputWindowHandleObj);
971    }
972    return result;
973}
974
975void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
976    android_server_PowerManagerService_userActivity(eventTime, eventType);
977}
978
979
980bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
981        int32_t injectorPid, int32_t injectorUid) {
982    JNIEnv* env = jniEnv();
983    jboolean result = env->CallBooleanMethod(mServiceObj,
984            gServiceClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
985    if (checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission")) {
986        result = false;
987    }
988    return result;
989}
990
991void NativeInputManager::loadPointerResources(PointerResources* outResources) {
992    JNIEnv* env = jniEnv();
993
994    loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_HOVER,
995            &outResources->spotHover);
996    loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_TOUCH,
997            &outResources->spotTouch);
998    loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_ANCHOR,
999            &outResources->spotAnchor);
1000}
1001
1002
1003// ----------------------------------------------------------------------------
1004
1005static jlong nativeInit(JNIEnv* env, jclass clazz,
1006        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
1007    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
1008    if (messageQueue == NULL) {
1009        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
1010        return 0;
1011    }
1012
1013    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
1014            messageQueue->getLooper());
1015    im->incStrong(0);
1016    return reinterpret_cast<jlong>(im);
1017}
1018
1019static void nativeStart(JNIEnv* env, jclass clazz, jlong ptr) {
1020    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1021
1022    status_t result = im->getInputManager()->start();
1023    if (result) {
1024        jniThrowRuntimeException(env, "Input manager could not be started.");
1025    }
1026}
1027
1028static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jlong ptr, jboolean external,
1029        jint displayId, jint orientation,
1030        jint logicalLeft, jint logicalTop, jint logicalRight, jint logicalBottom,
1031        jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom,
1032        jint deviceWidth, jint deviceHeight) {
1033    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1034
1035    DisplayViewport v;
1036    v.displayId = displayId;
1037    v.orientation = orientation;
1038    v.logicalLeft = logicalLeft;
1039    v.logicalTop = logicalTop;
1040    v.logicalRight = logicalRight;
1041    v.logicalBottom = logicalBottom;
1042    v.physicalLeft = physicalLeft;
1043    v.physicalTop = physicalTop;
1044    v.physicalRight = physicalRight;
1045    v.physicalBottom = physicalBottom;
1046    v.deviceWidth = deviceWidth;
1047    v.deviceHeight = deviceHeight;
1048    im->setDisplayViewport(external, v);
1049}
1050
1051static jint nativeGetScanCodeState(JNIEnv* env, jclass clazz,
1052        jlong ptr, jint deviceId, jint sourceMask, jint scanCode) {
1053    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1054
1055    return (jint) im->getInputManager()->getReader()->getScanCodeState(
1056            deviceId, uint32_t(sourceMask), scanCode);
1057}
1058
1059static jint nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
1060        jlong ptr, jint deviceId, jint sourceMask, jint keyCode) {
1061    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1062
1063    return (jint) im->getInputManager()->getReader()->getKeyCodeState(
1064            deviceId, uint32_t(sourceMask), keyCode);
1065}
1066
1067static jint nativeGetSwitchState(JNIEnv* env, jclass clazz,
1068        jlong ptr, jint deviceId, jint sourceMask, jint sw) {
1069    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1070
1071    return (jint) im->getInputManager()->getReader()->getSwitchState(
1072            deviceId, uint32_t(sourceMask), sw);
1073}
1074
1075static jboolean nativeHasKeys(JNIEnv* env, jclass clazz,
1076        jlong ptr, jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
1077    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1078
1079    int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
1080    uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
1081    jsize numCodes = env->GetArrayLength(keyCodes);
1082    jboolean result;
1083    if (numCodes == env->GetArrayLength(keyCodes)) {
1084        if (im->getInputManager()->getReader()->hasKeys(
1085                deviceId, uint32_t(sourceMask), numCodes, codes, flags)) {
1086            result = JNI_TRUE;
1087        } else {
1088            result = JNI_FALSE;
1089        }
1090    } else {
1091        result = JNI_FALSE;
1092    }
1093
1094    env->ReleaseBooleanArrayElements(outFlags, flags, 0);
1095    env->ReleaseIntArrayElements(keyCodes, codes, 0);
1096    return result;
1097}
1098
1099static void throwInputChannelNotInitialized(JNIEnv* env) {
1100    jniThrowException(env, "java/lang/IllegalStateException",
1101             "inputChannel is not initialized");
1102}
1103
1104static void handleInputChannelDisposed(JNIEnv* env,
1105        jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
1106    NativeInputManager* im = static_cast<NativeInputManager*>(data);
1107
1108    ALOGW("Input channel object '%s' was disposed without first being unregistered with "
1109            "the input manager!", inputChannel->getName().string());
1110    im->unregisterInputChannel(env, inputChannel);
1111}
1112
1113static void nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
1114        jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
1115    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1116
1117    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1118            inputChannelObj);
1119    if (inputChannel == NULL) {
1120        throwInputChannelNotInitialized(env);
1121        return;
1122    }
1123
1124    sp<InputWindowHandle> inputWindowHandle =
1125            android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
1126
1127    status_t status = im->registerInputChannel(
1128            env, inputChannel, inputWindowHandle, monitor);
1129    if (status) {
1130        String8 message;
1131        message.appendFormat("Failed to register input channel.  status=%d", status);
1132        jniThrowRuntimeException(env, message.string());
1133        return;
1134    }
1135
1136    if (! monitor) {
1137        android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
1138                handleInputChannelDisposed, im);
1139    }
1140}
1141
1142static void nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
1143        jlong ptr, jobject inputChannelObj) {
1144    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1145
1146    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1147            inputChannelObj);
1148    if (inputChannel == NULL) {
1149        throwInputChannelNotInitialized(env);
1150        return;
1151    }
1152
1153    android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
1154
1155    status_t status = im->unregisterInputChannel(env, inputChannel);
1156    if (status && status != BAD_VALUE) { // ignore already unregistered channel
1157        String8 message;
1158        message.appendFormat("Failed to unregister input channel.  status=%d", status);
1159        jniThrowRuntimeException(env, message.string());
1160    }
1161}
1162
1163static void nativeSetInputFilterEnabled(JNIEnv* env, jclass clazz,
1164        jlong ptr, jboolean enabled) {
1165    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1166
1167    im->getInputManager()->getDispatcher()->setInputFilterEnabled(enabled);
1168}
1169
1170static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz,
1171        jlong ptr, jobject inputEventObj, jint displayId, jint injectorPid, jint injectorUid,
1172        jint syncMode, jint timeoutMillis, jint policyFlags) {
1173    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1174
1175    if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
1176        KeyEvent keyEvent;
1177        status_t status = android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent);
1178        if (status) {
1179            jniThrowRuntimeException(env, "Could not read contents of KeyEvent object.");
1180            return INPUT_EVENT_INJECTION_FAILED;
1181        }
1182
1183        return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
1184                & keyEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,
1185                uint32_t(policyFlags));
1186    } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
1187        const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj);
1188        if (!motionEvent) {
1189            jniThrowRuntimeException(env, "Could not read contents of MotionEvent object.");
1190            return INPUT_EVENT_INJECTION_FAILED;
1191        }
1192
1193        return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
1194                motionEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,
1195                uint32_t(policyFlags));
1196    } else {
1197        jniThrowRuntimeException(env, "Invalid input event type.");
1198        return INPUT_EVENT_INJECTION_FAILED;
1199    }
1200}
1201
1202static void nativeSetInputWindows(JNIEnv* env, jclass clazz,
1203        jlong ptr, jobjectArray windowHandleObjArray) {
1204    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1205
1206    im->setInputWindows(env, windowHandleObjArray);
1207}
1208
1209static void nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
1210        jlong ptr, jobject applicationHandleObj) {
1211    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1212
1213    im->setFocusedApplication(env, applicationHandleObj);
1214}
1215
1216static void nativeSetInputDispatchMode(JNIEnv* env,
1217        jclass clazz, jlong ptr, jboolean enabled, jboolean frozen) {
1218    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1219
1220    im->setInputDispatchMode(enabled, frozen);
1221}
1222
1223static void nativeSetSystemUiVisibility(JNIEnv* env,
1224        jclass clazz, jlong ptr, jint visibility) {
1225    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1226
1227    im->setSystemUiVisibility(visibility);
1228}
1229
1230static jboolean nativeTransferTouchFocus(JNIEnv* env,
1231        jclass clazz, jlong ptr, jobject fromChannelObj, jobject toChannelObj) {
1232    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1233
1234    sp<InputChannel> fromChannel =
1235            android_view_InputChannel_getInputChannel(env, fromChannelObj);
1236    sp<InputChannel> toChannel =
1237            android_view_InputChannel_getInputChannel(env, toChannelObj);
1238
1239    if (fromChannel == NULL || toChannel == NULL) {
1240        return JNI_FALSE;
1241    }
1242
1243    if (im->getInputManager()->getDispatcher()->
1244            transferTouchFocus(fromChannel, toChannel)) {
1245        return JNI_TRUE;
1246    } else {
1247        return JNI_FALSE;
1248    }
1249}
1250
1251static void nativeSetPointerSpeed(JNIEnv* env,
1252        jclass clazz, jlong ptr, jint speed) {
1253    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1254
1255    im->setPointerSpeed(speed);
1256}
1257
1258static void nativeSetShowTouches(JNIEnv* env,
1259        jclass clazz, jlong ptr, jboolean enabled) {
1260    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1261
1262    im->setShowTouches(enabled);
1263}
1264
1265static void nativeSetInteractive(JNIEnv* env,
1266        jclass clazz, jlong ptr, jboolean interactive) {
1267    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1268
1269    im->setInteractive(interactive);
1270}
1271
1272static void nativeReloadCalibration(JNIEnv* env, jclass clazz, jlong ptr) {
1273    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1274    im->reloadCalibration();
1275}
1276
1277static void nativeVibrate(JNIEnv* env,
1278        jclass clazz, jlong ptr, jint deviceId, jlongArray patternObj,
1279        jint repeat, jint token) {
1280    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1281
1282    size_t patternSize = env->GetArrayLength(patternObj);
1283    if (patternSize > MAX_VIBRATE_PATTERN_SIZE) {
1284        ALOGI("Skipped requested vibration because the pattern size is %zu "
1285                "which is more than the maximum supported size of %d.",
1286                patternSize, MAX_VIBRATE_PATTERN_SIZE);
1287        return; // limit to reasonable size
1288    }
1289
1290    jlong* patternMillis = static_cast<jlong*>(env->GetPrimitiveArrayCritical(
1291            patternObj, NULL));
1292    nsecs_t pattern[patternSize];
1293    for (size_t i = 0; i < patternSize; i++) {
1294        pattern[i] = max(jlong(0), min(patternMillis[i],
1295                (jlong)(MAX_VIBRATE_PATTERN_DELAY_NSECS / 1000000LL))) * 1000000LL;
1296    }
1297    env->ReleasePrimitiveArrayCritical(patternObj, patternMillis, JNI_ABORT);
1298
1299    im->getInputManager()->getReader()->vibrate(deviceId, pattern, patternSize, repeat, token);
1300}
1301
1302static void nativeCancelVibrate(JNIEnv* env,
1303        jclass clazz, jlong ptr, jint deviceId, jint token) {
1304    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1305
1306    im->getInputManager()->getReader()->cancelVibrate(deviceId, token);
1307}
1308
1309static void nativeReloadKeyboardLayouts(JNIEnv* env,
1310        jclass clazz, jlong ptr) {
1311    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1312
1313    im->getInputManager()->getReader()->requestRefreshConfiguration(
1314            InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS);
1315}
1316
1317static void nativeReloadDeviceAliases(JNIEnv* env,
1318        jclass clazz, jlong ptr) {
1319    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1320
1321    im->getInputManager()->getReader()->requestRefreshConfiguration(
1322            InputReaderConfiguration::CHANGE_DEVICE_ALIAS);
1323}
1324
1325static jstring nativeDump(JNIEnv* env, jclass clazz, jlong ptr) {
1326    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1327
1328    String8 dump;
1329    im->dump(dump);
1330    return env->NewStringUTF(dump.string());
1331}
1332
1333static void nativeMonitor(JNIEnv* env, jclass clazz, jlong ptr) {
1334    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1335
1336    im->getInputManager()->getReader()->monitor();
1337    im->getInputManager()->getDispatcher()->monitor();
1338}
1339
1340// ----------------------------------------------------------------------------
1341
1342static JNINativeMethod gInputManagerMethods[] = {
1343    /* name, signature, funcPtr */
1344    { "nativeInit",
1345            "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J",
1346            (void*) nativeInit },
1347    { "nativeStart", "(J)V",
1348            (void*) nativeStart },
1349    { "nativeSetDisplayViewport", "(JZIIIIIIIIIIII)V",
1350            (void*) nativeSetDisplayViewport },
1351    { "nativeGetScanCodeState", "(JIII)I",
1352            (void*) nativeGetScanCodeState },
1353    { "nativeGetKeyCodeState", "(JIII)I",
1354            (void*) nativeGetKeyCodeState },
1355    { "nativeGetSwitchState", "(JIII)I",
1356            (void*) nativeGetSwitchState },
1357    { "nativeHasKeys", "(JII[I[Z)Z",
1358            (void*) nativeHasKeys },
1359    { "nativeRegisterInputChannel",
1360            "(JLandroid/view/InputChannel;Lcom/android/server/input/InputWindowHandle;Z)V",
1361            (void*) nativeRegisterInputChannel },
1362    { "nativeUnregisterInputChannel", "(JLandroid/view/InputChannel;)V",
1363            (void*) nativeUnregisterInputChannel },
1364    { "nativeSetInputFilterEnabled", "(JZ)V",
1365            (void*) nativeSetInputFilterEnabled },
1366    { "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I",
1367            (void*) nativeInjectInputEvent },
1368    { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V",
1369            (void*) nativeSetInputWindows },
1370    { "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V",
1371            (void*) nativeSetFocusedApplication },
1372    { "nativeSetInputDispatchMode", "(JZZ)V",
1373            (void*) nativeSetInputDispatchMode },
1374    { "nativeSetSystemUiVisibility", "(JI)V",
1375            (void*) nativeSetSystemUiVisibility },
1376    { "nativeTransferTouchFocus", "(JLandroid/view/InputChannel;Landroid/view/InputChannel;)Z",
1377            (void*) nativeTransferTouchFocus },
1378    { "nativeSetPointerSpeed", "(JI)V",
1379            (void*) nativeSetPointerSpeed },
1380    { "nativeSetShowTouches", "(JZ)V",
1381            (void*) nativeSetShowTouches },
1382    { "nativeSetInteractive", "(JZ)V",
1383            (void*) nativeSetInteractive },
1384    { "nativeReloadCalibration", "(J)V",
1385            (void*) nativeReloadCalibration },
1386    { "nativeVibrate", "(JI[JII)V",
1387            (void*) nativeVibrate },
1388    { "nativeCancelVibrate", "(JII)V",
1389            (void*) nativeCancelVibrate },
1390    { "nativeReloadKeyboardLayouts", "(J)V",
1391            (void*) nativeReloadKeyboardLayouts },
1392    { "nativeReloadDeviceAliases", "(J)V",
1393            (void*) nativeReloadDeviceAliases },
1394    { "nativeDump", "(J)Ljava/lang/String;",
1395            (void*) nativeDump },
1396    { "nativeMonitor", "(J)V",
1397            (void*) nativeMonitor },
1398};
1399
1400#define FIND_CLASS(var, className) \
1401        var = env->FindClass(className); \
1402        LOG_FATAL_IF(! var, "Unable to find class " className);
1403
1404#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
1405        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
1406        LOG_FATAL_IF(! var, "Unable to find method " methodName);
1407
1408#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
1409        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
1410        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
1411
1412int register_android_server_InputManager(JNIEnv* env) {
1413    int res = jniRegisterNativeMethods(env, "com/android/server/input/InputManagerService",
1414            gInputManagerMethods, NELEM(gInputManagerMethods));
1415    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
1416
1417    // Callbacks
1418
1419    jclass clazz;
1420    FIND_CLASS(clazz, "com/android/server/input/InputManagerService");
1421
1422    GET_METHOD_ID(gServiceClassInfo.notifyConfigurationChanged, clazz,
1423            "notifyConfigurationChanged", "(J)V");
1424
1425    GET_METHOD_ID(gServiceClassInfo.notifyInputDevicesChanged, clazz,
1426            "notifyInputDevicesChanged", "([Landroid/view/InputDevice;)V");
1427
1428    GET_METHOD_ID(gServiceClassInfo.notifySwitch, clazz,
1429            "notifySwitch", "(JII)V");
1430
1431    GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz,
1432            "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V");
1433
1434    GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
1435            "notifyANR",
1436            "(Lcom/android/server/input/InputApplicationHandle;Lcom/android/server/input/InputWindowHandle;Ljava/lang/String;)J");
1437
1438    GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
1439            "filterInputEvent", "(Landroid/view/InputEvent;I)Z");
1440
1441    GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
1442            "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I");
1443
1444    GET_METHOD_ID(gServiceClassInfo.interceptWakeMotionBeforeQueueing, clazz,
1445            "interceptWakeMotionBeforeQueueing", "(JI)I");
1446
1447    GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
1448            "interceptKeyBeforeDispatching",
1449            "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)J");
1450
1451    GET_METHOD_ID(gServiceClassInfo.dispatchUnhandledKey, clazz,
1452            "dispatchUnhandledKey",
1453            "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
1454
1455    GET_METHOD_ID(gServiceClassInfo.checkInjectEventsPermission, clazz,
1456            "checkInjectEventsPermission", "(II)Z");
1457
1458    GET_METHOD_ID(gServiceClassInfo.getVirtualKeyQuietTimeMillis, clazz,
1459            "getVirtualKeyQuietTimeMillis", "()I");
1460
1461    GET_METHOD_ID(gServiceClassInfo.getExcludedDeviceNames, clazz,
1462            "getExcludedDeviceNames", "()[Ljava/lang/String;");
1463
1464    GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz,
1465            "getKeyRepeatTimeout", "()I");
1466
1467    GET_METHOD_ID(gServiceClassInfo.getKeyRepeatDelay, clazz,
1468            "getKeyRepeatDelay", "()I");
1469
1470    GET_METHOD_ID(gServiceClassInfo.getHoverTapTimeout, clazz,
1471            "getHoverTapTimeout", "()I");
1472
1473    GET_METHOD_ID(gServiceClassInfo.getHoverTapSlop, clazz,
1474            "getHoverTapSlop", "()I");
1475
1476    GET_METHOD_ID(gServiceClassInfo.getDoubleTapTimeout, clazz,
1477            "getDoubleTapTimeout", "()I");
1478
1479    GET_METHOD_ID(gServiceClassInfo.getLongPressTimeout, clazz,
1480            "getLongPressTimeout", "()I");
1481
1482    GET_METHOD_ID(gServiceClassInfo.getPointerLayer, clazz,
1483            "getPointerLayer", "()I");
1484
1485    GET_METHOD_ID(gServiceClassInfo.getPointerIcon, clazz,
1486            "getPointerIcon", "()Landroid/view/PointerIcon;");
1487
1488    GET_METHOD_ID(gServiceClassInfo.getKeyboardLayoutOverlay, clazz,
1489            "getKeyboardLayoutOverlay",
1490            "(Landroid/hardware/input/InputDeviceIdentifier;)[Ljava/lang/String;");
1491
1492    GET_METHOD_ID(gServiceClassInfo.getDeviceAlias, clazz,
1493            "getDeviceAlias", "(Ljava/lang/String;)Ljava/lang/String;");
1494
1495    GET_METHOD_ID(gServiceClassInfo.getTouchCalibrationForInputDevice, clazz,
1496            "getTouchCalibrationForInputDevice",
1497            "(Ljava/lang/String;I)Landroid/hardware/input/TouchCalibration;");
1498
1499    // InputDevice
1500
1501    FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");
1502    gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz));
1503
1504    // KeyEvent
1505
1506    FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
1507    gKeyEventClassInfo.clazz = jclass(env->NewGlobalRef(gKeyEventClassInfo.clazz));
1508
1509    // MotionEvent
1510
1511    FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
1512    gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz));
1513
1514    // InputDeviceIdentifier
1515
1516    FIND_CLASS(gInputDeviceIdentifierInfo.clazz, "android/hardware/input/InputDeviceIdentifier");
1517    gInputDeviceIdentifierInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceIdentifierInfo.clazz));
1518    GET_METHOD_ID(gInputDeviceIdentifierInfo.constructor, gInputDeviceIdentifierInfo.clazz,
1519            "<init>", "(Ljava/lang/String;II)V");
1520
1521    // TouchCalibration
1522
1523    FIND_CLASS(gTouchCalibrationClassInfo.clazz, "android/hardware/input/TouchCalibration");
1524    gTouchCalibrationClassInfo.clazz = jclass(env->NewGlobalRef(gTouchCalibrationClassInfo.clazz));
1525
1526    GET_METHOD_ID(gTouchCalibrationClassInfo.getAffineTransform, gTouchCalibrationClassInfo.clazz,
1527            "getAffineTransform", "()[F");
1528
1529    return 0;
1530}
1531
1532} /* namespace android */
1533