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