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