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