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