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