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