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