com_android_server_input_InputManagerService.cpp revision 857aa7be880c53d78f72a9f227cbdf72ee68d587
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, SkBitmap::kARGB_8888_Config);
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    TouchAffineTransformation getTouchAffineTransformation(JNIEnv *env, jfloatArray matrixArr);
202    TouchAffineTransformation getTouchAffineTransformation(const String8& inputDeviceDescriptor);
203
204    /* --- InputDispatcherPolicyInterface implementation --- */
205
206    virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
207            uint32_t policyFlags);
208    virtual void notifyConfigurationChanged(nsecs_t when);
209    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
210            const sp<InputWindowHandle>& inputWindowHandle,
211            const String8& reason);
212    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
213    virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags);
214    virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig);
215    virtual bool isKeyRepeatEnabled();
216    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
217    virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
218    virtual nsecs_t interceptKeyBeforeDispatching(
219            const sp<InputWindowHandle>& inputWindowHandle,
220            const KeyEvent* keyEvent, uint32_t policyFlags);
221    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
222            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
223    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
224    virtual bool checkInjectEventsPermissionNonReentrant(
225            int32_t injectorPid, int32_t injectorUid);
226
227    /* --- PointerControllerPolicyInterface implementation --- */
228
229    virtual void loadPointerResources(PointerResources* outResources);
230
231private:
232    sp<InputManager> mInputManager;
233
234    jobject mContextObj;
235    jobject mServiceObj;
236    sp<Looper> mLooper;
237
238    Mutex mLock;
239    struct Locked {
240        // Display size information.
241        DisplayViewport internalViewport;
242        DisplayViewport externalViewport;
243
244        // System UI visibility.
245        int32_t systemUiVisibility;
246
247        // Pointer speed.
248        int32_t pointerSpeed;
249
250        // True if pointer gestures are enabled.
251        bool pointerGesturesEnabled;
252
253        // Show touches feature enable/disable.
254        bool showTouches;
255
256        // Sprite controller singleton, created on first use.
257        sp<SpriteController> spriteController;
258
259        // Pointer controller singleton, created and destroyed as needed.
260        wp<PointerController> pointerController;
261    } mLocked;
262
263    void updateInactivityTimeoutLocked(const sp<PointerController>& controller);
264    void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
265    void ensureSpriteControllerLocked();
266
267    // Power manager interactions.
268    bool isScreenOn();
269    bool isScreenBright();
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) {
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
638bool NativeInputManager::isKeyRepeatEnabled() {
639    // Only enable automatic key repeating when the screen is on.
640    return isScreenOn();
641}
642
643void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) {
644    Vector<sp<InputWindowHandle> > windowHandles;
645
646    if (windowHandleObjArray) {
647        jsize length = env->GetArrayLength(windowHandleObjArray);
648        for (jsize i = 0; i < length; i++) {
649            jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i);
650            if (! windowHandleObj) {
651                break; // found null element indicating end of used portion of the array
652            }
653
654            sp<InputWindowHandle> windowHandle =
655                    android_server_InputWindowHandle_getHandle(env, windowHandleObj);
656            if (windowHandle != NULL) {
657                windowHandles.push(windowHandle);
658            }
659            env->DeleteLocalRef(windowHandleObj);
660        }
661    }
662
663    mInputManager->getDispatcher()->setInputWindows(windowHandles);
664
665    // Do this after the dispatcher has updated the window handle state.
666    bool newPointerGesturesEnabled = true;
667    size_t numWindows = windowHandles.size();
668    for (size_t i = 0; i < numWindows; i++) {
669        const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
670        const InputWindowInfo* windowInfo = windowHandle->getInfo();
671        if (windowInfo && windowInfo->hasFocus && (windowInfo->inputFeatures
672                & InputWindowInfo::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) {
673            newPointerGesturesEnabled = false;
674        }
675    }
676
677    uint32_t changes = 0;
678    { // acquire lock
679        AutoMutex _l(mLock);
680
681        if (mLocked.pointerGesturesEnabled != newPointerGesturesEnabled) {
682            mLocked.pointerGesturesEnabled = newPointerGesturesEnabled;
683            changes |= InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT;
684        }
685    } // release lock
686
687    if (changes) {
688        mInputManager->getReader()->requestRefreshConfiguration(changes);
689    }
690}
691
692void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationHandleObj) {
693    sp<InputApplicationHandle> applicationHandle =
694            android_server_InputApplicationHandle_getHandle(env, applicationHandleObj);
695    mInputManager->getDispatcher()->setFocusedApplication(applicationHandle);
696}
697
698void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
699    mInputManager->getDispatcher()->setInputDispatchMode(enabled, frozen);
700}
701
702void NativeInputManager::setSystemUiVisibility(int32_t visibility) {
703    AutoMutex _l(mLock);
704
705    if (mLocked.systemUiVisibility != visibility) {
706        mLocked.systemUiVisibility = visibility;
707
708        sp<PointerController> controller = mLocked.pointerController.promote();
709        if (controller != NULL) {
710            updateInactivityTimeoutLocked(controller);
711        }
712    }
713}
714
715void NativeInputManager::updateInactivityTimeoutLocked(const sp<PointerController>& controller) {
716    bool lightsOut = mLocked.systemUiVisibility & ASYSTEM_UI_VISIBILITY_STATUS_BAR_HIDDEN;
717    controller->setInactivityTimeout(lightsOut
718            ? PointerController::INACTIVITY_TIMEOUT_SHORT
719            : PointerController::INACTIVITY_TIMEOUT_NORMAL);
720}
721
722void NativeInputManager::setPointerSpeed(int32_t speed) {
723    { // acquire lock
724        AutoMutex _l(mLock);
725
726        if (mLocked.pointerSpeed == speed) {
727            return;
728        }
729
730        ALOGI("Setting pointer speed to %d.", speed);
731        mLocked.pointerSpeed = speed;
732    } // release lock
733
734    mInputManager->getReader()->requestRefreshConfiguration(
735            InputReaderConfiguration::CHANGE_POINTER_SPEED);
736}
737
738void NativeInputManager::setShowTouches(bool enabled) {
739    { // acquire lock
740        AutoMutex _l(mLock);
741
742        if (mLocked.showTouches == enabled) {
743            return;
744        }
745
746        ALOGI("Setting show touches feature to %s.", enabled ? "enabled" : "disabled");
747        mLocked.showTouches = enabled;
748    } // release lock
749
750    mInputManager->getReader()->requestRefreshConfiguration(
751            InputReaderConfiguration::CHANGE_SHOW_TOUCHES);
752}
753
754void NativeInputManager::reloadCalibration() {
755    mInputManager->getReader()->requestRefreshConfiguration(
756            InputReaderConfiguration::TOUCH_AFFINE_TRANSFORMATION);
757}
758
759bool NativeInputManager::isScreenOn() {
760    return android_server_PowerManagerService_isScreenOn();
761}
762
763bool NativeInputManager::isScreenBright() {
764    return android_server_PowerManagerService_isScreenBright();
765}
766
767TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
768        JNIEnv *env, jfloatArray matrixArr) {
769    ScopedFloatArrayRO matrix(env, matrixArr);
770    assert(matrix.size() == 6);
771
772    TouchAffineTransformation transform;
773    transform.x_scale  = matrix[0];
774    transform.x_ymix   = matrix[1];
775    transform.x_offset = matrix[2];
776    transform.y_xmix   = matrix[3];
777    transform.y_scale  = matrix[4];
778    transform.y_offset = matrix[5];
779
780    return transform;
781}
782
783TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
784        const String8& inputDeviceDescriptor) {
785    JNIEnv* env = jniEnv();
786
787    ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.string()));
788
789    jobject cal = env->CallObjectMethod(mServiceObj,
790            gServiceClassInfo.getTouchCalibrationForInputDevice, descriptorObj.get());
791
792    jfloatArray matrixArr = jfloatArray(env->CallObjectMethod(cal,
793            gTouchCalibrationClassInfo.getAffineTransform));
794
795    TouchAffineTransformation transform = getTouchAffineTransformation(env, matrixArr);
796
797    env->DeleteLocalRef(matrixArr);
798    env->DeleteLocalRef(cal);
799
800    return transform;
801}
802
803bool NativeInputManager::filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
804    jobject inputEventObj;
805
806    JNIEnv* env = jniEnv();
807    switch (inputEvent->getType()) {
808    case AINPUT_EVENT_TYPE_KEY:
809        inputEventObj = android_view_KeyEvent_fromNative(env,
810                static_cast<const KeyEvent*>(inputEvent));
811        break;
812    case AINPUT_EVENT_TYPE_MOTION:
813        inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
814                static_cast<const MotionEvent*>(inputEvent));
815        break;
816    default:
817        return true; // dispatch the event normally
818    }
819
820    if (!inputEventObj) {
821        ALOGE("Failed to obtain input event object for filterInputEvent.");
822        return true; // dispatch the event normally
823    }
824
825    // The callee is responsible for recycling the event.
826    jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,
827            inputEventObj, policyFlags);
828    if (checkAndClearExceptionFromCallback(env, "filterInputEvent")) {
829        pass = true;
830    }
831    env->DeleteLocalRef(inputEventObj);
832    return pass;
833}
834
835void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
836        uint32_t& policyFlags) {
837    // Policy:
838    // - Ignore untrusted events and pass them along.
839    // - Ask the window manager what to do with normal events and trusted injected events.
840    // - For normal events wake and brighten the screen if currently off or dim.
841    if ((policyFlags & POLICY_FLAG_TRUSTED)) {
842        nsecs_t when = keyEvent->getEventTime();
843        bool isScreenOn = this->isScreenOn();
844        bool isScreenBright = this->isScreenBright();
845
846        JNIEnv* env = jniEnv();
847        jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
848        jint wmActions;
849        if (keyEventObj) {
850            wmActions = env->CallIntMethod(mServiceObj,
851                    gServiceClassInfo.interceptKeyBeforeQueueing,
852                    keyEventObj, policyFlags, isScreenOn);
853            if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
854                wmActions = 0;
855            }
856            android_view_KeyEvent_recycle(env, keyEventObj);
857            env->DeleteLocalRef(keyEventObj);
858        } else {
859            ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing.");
860            wmActions = 0;
861        }
862
863        if (!(policyFlags & POLICY_FLAG_INJECTED)) {
864            if (!isScreenOn) {
865                policyFlags |= POLICY_FLAG_WOKE_HERE;
866            }
867
868            if (!isScreenBright) {
869                policyFlags |= POLICY_FLAG_BRIGHT_HERE;
870            }
871        }
872
873        handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
874    } else {
875        policyFlags |= POLICY_FLAG_PASS_TO_USER;
876    }
877}
878
879void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
880    // Policy:
881    // - Ignore untrusted events and pass them along.
882    // - No special filtering for injected events required at this time.
883    // - Filter normal events based on screen state.
884    // - For normal events brighten (but do not wake) the screen if currently dim.
885    if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {
886        if (isScreenOn()) {
887            policyFlags |= POLICY_FLAG_PASS_TO_USER;
888
889            if (!isScreenBright()) {
890                policyFlags |= POLICY_FLAG_BRIGHT_HERE;
891            }
892        } else {
893            JNIEnv* env = jniEnv();
894            jint wmActions = env->CallIntMethod(mServiceObj,
895                        gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
896                        when, policyFlags);
897            if (checkAndClearExceptionFromCallback(env,
898                    "interceptMotionBeforeQueueingWhenScreenOff")) {
899                wmActions = 0;
900            }
901
902            policyFlags |= POLICY_FLAG_WOKE_HERE | POLICY_FLAG_BRIGHT_HERE;
903            handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
904        }
905    } else {
906        policyFlags |= POLICY_FLAG_PASS_TO_USER;
907    }
908}
909
910void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
911        uint32_t& policyFlags) {
912    if (wmActions & WM_ACTION_PASS_TO_USER) {
913        policyFlags |= POLICY_FLAG_PASS_TO_USER;
914    } else {
915#if DEBUG_INPUT_DISPATCHER_POLICY
916        ALOGD("handleInterceptActions: Not passing key to user.");
917#endif
918    }
919}
920
921nsecs_t NativeInputManager::interceptKeyBeforeDispatching(
922        const sp<InputWindowHandle>& inputWindowHandle,
923        const KeyEvent* keyEvent, uint32_t policyFlags) {
924    // Policy:
925    // - Ignore untrusted events and pass them along.
926    // - Filter normal events and trusted injected events through the window manager policy to
927    //   handle the HOME key and the like.
928    nsecs_t result = 0;
929    if (policyFlags & POLICY_FLAG_TRUSTED) {
930        JNIEnv* env = jniEnv();
931
932        // Note: inputWindowHandle may be null.
933        jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
934        jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
935        if (keyEventObj) {
936            jlong delayMillis = env->CallLongMethod(mServiceObj,
937                    gServiceClassInfo.interceptKeyBeforeDispatching,
938                    inputWindowHandleObj, keyEventObj, policyFlags);
939            bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
940            android_view_KeyEvent_recycle(env, keyEventObj);
941            env->DeleteLocalRef(keyEventObj);
942            if (!error) {
943                if (delayMillis < 0) {
944                    result = -1;
945                } else if (delayMillis > 0) {
946                    result = milliseconds_to_nanoseconds(delayMillis);
947                }
948            }
949        } else {
950            ALOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
951        }
952        env->DeleteLocalRef(inputWindowHandleObj);
953    }
954    return result;
955}
956
957bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
958        const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
959    // Policy:
960    // - Ignore untrusted events and do not perform default handling.
961    bool result = false;
962    if (policyFlags & POLICY_FLAG_TRUSTED) {
963        JNIEnv* env = jniEnv();
964
965        // Note: inputWindowHandle may be null.
966        jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
967        jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
968        if (keyEventObj) {
969            jobject fallbackKeyEventObj = env->CallObjectMethod(mServiceObj,
970                    gServiceClassInfo.dispatchUnhandledKey,
971                    inputWindowHandleObj, keyEventObj, policyFlags);
972            if (checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey")) {
973                fallbackKeyEventObj = NULL;
974            }
975            android_view_KeyEvent_recycle(env, keyEventObj);
976            env->DeleteLocalRef(keyEventObj);
977
978            if (fallbackKeyEventObj) {
979                // Note: outFallbackKeyEvent may be the same object as keyEvent.
980                if (!android_view_KeyEvent_toNative(env, fallbackKeyEventObj,
981                        outFallbackKeyEvent)) {
982                    result = true;
983                }
984                android_view_KeyEvent_recycle(env, fallbackKeyEventObj);
985                env->DeleteLocalRef(fallbackKeyEventObj);
986            }
987        } else {
988            ALOGE("Failed to obtain key event object for dispatchUnhandledKey.");
989        }
990        env->DeleteLocalRef(inputWindowHandleObj);
991    }
992    return result;
993}
994
995void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
996    android_server_PowerManagerService_userActivity(eventTime, eventType);
997}
998
999
1000bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
1001        int32_t injectorPid, int32_t injectorUid) {
1002    JNIEnv* env = jniEnv();
1003    jboolean result = env->CallBooleanMethod(mServiceObj,
1004            gServiceClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
1005    if (checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission")) {
1006        result = false;
1007    }
1008    return result;
1009}
1010
1011void NativeInputManager::loadPointerResources(PointerResources* outResources) {
1012    JNIEnv* env = jniEnv();
1013
1014    loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_HOVER,
1015            &outResources->spotHover);
1016    loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_TOUCH,
1017            &outResources->spotTouch);
1018    loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_ANCHOR,
1019            &outResources->spotAnchor);
1020}
1021
1022
1023// ----------------------------------------------------------------------------
1024
1025static jlong nativeInit(JNIEnv* env, jclass clazz,
1026        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
1027    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
1028    if (messageQueue == NULL) {
1029        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
1030        return 0;
1031    }
1032
1033    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
1034            messageQueue->getLooper());
1035    im->incStrong(0);
1036    return reinterpret_cast<jlong>(im);
1037}
1038
1039static void nativeStart(JNIEnv* env, jclass clazz, jlong ptr) {
1040    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1041
1042    status_t result = im->getInputManager()->start();
1043    if (result) {
1044        jniThrowRuntimeException(env, "Input manager could not be started.");
1045    }
1046}
1047
1048static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, jlong ptr, jboolean external,
1049        jint displayId, jint orientation,
1050        jint logicalLeft, jint logicalTop, jint logicalRight, jint logicalBottom,
1051        jint physicalLeft, jint physicalTop, jint physicalRight, jint physicalBottom,
1052        jint deviceWidth, jint deviceHeight) {
1053    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1054
1055    DisplayViewport v;
1056    v.displayId = displayId;
1057    v.orientation = orientation;
1058    v.logicalLeft = logicalLeft;
1059    v.logicalTop = logicalTop;
1060    v.logicalRight = logicalRight;
1061    v.logicalBottom = logicalBottom;
1062    v.physicalLeft = physicalLeft;
1063    v.physicalTop = physicalTop;
1064    v.physicalRight = physicalRight;
1065    v.physicalBottom = physicalBottom;
1066    v.deviceWidth = deviceWidth;
1067    v.deviceHeight = deviceHeight;
1068    im->setDisplayViewport(external, v);
1069}
1070
1071static jint nativeGetScanCodeState(JNIEnv* env, jclass clazz,
1072        jlong ptr, jint deviceId, jint sourceMask, jint scanCode) {
1073    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1074
1075    return (jint) im->getInputManager()->getReader()->getScanCodeState(
1076            deviceId, uint32_t(sourceMask), scanCode);
1077}
1078
1079static jint nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
1080        jlong ptr, jint deviceId, jint sourceMask, jint keyCode) {
1081    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1082
1083    return (jint) im->getInputManager()->getReader()->getKeyCodeState(
1084            deviceId, uint32_t(sourceMask), keyCode);
1085}
1086
1087static jint nativeGetSwitchState(JNIEnv* env, jclass clazz,
1088        jlong ptr, jint deviceId, jint sourceMask, jint sw) {
1089    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1090
1091    return (jint) im->getInputManager()->getReader()->getSwitchState(
1092            deviceId, uint32_t(sourceMask), sw);
1093}
1094
1095static jboolean nativeHasKeys(JNIEnv* env, jclass clazz,
1096        jlong ptr, jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
1097    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1098
1099    int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
1100    uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
1101    jsize numCodes = env->GetArrayLength(keyCodes);
1102    jboolean result;
1103    if (numCodes == env->GetArrayLength(keyCodes)) {
1104        if (im->getInputManager()->getReader()->hasKeys(
1105                deviceId, uint32_t(sourceMask), numCodes, codes, flags)) {
1106            result = JNI_TRUE;
1107        } else {
1108            result = JNI_FALSE;
1109        }
1110    } else {
1111        result = JNI_FALSE;
1112    }
1113
1114    env->ReleaseBooleanArrayElements(outFlags, flags, 0);
1115    env->ReleaseIntArrayElements(keyCodes, codes, 0);
1116    return result;
1117}
1118
1119static void throwInputChannelNotInitialized(JNIEnv* env) {
1120    jniThrowException(env, "java/lang/IllegalStateException",
1121             "inputChannel is not initialized");
1122}
1123
1124static void handleInputChannelDisposed(JNIEnv* env,
1125        jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
1126    NativeInputManager* im = static_cast<NativeInputManager*>(data);
1127
1128    ALOGW("Input channel object '%s' was disposed without first being unregistered with "
1129            "the input manager!", inputChannel->getName().string());
1130    im->unregisterInputChannel(env, inputChannel);
1131}
1132
1133static void nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
1134        jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
1135    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1136
1137    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1138            inputChannelObj);
1139    if (inputChannel == NULL) {
1140        throwInputChannelNotInitialized(env);
1141        return;
1142    }
1143
1144    sp<InputWindowHandle> inputWindowHandle =
1145            android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
1146
1147    status_t status = im->registerInputChannel(
1148            env, inputChannel, inputWindowHandle, monitor);
1149    if (status) {
1150        String8 message;
1151        message.appendFormat("Failed to register input channel.  status=%d", status);
1152        jniThrowRuntimeException(env, message.string());
1153        return;
1154    }
1155
1156    if (! monitor) {
1157        android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
1158                handleInputChannelDisposed, im);
1159    }
1160}
1161
1162static void nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
1163        jlong ptr, jobject inputChannelObj) {
1164    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1165
1166    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1167            inputChannelObj);
1168    if (inputChannel == NULL) {
1169        throwInputChannelNotInitialized(env);
1170        return;
1171    }
1172
1173    android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
1174
1175    status_t status = im->unregisterInputChannel(env, inputChannel);
1176    if (status && status != BAD_VALUE) { // ignore already unregistered channel
1177        String8 message;
1178        message.appendFormat("Failed to unregister input channel.  status=%d", status);
1179        jniThrowRuntimeException(env, message.string());
1180    }
1181}
1182
1183static void nativeSetInputFilterEnabled(JNIEnv* env, jclass clazz,
1184        jlong ptr, jboolean enabled) {
1185    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1186
1187    im->getInputManager()->getDispatcher()->setInputFilterEnabled(enabled);
1188}
1189
1190static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz,
1191        jlong ptr, jobject inputEventObj, jint displayId, jint injectorPid, jint injectorUid,
1192        jint syncMode, jint timeoutMillis, jint policyFlags) {
1193    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1194
1195    if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
1196        KeyEvent keyEvent;
1197        status_t status = android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent);
1198        if (status) {
1199            jniThrowRuntimeException(env, "Could not read contents of KeyEvent object.");
1200            return INPUT_EVENT_INJECTION_FAILED;
1201        }
1202
1203        return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
1204                & keyEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,
1205                uint32_t(policyFlags));
1206    } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
1207        const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj);
1208        if (!motionEvent) {
1209            jniThrowRuntimeException(env, "Could not read contents of MotionEvent object.");
1210            return INPUT_EVENT_INJECTION_FAILED;
1211        }
1212
1213        return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
1214                motionEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,
1215                uint32_t(policyFlags));
1216    } else {
1217        jniThrowRuntimeException(env, "Invalid input event type.");
1218        return INPUT_EVENT_INJECTION_FAILED;
1219    }
1220}
1221
1222static void nativeSetInputWindows(JNIEnv* env, jclass clazz,
1223        jlong ptr, jobjectArray windowHandleObjArray) {
1224    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1225
1226    im->setInputWindows(env, windowHandleObjArray);
1227}
1228
1229static void nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
1230        jlong ptr, jobject applicationHandleObj) {
1231    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1232
1233    im->setFocusedApplication(env, applicationHandleObj);
1234}
1235
1236static void nativeSetInputDispatchMode(JNIEnv* env,
1237        jclass clazz, jlong ptr, jboolean enabled, jboolean frozen) {
1238    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1239
1240    im->setInputDispatchMode(enabled, frozen);
1241}
1242
1243static void nativeSetSystemUiVisibility(JNIEnv* env,
1244        jclass clazz, jlong ptr, jint visibility) {
1245    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1246
1247    im->setSystemUiVisibility(visibility);
1248}
1249
1250static jboolean nativeTransferTouchFocus(JNIEnv* env,
1251        jclass clazz, jlong ptr, jobject fromChannelObj, jobject toChannelObj) {
1252    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1253
1254    sp<InputChannel> fromChannel =
1255            android_view_InputChannel_getInputChannel(env, fromChannelObj);
1256    sp<InputChannel> toChannel =
1257            android_view_InputChannel_getInputChannel(env, toChannelObj);
1258
1259    if (fromChannel == NULL || toChannel == NULL) {
1260        return JNI_FALSE;
1261    }
1262
1263    if (im->getInputManager()->getDispatcher()->
1264            transferTouchFocus(fromChannel, toChannel)) {
1265        return JNI_TRUE;
1266    } else {
1267        return JNI_FALSE;
1268    }
1269}
1270
1271static void nativeSetPointerSpeed(JNIEnv* env,
1272        jclass clazz, jlong ptr, jint speed) {
1273    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1274
1275    im->setPointerSpeed(speed);
1276}
1277
1278static void nativeSetShowTouches(JNIEnv* env,
1279        jclass clazz, jlong ptr, jboolean enabled) {
1280    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1281
1282    im->setShowTouches(enabled);
1283}
1284
1285static void nativeReloadCalibration(JNIEnv* env, jclass clazz, jlong ptr) {
1286    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1287    im->reloadCalibration();
1288}
1289
1290static void nativeVibrate(JNIEnv* env,
1291        jclass clazz, jlong ptr, jint deviceId, jlongArray patternObj,
1292        jint repeat, jint token) {
1293    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1294
1295    size_t patternSize = env->GetArrayLength(patternObj);
1296    if (patternSize > MAX_VIBRATE_PATTERN_SIZE) {
1297        ALOGI("Skipped requested vibration because the pattern size is %d "
1298                "which is more than the maximum supported size of %d.",
1299                patternSize, MAX_VIBRATE_PATTERN_SIZE);
1300        return; // limit to reasonable size
1301    }
1302
1303    jlong* patternMillis = static_cast<jlong*>(env->GetPrimitiveArrayCritical(
1304            patternObj, NULL));
1305    nsecs_t pattern[patternSize];
1306    for (size_t i = 0; i < patternSize; i++) {
1307        pattern[i] = max(jlong(0), min(patternMillis[i],
1308                (jlong)(MAX_VIBRATE_PATTERN_DELAY_NSECS / 1000000LL))) * 1000000LL;
1309    }
1310    env->ReleasePrimitiveArrayCritical(patternObj, patternMillis, JNI_ABORT);
1311
1312    im->getInputManager()->getReader()->vibrate(deviceId, pattern, patternSize, repeat, token);
1313}
1314
1315static void nativeCancelVibrate(JNIEnv* env,
1316        jclass clazz, jlong ptr, jint deviceId, jint token) {
1317    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1318
1319    im->getInputManager()->getReader()->cancelVibrate(deviceId, token);
1320}
1321
1322static void nativeReloadKeyboardLayouts(JNIEnv* env,
1323        jclass clazz, jlong ptr) {
1324    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1325
1326    im->getInputManager()->getReader()->requestRefreshConfiguration(
1327            InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS);
1328}
1329
1330static void nativeReloadDeviceAliases(JNIEnv* env,
1331        jclass clazz, jlong ptr) {
1332    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1333
1334    im->getInputManager()->getReader()->requestRefreshConfiguration(
1335            InputReaderConfiguration::CHANGE_DEVICE_ALIAS);
1336}
1337
1338static jstring nativeDump(JNIEnv* env, jclass clazz, jlong ptr) {
1339    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1340
1341    String8 dump;
1342    im->dump(dump);
1343    return env->NewStringUTF(dump.string());
1344}
1345
1346static void nativeMonitor(JNIEnv* env, jclass clazz, jlong ptr) {
1347    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1348
1349    im->getInputManager()->getReader()->monitor();
1350    im->getInputManager()->getDispatcher()->monitor();
1351}
1352
1353// ----------------------------------------------------------------------------
1354
1355static JNINativeMethod gInputManagerMethods[] = {
1356    /* name, signature, funcPtr */
1357    { "nativeInit",
1358            "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J",
1359            (void*) nativeInit },
1360    { "nativeStart", "(J)V",
1361            (void*) nativeStart },
1362    { "nativeSetDisplayViewport", "(JZIIIIIIIIIIII)V",
1363            (void*) nativeSetDisplayViewport },
1364    { "nativeGetScanCodeState", "(JIII)I",
1365            (void*) nativeGetScanCodeState },
1366    { "nativeGetKeyCodeState", "(JIII)I",
1367            (void*) nativeGetKeyCodeState },
1368    { "nativeGetSwitchState", "(JIII)I",
1369            (void*) nativeGetSwitchState },
1370    { "nativeHasKeys", "(JII[I[Z)Z",
1371            (void*) nativeHasKeys },
1372    { "nativeRegisterInputChannel",
1373            "(JLandroid/view/InputChannel;Lcom/android/server/input/InputWindowHandle;Z)V",
1374            (void*) nativeRegisterInputChannel },
1375    { "nativeUnregisterInputChannel", "(JLandroid/view/InputChannel;)V",
1376            (void*) nativeUnregisterInputChannel },
1377    { "nativeSetInputFilterEnabled", "(JZ)V",
1378            (void*) nativeSetInputFilterEnabled },
1379    { "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I",
1380            (void*) nativeInjectInputEvent },
1381    { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V",
1382            (void*) nativeSetInputWindows },
1383    { "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V",
1384            (void*) nativeSetFocusedApplication },
1385    { "nativeSetInputDispatchMode", "(JZZ)V",
1386            (void*) nativeSetInputDispatchMode },
1387    { "nativeSetSystemUiVisibility", "(JI)V",
1388            (void*) nativeSetSystemUiVisibility },
1389    { "nativeTransferTouchFocus", "(JLandroid/view/InputChannel;Landroid/view/InputChannel;)Z",
1390            (void*) nativeTransferTouchFocus },
1391    { "nativeSetPointerSpeed", "(JI)V",
1392            (void*) nativeSetPointerSpeed },
1393    { "nativeSetShowTouches", "(JZ)V",
1394            (void*) nativeSetShowTouches },
1395    { "nativeReloadCalibration", "(J)V",
1396            (void*) nativeReloadCalibration },
1397    { "nativeVibrate", "(JI[JII)V",
1398            (void*) nativeVibrate },
1399    { "nativeCancelVibrate", "(JII)V",
1400            (void*) nativeCancelVibrate },
1401    { "nativeReloadKeyboardLayouts", "(J)V",
1402            (void*) nativeReloadKeyboardLayouts },
1403    { "nativeReloadDeviceAliases", "(J)V",
1404            (void*) nativeReloadDeviceAliases },
1405    { "nativeDump", "(J)Ljava/lang/String;",
1406            (void*) nativeDump },
1407    { "nativeMonitor", "(J)V",
1408            (void*) nativeMonitor },
1409};
1410
1411#define FIND_CLASS(var, className) \
1412        var = env->FindClass(className); \
1413        LOG_FATAL_IF(! var, "Unable to find class " className);
1414
1415#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
1416        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
1417        LOG_FATAL_IF(! var, "Unable to find method " methodName);
1418
1419#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
1420        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
1421        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
1422
1423int register_android_server_InputManager(JNIEnv* env) {
1424    int res = jniRegisterNativeMethods(env, "com/android/server/input/InputManagerService",
1425            gInputManagerMethods, NELEM(gInputManagerMethods));
1426    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
1427
1428    // Callbacks
1429
1430    jclass clazz;
1431    FIND_CLASS(clazz, "com/android/server/input/InputManagerService");
1432
1433    GET_METHOD_ID(gServiceClassInfo.notifyConfigurationChanged, clazz,
1434            "notifyConfigurationChanged", "(J)V");
1435
1436    GET_METHOD_ID(gServiceClassInfo.notifyInputDevicesChanged, clazz,
1437            "notifyInputDevicesChanged", "([Landroid/view/InputDevice;)V");
1438
1439    GET_METHOD_ID(gServiceClassInfo.notifySwitch, clazz,
1440            "notifySwitch", "(JII)V");
1441
1442    GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz,
1443            "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V");
1444
1445    GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
1446            "notifyANR",
1447            "(Lcom/android/server/input/InputApplicationHandle;Lcom/android/server/input/InputWindowHandle;Ljava/lang/String;)J");
1448
1449    GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
1450            "filterInputEvent", "(Landroid/view/InputEvent;I)Z");
1451
1452    GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
1453            "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
1454
1455    GET_METHOD_ID(gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
1456            clazz,
1457            "interceptMotionBeforeQueueingWhenScreenOff", "(JI)I");
1458
1459    GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
1460            "interceptKeyBeforeDispatching",
1461            "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)J");
1462
1463    GET_METHOD_ID(gServiceClassInfo.dispatchUnhandledKey, clazz,
1464            "dispatchUnhandledKey",
1465            "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
1466
1467    GET_METHOD_ID(gServiceClassInfo.checkInjectEventsPermission, clazz,
1468            "checkInjectEventsPermission", "(II)Z");
1469
1470    GET_METHOD_ID(gServiceClassInfo.getVirtualKeyQuietTimeMillis, clazz,
1471            "getVirtualKeyQuietTimeMillis", "()I");
1472
1473    GET_METHOD_ID(gServiceClassInfo.getExcludedDeviceNames, clazz,
1474            "getExcludedDeviceNames", "()[Ljava/lang/String;");
1475
1476    GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz,
1477            "getKeyRepeatTimeout", "()I");
1478
1479    GET_METHOD_ID(gServiceClassInfo.getKeyRepeatDelay, clazz,
1480            "getKeyRepeatDelay", "()I");
1481
1482    GET_METHOD_ID(gServiceClassInfo.getHoverTapTimeout, clazz,
1483            "getHoverTapTimeout", "()I");
1484
1485    GET_METHOD_ID(gServiceClassInfo.getHoverTapSlop, clazz,
1486            "getHoverTapSlop", "()I");
1487
1488    GET_METHOD_ID(gServiceClassInfo.getDoubleTapTimeout, clazz,
1489            "getDoubleTapTimeout", "()I");
1490
1491    GET_METHOD_ID(gServiceClassInfo.getLongPressTimeout, clazz,
1492            "getLongPressTimeout", "()I");
1493
1494    GET_METHOD_ID(gServiceClassInfo.getPointerLayer, clazz,
1495            "getPointerLayer", "()I");
1496
1497    GET_METHOD_ID(gServiceClassInfo.getPointerIcon, clazz,
1498            "getPointerIcon", "()Landroid/view/PointerIcon;");
1499
1500    GET_METHOD_ID(gServiceClassInfo.getKeyboardLayoutOverlay, clazz,
1501            "getKeyboardLayoutOverlay",
1502            "(Landroid/hardware/input/InputDeviceIdentifier;)[Ljava/lang/String;");
1503
1504    GET_METHOD_ID(gServiceClassInfo.getDeviceAlias, clazz,
1505            "getDeviceAlias", "(Ljava/lang/String;)Ljava/lang/String;");
1506
1507    GET_METHOD_ID(gServiceClassInfo.getTouchCalibrationForInputDevice, clazz,
1508            "getTouchCalibrationForInputDevice",
1509            "(Ljava/lang/String;)Landroid/hardware/input/TouchCalibration;");
1510
1511    // InputDevice
1512
1513    FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");
1514    gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz));
1515
1516    // KeyEvent
1517
1518    FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
1519    gKeyEventClassInfo.clazz = jclass(env->NewGlobalRef(gKeyEventClassInfo.clazz));
1520
1521    // MotionEvent
1522
1523    FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
1524    gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz));
1525
1526    // InputDeviceIdentifier
1527
1528    FIND_CLASS(gInputDeviceIdentifierInfo.clazz, "android/hardware/input/InputDeviceIdentifier");
1529    gInputDeviceIdentifierInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceIdentifierInfo.clazz));
1530    GET_METHOD_ID(gInputDeviceIdentifierInfo.constructor, gInputDeviceIdentifierInfo.clazz,
1531            "<init>", "(Ljava/lang/String;II)V");
1532
1533    // TouchCalibration
1534
1535    FIND_CLASS(gTouchCalibrationClassInfo.clazz, "android/hardware/input/TouchCalibration");
1536    gTouchCalibrationClassInfo.clazz = jclass(env->NewGlobalRef(gTouchCalibrationClassInfo.clazz));
1537
1538    GET_METHOD_ID(gTouchCalibrationClassInfo.getAffineTransform, gTouchCalibrationClassInfo.clazz,
1539            "getAffineTransform", "()[F");
1540
1541    return 0;
1542}
1543
1544} /* namespace android */
1545