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