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