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