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