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