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