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