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