blob: 0106e6c16eae31185583ae88a3fb7547e998673b [file] [log] [blame]
Jeff Brown46b9ac02010-04-22 18:58:52 -07001/*
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
Jeff Brown9c3cda02010-06-15 01:31:58 -070019//#define LOG_NDEBUG 0
20
21// Log debug messages about InputReaderPolicy
Jeff Brown349703e2010-06-22 01:27:15 -070022#define DEBUG_INPUT_READER_POLICY 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070023
24// Log debug messages about InputDispatcherPolicy
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_INPUT_DISPATCHER_POLICY 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070026
Jeff Brown349703e2010-06-22 01:27:15 -070027// Log debug messages about input focus tracking
28#define DEBUG_FOCUS 0
Jeff Brown9c3cda02010-06-15 01:31:58 -070029
Jeff Brown46b9ac02010-04-22 18:58:52 -070030#include "JNIHelp.h"
31#include "jni.h"
Jeff Brown349703e2010-06-22 01:27:15 -070032#include <limits.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070033#include <android_runtime/AndroidRuntime.h>
Jeff Brown9c3cda02010-06-15 01:31:58 -070034#include <ui/InputReader.h>
35#include <ui/InputDispatcher.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070036#include <ui/InputManager.h>
37#include <ui/InputTransport.h>
38#include <utils/Log.h>
39#include <utils/threads.h>
40#include "../../core/jni/android_view_KeyEvent.h"
41#include "../../core/jni/android_view_MotionEvent.h"
42#include "../../core/jni/android_view_InputChannel.h"
Jeff Brown46b9ac02010-04-22 18:58:52 -070043
44namespace android {
45
Jeff Brown349703e2010-06-22 01:27:15 -070046// Window flags from WindowManager.LayoutParams
47enum {
48 FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
49 FLAG_DIM_BEHIND = 0x00000002,
50 FLAG_BLUR_BEHIND = 0x00000004,
51 FLAG_NOT_FOCUSABLE = 0x00000008,
52 FLAG_NOT_TOUCHABLE = 0x00000010,
53 FLAG_NOT_TOUCH_MODAL = 0x00000020,
54 FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
55 FLAG_KEEP_SCREEN_ON = 0x00000080,
56 FLAG_LAYOUT_IN_SCREEN = 0x00000100,
57 FLAG_LAYOUT_NO_LIMITS = 0x00000200,
58 FLAG_FULLSCREEN = 0x00000400,
59 FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
60 FLAG_DITHER = 0x00001000,
61 FLAG_SECURE = 0x00002000,
62 FLAG_SCALED = 0x00004000,
63 FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
64 FLAG_LAYOUT_INSET_DECOR = 0x00010000,
65 FLAG_ALT_FOCUSABLE_IM = 0x00020000,
66 FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
67 FLAG_SHOW_WHEN_LOCKED = 0x00080000,
68 FLAG_SHOW_WALLPAPER = 0x00100000,
69 FLAG_TURN_SCREEN_ON = 0x00200000,
70 FLAG_DISMISS_KEYGUARD = 0x00400000,
71 FLAG_IMMERSIVE = 0x00800000,
72 FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
73 FLAG_COMPATIBLE_WINDOW = 0x20000000,
74 FLAG_SYSTEM_ERROR = 0x40000000,
75};
76
77// Window types from WindowManager.LayoutParams
78enum {
79 FIRST_APPLICATION_WINDOW = 1,
80 TYPE_BASE_APPLICATION = 1,
81 TYPE_APPLICATION = 2,
82 TYPE_APPLICATION_STARTING = 3,
83 LAST_APPLICATION_WINDOW = 99,
84 FIRST_SUB_WINDOW = 1000,
85 TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
86 TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
87 TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
88 TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
89 TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
90 LAST_SUB_WINDOW = 1999,
91 FIRST_SYSTEM_WINDOW = 2000,
92 TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
93 TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
94 TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
95 TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
96 TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
97 TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
98 TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
99 TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
100 TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
101 TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
102 TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
103 TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
104 TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
105 TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
106 TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14,
107 LAST_SYSTEM_WINDOW = 2999,
108};
109
110enum {
111 POWER_MANAGER_OTHER_EVENT = 0,
112 POWER_MANAGER_CHEEK_EVENT = 1,
113 POWER_MANAGER_TOUCH_EVENT = 2, // touch events are TOUCH for 300ms, and then either
114 // up events or LONG_TOUCH events.
115 POWER_MANAGER_LONG_TOUCH_EVENT = 3,
116 POWER_MANAGER_TOUCH_UP_EVENT = 4,
117 POWER_MANAGER_BUTTON_EVENT = 5, // Button and trackball events.
118};
119
120// Delay between reporting long touch events to the power manager.
121const nsecs_t EVENT_IGNORE_DURATION = 300 * 1000000LL; // 300 ms
122
123// Default input dispatching timeout if there is no focused application or paused window
124// from which to determine an appropriate dispatching timeout.
125const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
126
127// Minimum amount of time to provide to the input dispatcher for delivery of an event
128// regardless of how long the application window was paused.
129const nsecs_t MIN_INPUT_DISPATCHING_TIMEOUT = 1000 * 1000000LL; // 1 sec
130
Jeff Brown9c3cda02010-06-15 01:31:58 -0700131// ----------------------------------------------------------------------------
Jeff Brown46b9ac02010-04-22 18:58:52 -0700132
133static struct {
134 jclass clazz;
135
136 jmethodID isScreenOn;
137 jmethodID isScreenBright;
138 jmethodID notifyConfigurationChanged;
139 jmethodID notifyLidSwitchChanged;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700140 jmethodID notifyInputChannelBroken;
141 jmethodID notifyInputChannelANR;
142 jmethodID notifyInputChannelRecoveredFromANR;
Jeff Brown349703e2010-06-22 01:27:15 -0700143 jmethodID notifyANR;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700144 jmethodID virtualKeyFeedback;
Jeff Brown349703e2010-06-22 01:27:15 -0700145 jmethodID interceptKeyBeforeQueueing;
146 jmethodID interceptKeyBeforeDispatching;
147 jmethodID checkInjectEventsPermission;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700148 jmethodID goToSleep;
Jeff Brown349703e2010-06-22 01:27:15 -0700149 jmethodID pokeUserActivity;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700150 jmethodID notifyAppSwitchComing;
151 jmethodID filterTouchEvents;
152 jmethodID filterJumpyTouchEvents;
153 jmethodID getVirtualKeyDefinitions;
154 jmethodID getExcludedDeviceNames;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700155} gCallbacksClassInfo;
156
157static struct {
158 jclass clazz;
159
160 jfieldID scanCode;
161 jfieldID centerX;
162 jfieldID centerY;
163 jfieldID width;
164 jfieldID height;
165} gVirtualKeyDefinitionClassInfo;
166
Jeff Brown7fbdc842010-06-17 20:52:56 -0700167static struct {
168 jclass clazz;
169
Jeff Brown349703e2010-06-22 01:27:15 -0700170 jfieldID inputChannel;
171 jfieldID layoutParamsFlags;
172 jfieldID layoutParamsType;
173 jfieldID dispatchingTimeoutNanos;
174 jfieldID frameLeft;
175 jfieldID frameTop;
176 jfieldID touchableAreaLeft;
177 jfieldID touchableAreaTop;
178 jfieldID touchableAreaRight;
179 jfieldID touchableAreaBottom;
180 jfieldID visible;
181 jfieldID hasFocus;
182 jfieldID hasWallpaper;
183 jfieldID paused;
184 jfieldID ownerPid;
185 jfieldID ownerUid;
186} gInputWindowClassInfo;
187
188static struct {
189 jclass clazz;
190
191 jfieldID name;
192 jfieldID dispatchingTimeoutNanos;
193 jfieldID token;
194} gInputApplicationClassInfo;
195
196// ----------------------------------------------------------------------------
197
198static inline nsecs_t now() {
199 return systemTime(SYSTEM_TIME_MONOTONIC);
200}
Jeff Brown7fbdc842010-06-17 20:52:56 -0700201
Jeff Brown9c3cda02010-06-15 01:31:58 -0700202// ----------------------------------------------------------------------------
203
204class NativeInputManager : public virtual RefBase,
205 public virtual InputReaderPolicyInterface,
206 public virtual InputDispatcherPolicyInterface {
207protected:
208 virtual ~NativeInputManager();
209
210public:
211 NativeInputManager(jobject callbacksObj);
212
213 inline sp<InputManager> getInputManager() const { return mInputManager; }
214
215 void setDisplaySize(int32_t displayId, int32_t width, int32_t height);
216 void setDisplayOrientation(int32_t displayId, int32_t orientation);
217
Jeff Brown7fbdc842010-06-17 20:52:56 -0700218 status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
219 jweak inputChannelObjWeak);
220 status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
221
Jeff Brown349703e2010-06-22 01:27:15 -0700222 void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
223 void setFocusedApplication(JNIEnv* env, jobject applicationObj);
224 void setInputDispatchMode(bool enabled, bool frozen);
225 void preemptInputDispatch();
226
Jeff Brown9c3cda02010-06-15 01:31:58 -0700227 /* --- InputReaderPolicyInterface implementation --- */
228
229 virtual bool getDisplayInfo(int32_t displayId,
230 int32_t* width, int32_t* height, int32_t* orientation);
231 virtual void virtualKeyFeedback(nsecs_t when, int32_t deviceId,
232 int32_t action, int32_t flags, int32_t keyCode,
233 int32_t scanCode, int32_t metaState, nsecs_t downTime);
234 virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
235 bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags);
236 virtual int32_t interceptTrackball(nsecs_t when, bool buttonChanged, bool buttonDown,
237 bool rolled);
238 virtual int32_t interceptTouch(nsecs_t when);
239 virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue);
240 virtual bool filterTouchEvents();
241 virtual bool filterJumpyTouchEvents();
242 virtual void getVirtualKeyDefinitions(const String8& deviceName,
243 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions);
244 virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
245
246 /* --- InputDispatcherPolicyInterface implementation --- */
247
248 virtual void notifyConfigurationChanged(nsecs_t when);
249 virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700250 virtual bool notifyInputChannelANR(const sp<InputChannel>& inputChannel,
251 nsecs_t& outNewTimeout);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700252 virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel);
253 virtual nsecs_t getKeyRepeatTimeout();
Jeff Brown349703e2010-06-22 01:27:15 -0700254 virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700255 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -0700256 virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700257 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700258
259private:
Jeff Brown349703e2010-06-22 01:27:15 -0700260 struct InputWindow {
261 sp<InputChannel> inputChannel;
262 int32_t layoutParamsFlags;
263 int32_t layoutParamsType;
264 nsecs_t dispatchingTimeout;
265 int32_t frameLeft;
266 int32_t frameTop;
267 int32_t touchableAreaLeft;
268 int32_t touchableAreaTop;
269 int32_t touchableAreaRight;
270 int32_t touchableAreaBottom;
271 bool visible;
272 bool hasFocus;
273 bool hasWallpaper;
274 bool paused;
275 int32_t ownerPid;
276 int32_t ownerUid;
277
278 inline bool touchableAreaContainsPoint(int32_t x, int32_t y) {
279 return x >= touchableAreaLeft && x <= touchableAreaRight
280 && y >= touchableAreaTop && y <= touchableAreaBottom;
281 }
282 };
283
284 struct InputApplication {
285 String8 name;
286 nsecs_t dispatchingTimeout;
287 jweak tokenObjWeak;
288 };
289
290 class ANRTimer {
291 enum Budget {
292 SYSTEM = 0,
293 APPLICATION = 1
294 };
295
296 Budget mBudget;
297 nsecs_t mStartTime;
298 bool mFrozen;
299 InputWindow* mPausedWindow;
300
301 public:
302 ANRTimer();
303
304 void dispatchFrozenBySystem();
305 void dispatchPausedByApplication(InputWindow* pausedWindow);
306 bool waitForDispatchStateChangeLd(NativeInputManager* inputManager);
307
308 nsecs_t getTimeSpentWaitingForApplication() const;
309 };
310
Jeff Brown9c3cda02010-06-15 01:31:58 -0700311 sp<InputManager> mInputManager;
312
313 jobject mCallbacksObj;
314
315 // Cached filtering policies.
316 int32_t mFilterTouchEvents;
317 int32_t mFilterJumpyTouchEvents;
318
319 // Cached display state. (lock mDisplayLock)
320 Mutex mDisplayLock;
321 int32_t mDisplayWidth, mDisplayHeight;
322 int32_t mDisplayOrientation;
323
324 // Callbacks.
325 bool isScreenOn();
326 bool isScreenBright();
327
Jeff Brown7fbdc842010-06-17 20:52:56 -0700328 // Weak references to all currently registered input channels by receive fd.
329 Mutex mInputChannelRegistryLock;
330 KeyedVector<int, jweak> mInputChannelObjWeakByReceiveFd;
331
332 jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
333
Jeff Brown349703e2010-06-22 01:27:15 -0700334 // Input target and focus tracking. (lock mDispatchLock)
335 Mutex mDispatchLock;
336 Condition mDispatchStateChanged;
337
338 bool mDispatchEnabled;
339 bool mDispatchFrozen;
340 bool mWindowsReady;
341 Vector<InputWindow> mWindows;
342 Vector<InputWindow*> mWallpaperWindows;
343
344 // Focus tracking for keys, trackball, etc.
345 InputWindow* mFocusedWindow;
346
347 // Focus tracking for touch.
348 bool mTouchDown;
349 InputWindow* mTouchedWindow; // primary target for current down
350 Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
351
352 Vector<InputWindow*> mTempTouchedOutsideWindows; // temporary outside touch targets
353 Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
354
355 // Focused application.
356 InputApplication* mFocusedApplication;
357 InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
358
359 void dumpDispatchStateLd();
360
361 bool notifyANR(jobject tokenObj, nsecs_t& outNewTimeout);
362 void releaseFocusedApplicationLd(JNIEnv* env);
363
364 int32_t waitForFocusedWindowLd(uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
365 Vector<InputTarget>& outTargets, InputWindow*& outFocusedWindow);
366 int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
367 int32_t injectorPid, int32_t injectorUid,
368 Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
369
370 void releaseTouchedWindowLd();
371
372 int32_t identifyTrackballEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
373 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
374 int32_t identifyTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
375 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
376
377 void pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType);
378 void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
379 bool checkInjectionPermission(const InputWindow* window,
380 int32_t injectorPid, int32_t injectorUid);
381
382 static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
383 static void addTarget(const InputWindow* window, int32_t targetFlags,
384 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets);
385
Jeff Brown9c3cda02010-06-15 01:31:58 -0700386 static inline JNIEnv* jniEnv() {
387 return AndroidRuntime::getJNIEnv();
388 }
389
390 static bool isAppSwitchKey(int32_t keyCode);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700391 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700392};
393
394// ----------------------------------------------------------------------------
395
396NativeInputManager::NativeInputManager(jobject callbacksObj) :
397 mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
Jeff Brown349703e2010-06-22 01:27:15 -0700398 mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(-1),
399 mDispatchEnabled(true), mDispatchFrozen(false), mWindowsReady(true),
400 mFocusedWindow(NULL), mTouchDown(false), mTouchedWindow(NULL),
401 mFocusedApplication(NULL) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700402 JNIEnv* env = jniEnv();
403
404 mCallbacksObj = env->NewGlobalRef(callbacksObj);
405
406 sp<EventHub> eventHub = new EventHub();
407 mInputManager = new InputManager(eventHub, this, this);
408}
409
410NativeInputManager::~NativeInputManager() {
411 JNIEnv* env = jniEnv();
412
413 env->DeleteGlobalRef(mCallbacksObj);
Jeff Brown349703e2010-06-22 01:27:15 -0700414
415 releaseFocusedApplicationLd(env);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700416}
417
418bool NativeInputManager::isAppSwitchKey(int32_t keyCode) {
419 return keyCode == KEYCODE_HOME || keyCode == KEYCODE_ENDCALL;
420}
421
Jeff Brown7fbdc842010-06-17 20:52:56 -0700422bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700423 if (env->ExceptionCheck()) {
424 LOGE("An exception was thrown by callback '%s'.", methodName);
425 LOGE_EX(env);
426 env->ExceptionClear();
427 return true;
428 }
429 return false;
430}
431
432void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
433 if (displayId == 0) {
434 AutoMutex _l(mDisplayLock);
435
436 mDisplayWidth = width;
437 mDisplayHeight = height;
438 }
439}
440
441void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
442 if (displayId == 0) {
443 AutoMutex _l(mDisplayLock);
444
445 mDisplayOrientation = orientation;
446 }
447}
448
Jeff Brown7fbdc842010-06-17 20:52:56 -0700449status_t NativeInputManager::registerInputChannel(JNIEnv* env,
450 const sp<InputChannel>& inputChannel, jobject inputChannelObj) {
451 jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
452 if (! inputChannelObjWeak) {
453 LOGE("Could not create weak reference for input channel.");
454 LOGE_EX(env);
455 return NO_MEMORY;
456 }
457
458 status_t status;
459 {
460 AutoMutex _l(mInputChannelRegistryLock);
461
462 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
463 inputChannel->getReceivePipeFd());
464 if (index >= 0) {
465 LOGE("Input channel object '%s' has already been registered",
466 inputChannel->getName().string());
467 status = INVALID_OPERATION;
468 goto DeleteWeakRef;
469 }
470
471 mInputChannelObjWeakByReceiveFd.add(inputChannel->getReceivePipeFd(),
472 inputChannelObjWeak);
473 }
474
475 status = mInputManager->registerInputChannel(inputChannel);
476 if (! status) {
477 return OK;
478 }
479
480 {
481 AutoMutex _l(mInputChannelRegistryLock);
482 mInputChannelObjWeakByReceiveFd.removeItem(inputChannel->getReceivePipeFd());
483 }
484
485DeleteWeakRef:
486 env->DeleteWeakGlobalRef(inputChannelObjWeak);
487 return status;
488}
489
490status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
491 const sp<InputChannel>& inputChannel) {
492 jweak inputChannelObjWeak;
493 {
494 AutoMutex _l(mInputChannelRegistryLock);
495
496 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
497 inputChannel->getReceivePipeFd());
498 if (index < 0) {
499 LOGE("Input channel object '%s' is not currently registered",
500 inputChannel->getName().string());
501 return INVALID_OPERATION;
502 }
503
504 inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
505 mInputChannelObjWeakByReceiveFd.removeItemsAt(index);
506 }
507
508 env->DeleteWeakGlobalRef(inputChannelObjWeak);
509
510 return mInputManager->unregisterInputChannel(inputChannel);
511}
512
513jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
514 const sp<InputChannel>& inputChannel) {
515 {
516 AutoMutex _l(mInputChannelRegistryLock);
517
518 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
519 inputChannel->getReceivePipeFd());
520 if (index < 0) {
521 return NULL;
522 }
523
524 jweak inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
525 return env->NewLocalRef(inputChannelObjWeak);
526 }
527}
528
Jeff Brown9c3cda02010-06-15 01:31:58 -0700529bool NativeInputManager::getDisplayInfo(int32_t displayId,
530 int32_t* width, int32_t* height, int32_t* orientation) {
531 bool result = false;
532 if (displayId == 0) {
533 AutoMutex _l(mDisplayLock);
534
535 if (mDisplayWidth > 0) {
536 *width = mDisplayWidth;
537 *height = mDisplayHeight;
538 *orientation = mDisplayOrientation;
539 result = true;
540 }
541 }
542 return result;
543}
544
545bool NativeInputManager::isScreenOn() {
546 JNIEnv* env = jniEnv();
547
548 jboolean result = env->CallBooleanMethod(mCallbacksObj, gCallbacksClassInfo.isScreenOn);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700549 if (checkAndClearExceptionFromCallback(env, "isScreenOn")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700550 return true;
551 }
552 return result;
553}
554
555bool NativeInputManager::isScreenBright() {
556 JNIEnv* env = jniEnv();
557
558 jboolean result = env->CallBooleanMethod(mCallbacksObj, gCallbacksClassInfo.isScreenBright);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700559 if (checkAndClearExceptionFromCallback(env, "isScreenBright")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700560 return true;
561 }
562 return result;
563}
564
565void NativeInputManager::virtualKeyFeedback(nsecs_t when, int32_t deviceId,
566 int32_t action, int32_t flags, int32_t keyCode,
567 int32_t scanCode, int32_t metaState, nsecs_t downTime) {
568#if DEBUG_INPUT_READER_POLICY
569 LOGD("virtualKeyFeedback - when=%lld, deviceId=%d, action=%d, flags=%d, keyCode=%d, "
570 "scanCode=%d, metaState=%d, downTime=%lld",
571 when, deviceId, action, flags, keyCode, scanCode, metaState, downTime);
572#endif
573
574 JNIEnv* env = jniEnv();
575
576 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyFeedback,
577 when, deviceId, action, flags, keyCode, scanCode, metaState, downTime);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700578 checkAndClearExceptionFromCallback(env, "virtualKeyFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700579}
580
581int32_t NativeInputManager::interceptKey(nsecs_t when,
582 int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
583#if DEBUG_INPUT_READER_POLICY
584 LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
Jeff Brown349703e2010-06-22 01:27:15 -0700585 "policyFlags=0x%x",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700586 when, deviceId, down, keyCode, scanCode, policyFlags);
587#endif
588
589 const int32_t WM_ACTION_PASS_TO_USER = 1;
590 const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
591 const int32_t WM_ACTION_GO_TO_SLEEP = 4;
592
593 JNIEnv* env = jniEnv();
594
595 bool isScreenOn = this->isScreenOn();
596 bool isScreenBright = this->isScreenBright();
597
Jeff Brown349703e2010-06-22 01:27:15 -0700598 jint wmActions = env->CallIntMethod(mCallbacksObj,
599 gCallbacksClassInfo.interceptKeyBeforeQueueing,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700600 deviceId, EV_KEY, scanCode, keyCode, policyFlags, down ? 1 : 0, when, isScreenOn);
Jeff Brown349703e2010-06-22 01:27:15 -0700601 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700602 wmActions = 0;
603 }
604
605 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
606 if (! isScreenOn) {
607 // Key presses and releases wake the device.
608 actions |= InputReaderPolicyInterface::ACTION_WOKE_HERE;
609 }
610
611 if (! isScreenBright) {
612 // Key presses and releases brighten the screen if dimmed.
613 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
614 }
615
616 if (wmActions & WM_ACTION_GO_TO_SLEEP) {
617 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.goToSleep, when);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700618 checkAndClearExceptionFromCallback(env, "goToSleep");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700619 }
620
621 if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
Jeff Brown349703e2010-06-22 01:27:15 -0700622 pokeUserActivity(when, POWER_MANAGER_BUTTON_EVENT);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700623 }
624
625 if (wmActions & WM_ACTION_PASS_TO_USER) {
626 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700627
Jeff Brown9c3cda02010-06-15 01:31:58 -0700628 if (down && isAppSwitchKey(keyCode)) {
629 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700630 checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700631
632 actions |= InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING;
633 }
634 }
Jeff Brown349703e2010-06-22 01:27:15 -0700635
636 // TODO Be smarter about which keys cause us to request interception during dispatch.
637 actions |= InputReaderPolicyInterface::ACTION_INTERCEPT_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700638 return actions;
639}
640
641int32_t NativeInputManager::interceptTouch(nsecs_t when) {
642#if DEBUG_INPUT_READER_POLICY
643 LOGD("interceptTouch - when=%lld", when);
644#endif
645
Jeff Brown5c225b12010-06-16 01:53:36 -0700646 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
647 if (isScreenOn()) {
648 // Only dispatch touch events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700649 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700650 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700651
Jeff Brown349703e2010-06-22 01:27:15 -0700652 if (! isScreenBright()) {
653 // Brighten the screen if dimmed.
654 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
655 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700656 }
657
658 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700659}
660
661int32_t NativeInputManager::interceptTrackball(nsecs_t when,
662 bool buttonChanged, bool buttonDown, bool rolled) {
663#if DEBUG_INPUT_READER_POLICY
664 LOGD("interceptTrackball - when=%lld, buttonChanged=%d, buttonDown=%d, rolled=%d",
665 when, buttonChanged, buttonDown, rolled);
666#endif
667
Jeff Brown5c225b12010-06-16 01:53:36 -0700668 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
669 if (isScreenOn()) {
670 // Only dispatch trackball events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700671 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700672 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700673
Jeff Brown349703e2010-06-22 01:27:15 -0700674 if (! isScreenBright()) {
675 // Brighten the screen if dimmed.
676 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
677 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700678 }
679
680 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700681}
682
683int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
684 int32_t switchValue) {
685#if DEBUG_INPUT_READER_POLICY
686 LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d",
687 when, switchCode, switchValue);
688#endif
689
690 JNIEnv* env = jniEnv();
691
692 switch (switchCode) {
693 case SW_LID:
694 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
695 when, switchValue == 0);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700696 checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700697 break;
698 }
699
700 return InputReaderPolicyInterface::ACTION_NONE;
701}
702
703bool NativeInputManager::filterTouchEvents() {
704 if (mFilterTouchEvents < 0) {
705 JNIEnv* env = jniEnv();
706
707 jboolean result = env->CallBooleanMethod(mCallbacksObj,
708 gCallbacksClassInfo.filterTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700709 if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700710 result = false;
711 }
712
713 mFilterTouchEvents = result ? 1 : 0;
714 }
715 return mFilterTouchEvents;
716}
717
718bool NativeInputManager::filterJumpyTouchEvents() {
719 if (mFilterJumpyTouchEvents < 0) {
720 JNIEnv* env = jniEnv();
721
722 jboolean result = env->CallBooleanMethod(mCallbacksObj,
723 gCallbacksClassInfo.filterJumpyTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700724 if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700725 result = false;
726 }
727
728 mFilterJumpyTouchEvents = result ? 1 : 0;
729 }
730 return mFilterJumpyTouchEvents;
731}
732
733void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
734 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions) {
735 JNIEnv* env = jniEnv();
736
737 jstring deviceNameStr = env->NewStringUTF(deviceName.string());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700738 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700739 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
740 gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700741 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700742 jsize length = env->GetArrayLength(result);
743 for (jsize i = 0; i < length; i++) {
744 jobject item = env->GetObjectArrayElement(result, i);
745
746 outVirtualKeyDefinitions.add();
747 outVirtualKeyDefinitions.editTop().scanCode =
748 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode));
749 outVirtualKeyDefinitions.editTop().centerX =
750 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX));
751 outVirtualKeyDefinitions.editTop().centerY =
752 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY));
753 outVirtualKeyDefinitions.editTop().width =
754 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width));
755 outVirtualKeyDefinitions.editTop().height =
756 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height));
757
758 env->DeleteLocalRef(item);
759 }
760 env->DeleteLocalRef(result);
761 }
762 env->DeleteLocalRef(deviceNameStr);
763 }
764}
765
766void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
767 JNIEnv* env = jniEnv();
768
769 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
770 gCallbacksClassInfo.getExcludedDeviceNames));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700771 if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700772 jsize length = env->GetArrayLength(result);
773 for (jsize i = 0; i < length; i++) {
774 jstring item = jstring(env->GetObjectArrayElement(result, i));
775
776 const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
777 outExcludedDeviceNames.add(String8(deviceNameChars));
778 env->ReleaseStringUTFChars(item, deviceNameChars);
779
780 env->DeleteLocalRef(item);
781 }
782 env->DeleteLocalRef(result);
783 }
784}
785
786void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
787#if DEBUG_INPUT_DISPATCHER_POLICY
788 LOGD("notifyConfigurationChanged - when=%lld", when);
789#endif
790
791 JNIEnv* env = jniEnv();
792
793 InputConfiguration config;
794 mInputManager->getInputConfiguration(& config);
795
796 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
797 when, config.touchScreen, config.keyboard, config.navigation);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700798 checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700799}
800
801void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
802#if DEBUG_INPUT_DISPATCHER_POLICY
803 LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
804#endif
805
Jeff Brown7fbdc842010-06-17 20:52:56 -0700806 JNIEnv* env = jniEnv();
807
808 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
809 if (inputChannelObjLocal) {
810 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
811 inputChannelObjLocal);
812 checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
813
814 env->DeleteLocalRef(inputChannelObjLocal);
815 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700816}
817
Jeff Brown7fbdc842010-06-17 20:52:56 -0700818bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel,
819 nsecs_t& outNewTimeout) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700820#if DEBUG_INPUT_DISPATCHER_POLICY
821 LOGD("notifyInputChannelANR - inputChannel='%s'",
822 inputChannel->getName().string());
823#endif
824
Jeff Brown7fbdc842010-06-17 20:52:56 -0700825 JNIEnv* env = jniEnv();
826
827 jlong newTimeout;
828 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
829 if (inputChannelObjLocal) {
830 newTimeout = env->CallLongMethod(mCallbacksObj,
831 gCallbacksClassInfo.notifyInputChannelANR, inputChannelObjLocal);
832 if (checkAndClearExceptionFromCallback(env, "notifyInputChannelANR")) {
833 newTimeout = -2;
834 }
835
836 env->DeleteLocalRef(inputChannelObjLocal);
837 } else {
838 newTimeout = -2;
839 }
840
841 if (newTimeout == -2) {
842 return false; // abort
843 }
844
845 outNewTimeout = newTimeout;
846 return true; // resume
Jeff Brown9c3cda02010-06-15 01:31:58 -0700847}
848
849void NativeInputManager::notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) {
850#if DEBUG_INPUT_DISPATCHER_POLICY
851 LOGD("notifyInputChannelRecoveredFromANR - inputChannel='%s'",
852 inputChannel->getName().string());
853#endif
854
Jeff Brown7fbdc842010-06-17 20:52:56 -0700855 JNIEnv* env = jniEnv();
856
857 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
858 if (inputChannelObjLocal) {
859 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelRecoveredFromANR,
860 inputChannelObjLocal);
861 checkAndClearExceptionFromCallback(env, "notifyInputChannelRecoveredFromANR");
862
863 env->DeleteLocalRef(inputChannelObjLocal);
864 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700865}
866
Jeff Brown349703e2010-06-22 01:27:15 -0700867bool NativeInputManager::notifyANR(jobject tokenObj, nsecs_t& outNewTimeout) {
868#if DEBUG_INPUT_DISPATCHER_POLICY
869 LOGD("notifyANR");
870#endif
871
872 JNIEnv* env = jniEnv();
873
874 jlong newTimeout = env->CallLongMethod(mCallbacksObj,
875 gCallbacksClassInfo.notifyANR, tokenObj);
876 if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
877 newTimeout = -2;
878 }
879
880 if (newTimeout == -2) {
881 return false; // abort
882 }
883
884 outNewTimeout = newTimeout;
885 return true; // resume
886}
887
Jeff Brown9c3cda02010-06-15 01:31:58 -0700888nsecs_t NativeInputManager::getKeyRepeatTimeout() {
889 if (! isScreenOn()) {
890 // Disable key repeat when the screen is off.
891 return -1;
892 } else {
893 // TODO use ViewConfiguration.getLongPressTimeout()
894 return milliseconds_to_nanoseconds(500);
895 }
896}
897
Jeff Brown349703e2010-06-22 01:27:15 -0700898void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
899#if DEBUG_FOCUS
900 LOGD("setInputWindows");
901#endif
902 { // acquire lock
903 AutoMutex _l(mDispatchLock);
904
905 sp<InputChannel> touchedWindowChannel;
906 if (mTouchedWindow) {
907 touchedWindowChannel = mTouchedWindow->inputChannel;
908 mTouchedWindow = NULL;
909 }
910 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
911 if (numTouchedWallpapers != 0) {
912 for (size_t i = 0; i < numTouchedWallpapers; i++) {
913 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
914 }
915 mTouchedWallpaperWindows.clear();
916 }
917
918 mWindows.clear();
919 mFocusedWindow = NULL;
920 mWallpaperWindows.clear();
921
922 if (windowObjArray) {
923 mWindowsReady = true;
924
925 jsize length = env->GetArrayLength(windowObjArray);
926 for (jsize i = 0; i < length; i++) {
927 jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
928 if (! inputTargetObj) {
929 break; // found null element indicating end of used portion of the array
930 }
931
932 mWindows.push();
933 InputWindow& window = mWindows.editTop();
934 bool valid = populateWindow(env, inputTargetObj, window);
935 if (! valid) {
936 mWindows.pop();
937 }
938
939 env->DeleteLocalRef(inputTargetObj);
940 }
941
942 size_t numWindows = mWindows.size();
943 for (size_t i = 0; i < numWindows; i++) {
944 InputWindow* window = & mWindows.editItemAt(i);
945 if (window->hasFocus) {
946 mFocusedWindow = window;
947 }
948
949 if (window->layoutParamsType == TYPE_WALLPAPER) {
950 mWallpaperWindows.push(window);
951
952 for (size_t j = 0; j < numTouchedWallpapers; j++) {
953 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
954 mTouchedWallpaperWindows.push(window);
955 }
956 }
957 }
958
959 if (window->inputChannel == touchedWindowChannel) {
960 mTouchedWindow = window;
961 }
962 }
963 } else {
964 mWindowsReady = false;
965 }
966
967 mTempTouchedWallpaperChannels.clear();
968
969 mDispatchStateChanged.broadcast();
970
971#if DEBUG_FOCUS
972 dumpDispatchStateLd();
973#endif
974 } // release lock
975}
976
977bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
978 InputWindow& outWindow) {
979 bool valid = false;
980
981 jobject inputChannelObj = env->GetObjectField(windowObj,
982 gInputWindowClassInfo.inputChannel);
983 if (inputChannelObj) {
984 sp<InputChannel> inputChannel =
985 android_view_InputChannel_getInputChannel(env, inputChannelObj);
986 if (inputChannel != NULL) {
987 jint layoutParamsFlags = env->GetIntField(windowObj,
988 gInputWindowClassInfo.layoutParamsFlags);
989 jint layoutParamsType = env->GetIntField(windowObj,
990 gInputWindowClassInfo.layoutParamsType);
991 jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
992 gInputWindowClassInfo.dispatchingTimeoutNanos);
993 jint frameLeft = env->GetIntField(windowObj,
994 gInputWindowClassInfo.frameLeft);
995 jint frameTop = env->GetIntField(windowObj,
996 gInputWindowClassInfo.frameTop);
997 jint touchableAreaLeft = env->GetIntField(windowObj,
998 gInputWindowClassInfo.touchableAreaLeft);
999 jint touchableAreaTop = env->GetIntField(windowObj,
1000 gInputWindowClassInfo.touchableAreaTop);
1001 jint touchableAreaRight = env->GetIntField(windowObj,
1002 gInputWindowClassInfo.touchableAreaRight);
1003 jint touchableAreaBottom = env->GetIntField(windowObj,
1004 gInputWindowClassInfo.touchableAreaBottom);
1005 jboolean visible = env->GetBooleanField(windowObj,
1006 gInputWindowClassInfo.visible);
1007 jboolean hasFocus = env->GetBooleanField(windowObj,
1008 gInputWindowClassInfo.hasFocus);
1009 jboolean hasWallpaper = env->GetBooleanField(windowObj,
1010 gInputWindowClassInfo.hasWallpaper);
1011 jboolean paused = env->GetBooleanField(windowObj,
1012 gInputWindowClassInfo.paused);
1013 jint ownerPid = env->GetIntField(windowObj,
1014 gInputWindowClassInfo.ownerPid);
1015 jint ownerUid = env->GetIntField(windowObj,
1016 gInputWindowClassInfo.ownerUid);
1017
1018 outWindow.inputChannel = inputChannel;
1019 outWindow.layoutParamsFlags = layoutParamsFlags;
1020 outWindow.layoutParamsType = layoutParamsType;
1021 outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
1022 outWindow.frameLeft = frameLeft;
1023 outWindow.frameTop = frameTop;
1024 outWindow.touchableAreaLeft = touchableAreaLeft;
1025 outWindow.touchableAreaTop = touchableAreaTop;
1026 outWindow.touchableAreaRight = touchableAreaRight;
1027 outWindow.touchableAreaBottom = touchableAreaBottom;
1028 outWindow.visible = visible;
1029 outWindow.hasFocus = hasFocus;
1030 outWindow.hasWallpaper = hasWallpaper;
1031 outWindow.paused = paused;
1032 outWindow.ownerPid = ownerPid;
1033 outWindow.ownerUid = ownerUid;
1034 valid = true;
1035 } else {
1036 LOGW("Dropping input target because its input channel is not initialized.");
1037 }
1038
1039 env->DeleteLocalRef(inputChannelObj);
1040 } else {
1041 LOGW("Dropping input target because the input channel object was null.");
1042 }
1043 return valid;
1044}
1045
1046void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
1047#if DEBUG_FOCUS
1048 LOGD("setFocusedApplication");
1049#endif
1050 { // acquire lock
1051 AutoMutex _l(mDispatchLock);
1052
1053 releaseFocusedApplicationLd(env);
1054
1055 if (applicationObj) {
1056 jstring nameObj = jstring(env->GetObjectField(applicationObj,
1057 gInputApplicationClassInfo.name));
1058 jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
1059 gInputApplicationClassInfo.dispatchingTimeoutNanos);
1060 jobject tokenObj = env->GetObjectField(applicationObj,
1061 gInputApplicationClassInfo.token);
1062 jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
1063 if (! tokenObjWeak) {
1064 LOGE("Could not create weak reference for application token.");
1065 LOGE_EX(env);
1066 env->ExceptionClear();
1067 }
1068 env->DeleteLocalRef(tokenObj);
1069
1070 mFocusedApplication = & mFocusedApplicationStorage;
1071
1072 if (nameObj) {
1073 const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
1074 mFocusedApplication->name.setTo(nameStr);
1075 env->ReleaseStringUTFChars(nameObj, nameStr);
1076 env->DeleteLocalRef(nameObj);
1077 } else {
1078 LOGE("InputApplication.name should not be null.");
1079 mFocusedApplication->name.setTo("unknown");
1080 }
1081
1082 mFocusedApplication->dispatchingTimeout = dispatchingTimeoutNanos;
1083 mFocusedApplication->tokenObjWeak = tokenObjWeak;
1084 }
1085
1086 mDispatchStateChanged.broadcast();
1087
1088#if DEBUG_FOCUS
1089 dumpDispatchStateLd();
1090#endif
1091 } // release lock
1092}
1093
1094void NativeInputManager::releaseFocusedApplicationLd(JNIEnv* env) {
1095 if (mFocusedApplication) {
1096 env->DeleteWeakGlobalRef(mFocusedApplication->tokenObjWeak);
1097 mFocusedApplication = NULL;
1098 }
1099}
1100
1101void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
1102#if DEBUG_FOCUS
1103 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001104#endif
1105
Jeff Brown349703e2010-06-22 01:27:15 -07001106 { // acquire lock
1107 AutoMutex _l(mDispatchLock);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001108
Jeff Brown349703e2010-06-22 01:27:15 -07001109 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
1110 mDispatchEnabled = enabled;
1111 mDispatchFrozen = frozen;
1112
1113 mDispatchStateChanged.broadcast();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001114 }
Jeff Brown349703e2010-06-22 01:27:15 -07001115
1116#if DEBUG_FOCUS
1117 dumpDispatchStateLd();
1118#endif
1119 } // release lock
1120}
1121
1122void NativeInputManager::preemptInputDispatch() {
1123#if DEBUG_FOCUS
1124 LOGD("preemptInputDispatch");
1125#endif
1126
1127 mInputManager->preemptInputDispatch();
1128}
1129
1130int32_t NativeInputManager::waitForFocusedWindowLd(uint32_t policyFlags,
1131 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1132 InputWindow*& outFocusedWindow) {
1133
1134 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1135 bool firstIteration = true;
1136 ANRTimer anrTimer;
1137 for (;;) {
1138 if (firstIteration) {
1139 firstIteration = false;
1140 } else {
1141 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1142 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1143 "the window that should receive it.");
1144 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1145 break;
1146 }
1147 }
1148
1149 // If dispatch is not enabled then fail.
1150 if (! mDispatchEnabled) {
1151 LOGI("Dropping event because input dispatch is disabled.");
1152 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1153 break;
1154 }
1155
1156 // If dispatch is frozen or we don't have valid window data yet then wait.
1157 if (mDispatchFrozen || ! mWindowsReady) {
1158#if DEBUG_FOCUS
1159 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1160#endif
1161 anrTimer.dispatchFrozenBySystem();
1162 continue;
1163 }
1164
1165 // If there is no currently focused window and no focused application
1166 // then drop the event.
1167 if (! mFocusedWindow) {
1168 if (mFocusedApplication) {
1169#if DEBUG_FOCUS
1170 LOGD("Waiting because there is no focused window but there is a "
1171 "focused application that may yet introduce a new target: '%s'.",
1172 mFocusedApplication->name.string());
1173#endif
1174 continue;
1175 }
1176
1177 LOGI("Dropping event because there is no focused window or focused application.");
1178 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1179 break;
1180 }
1181
1182 // Check permissions.
1183 if (! checkInjectionPermission(mFocusedWindow, injectorPid, injectorUid)) {
1184 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1185 break;
1186 }
1187
1188 // If the currently focused window is paused then keep waiting.
1189 if (mFocusedWindow->paused) {
1190#if DEBUG_FOCUS
1191 LOGD("Waiting because focused window is paused.");
1192#endif
1193 anrTimer.dispatchPausedByApplication(mFocusedWindow);
1194 continue;
1195 }
1196
1197 // Success!
1198 break; // done waiting, exit loop
Jeff Brown9c3cda02010-06-15 01:31:58 -07001199 }
Jeff Brown349703e2010-06-22 01:27:15 -07001200
1201 // Output targets.
1202 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1203 addTarget(mFocusedWindow, InputTarget::FLAG_SYNC,
1204 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1205
1206 outFocusedWindow = mFocusedWindow;
1207 } else {
1208 outFocusedWindow = NULL;
1209 }
1210
1211#if DEBUG_FOCUS
1212 LOGD("waitForFocusedWindow finished: injectionResult=%d",
1213 injectionResult);
1214 dumpDispatchStateLd();
1215#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001216 return injectionResult;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001217}
1218
Jeff Brown349703e2010-06-22 01:27:15 -07001219int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
1220 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1221 InputWindow*& outTouchedWindow) {
1222 nsecs_t startTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001223
Jeff Brown349703e2010-06-22 01:27:15 -07001224 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1225 int32_t action = motionEvent->getAction();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001226
Jeff Brown349703e2010-06-22 01:27:15 -07001227 // For security reasons, we defer updating the touch state until we are sure that
1228 // event injection will be allowed.
1229 //
1230 // FIXME In the original code, screenWasOff could never be set to true.
1231 // The reason is that the POLICY_FLAG_WOKE_HERE
1232 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
1233 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
1234 // actually enqueued using the policyFlags that appeared in the final EV_SYN
1235 // events upon which no preprocessing took place. So policyFlags was always 0.
1236 // In the new native input dispatcher we're a bit more careful about event
1237 // preprocessing so the touches we receive can actually have non-zero policyFlags.
1238 // Unfortunately we obtain undesirable behavior.
1239 //
1240 // Here's what happens:
1241 //
1242 // When the device dims in anticipation of going to sleep, touches
1243 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
1244 // the device to brighten and reset the user activity timer.
1245 // Touches on other windows (such as the launcher window)
1246 // are dropped. Then after a moment, the device goes to sleep. Oops.
1247 //
1248 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
1249 // instead of POLICY_FLAG_WOKE_HERE...
1250 //
1251 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
1252 bool firstIteration = true;
1253 ANRTimer anrTimer;
1254 for (;;) {
1255 if (firstIteration) {
1256 firstIteration = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001257 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001258 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1259 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1260 "the window that should receive it.");
1261 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1262 break;
1263 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001264 }
Jeff Brown349703e2010-06-22 01:27:15 -07001265
1266 // If dispatch is not enabled then fail.
1267 if (! mDispatchEnabled) {
1268 LOGI("Dropping event because input dispatch is disabled.");
1269 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1270 break; // failed, exit wait loop
1271 }
1272
1273 // If dispatch is frozen or we don't have valid window data yet then wait.
1274 if (mDispatchFrozen || ! mWindowsReady) {
1275#if DEBUG_INPUT_DISPATCHER_POLICY
1276 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1277#endif
1278 anrTimer.dispatchFrozenBySystem();
1279 continue;
1280 }
1281
1282 // Update the touch state as needed based on the properties of the touch event.
1283 if (action == MOTION_EVENT_ACTION_DOWN) {
1284 InputWindow* newTouchedWindow = NULL;
1285 mTempTouchedOutsideWindows.clear();
1286
1287 int32_t x = int32_t(motionEvent->getX(0));
1288 int32_t y = int32_t(motionEvent->getY(0));
1289 InputWindow* topErrorWindow = NULL;
1290
1291 // Traverse windows from front to back to find touched window and outside targets.
1292 size_t numWindows = mWindows.size();
1293 for (size_t i = 0; i < numWindows; i++) {
1294 InputWindow* window = & mWindows.editItemAt(i);
1295 int32_t flags = window->layoutParamsFlags;
1296
1297 if (flags & FLAG_SYSTEM_ERROR) {
1298 if (! topErrorWindow) {
1299 topErrorWindow = window;
1300 }
1301 }
1302
1303 if (window->visible) {
1304 if (! (flags & FLAG_NOT_TOUCHABLE)) {
1305 bool isTouchModal = (flags &
1306 (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL)) == 0;
1307 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
1308 if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
1309 newTouchedWindow = window;
1310 }
1311 break; // found touched window, exit window loop
1312 }
1313 }
1314
1315 if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
1316 mTempTouchedOutsideWindows.push(window);
1317 }
1318 }
1319 }
1320
1321 // If there is an error window but it is not taking focus (typically because
1322 // it is invisible) then wait for it. Any other focused window may in
1323 // fact be in ANR state.
1324 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1325#if DEBUG_INPUT_DISPATCHER_POLICY
1326 LOGD("Waiting because system error window is pending.");
1327#endif
1328 anrTimer.dispatchFrozenBySystem();
1329 continue; // wait some more
1330 }
1331
1332 // If we did not find a touched window then fail.
1333 if (! newTouchedWindow) {
1334 if (mFocusedApplication) {
1335#if DEBUG_FOCUS
1336 LOGD("Waiting because there is no focused window but there is a "
1337 "focused application that may yet introduce a new target: '%s'.",
1338 mFocusedApplication->name.string());
1339#endif
1340 continue;
1341 }
1342
1343 LOGI("Dropping event because there is no touched window or focused application.");
1344 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1345 break; // failed, exit wait loop
1346 }
1347
1348 // Check permissions.
1349 if (! checkInjectionPermission(newTouchedWindow, injectorPid, injectorUid)) {
1350 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1351 break; // failed, exit wait loop
1352 }
1353
1354 // If the touched window is paused then keep waiting.
1355 if (newTouchedWindow->paused) {
1356#if DEBUG_INPUT_DISPATCHER_POLICY
1357 LOGD("Waiting because touched window is paused.");
1358#endif
1359 anrTimer.dispatchPausedByApplication(newTouchedWindow);
1360 continue; // wait some more
1361 }
1362
1363 // Success! Update the touch dispatch state for real.
1364 releaseTouchedWindowLd();
1365
1366 mTouchedWindow = newTouchedWindow;
1367
1368 if (newTouchedWindow->hasWallpaper) {
1369 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1370 }
1371 break; // done
1372 } else {
1373 // Check permissions.
1374 if (! checkInjectionPermission(mTouchedWindow, injectorPid, injectorUid)) {
1375 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1376 break; // failed, exit wait loop
1377 }
1378
1379 // If there is no currently touched window then fail.
1380 if (! mTouchedWindow || ! mTouchDown) {
1381 LOGI("Dropping event because touched window is no longer valid.");
1382 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1383 break; // failed, exit wait loop
1384 }
1385
1386 // If the touched window is paused then keep waiting.
1387 if (mTouchedWindow->paused) {
1388#if DEBUG_INPUT_DISPATCHER_POLICY
1389 LOGD("Waiting because touched window is paused.");
1390#endif
1391 anrTimer.dispatchPausedByApplication(mTouchedWindow);
1392 continue; // wait some more
1393 }
1394
1395 // Success!
1396 break; // done
1397 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001398 }
Jeff Brown349703e2010-06-22 01:27:15 -07001399
1400 // Output targets.
1401 bool havePermission;
1402 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1403 // Injection succeeded so the injector must have permission.
1404 havePermission = true;
1405
1406 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1407 for (size_t i = 0; i < numWallpaperWindows; i++) {
1408 addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
1409 }
1410
1411 size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
1412 for (size_t i = 0; i < numOutsideWindows; i++) {
1413 addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
1414 }
1415
1416 addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
1417 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1418 outTouchedWindow = mTouchedWindow;
1419 } else {
1420 if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED
1421 && checkInjectionPermission(NULL, injectorPid, injectorUid)) {
1422 // Injection failed but the injector does have permission to inject events.
1423 // While we might not have found a valid target for the injected event, we
1424 // still want to update the dispatch state to take it into account.
1425 havePermission = true;
1426 } else {
1427 // Injector does not have permission to inject events.
1428 // We make sure to leave the dispatch state unchanged.
1429 havePermission = false;
1430 }
1431 outTouchedWindow = NULL;
1432 }
1433 mTempTouchedOutsideWindows.clear();
1434
1435 // Update final pieces of touch state now that we know for sure whether the injector
1436 // had permission to perform the injection.
1437 if (havePermission) {
1438 if (action == MOTION_EVENT_ACTION_DOWN) {
1439 if (mTouchDown) {
1440 // This is weird. We got a down but we thought it was already down!
1441 LOGW("Pointer down received while already down.");
1442 } else {
1443 mTouchDown = true;
1444 }
1445
1446 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1447 // Since we failed to identify a target for this touch down, we may still
1448 // be holding on to an earlier target from a previous touch down. Release it.
1449 releaseTouchedWindowLd();
1450 }
1451 } else if (action == MOTION_EVENT_ACTION_UP) {
1452 mTouchDown = false;
1453 releaseTouchedWindowLd();
1454 }
1455 }
1456
1457#if DEBUG_FOCUS
1458 LOGD("waitForTouchedWindow finished: injectionResult=%d",
1459 injectionResult);
1460 dumpDispatchStateLd();
1461#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001462 return injectionResult;
1463}
1464
Jeff Brown349703e2010-06-22 01:27:15 -07001465void NativeInputManager::releaseTouchedWindowLd() {
1466 mTouchedWindow = NULL;
1467 mTouchedWallpaperWindows.clear();
1468}
1469
1470void NativeInputManager::addTarget(const InputWindow* window, int32_t targetFlags,
1471 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets) {
1472 nsecs_t timeout = window->dispatchingTimeout - timeSpentWaitingForApplication;
1473 if (timeout < MIN_INPUT_DISPATCHING_TIMEOUT) {
1474 timeout = MIN_INPUT_DISPATCHING_TIMEOUT;
1475 }
1476
1477 outTargets.push();
1478
1479 InputTarget& target = outTargets.editTop();
1480 target.inputChannel = window->inputChannel;
1481 target.flags = targetFlags;
1482 target.timeout = timeout;
1483 target.xOffset = - window->frameLeft;
1484 target.yOffset = - window->frameTop;
1485}
1486
1487bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
1488 int32_t injectorPid, int32_t injectorUid) {
1489 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1490 JNIEnv* env = jniEnv();
1491 jboolean result = env->CallBooleanMethod(mCallbacksObj,
1492 gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
1493 checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission");
1494
1495 if (! result) {
1496 if (window) {
1497 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1498 "with input channel %s owned by uid %d",
1499 injectorPid, injectorUid, window->inputChannel->getName().string(),
1500 window->ownerUid);
1501 } else {
1502 LOGW("Permission denied: injecting event from pid %d uid %d",
1503 injectorPid, injectorUid);
1504 }
1505 return false;
1506 }
1507 }
1508
1509 return true;
1510}
1511
1512int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
1513 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
1514#if DEBUG_INPUT_DISPATCHER_POLICY
1515 LOGD("waitForKeyEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1516 policyFlags, injectorPid, injectorUid);
1517#endif
1518
1519 int32_t windowType;
1520 { // acquire lock
1521 AutoMutex _l(mDispatchLock);
1522
1523 InputWindow* focusedWindow;
1524 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1525 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1526 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1527 return injectionResult;
1528 }
1529
1530 windowType = focusedWindow->layoutParamsType;
1531 } // release lock
1532
1533 if (policyFlags & POLICY_FLAG_INTERCEPT_DISPATCH) {
1534 const InputTarget& target = outTargets.top();
1535
1536 JNIEnv* env = jniEnv();
1537
1538 jobject inputChannelObj = getInputChannelObjLocal(env, target.inputChannel);
1539 if (inputChannelObj) {
1540 jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
1541 gCallbacksClassInfo.interceptKeyBeforeDispatching,
1542 inputChannelObj, keyEvent->getKeyCode(), keyEvent->getMetaState(),
1543 keyEvent->getAction() == KEY_EVENT_ACTION_DOWN,
1544 keyEvent->getRepeatCount(), policyFlags);
1545 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatch");
1546
1547 env->DeleteLocalRef(inputChannelObj);
1548
1549 if (error) {
1550 return INPUT_EVENT_INJECTION_FAILED;
1551 }
1552
1553 if (consumed) {
1554 outTargets.clear();
1555 return INPUT_EVENT_INJECTION_SUCCEEDED;
1556 }
1557 } else {
1558 LOGW("Could not apply key dispatch policy because input channel '%s' is "
1559 "no longer valid.", target.inputChannel->getName().string());
1560 }
1561 }
1562
1563 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1564 return INPUT_EVENT_INJECTION_SUCCEEDED;
1565}
1566
1567int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
1568 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001569 Vector<InputTarget>& outTargets) {
Jeff Brown349703e2010-06-22 01:27:15 -07001570#if DEBUG_INPUT_DISPATCHER_POLICY
1571 LOGD("waitForMotionEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1572 policyFlags, injectorPid, injectorUid);
1573#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001574
Jeff Brown349703e2010-06-22 01:27:15 -07001575 switch (motionEvent->getNature()) {
1576 case INPUT_EVENT_NATURE_TRACKBALL:
1577 return identifyTrackballEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
1578 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001579
Jeff Brown349703e2010-06-22 01:27:15 -07001580 case INPUT_EVENT_NATURE_TOUCH:
1581 return identifyTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
1582 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001583
Jeff Brown349703e2010-06-22 01:27:15 -07001584 default:
1585 assert(false);
1586 return INPUT_EVENT_INJECTION_FAILED;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001587 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001588}
1589
Jeff Brown349703e2010-06-22 01:27:15 -07001590int32_t NativeInputManager::identifyTrackballEventTargets(MotionEvent* motionEvent,
1591 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1592 Vector<InputTarget>& outTargets) {
1593#if DEBUG_INPUT_DISPATCHER_POLICY
1594 LOGD("identifyTrackballEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1595 policyFlags, injectorPid, injectorUid);
1596#endif
1597
1598 int32_t windowType;
1599 { // acquire lock
1600 AutoMutex _l(mDispatchLock);
1601
1602 InputWindow* focusedWindow;
1603 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1604 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1605 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1606 return injectionResult;
1607 }
1608
1609 windowType = focusedWindow->layoutParamsType;
1610 } // release lock
1611
1612 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1613 return INPUT_EVENT_INJECTION_SUCCEEDED;
1614}
1615
1616int32_t NativeInputManager::identifyTouchEventTargets(MotionEvent* motionEvent,
1617 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1618 Vector<InputTarget>& outTargets) {
1619#if DEBUG_INPUT_DISPATCHER_POLICY
1620 LOGD("identifyTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1621 policyFlags, injectorPid, injectorUid);
1622#endif
1623
1624 int32_t windowType;
1625 { // acquire lock
1626 AutoMutex _l(mDispatchLock);
1627
1628 InputWindow* touchedWindow;
1629 int32_t injectionResult = waitForTouchedWindowLd(motionEvent, policyFlags,
1630 injectorPid, injectorUid, outTargets, /*out*/ touchedWindow);
1631 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1632 return injectionResult;
1633 }
1634
1635 windowType = touchedWindow->layoutParamsType;
1636 } // release lock
1637
1638 int32_t eventType;
1639 switch (motionEvent->getAction()) {
1640 case MOTION_EVENT_ACTION_DOWN:
1641 eventType = POWER_MANAGER_TOUCH_EVENT;
1642 break;
1643 case MOTION_EVENT_ACTION_UP:
1644 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
1645 break;
1646 default:
1647 if (motionEvent->getEventTime() - motionEvent->getDownTime()
1648 >= EVENT_IGNORE_DURATION) {
1649 eventType = POWER_MANAGER_TOUCH_EVENT;
1650 } else {
1651 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
1652 }
1653 break;
1654 }
1655 pokeUserActivityIfNeeded(windowType, eventType);
1656 return INPUT_EVENT_INJECTION_SUCCEEDED;
1657}
1658
1659void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType) {
1660 if (windowType != TYPE_KEYGUARD) {
1661 nsecs_t eventTime = now();
1662 pokeUserActivity(eventTime, eventType);
1663 }
1664}
1665
1666void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
1667 JNIEnv* env = jniEnv();
1668 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.pokeUserActivity,
1669 eventTime, eventType);
1670 checkAndClearExceptionFromCallback(env, "pokeUserActivity");
1671}
1672
1673void NativeInputManager::dumpDispatchStateLd() {
1674#if DEBUG_FOCUS
1675 LOGD(" dispatcherState: dispatchEnabled=%d, dispatchFrozen=%d, windowsReady=%d",
1676 mDispatchEnabled, mDispatchFrozen, mWindowsReady);
1677 if (mFocusedApplication) {
1678 LOGD(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms",
1679 mFocusedApplication->name.string(),
1680 mFocusedApplication->dispatchingTimeout / 1000000.0);
1681 } else {
1682 LOGD(" focusedApplication: <null>");
1683 }
1684 LOGD(" focusedWindow: '%s'",
1685 mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
1686 LOGD(" touchedWindow: '%s', touchDown=%d",
1687 mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
1688 mTouchDown);
1689 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
1690 LOGD(" touchedWallpaperWindows[%d]: '%s'",
1691 i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
1692 }
1693 for (size_t i = 0; i < mWindows.size(); i++) {
1694 LOGD(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, visible=%d, "
1695 "flags=0x%08x, type=0x%08x, "
1696 "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
1697 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms",
1698 i, mWindows[i].inputChannel->getName().string(),
1699 mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
1700 mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
1701 mWindows[i].frameLeft, mWindows[i].frameTop,
1702 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
1703 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
1704 mWindows[i].ownerPid, mWindows[i].ownerUid,
1705 mWindows[i].dispatchingTimeout / 1000000.0);
1706 }
1707#endif
1708}
1709
1710// ----------------------------------------------------------------------------
1711
1712NativeInputManager::ANRTimer::ANRTimer() :
1713 mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
1714}
1715
1716void NativeInputManager::ANRTimer::dispatchFrozenBySystem() {
1717 mFrozen = true;
1718}
1719
1720void NativeInputManager::ANRTimer::dispatchPausedByApplication(InputWindow* pausedWindow) {
1721 mPausedWindow = pausedWindow;
1722}
1723
1724bool NativeInputManager::ANRTimer::waitForDispatchStateChangeLd(NativeInputManager* inputManager) {
1725 nsecs_t currentTime = now();
1726
1727 Budget newBudget;
1728 nsecs_t dispatchingTimeout;
1729 sp<InputChannel> pausedChannel = NULL;
1730 jobject tokenObj = NULL;
1731 if (mFrozen) {
1732 newBudget = SYSTEM;
1733 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1734 mFrozen = false;
1735 } else if (mPausedWindow) {
1736 newBudget = APPLICATION;
1737 dispatchingTimeout = mPausedWindow->dispatchingTimeout;
1738 pausedChannel = mPausedWindow->inputChannel;
1739 mPausedWindow = NULL;
1740 } else if (inputManager->mFocusedApplication) {
1741 newBudget = APPLICATION;
1742 dispatchingTimeout = inputManager->mFocusedApplication->dispatchingTimeout;
1743 tokenObj = jniEnv()->NewLocalRef(inputManager->mFocusedApplication->tokenObjWeak);
1744 } else {
1745 newBudget = APPLICATION;
1746 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1747 }
1748
1749 if (mBudget != newBudget) {
1750 mBudget = newBudget;
1751 mStartTime = currentTime;
1752 }
1753
1754 bool result = false;
1755 nsecs_t timeoutRemaining = mStartTime + dispatchingTimeout - currentTime;
1756 if (timeoutRemaining > 0
1757 && inputManager->mDispatchStateChanged.waitRelative(inputManager->mDispatchLock,
1758 timeoutRemaining) == OK) {
1759 result = true;
1760 } else {
1761 if (pausedChannel != NULL || tokenObj != NULL) {
1762 bool resumed;
1763 nsecs_t newTimeout = 0;
1764
1765 inputManager->mDispatchLock.unlock(); // release lock
1766 if (pausedChannel != NULL) {
1767 resumed = inputManager->notifyInputChannelANR(pausedChannel, /*out*/ newTimeout);
1768 } else {
1769 resumed = inputManager->notifyANR(tokenObj, /*out*/ newTimeout);
1770 }
1771 inputManager->mDispatchLock.lock(); // re-acquire lock
1772
1773 if (resumed) {
1774 mStartTime = now() - dispatchingTimeout + newTimeout;
1775 result = true;
1776 }
1777 }
1778 }
1779
1780 if (tokenObj) {
1781 jniEnv()->DeleteLocalRef(tokenObj);
1782 }
1783
1784 return result;
1785}
1786
1787nsecs_t NativeInputManager::ANRTimer::getTimeSpentWaitingForApplication() const {
1788 return mBudget == APPLICATION ? now() - mStartTime : 0;
1789}
Jeff Brown9c3cda02010-06-15 01:31:58 -07001790
1791// ----------------------------------------------------------------------------
1792
1793static sp<NativeInputManager> gNativeInputManager;
1794
Jeff Brown46b9ac02010-04-22 18:58:52 -07001795static bool checkInputManagerUnitialized(JNIEnv* env) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001796 if (gNativeInputManager == NULL) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001797 LOGE("Input manager not initialized.");
1798 jniThrowRuntimeException(env, "Input manager not initialized.");
1799 return true;
1800 }
1801 return false;
1802}
1803
1804static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
1805 jobject callbacks) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001806 if (gNativeInputManager == NULL) {
1807 gNativeInputManager = new NativeInputManager(callbacks);
1808 } else {
1809 LOGE("Input manager already initialized.");
1810 jniThrowRuntimeException(env, "Input manager already initialized.");
Jeff Brown46b9ac02010-04-22 18:58:52 -07001811 }
1812}
1813
1814static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
1815 if (checkInputManagerUnitialized(env)) {
1816 return;
1817 }
1818
Jeff Brown9c3cda02010-06-15 01:31:58 -07001819 status_t result = gNativeInputManager->getInputManager()->start();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001820 if (result) {
1821 jniThrowRuntimeException(env, "Input manager could not be started.");
1822 }
1823}
1824
1825static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
1826 jint displayId, jint width, jint height) {
1827 if (checkInputManagerUnitialized(env)) {
1828 return;
1829 }
1830
1831 // XXX we could get this from the SurfaceFlinger directly instead of requiring it
1832 // to be passed in like this, not sure which is better but leaving it like this
1833 // keeps the window manager in direct control of when display transitions propagate down
1834 // to the input dispatcher
Jeff Brown9c3cda02010-06-15 01:31:58 -07001835 gNativeInputManager->setDisplaySize(displayId, width, height);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001836}
1837
1838static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
1839 jint displayId, jint orientation) {
1840 if (checkInputManagerUnitialized(env)) {
1841 return;
1842 }
1843
Jeff Brown9c3cda02010-06-15 01:31:58 -07001844 gNativeInputManager->setDisplayOrientation(displayId, orientation);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001845}
1846
1847static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
1848 jint deviceId, jint deviceClasses, jint scanCode) {
1849 if (checkInputManagerUnitialized(env)) {
1850 return KEY_STATE_UNKNOWN;
1851 }
1852
Jeff Brown9c3cda02010-06-15 01:31:58 -07001853 return gNativeInputManager->getInputManager()->getScanCodeState(
1854 deviceId, deviceClasses, scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001855}
1856
1857static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
1858 jint deviceId, jint deviceClasses, jint keyCode) {
1859 if (checkInputManagerUnitialized(env)) {
1860 return KEY_STATE_UNKNOWN;
1861 }
1862
Jeff Brown9c3cda02010-06-15 01:31:58 -07001863 return gNativeInputManager->getInputManager()->getKeyCodeState(
1864 deviceId, deviceClasses, keyCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001865}
1866
1867static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
1868 jint deviceId, jint deviceClasses, jint sw) {
1869 if (checkInputManagerUnitialized(env)) {
1870 return KEY_STATE_UNKNOWN;
1871 }
1872
Jeff Brown9c3cda02010-06-15 01:31:58 -07001873 return gNativeInputManager->getInputManager()->getSwitchState(deviceId, deviceClasses, sw);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001874}
1875
1876static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
1877 jintArray keyCodes, jbooleanArray outFlags) {
1878 if (checkInputManagerUnitialized(env)) {
1879 return JNI_FALSE;
1880 }
1881
1882 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
1883 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
1884 jsize numCodes = env->GetArrayLength(keyCodes);
1885 jboolean result;
1886 if (numCodes == env->GetArrayLength(outFlags)) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001887 result = gNativeInputManager->getInputManager()->hasKeys(numCodes, codes, flags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001888 } else {
1889 result = JNI_FALSE;
1890 }
1891
1892 env->ReleaseBooleanArrayElements(outFlags, flags, 0);
1893 env->ReleaseIntArrayElements(keyCodes, codes, 0);
1894 return result;
1895}
1896
1897static void throwInputChannelNotInitialized(JNIEnv* env) {
1898 jniThrowException(env, "java/lang/IllegalStateException",
1899 "inputChannel is not initialized");
1900}
1901
1902static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
1903 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
1904 LOGW("Input channel object '%s' was disposed without first being unregistered with "
1905 "the input manager!", inputChannel->getName().string());
1906
Jeff Brown9c3cda02010-06-15 01:31:58 -07001907 if (gNativeInputManager != NULL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001908 gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001909 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001910}
1911
1912static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
1913 jobject inputChannelObj) {
1914 if (checkInputManagerUnitialized(env)) {
1915 return;
1916 }
1917
1918 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1919 inputChannelObj);
1920 if (inputChannel == NULL) {
1921 throwInputChannelNotInitialized(env);
1922 return;
1923 }
1924
Jeff Brown7fbdc842010-06-17 20:52:56 -07001925
1926 status_t status = gNativeInputManager->registerInputChannel(
1927 env, inputChannel, inputChannelObj);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001928 if (status) {
1929 jniThrowRuntimeException(env, "Failed to register input channel. "
1930 "Check logs for details.");
1931 return;
1932 }
1933
1934 android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
1935 android_server_InputManager_handleInputChannelDisposed, NULL);
1936}
1937
1938static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
1939 jobject inputChannelObj) {
1940 if (checkInputManagerUnitialized(env)) {
1941 return;
1942 }
1943
1944 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1945 inputChannelObj);
1946 if (inputChannel == NULL) {
1947 throwInputChannelNotInitialized(env);
1948 return;
1949 }
1950
1951 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
1952
Jeff Brown7fbdc842010-06-17 20:52:56 -07001953 status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001954 if (status) {
1955 jniThrowRuntimeException(env, "Failed to unregister input channel. "
1956 "Check logs for details.");
1957 }
1958}
1959
Jeff Brown7fbdc842010-06-17 20:52:56 -07001960static jint android_server_InputManager_nativeInjectKeyEvent(JNIEnv* env, jclass clazz,
1961 jobject keyEventObj, jint nature, jint injectorPid, jint injectorUid,
1962 jboolean sync, jint timeoutMillis) {
1963 if (checkInputManagerUnitialized(env)) {
1964 return INPUT_EVENT_INJECTION_FAILED;
1965 }
1966
1967 KeyEvent keyEvent;
1968 android_view_KeyEvent_toNative(env, keyEventObj, nature, & keyEvent);
1969
1970 return gNativeInputManager->getInputManager()->injectInputEvent(& keyEvent,
1971 injectorPid, injectorUid, sync, timeoutMillis);
1972}
1973
1974static jint android_server_InputManager_nativeInjectMotionEvent(JNIEnv* env, jclass clazz,
1975 jobject motionEventObj, jint nature, jint injectorPid, jint injectorUid,
1976 jboolean sync, jint timeoutMillis) {
1977 if (checkInputManagerUnitialized(env)) {
1978 return INPUT_EVENT_INJECTION_FAILED;
1979 }
1980
1981 MotionEvent motionEvent;
1982 android_view_MotionEvent_toNative(env, motionEventObj, nature, & motionEvent);
1983
1984 return gNativeInputManager->getInputManager()->injectInputEvent(& motionEvent,
1985 injectorPid, injectorUid, sync, timeoutMillis);
1986}
1987
Jeff Brown349703e2010-06-22 01:27:15 -07001988static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
1989 jobjectArray windowObjArray) {
1990 if (checkInputManagerUnitialized(env)) {
1991 return;
1992 }
1993
1994 gNativeInputManager->setInputWindows(env, windowObjArray);
1995}
1996
1997static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
1998 jobject applicationObj) {
1999 if (checkInputManagerUnitialized(env)) {
2000 return;
2001 }
2002
2003 gNativeInputManager->setFocusedApplication(env, applicationObj);
2004}
2005
2006static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
2007 jclass clazz, jboolean enabled, jboolean frozen) {
2008 if (checkInputManagerUnitialized(env)) {
2009 return;
2010 }
2011
2012 gNativeInputManager->setInputDispatchMode(enabled, frozen);
2013}
2014
2015static void android_server_InputManager_nativePreemptInputDispatch(JNIEnv* env,
2016 jclass clazz) {
2017 if (checkInputManagerUnitialized(env)) {
2018 return;
2019 }
2020
2021 gNativeInputManager->preemptInputDispatch();
2022}
2023
Jeff Brown9c3cda02010-06-15 01:31:58 -07002024// ----------------------------------------------------------------------------
2025
Jeff Brown46b9ac02010-04-22 18:58:52 -07002026static JNINativeMethod gInputManagerMethods[] = {
2027 /* name, signature, funcPtr */
2028 { "nativeInit", "(Lcom/android/server/InputManager$Callbacks;)V",
2029 (void*) android_server_InputManager_nativeInit },
2030 { "nativeStart", "()V",
2031 (void*) android_server_InputManager_nativeStart },
2032 { "nativeSetDisplaySize", "(III)V",
2033 (void*) android_server_InputManager_nativeSetDisplaySize },
2034 { "nativeSetDisplayOrientation", "(II)V",
2035 (void*) android_server_InputManager_nativeSetDisplayOrientation },
2036 { "nativeGetScanCodeState", "(III)I",
2037 (void*) android_server_InputManager_nativeGetScanCodeState },
2038 { "nativeGetKeyCodeState", "(III)I",
2039 (void*) android_server_InputManager_nativeGetKeyCodeState },
2040 { "nativeGetSwitchState", "(III)I",
2041 (void*) android_server_InputManager_nativeGetSwitchState },
2042 { "nativeHasKeys", "([I[Z)Z",
2043 (void*) android_server_InputManager_nativeHasKeys },
2044 { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;)V",
2045 (void*) android_server_InputManager_nativeRegisterInputChannel },
2046 { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002047 (void*) android_server_InputManager_nativeUnregisterInputChannel },
2048 { "nativeInjectKeyEvent", "(Landroid/view/KeyEvent;IIIZI)I",
2049 (void*) android_server_InputManager_nativeInjectKeyEvent },
2050 { "nativeInjectMotionEvent", "(Landroid/view/MotionEvent;IIIZI)I",
Jeff Brown349703e2010-06-22 01:27:15 -07002051 (void*) android_server_InputManager_nativeInjectMotionEvent },
2052 { "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V",
2053 (void*) android_server_InputManager_nativeSetInputWindows },
2054 { "nativeSetFocusedApplication", "(Lcom/android/server/InputApplication;)V",
2055 (void*) android_server_InputManager_nativeSetFocusedApplication },
2056 { "nativeSetInputDispatchMode", "(ZZ)V",
2057 (void*) android_server_InputManager_nativeSetInputDispatchMode },
2058 { "nativePreemptInputDispatch", "()V",
2059 (void*) android_server_InputManager_nativePreemptInputDispatch }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002060};
2061
2062#define FIND_CLASS(var, className) \
2063 var = env->FindClass(className); \
2064 LOG_FATAL_IF(! var, "Unable to find class " className); \
2065 var = jclass(env->NewGlobalRef(var));
2066
2067#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2068 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2069 LOG_FATAL_IF(! var, "Unable to find method " methodName);
2070
2071#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
2072 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
2073 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
2074
2075int register_android_server_InputManager(JNIEnv* env) {
2076 int res = jniRegisterNativeMethods(env, "com/android/server/InputManager",
2077 gInputManagerMethods, NELEM(gInputManagerMethods));
2078 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2079
Jeff Brown9c3cda02010-06-15 01:31:58 -07002080 // Callbacks
Jeff Brown46b9ac02010-04-22 18:58:52 -07002081
2082 FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
2083
2084 GET_METHOD_ID(gCallbacksClassInfo.isScreenOn, gCallbacksClassInfo.clazz,
2085 "isScreenOn", "()Z");
2086
2087 GET_METHOD_ID(gCallbacksClassInfo.isScreenBright, gCallbacksClassInfo.clazz,
2088 "isScreenBright", "()Z");
2089
2090 GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
2091 "notifyConfigurationChanged", "(JIII)V");
2092
2093 GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
2094 "notifyLidSwitchChanged", "(JZ)V");
2095
Jeff Brown7fbdc842010-06-17 20:52:56 -07002096 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
2097 "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
2098
2099 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelANR, gCallbacksClassInfo.clazz,
2100 "notifyInputChannelANR", "(Landroid/view/InputChannel;)J");
2101
2102 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelRecoveredFromANR, gCallbacksClassInfo.clazz,
2103 "notifyInputChannelRecoveredFromANR", "(Landroid/view/InputChannel;)V");
2104
Jeff Brown349703e2010-06-22 01:27:15 -07002105 GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
2106 "notifyANR", "(Ljava/lang/Object;)J");
2107
Jeff Brown46b9ac02010-04-22 18:58:52 -07002108 GET_METHOD_ID(gCallbacksClassInfo.virtualKeyFeedback, gCallbacksClassInfo.clazz,
2109 "virtualKeyFeedback", "(JIIIIIIJ)V");
2110
Jeff Brown349703e2010-06-22 01:27:15 -07002111 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
2112 "interceptKeyBeforeQueueing", "(IIIIIIJZ)I");
2113
2114 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
2115 "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIZII)Z");
2116
2117 GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
2118 "checkInjectEventsPermission", "(II)Z");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002119
2120 GET_METHOD_ID(gCallbacksClassInfo.goToSleep, gCallbacksClassInfo.clazz,
2121 "goToSleep", "(J)V");
2122
Jeff Brown349703e2010-06-22 01:27:15 -07002123 GET_METHOD_ID(gCallbacksClassInfo.pokeUserActivity, gCallbacksClassInfo.clazz,
2124 "pokeUserActivity", "(JI)V");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002125
2126 GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz,
2127 "notifyAppSwitchComing", "()V");
2128
2129 GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz,
2130 "filterTouchEvents", "()Z");
2131
2132 GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
2133 "filterJumpyTouchEvents", "()Z");
2134
2135 GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz,
2136 "getVirtualKeyDefinitions",
2137 "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
2138
2139 GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
2140 "getExcludedDeviceNames", "()[Ljava/lang/String;");
2141
Jeff Brown46b9ac02010-04-22 18:58:52 -07002142 // VirtualKeyDefinition
2143
2144 FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
2145 "com/android/server/InputManager$VirtualKeyDefinition");
2146
2147 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz,
2148 "scanCode", "I");
2149
2150 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz,
2151 "centerX", "I");
2152
2153 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz,
2154 "centerY", "I");
2155
2156 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz,
2157 "width", "I");
2158
2159 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
2160 "height", "I");
2161
Jeff Brown349703e2010-06-22 01:27:15 -07002162 // InputWindow
Jeff Brown7fbdc842010-06-17 20:52:56 -07002163
Jeff Brown349703e2010-06-22 01:27:15 -07002164 FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002165
Jeff Brown349703e2010-06-22 01:27:15 -07002166 GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
2167 "inputChannel", "Landroid/view/InputChannel;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002168
Jeff Brown349703e2010-06-22 01:27:15 -07002169 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
2170 "layoutParamsFlags", "I");
2171
2172 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
2173 "layoutParamsType", "I");
2174
2175 GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
2176 "dispatchingTimeoutNanos", "J");
2177
2178 GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
2179 "frameLeft", "I");
2180
2181 GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
2182 "frameTop", "I");
2183
2184 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
2185 "touchableAreaLeft", "I");
2186
2187 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
2188 "touchableAreaTop", "I");
2189
2190 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
2191 "touchableAreaRight", "I");
2192
2193 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
2194 "touchableAreaBottom", "I");
2195
2196 GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
2197 "visible", "Z");
2198
2199 GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
2200 "hasFocus", "Z");
2201
2202 GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
2203 "hasWallpaper", "Z");
2204
2205 GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
2206 "paused", "Z");
2207
2208 GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
2209 "ownerPid", "I");
2210
2211 GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
2212 "ownerUid", "I");
2213
2214 // InputApplication
2215
2216 FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
2217
2218 GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
2219 "name", "Ljava/lang/String;");
2220
2221 GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
2222 gInputApplicationClassInfo.clazz,
2223 "dispatchingTimeoutNanos", "J");
2224
2225 GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
2226 "token", "Ljava/lang/Object;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002227
Jeff Brown46b9ac02010-04-22 18:58:52 -07002228 return 0;
2229}
2230
Jeff Brown46b9ac02010-04-22 18:58:52 -07002231} /* namespace android */