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