blob: d0f856b84f5ae50b0be4f118211c1a55e25c6d8b [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
Jeff Brownd0097872010-06-30 14:41:59 -0700377 bool interceptKeyBeforeDispatching(const InputTarget& target,
378 const KeyEvent* keyEvent, uint32_t policyFlags);
379
Jeff Brown349703e2010-06-22 01:27:15 -0700380 void pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType);
381 void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
382 bool checkInjectionPermission(const InputWindow* window,
383 int32_t injectorPid, int32_t injectorUid);
384
385 static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
386 static void addTarget(const InputWindow* window, int32_t targetFlags,
387 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets);
388
Jeff Brown9c3cda02010-06-15 01:31:58 -0700389 static inline JNIEnv* jniEnv() {
390 return AndroidRuntime::getJNIEnv();
391 }
392
393 static bool isAppSwitchKey(int32_t keyCode);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700394 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700395};
396
397// ----------------------------------------------------------------------------
398
399NativeInputManager::NativeInputManager(jobject callbacksObj) :
400 mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
Jeff Brown0b72e822010-06-29 16:52:21 -0700401 mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0),
Jeff Brown349703e2010-06-22 01:27:15 -0700402 mDispatchEnabled(true), mDispatchFrozen(false), mWindowsReady(true),
403 mFocusedWindow(NULL), mTouchDown(false), mTouchedWindow(NULL),
404 mFocusedApplication(NULL) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700405 JNIEnv* env = jniEnv();
406
407 mCallbacksObj = env->NewGlobalRef(callbacksObj);
408
409 sp<EventHub> eventHub = new EventHub();
410 mInputManager = new InputManager(eventHub, this, this);
411}
412
413NativeInputManager::~NativeInputManager() {
414 JNIEnv* env = jniEnv();
415
416 env->DeleteGlobalRef(mCallbacksObj);
Jeff Brown349703e2010-06-22 01:27:15 -0700417
418 releaseFocusedApplicationLd(env);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700419}
420
421bool NativeInputManager::isAppSwitchKey(int32_t keyCode) {
422 return keyCode == KEYCODE_HOME || keyCode == KEYCODE_ENDCALL;
423}
424
Jeff Brown7fbdc842010-06-17 20:52:56 -0700425bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700426 if (env->ExceptionCheck()) {
427 LOGE("An exception was thrown by callback '%s'.", methodName);
428 LOGE_EX(env);
429 env->ExceptionClear();
430 return true;
431 }
432 return false;
433}
434
435void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
436 if (displayId == 0) {
437 AutoMutex _l(mDisplayLock);
438
439 mDisplayWidth = width;
440 mDisplayHeight = height;
441 }
442}
443
444void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
445 if (displayId == 0) {
446 AutoMutex _l(mDisplayLock);
447
448 mDisplayOrientation = orientation;
449 }
450}
451
Jeff Brown7fbdc842010-06-17 20:52:56 -0700452status_t NativeInputManager::registerInputChannel(JNIEnv* env,
453 const sp<InputChannel>& inputChannel, jobject inputChannelObj) {
454 jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
455 if (! inputChannelObjWeak) {
456 LOGE("Could not create weak reference for input channel.");
457 LOGE_EX(env);
458 return NO_MEMORY;
459 }
460
461 status_t status;
462 {
463 AutoMutex _l(mInputChannelRegistryLock);
464
465 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
466 inputChannel->getReceivePipeFd());
467 if (index >= 0) {
468 LOGE("Input channel object '%s' has already been registered",
469 inputChannel->getName().string());
470 status = INVALID_OPERATION;
471 goto DeleteWeakRef;
472 }
473
474 mInputChannelObjWeakByReceiveFd.add(inputChannel->getReceivePipeFd(),
475 inputChannelObjWeak);
476 }
477
478 status = mInputManager->registerInputChannel(inputChannel);
479 if (! status) {
480 return OK;
481 }
482
483 {
484 AutoMutex _l(mInputChannelRegistryLock);
485 mInputChannelObjWeakByReceiveFd.removeItem(inputChannel->getReceivePipeFd());
486 }
487
488DeleteWeakRef:
489 env->DeleteWeakGlobalRef(inputChannelObjWeak);
490 return status;
491}
492
493status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
494 const sp<InputChannel>& inputChannel) {
495 jweak inputChannelObjWeak;
496 {
497 AutoMutex _l(mInputChannelRegistryLock);
498
499 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
500 inputChannel->getReceivePipeFd());
501 if (index < 0) {
502 LOGE("Input channel object '%s' is not currently registered",
503 inputChannel->getName().string());
504 return INVALID_OPERATION;
505 }
506
507 inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
508 mInputChannelObjWeakByReceiveFd.removeItemsAt(index);
509 }
510
511 env->DeleteWeakGlobalRef(inputChannelObjWeak);
512
513 return mInputManager->unregisterInputChannel(inputChannel);
514}
515
516jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
517 const sp<InputChannel>& inputChannel) {
518 {
519 AutoMutex _l(mInputChannelRegistryLock);
520
521 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
522 inputChannel->getReceivePipeFd());
523 if (index < 0) {
524 return NULL;
525 }
526
527 jweak inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
528 return env->NewLocalRef(inputChannelObjWeak);
529 }
530}
531
Jeff Brown9c3cda02010-06-15 01:31:58 -0700532bool NativeInputManager::getDisplayInfo(int32_t displayId,
533 int32_t* width, int32_t* height, int32_t* orientation) {
534 bool result = false;
535 if (displayId == 0) {
536 AutoMutex _l(mDisplayLock);
537
538 if (mDisplayWidth > 0) {
539 *width = mDisplayWidth;
540 *height = mDisplayHeight;
541 *orientation = mDisplayOrientation;
542 result = true;
543 }
544 }
545 return result;
546}
547
548bool NativeInputManager::isScreenOn() {
549 JNIEnv* env = jniEnv();
550
551 jboolean result = env->CallBooleanMethod(mCallbacksObj, gCallbacksClassInfo.isScreenOn);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700552 if (checkAndClearExceptionFromCallback(env, "isScreenOn")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700553 return true;
554 }
555 return result;
556}
557
558bool NativeInputManager::isScreenBright() {
559 JNIEnv* env = jniEnv();
560
561 jboolean result = env->CallBooleanMethod(mCallbacksObj, gCallbacksClassInfo.isScreenBright);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700562 if (checkAndClearExceptionFromCallback(env, "isScreenBright")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700563 return true;
564 }
565 return result;
566}
567
568void NativeInputManager::virtualKeyFeedback(nsecs_t when, int32_t deviceId,
569 int32_t action, int32_t flags, int32_t keyCode,
570 int32_t scanCode, int32_t metaState, nsecs_t downTime) {
571#if DEBUG_INPUT_READER_POLICY
572 LOGD("virtualKeyFeedback - when=%lld, deviceId=%d, action=%d, flags=%d, keyCode=%d, "
573 "scanCode=%d, metaState=%d, downTime=%lld",
574 when, deviceId, action, flags, keyCode, scanCode, metaState, downTime);
575#endif
576
577 JNIEnv* env = jniEnv();
578
579 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyFeedback,
580 when, deviceId, action, flags, keyCode, scanCode, metaState, downTime);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700581 checkAndClearExceptionFromCallback(env, "virtualKeyFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700582}
583
584int32_t NativeInputManager::interceptKey(nsecs_t when,
585 int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
586#if DEBUG_INPUT_READER_POLICY
587 LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
Jeff Brown349703e2010-06-22 01:27:15 -0700588 "policyFlags=0x%x",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700589 when, deviceId, down, keyCode, scanCode, policyFlags);
590#endif
591
592 const int32_t WM_ACTION_PASS_TO_USER = 1;
593 const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
594 const int32_t WM_ACTION_GO_TO_SLEEP = 4;
595
596 JNIEnv* env = jniEnv();
597
598 bool isScreenOn = this->isScreenOn();
599 bool isScreenBright = this->isScreenBright();
600
Jeff Brown349703e2010-06-22 01:27:15 -0700601 jint wmActions = env->CallIntMethod(mCallbacksObj,
602 gCallbacksClassInfo.interceptKeyBeforeQueueing,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700603 deviceId, EV_KEY, scanCode, keyCode, policyFlags, down ? 1 : 0, when, isScreenOn);
Jeff Brown349703e2010-06-22 01:27:15 -0700604 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700605 wmActions = 0;
606 }
607
608 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
609 if (! isScreenOn) {
610 // Key presses and releases wake the device.
611 actions |= InputReaderPolicyInterface::ACTION_WOKE_HERE;
612 }
613
614 if (! isScreenBright) {
615 // Key presses and releases brighten the screen if dimmed.
616 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
617 }
618
619 if (wmActions & WM_ACTION_GO_TO_SLEEP) {
620 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.goToSleep, when);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700621 checkAndClearExceptionFromCallback(env, "goToSleep");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700622 }
623
624 if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
Jeff Brown349703e2010-06-22 01:27:15 -0700625 pokeUserActivity(when, POWER_MANAGER_BUTTON_EVENT);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700626 }
627
628 if (wmActions & WM_ACTION_PASS_TO_USER) {
629 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700630
Jeff Brown9c3cda02010-06-15 01:31:58 -0700631 if (down && isAppSwitchKey(keyCode)) {
632 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700633 checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700634
635 actions |= InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING;
636 }
637 }
Jeff Brown349703e2010-06-22 01:27:15 -0700638
Jeff Brown9c3cda02010-06-15 01:31:58 -0700639 return actions;
640}
641
642int32_t NativeInputManager::interceptTouch(nsecs_t when) {
643#if DEBUG_INPUT_READER_POLICY
644 LOGD("interceptTouch - when=%lld", when);
645#endif
646
Jeff Brown5c225b12010-06-16 01:53:36 -0700647 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
648 if (isScreenOn()) {
649 // Only dispatch touch events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700650 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700651 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700652
Jeff Brown349703e2010-06-22 01:27:15 -0700653 if (! isScreenBright()) {
654 // Brighten the screen if dimmed.
655 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
656 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700657 }
658
659 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700660}
661
662int32_t NativeInputManager::interceptTrackball(nsecs_t when,
663 bool buttonChanged, bool buttonDown, bool rolled) {
664#if DEBUG_INPUT_READER_POLICY
665 LOGD("interceptTrackball - when=%lld, buttonChanged=%d, buttonDown=%d, rolled=%d",
666 when, buttonChanged, buttonDown, rolled);
667#endif
668
Jeff Brown5c225b12010-06-16 01:53:36 -0700669 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
670 if (isScreenOn()) {
671 // Only dispatch trackball events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700672 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700673 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700674
Jeff Brown349703e2010-06-22 01:27:15 -0700675 if (! isScreenBright()) {
676 // Brighten the screen if dimmed.
677 actions |= InputReaderPolicyInterface::ACTION_BRIGHT_HERE;
678 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700679 }
680
681 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700682}
683
684int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
685 int32_t switchValue) {
686#if DEBUG_INPUT_READER_POLICY
687 LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d",
688 when, switchCode, switchValue);
689#endif
690
691 JNIEnv* env = jniEnv();
692
693 switch (switchCode) {
694 case SW_LID:
695 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
696 when, switchValue == 0);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700697 checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700698 break;
699 }
700
701 return InputReaderPolicyInterface::ACTION_NONE;
702}
703
704bool NativeInputManager::filterTouchEvents() {
705 if (mFilterTouchEvents < 0) {
706 JNIEnv* env = jniEnv();
707
708 jboolean result = env->CallBooleanMethod(mCallbacksObj,
709 gCallbacksClassInfo.filterTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700710 if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700711 result = false;
712 }
713
714 mFilterTouchEvents = result ? 1 : 0;
715 }
716 return mFilterTouchEvents;
717}
718
719bool NativeInputManager::filterJumpyTouchEvents() {
720 if (mFilterJumpyTouchEvents < 0) {
721 JNIEnv* env = jniEnv();
722
723 jboolean result = env->CallBooleanMethod(mCallbacksObj,
724 gCallbacksClassInfo.filterJumpyTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700725 if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700726 result = false;
727 }
728
729 mFilterJumpyTouchEvents = result ? 1 : 0;
730 }
731 return mFilterJumpyTouchEvents;
732}
733
734void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
735 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions) {
736 JNIEnv* env = jniEnv();
737
738 jstring deviceNameStr = env->NewStringUTF(deviceName.string());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700739 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700740 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
741 gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700742 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700743 jsize length = env->GetArrayLength(result);
744 for (jsize i = 0; i < length; i++) {
745 jobject item = env->GetObjectArrayElement(result, i);
746
747 outVirtualKeyDefinitions.add();
748 outVirtualKeyDefinitions.editTop().scanCode =
749 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode));
750 outVirtualKeyDefinitions.editTop().centerX =
751 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX));
752 outVirtualKeyDefinitions.editTop().centerY =
753 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY));
754 outVirtualKeyDefinitions.editTop().width =
755 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width));
756 outVirtualKeyDefinitions.editTop().height =
757 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height));
758
759 env->DeleteLocalRef(item);
760 }
761 env->DeleteLocalRef(result);
762 }
763 env->DeleteLocalRef(deviceNameStr);
764 }
765}
766
767void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
768 JNIEnv* env = jniEnv();
769
770 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
771 gCallbacksClassInfo.getExcludedDeviceNames));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700772 if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700773 jsize length = env->GetArrayLength(result);
774 for (jsize i = 0; i < length; i++) {
775 jstring item = jstring(env->GetObjectArrayElement(result, i));
776
777 const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
778 outExcludedDeviceNames.add(String8(deviceNameChars));
779 env->ReleaseStringUTFChars(item, deviceNameChars);
780
781 env->DeleteLocalRef(item);
782 }
783 env->DeleteLocalRef(result);
784 }
785}
786
787void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
788#if DEBUG_INPUT_DISPATCHER_POLICY
789 LOGD("notifyConfigurationChanged - when=%lld", when);
790#endif
791
792 JNIEnv* env = jniEnv();
793
794 InputConfiguration config;
795 mInputManager->getInputConfiguration(& config);
796
797 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
798 when, config.touchScreen, config.keyboard, config.navigation);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700799 checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700800}
801
802void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
803#if DEBUG_INPUT_DISPATCHER_POLICY
804 LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
805#endif
806
Jeff Brown7fbdc842010-06-17 20:52:56 -0700807 JNIEnv* env = jniEnv();
808
809 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
810 if (inputChannelObjLocal) {
811 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
812 inputChannelObjLocal);
813 checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
814
815 env->DeleteLocalRef(inputChannelObjLocal);
816 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700817}
818
Jeff Brown7fbdc842010-06-17 20:52:56 -0700819bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel,
820 nsecs_t& outNewTimeout) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700821#if DEBUG_INPUT_DISPATCHER_POLICY
822 LOGD("notifyInputChannelANR - inputChannel='%s'",
823 inputChannel->getName().string());
824#endif
825
Jeff Brown7fbdc842010-06-17 20:52:56 -0700826 JNIEnv* env = jniEnv();
827
828 jlong newTimeout;
829 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
830 if (inputChannelObjLocal) {
831 newTimeout = env->CallLongMethod(mCallbacksObj,
832 gCallbacksClassInfo.notifyInputChannelANR, inputChannelObjLocal);
833 if (checkAndClearExceptionFromCallback(env, "notifyInputChannelANR")) {
834 newTimeout = -2;
835 }
836
837 env->DeleteLocalRef(inputChannelObjLocal);
838 } else {
839 newTimeout = -2;
840 }
841
842 if (newTimeout == -2) {
843 return false; // abort
844 }
845
846 outNewTimeout = newTimeout;
847 return true; // resume
Jeff Brown9c3cda02010-06-15 01:31:58 -0700848}
849
850void NativeInputManager::notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) {
851#if DEBUG_INPUT_DISPATCHER_POLICY
852 LOGD("notifyInputChannelRecoveredFromANR - inputChannel='%s'",
853 inputChannel->getName().string());
854#endif
855
Jeff Brown7fbdc842010-06-17 20:52:56 -0700856 JNIEnv* env = jniEnv();
857
858 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
859 if (inputChannelObjLocal) {
860 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelRecoveredFromANR,
861 inputChannelObjLocal);
862 checkAndClearExceptionFromCallback(env, "notifyInputChannelRecoveredFromANR");
863
864 env->DeleteLocalRef(inputChannelObjLocal);
865 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700866}
867
Jeff Brown349703e2010-06-22 01:27:15 -0700868bool NativeInputManager::notifyANR(jobject tokenObj, nsecs_t& outNewTimeout) {
869#if DEBUG_INPUT_DISPATCHER_POLICY
870 LOGD("notifyANR");
871#endif
872
873 JNIEnv* env = jniEnv();
874
875 jlong newTimeout = env->CallLongMethod(mCallbacksObj,
876 gCallbacksClassInfo.notifyANR, tokenObj);
877 if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
878 newTimeout = -2;
879 }
880
881 if (newTimeout == -2) {
882 return false; // abort
883 }
884
885 outNewTimeout = newTimeout;
886 return true; // resume
887}
888
Jeff Brown9c3cda02010-06-15 01:31:58 -0700889nsecs_t NativeInputManager::getKeyRepeatTimeout() {
890 if (! isScreenOn()) {
891 // Disable key repeat when the screen is off.
892 return -1;
893 } else {
894 // TODO use ViewConfiguration.getLongPressTimeout()
895 return milliseconds_to_nanoseconds(500);
896 }
897}
898
Jeff Brown349703e2010-06-22 01:27:15 -0700899void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
900#if DEBUG_FOCUS
901 LOGD("setInputWindows");
902#endif
903 { // acquire lock
904 AutoMutex _l(mDispatchLock);
905
906 sp<InputChannel> touchedWindowChannel;
907 if (mTouchedWindow) {
908 touchedWindowChannel = mTouchedWindow->inputChannel;
909 mTouchedWindow = NULL;
910 }
911 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
912 if (numTouchedWallpapers != 0) {
913 for (size_t i = 0; i < numTouchedWallpapers; i++) {
914 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
915 }
916 mTouchedWallpaperWindows.clear();
917 }
918
919 mWindows.clear();
920 mFocusedWindow = NULL;
921 mWallpaperWindows.clear();
922
923 if (windowObjArray) {
924 mWindowsReady = true;
925
926 jsize length = env->GetArrayLength(windowObjArray);
927 for (jsize i = 0; i < length; i++) {
928 jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
929 if (! inputTargetObj) {
930 break; // found null element indicating end of used portion of the array
931 }
932
933 mWindows.push();
934 InputWindow& window = mWindows.editTop();
935 bool valid = populateWindow(env, inputTargetObj, window);
936 if (! valid) {
937 mWindows.pop();
938 }
939
940 env->DeleteLocalRef(inputTargetObj);
941 }
942
943 size_t numWindows = mWindows.size();
944 for (size_t i = 0; i < numWindows; i++) {
945 InputWindow* window = & mWindows.editItemAt(i);
946 if (window->hasFocus) {
947 mFocusedWindow = window;
948 }
949
950 if (window->layoutParamsType == TYPE_WALLPAPER) {
951 mWallpaperWindows.push(window);
952
953 for (size_t j = 0; j < numTouchedWallpapers; j++) {
954 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
955 mTouchedWallpaperWindows.push(window);
956 }
957 }
958 }
959
960 if (window->inputChannel == touchedWindowChannel) {
961 mTouchedWindow = window;
962 }
963 }
964 } else {
965 mWindowsReady = false;
966 }
967
968 mTempTouchedWallpaperChannels.clear();
969
970 mDispatchStateChanged.broadcast();
971
972#if DEBUG_FOCUS
973 dumpDispatchStateLd();
974#endif
975 } // release lock
976}
977
978bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
979 InputWindow& outWindow) {
980 bool valid = false;
981
982 jobject inputChannelObj = env->GetObjectField(windowObj,
983 gInputWindowClassInfo.inputChannel);
984 if (inputChannelObj) {
985 sp<InputChannel> inputChannel =
986 android_view_InputChannel_getInputChannel(env, inputChannelObj);
987 if (inputChannel != NULL) {
988 jint layoutParamsFlags = env->GetIntField(windowObj,
989 gInputWindowClassInfo.layoutParamsFlags);
990 jint layoutParamsType = env->GetIntField(windowObj,
991 gInputWindowClassInfo.layoutParamsType);
992 jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
993 gInputWindowClassInfo.dispatchingTimeoutNanos);
994 jint frameLeft = env->GetIntField(windowObj,
995 gInputWindowClassInfo.frameLeft);
996 jint frameTop = env->GetIntField(windowObj,
997 gInputWindowClassInfo.frameTop);
998 jint touchableAreaLeft = env->GetIntField(windowObj,
999 gInputWindowClassInfo.touchableAreaLeft);
1000 jint touchableAreaTop = env->GetIntField(windowObj,
1001 gInputWindowClassInfo.touchableAreaTop);
1002 jint touchableAreaRight = env->GetIntField(windowObj,
1003 gInputWindowClassInfo.touchableAreaRight);
1004 jint touchableAreaBottom = env->GetIntField(windowObj,
1005 gInputWindowClassInfo.touchableAreaBottom);
1006 jboolean visible = env->GetBooleanField(windowObj,
1007 gInputWindowClassInfo.visible);
1008 jboolean hasFocus = env->GetBooleanField(windowObj,
1009 gInputWindowClassInfo.hasFocus);
1010 jboolean hasWallpaper = env->GetBooleanField(windowObj,
1011 gInputWindowClassInfo.hasWallpaper);
1012 jboolean paused = env->GetBooleanField(windowObj,
1013 gInputWindowClassInfo.paused);
1014 jint ownerPid = env->GetIntField(windowObj,
1015 gInputWindowClassInfo.ownerPid);
1016 jint ownerUid = env->GetIntField(windowObj,
1017 gInputWindowClassInfo.ownerUid);
1018
1019 outWindow.inputChannel = inputChannel;
1020 outWindow.layoutParamsFlags = layoutParamsFlags;
1021 outWindow.layoutParamsType = layoutParamsType;
1022 outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
1023 outWindow.frameLeft = frameLeft;
1024 outWindow.frameTop = frameTop;
1025 outWindow.touchableAreaLeft = touchableAreaLeft;
1026 outWindow.touchableAreaTop = touchableAreaTop;
1027 outWindow.touchableAreaRight = touchableAreaRight;
1028 outWindow.touchableAreaBottom = touchableAreaBottom;
1029 outWindow.visible = visible;
1030 outWindow.hasFocus = hasFocus;
1031 outWindow.hasWallpaper = hasWallpaper;
1032 outWindow.paused = paused;
1033 outWindow.ownerPid = ownerPid;
1034 outWindow.ownerUid = ownerUid;
1035 valid = true;
1036 } else {
1037 LOGW("Dropping input target because its input channel is not initialized.");
1038 }
1039
1040 env->DeleteLocalRef(inputChannelObj);
1041 } else {
1042 LOGW("Dropping input target because the input channel object was null.");
1043 }
1044 return valid;
1045}
1046
1047void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
1048#if DEBUG_FOCUS
1049 LOGD("setFocusedApplication");
1050#endif
1051 { // acquire lock
1052 AutoMutex _l(mDispatchLock);
1053
1054 releaseFocusedApplicationLd(env);
1055
1056 if (applicationObj) {
1057 jstring nameObj = jstring(env->GetObjectField(applicationObj,
1058 gInputApplicationClassInfo.name));
1059 jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
1060 gInputApplicationClassInfo.dispatchingTimeoutNanos);
1061 jobject tokenObj = env->GetObjectField(applicationObj,
1062 gInputApplicationClassInfo.token);
1063 jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
1064 if (! tokenObjWeak) {
1065 LOGE("Could not create weak reference for application token.");
1066 LOGE_EX(env);
1067 env->ExceptionClear();
1068 }
1069 env->DeleteLocalRef(tokenObj);
1070
1071 mFocusedApplication = & mFocusedApplicationStorage;
1072
1073 if (nameObj) {
1074 const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
1075 mFocusedApplication->name.setTo(nameStr);
1076 env->ReleaseStringUTFChars(nameObj, nameStr);
1077 env->DeleteLocalRef(nameObj);
1078 } else {
1079 LOGE("InputApplication.name should not be null.");
1080 mFocusedApplication->name.setTo("unknown");
1081 }
1082
1083 mFocusedApplication->dispatchingTimeout = dispatchingTimeoutNanos;
1084 mFocusedApplication->tokenObjWeak = tokenObjWeak;
1085 }
1086
1087 mDispatchStateChanged.broadcast();
1088
1089#if DEBUG_FOCUS
1090 dumpDispatchStateLd();
1091#endif
1092 } // release lock
1093}
1094
1095void NativeInputManager::releaseFocusedApplicationLd(JNIEnv* env) {
1096 if (mFocusedApplication) {
1097 env->DeleteWeakGlobalRef(mFocusedApplication->tokenObjWeak);
1098 mFocusedApplication = NULL;
1099 }
1100}
1101
1102void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
1103#if DEBUG_FOCUS
1104 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001105#endif
1106
Jeff Brown349703e2010-06-22 01:27:15 -07001107 { // acquire lock
1108 AutoMutex _l(mDispatchLock);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001109
Jeff Brown349703e2010-06-22 01:27:15 -07001110 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
1111 mDispatchEnabled = enabled;
1112 mDispatchFrozen = frozen;
1113
1114 mDispatchStateChanged.broadcast();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001115 }
Jeff Brown349703e2010-06-22 01:27:15 -07001116
1117#if DEBUG_FOCUS
1118 dumpDispatchStateLd();
1119#endif
1120 } // release lock
1121}
1122
1123void NativeInputManager::preemptInputDispatch() {
1124#if DEBUG_FOCUS
1125 LOGD("preemptInputDispatch");
1126#endif
1127
1128 mInputManager->preemptInputDispatch();
1129}
1130
1131int32_t NativeInputManager::waitForFocusedWindowLd(uint32_t policyFlags,
1132 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1133 InputWindow*& outFocusedWindow) {
1134
1135 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1136 bool firstIteration = true;
1137 ANRTimer anrTimer;
1138 for (;;) {
1139 if (firstIteration) {
1140 firstIteration = false;
1141 } else {
1142 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1143 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1144 "the window that should receive it.");
1145 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1146 break;
1147 }
1148 }
1149
1150 // If dispatch is not enabled then fail.
1151 if (! mDispatchEnabled) {
1152 LOGI("Dropping event because input dispatch is disabled.");
1153 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1154 break;
1155 }
1156
1157 // If dispatch is frozen or we don't have valid window data yet then wait.
1158 if (mDispatchFrozen || ! mWindowsReady) {
1159#if DEBUG_FOCUS
1160 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1161#endif
1162 anrTimer.dispatchFrozenBySystem();
1163 continue;
1164 }
1165
1166 // If there is no currently focused window and no focused application
1167 // then drop the event.
1168 if (! mFocusedWindow) {
1169 if (mFocusedApplication) {
1170#if DEBUG_FOCUS
1171 LOGD("Waiting because there is no focused window but there is a "
1172 "focused application that may yet introduce a new target: '%s'.",
1173 mFocusedApplication->name.string());
1174#endif
1175 continue;
1176 }
1177
1178 LOGI("Dropping event because there is no focused window or focused application.");
1179 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1180 break;
1181 }
1182
1183 // Check permissions.
1184 if (! checkInjectionPermission(mFocusedWindow, injectorPid, injectorUid)) {
1185 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1186 break;
1187 }
1188
1189 // If the currently focused window is paused then keep waiting.
1190 if (mFocusedWindow->paused) {
1191#if DEBUG_FOCUS
1192 LOGD("Waiting because focused window is paused.");
1193#endif
1194 anrTimer.dispatchPausedByApplication(mFocusedWindow);
1195 continue;
1196 }
1197
1198 // Success!
1199 break; // done waiting, exit loop
Jeff Brown9c3cda02010-06-15 01:31:58 -07001200 }
Jeff Brown349703e2010-06-22 01:27:15 -07001201
1202 // Output targets.
1203 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1204 addTarget(mFocusedWindow, InputTarget::FLAG_SYNC,
1205 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1206
1207 outFocusedWindow = mFocusedWindow;
1208 } else {
1209 outFocusedWindow = NULL;
1210 }
1211
1212#if DEBUG_FOCUS
1213 LOGD("waitForFocusedWindow finished: injectionResult=%d",
1214 injectionResult);
1215 dumpDispatchStateLd();
1216#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001217 return injectionResult;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001218}
1219
Jeff Brown349703e2010-06-22 01:27:15 -07001220int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
1221 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1222 InputWindow*& outTouchedWindow) {
1223 nsecs_t startTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001224
Jeff Brown349703e2010-06-22 01:27:15 -07001225 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1226 int32_t action = motionEvent->getAction();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001227
Jeff Brown349703e2010-06-22 01:27:15 -07001228 // For security reasons, we defer updating the touch state until we are sure that
1229 // event injection will be allowed.
1230 //
1231 // FIXME In the original code, screenWasOff could never be set to true.
1232 // The reason is that the POLICY_FLAG_WOKE_HERE
1233 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
1234 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
1235 // actually enqueued using the policyFlags that appeared in the final EV_SYN
1236 // events upon which no preprocessing took place. So policyFlags was always 0.
1237 // In the new native input dispatcher we're a bit more careful about event
1238 // preprocessing so the touches we receive can actually have non-zero policyFlags.
1239 // Unfortunately we obtain undesirable behavior.
1240 //
1241 // Here's what happens:
1242 //
1243 // When the device dims in anticipation of going to sleep, touches
1244 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
1245 // the device to brighten and reset the user activity timer.
1246 // Touches on other windows (such as the launcher window)
1247 // are dropped. Then after a moment, the device goes to sleep. Oops.
1248 //
1249 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
1250 // instead of POLICY_FLAG_WOKE_HERE...
1251 //
1252 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
1253 bool firstIteration = true;
1254 ANRTimer anrTimer;
1255 for (;;) {
1256 if (firstIteration) {
1257 firstIteration = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001258 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001259 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1260 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1261 "the window that should receive it.");
1262 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1263 break;
1264 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001265 }
Jeff Brown349703e2010-06-22 01:27:15 -07001266
1267 // If dispatch is not enabled then fail.
1268 if (! mDispatchEnabled) {
1269 LOGI("Dropping event because input dispatch is disabled.");
1270 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1271 break; // failed, exit wait loop
1272 }
1273
1274 // If dispatch is frozen or we don't have valid window data yet then wait.
1275 if (mDispatchFrozen || ! mWindowsReady) {
1276#if DEBUG_INPUT_DISPATCHER_POLICY
1277 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1278#endif
1279 anrTimer.dispatchFrozenBySystem();
1280 continue;
1281 }
1282
1283 // Update the touch state as needed based on the properties of the touch event.
1284 if (action == MOTION_EVENT_ACTION_DOWN) {
1285 InputWindow* newTouchedWindow = NULL;
1286 mTempTouchedOutsideWindows.clear();
1287
1288 int32_t x = int32_t(motionEvent->getX(0));
1289 int32_t y = int32_t(motionEvent->getY(0));
1290 InputWindow* topErrorWindow = NULL;
1291
1292 // Traverse windows from front to back to find touched window and outside targets.
1293 size_t numWindows = mWindows.size();
1294 for (size_t i = 0; i < numWindows; i++) {
1295 InputWindow* window = & mWindows.editItemAt(i);
1296 int32_t flags = window->layoutParamsFlags;
1297
1298 if (flags & FLAG_SYSTEM_ERROR) {
1299 if (! topErrorWindow) {
1300 topErrorWindow = window;
1301 }
1302 }
1303
1304 if (window->visible) {
1305 if (! (flags & FLAG_NOT_TOUCHABLE)) {
1306 bool isTouchModal = (flags &
1307 (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL)) == 0;
1308 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
1309 if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
1310 newTouchedWindow = window;
1311 }
1312 break; // found touched window, exit window loop
1313 }
1314 }
1315
1316 if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
1317 mTempTouchedOutsideWindows.push(window);
1318 }
1319 }
1320 }
1321
1322 // If there is an error window but it is not taking focus (typically because
1323 // it is invisible) then wait for it. Any other focused window may in
1324 // fact be in ANR state.
1325 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1326#if DEBUG_INPUT_DISPATCHER_POLICY
1327 LOGD("Waiting because system error window is pending.");
1328#endif
1329 anrTimer.dispatchFrozenBySystem();
1330 continue; // wait some more
1331 }
1332
1333 // If we did not find a touched window then fail.
1334 if (! newTouchedWindow) {
1335 if (mFocusedApplication) {
1336#if DEBUG_FOCUS
1337 LOGD("Waiting because there is no focused window but there is a "
1338 "focused application that may yet introduce a new target: '%s'.",
1339 mFocusedApplication->name.string());
1340#endif
1341 continue;
1342 }
1343
1344 LOGI("Dropping event because there is no touched window or focused application.");
1345 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1346 break; // failed, exit wait loop
1347 }
1348
1349 // Check permissions.
1350 if (! checkInjectionPermission(newTouchedWindow, injectorPid, injectorUid)) {
1351 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1352 break; // failed, exit wait loop
1353 }
1354
1355 // If the touched window is paused then keep waiting.
1356 if (newTouchedWindow->paused) {
1357#if DEBUG_INPUT_DISPATCHER_POLICY
1358 LOGD("Waiting because touched window is paused.");
1359#endif
1360 anrTimer.dispatchPausedByApplication(newTouchedWindow);
1361 continue; // wait some more
1362 }
1363
1364 // Success! Update the touch dispatch state for real.
1365 releaseTouchedWindowLd();
1366
1367 mTouchedWindow = newTouchedWindow;
1368
1369 if (newTouchedWindow->hasWallpaper) {
1370 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1371 }
1372 break; // done
1373 } else {
1374 // Check permissions.
1375 if (! checkInjectionPermission(mTouchedWindow, injectorPid, injectorUid)) {
1376 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1377 break; // failed, exit wait loop
1378 }
1379
1380 // If there is no currently touched window then fail.
1381 if (! mTouchedWindow || ! mTouchDown) {
1382 LOGI("Dropping event because touched window is no longer valid.");
1383 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1384 break; // failed, exit wait loop
1385 }
1386
1387 // If the touched window is paused then keep waiting.
1388 if (mTouchedWindow->paused) {
1389#if DEBUG_INPUT_DISPATCHER_POLICY
1390 LOGD("Waiting because touched window is paused.");
1391#endif
1392 anrTimer.dispatchPausedByApplication(mTouchedWindow);
1393 continue; // wait some more
1394 }
1395
1396 // Success!
1397 break; // done
1398 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001399 }
Jeff Brown349703e2010-06-22 01:27:15 -07001400
1401 // Output targets.
1402 bool havePermission;
1403 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1404 // Injection succeeded so the injector must have permission.
1405 havePermission = true;
1406
1407 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1408 for (size_t i = 0; i < numWallpaperWindows; i++) {
1409 addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
1410 }
1411
1412 size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
1413 for (size_t i = 0; i < numOutsideWindows; i++) {
1414 addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
1415 }
1416
1417 addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
1418 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1419 outTouchedWindow = mTouchedWindow;
1420 } else {
1421 if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED
1422 && checkInjectionPermission(NULL, injectorPid, injectorUid)) {
1423 // Injection failed but the injector does have permission to inject events.
1424 // While we might not have found a valid target for the injected event, we
1425 // still want to update the dispatch state to take it into account.
1426 havePermission = true;
1427 } else {
1428 // Injector does not have permission to inject events.
1429 // We make sure to leave the dispatch state unchanged.
1430 havePermission = false;
1431 }
1432 outTouchedWindow = NULL;
1433 }
1434 mTempTouchedOutsideWindows.clear();
1435
1436 // Update final pieces of touch state now that we know for sure whether the injector
1437 // had permission to perform the injection.
1438 if (havePermission) {
1439 if (action == MOTION_EVENT_ACTION_DOWN) {
1440 if (mTouchDown) {
1441 // This is weird. We got a down but we thought it was already down!
1442 LOGW("Pointer down received while already down.");
1443 } else {
1444 mTouchDown = true;
1445 }
1446
1447 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1448 // Since we failed to identify a target for this touch down, we may still
1449 // be holding on to an earlier target from a previous touch down. Release it.
1450 releaseTouchedWindowLd();
1451 }
1452 } else if (action == MOTION_EVENT_ACTION_UP) {
1453 mTouchDown = false;
1454 releaseTouchedWindowLd();
1455 }
1456 }
1457
1458#if DEBUG_FOCUS
1459 LOGD("waitForTouchedWindow finished: injectionResult=%d",
1460 injectionResult);
1461 dumpDispatchStateLd();
1462#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001463 return injectionResult;
1464}
1465
Jeff Brown349703e2010-06-22 01:27:15 -07001466void NativeInputManager::releaseTouchedWindowLd() {
1467 mTouchedWindow = NULL;
1468 mTouchedWallpaperWindows.clear();
1469}
1470
1471void NativeInputManager::addTarget(const InputWindow* window, int32_t targetFlags,
1472 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets) {
1473 nsecs_t timeout = window->dispatchingTimeout - timeSpentWaitingForApplication;
1474 if (timeout < MIN_INPUT_DISPATCHING_TIMEOUT) {
1475 timeout = MIN_INPUT_DISPATCHING_TIMEOUT;
1476 }
1477
1478 outTargets.push();
1479
1480 InputTarget& target = outTargets.editTop();
1481 target.inputChannel = window->inputChannel;
1482 target.flags = targetFlags;
1483 target.timeout = timeout;
1484 target.xOffset = - window->frameLeft;
1485 target.yOffset = - window->frameTop;
1486}
1487
1488bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
1489 int32_t injectorPid, int32_t injectorUid) {
1490 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1491 JNIEnv* env = jniEnv();
1492 jboolean result = env->CallBooleanMethod(mCallbacksObj,
1493 gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
1494 checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission");
1495
1496 if (! result) {
1497 if (window) {
1498 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1499 "with input channel %s owned by uid %d",
1500 injectorPid, injectorUid, window->inputChannel->getName().string(),
1501 window->ownerUid);
1502 } else {
1503 LOGW("Permission denied: injecting event from pid %d uid %d",
1504 injectorPid, injectorUid);
1505 }
1506 return false;
1507 }
1508 }
1509
1510 return true;
1511}
1512
1513int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
1514 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
1515#if DEBUG_INPUT_DISPATCHER_POLICY
1516 LOGD("waitForKeyEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1517 policyFlags, injectorPid, injectorUid);
1518#endif
1519
1520 int32_t windowType;
1521 { // acquire lock
1522 AutoMutex _l(mDispatchLock);
1523
1524 InputWindow* focusedWindow;
1525 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1526 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1527 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1528 return injectionResult;
1529 }
1530
1531 windowType = focusedWindow->layoutParamsType;
1532 } // release lock
1533
Jeff Brownd0097872010-06-30 14:41:59 -07001534 const InputTarget& target = outTargets.top();
1535 bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags);
1536 if (consumed) {
1537 outTargets.clear();
1538 return INPUT_EVENT_INJECTION_SUCCEEDED;
Jeff Brown349703e2010-06-22 01:27:15 -07001539 }
1540
1541 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1542 return INPUT_EVENT_INJECTION_SUCCEEDED;
1543}
1544
1545int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
1546 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001547 Vector<InputTarget>& outTargets) {
Jeff Brown349703e2010-06-22 01:27:15 -07001548#if DEBUG_INPUT_DISPATCHER_POLICY
1549 LOGD("waitForMotionEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1550 policyFlags, injectorPid, injectorUid);
1551#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001552
Jeff Brown349703e2010-06-22 01:27:15 -07001553 switch (motionEvent->getNature()) {
1554 case INPUT_EVENT_NATURE_TRACKBALL:
1555 return identifyTrackballEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
1556 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001557
Jeff Brown349703e2010-06-22 01:27:15 -07001558 case INPUT_EVENT_NATURE_TOUCH:
1559 return identifyTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
1560 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001561
Jeff Brown349703e2010-06-22 01:27:15 -07001562 default:
1563 assert(false);
1564 return INPUT_EVENT_INJECTION_FAILED;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001565 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001566}
1567
Jeff Brown349703e2010-06-22 01:27:15 -07001568int32_t NativeInputManager::identifyTrackballEventTargets(MotionEvent* motionEvent,
1569 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1570 Vector<InputTarget>& outTargets) {
1571#if DEBUG_INPUT_DISPATCHER_POLICY
1572 LOGD("identifyTrackballEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1573 policyFlags, injectorPid, injectorUid);
1574#endif
1575
1576 int32_t windowType;
1577 { // acquire lock
1578 AutoMutex _l(mDispatchLock);
1579
1580 InputWindow* focusedWindow;
1581 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1582 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1583 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1584 return injectionResult;
1585 }
1586
1587 windowType = focusedWindow->layoutParamsType;
1588 } // release lock
1589
1590 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1591 return INPUT_EVENT_INJECTION_SUCCEEDED;
1592}
1593
1594int32_t NativeInputManager::identifyTouchEventTargets(MotionEvent* motionEvent,
1595 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1596 Vector<InputTarget>& outTargets) {
1597#if DEBUG_INPUT_DISPATCHER_POLICY
1598 LOGD("identifyTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1599 policyFlags, injectorPid, injectorUid);
1600#endif
1601
1602 int32_t windowType;
1603 { // acquire lock
1604 AutoMutex _l(mDispatchLock);
1605
1606 InputWindow* touchedWindow;
1607 int32_t injectionResult = waitForTouchedWindowLd(motionEvent, policyFlags,
1608 injectorPid, injectorUid, outTargets, /*out*/ touchedWindow);
1609 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1610 return injectionResult;
1611 }
1612
1613 windowType = touchedWindow->layoutParamsType;
1614 } // release lock
1615
1616 int32_t eventType;
1617 switch (motionEvent->getAction()) {
1618 case MOTION_EVENT_ACTION_DOWN:
1619 eventType = POWER_MANAGER_TOUCH_EVENT;
1620 break;
1621 case MOTION_EVENT_ACTION_UP:
1622 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
1623 break;
1624 default:
1625 if (motionEvent->getEventTime() - motionEvent->getDownTime()
1626 >= EVENT_IGNORE_DURATION) {
1627 eventType = POWER_MANAGER_TOUCH_EVENT;
1628 } else {
1629 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
1630 }
1631 break;
1632 }
1633 pokeUserActivityIfNeeded(windowType, eventType);
1634 return INPUT_EVENT_INJECTION_SUCCEEDED;
1635}
1636
Jeff Brownd0097872010-06-30 14:41:59 -07001637bool NativeInputManager::interceptKeyBeforeDispatching(const InputTarget& target,
1638 const KeyEvent* keyEvent, uint32_t policyFlags) {
1639 JNIEnv* env = jniEnv();
1640
1641 jobject inputChannelObj = getInputChannelObjLocal(env, target.inputChannel);
1642 if (inputChannelObj) {
1643 jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
1644 gCallbacksClassInfo.interceptKeyBeforeDispatching,
1645 inputChannelObj, keyEvent->getKeyCode(), keyEvent->getMetaState(),
1646 keyEvent->getAction() == KEY_EVENT_ACTION_DOWN,
1647 keyEvent->getRepeatCount(), policyFlags);
1648 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
1649
1650 env->DeleteLocalRef(inputChannelObj);
1651
1652 return consumed && ! error;
1653 } else {
1654 LOGW("Could not apply key dispatch policy because input channel '%s' is "
1655 "no longer valid.", target.inputChannel->getName().string());
1656 return false;
1657 }
1658}
1659
Jeff Brown349703e2010-06-22 01:27:15 -07001660void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType) {
1661 if (windowType != TYPE_KEYGUARD) {
1662 nsecs_t eventTime = now();
1663 pokeUserActivity(eventTime, eventType);
1664 }
1665}
1666
1667void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
1668 JNIEnv* env = jniEnv();
1669 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.pokeUserActivity,
1670 eventTime, eventType);
1671 checkAndClearExceptionFromCallback(env, "pokeUserActivity");
1672}
1673
1674void NativeInputManager::dumpDispatchStateLd() {
1675#if DEBUG_FOCUS
1676 LOGD(" dispatcherState: dispatchEnabled=%d, dispatchFrozen=%d, windowsReady=%d",
1677 mDispatchEnabled, mDispatchFrozen, mWindowsReady);
1678 if (mFocusedApplication) {
1679 LOGD(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms",
1680 mFocusedApplication->name.string(),
1681 mFocusedApplication->dispatchingTimeout / 1000000.0);
1682 } else {
1683 LOGD(" focusedApplication: <null>");
1684 }
1685 LOGD(" focusedWindow: '%s'",
1686 mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
1687 LOGD(" touchedWindow: '%s', touchDown=%d",
1688 mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
1689 mTouchDown);
1690 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
1691 LOGD(" touchedWallpaperWindows[%d]: '%s'",
1692 i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
1693 }
1694 for (size_t i = 0; i < mWindows.size(); i++) {
1695 LOGD(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, visible=%d, "
1696 "flags=0x%08x, type=0x%08x, "
1697 "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
1698 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms",
1699 i, mWindows[i].inputChannel->getName().string(),
1700 mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
1701 mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
1702 mWindows[i].frameLeft, mWindows[i].frameTop,
1703 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
1704 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
1705 mWindows[i].ownerPid, mWindows[i].ownerUid,
1706 mWindows[i].dispatchingTimeout / 1000000.0);
1707 }
1708#endif
1709}
1710
1711// ----------------------------------------------------------------------------
1712
1713NativeInputManager::ANRTimer::ANRTimer() :
1714 mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
1715}
1716
1717void NativeInputManager::ANRTimer::dispatchFrozenBySystem() {
1718 mFrozen = true;
1719}
1720
1721void NativeInputManager::ANRTimer::dispatchPausedByApplication(InputWindow* pausedWindow) {
1722 mPausedWindow = pausedWindow;
1723}
1724
1725bool NativeInputManager::ANRTimer::waitForDispatchStateChangeLd(NativeInputManager* inputManager) {
1726 nsecs_t currentTime = now();
1727
1728 Budget newBudget;
1729 nsecs_t dispatchingTimeout;
1730 sp<InputChannel> pausedChannel = NULL;
1731 jobject tokenObj = NULL;
1732 if (mFrozen) {
1733 newBudget = SYSTEM;
1734 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1735 mFrozen = false;
1736 } else if (mPausedWindow) {
1737 newBudget = APPLICATION;
1738 dispatchingTimeout = mPausedWindow->dispatchingTimeout;
1739 pausedChannel = mPausedWindow->inputChannel;
1740 mPausedWindow = NULL;
1741 } else if (inputManager->mFocusedApplication) {
1742 newBudget = APPLICATION;
1743 dispatchingTimeout = inputManager->mFocusedApplication->dispatchingTimeout;
1744 tokenObj = jniEnv()->NewLocalRef(inputManager->mFocusedApplication->tokenObjWeak);
1745 } else {
1746 newBudget = APPLICATION;
1747 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1748 }
1749
1750 if (mBudget != newBudget) {
1751 mBudget = newBudget;
1752 mStartTime = currentTime;
1753 }
1754
1755 bool result = false;
1756 nsecs_t timeoutRemaining = mStartTime + dispatchingTimeout - currentTime;
1757 if (timeoutRemaining > 0
1758 && inputManager->mDispatchStateChanged.waitRelative(inputManager->mDispatchLock,
1759 timeoutRemaining) == OK) {
1760 result = true;
1761 } else {
1762 if (pausedChannel != NULL || tokenObj != NULL) {
1763 bool resumed;
1764 nsecs_t newTimeout = 0;
1765
1766 inputManager->mDispatchLock.unlock(); // release lock
1767 if (pausedChannel != NULL) {
1768 resumed = inputManager->notifyInputChannelANR(pausedChannel, /*out*/ newTimeout);
1769 } else {
1770 resumed = inputManager->notifyANR(tokenObj, /*out*/ newTimeout);
1771 }
1772 inputManager->mDispatchLock.lock(); // re-acquire lock
1773
1774 if (resumed) {
1775 mStartTime = now() - dispatchingTimeout + newTimeout;
1776 result = true;
1777 }
1778 }
1779 }
1780
1781 if (tokenObj) {
1782 jniEnv()->DeleteLocalRef(tokenObj);
1783 }
1784
1785 return result;
1786}
1787
1788nsecs_t NativeInputManager::ANRTimer::getTimeSpentWaitingForApplication() const {
1789 return mBudget == APPLICATION ? now() - mStartTime : 0;
1790}
Jeff Brown9c3cda02010-06-15 01:31:58 -07001791
1792// ----------------------------------------------------------------------------
1793
1794static sp<NativeInputManager> gNativeInputManager;
1795
Jeff Brown46b9ac02010-04-22 18:58:52 -07001796static bool checkInputManagerUnitialized(JNIEnv* env) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001797 if (gNativeInputManager == NULL) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001798 LOGE("Input manager not initialized.");
1799 jniThrowRuntimeException(env, "Input manager not initialized.");
1800 return true;
1801 }
1802 return false;
1803}
1804
1805static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
1806 jobject callbacks) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001807 if (gNativeInputManager == NULL) {
1808 gNativeInputManager = new NativeInputManager(callbacks);
1809 } else {
1810 LOGE("Input manager already initialized.");
1811 jniThrowRuntimeException(env, "Input manager already initialized.");
Jeff Brown46b9ac02010-04-22 18:58:52 -07001812 }
1813}
1814
1815static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
1816 if (checkInputManagerUnitialized(env)) {
1817 return;
1818 }
1819
Jeff Brown9c3cda02010-06-15 01:31:58 -07001820 status_t result = gNativeInputManager->getInputManager()->start();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001821 if (result) {
1822 jniThrowRuntimeException(env, "Input manager could not be started.");
1823 }
1824}
1825
1826static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
1827 jint displayId, jint width, jint height) {
1828 if (checkInputManagerUnitialized(env)) {
1829 return;
1830 }
1831
1832 // XXX we could get this from the SurfaceFlinger directly instead of requiring it
1833 // to be passed in like this, not sure which is better but leaving it like this
1834 // keeps the window manager in direct control of when display transitions propagate down
1835 // to the input dispatcher
Jeff Brown9c3cda02010-06-15 01:31:58 -07001836 gNativeInputManager->setDisplaySize(displayId, width, height);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001837}
1838
1839static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
1840 jint displayId, jint orientation) {
1841 if (checkInputManagerUnitialized(env)) {
1842 return;
1843 }
1844
Jeff Brown9c3cda02010-06-15 01:31:58 -07001845 gNativeInputManager->setDisplayOrientation(displayId, orientation);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001846}
1847
1848static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
1849 jint deviceId, jint deviceClasses, jint scanCode) {
1850 if (checkInputManagerUnitialized(env)) {
1851 return KEY_STATE_UNKNOWN;
1852 }
1853
Jeff Brown9c3cda02010-06-15 01:31:58 -07001854 return gNativeInputManager->getInputManager()->getScanCodeState(
1855 deviceId, deviceClasses, scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001856}
1857
1858static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
1859 jint deviceId, jint deviceClasses, jint keyCode) {
1860 if (checkInputManagerUnitialized(env)) {
1861 return KEY_STATE_UNKNOWN;
1862 }
1863
Jeff Brown9c3cda02010-06-15 01:31:58 -07001864 return gNativeInputManager->getInputManager()->getKeyCodeState(
1865 deviceId, deviceClasses, keyCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001866}
1867
1868static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
1869 jint deviceId, jint deviceClasses, jint sw) {
1870 if (checkInputManagerUnitialized(env)) {
1871 return KEY_STATE_UNKNOWN;
1872 }
1873
Jeff Brown9c3cda02010-06-15 01:31:58 -07001874 return gNativeInputManager->getInputManager()->getSwitchState(deviceId, deviceClasses, sw);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001875}
1876
1877static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
1878 jintArray keyCodes, jbooleanArray outFlags) {
1879 if (checkInputManagerUnitialized(env)) {
1880 return JNI_FALSE;
1881 }
1882
1883 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
1884 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
1885 jsize numCodes = env->GetArrayLength(keyCodes);
1886 jboolean result;
1887 if (numCodes == env->GetArrayLength(outFlags)) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001888 result = gNativeInputManager->getInputManager()->hasKeys(numCodes, codes, flags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001889 } else {
1890 result = JNI_FALSE;
1891 }
1892
1893 env->ReleaseBooleanArrayElements(outFlags, flags, 0);
1894 env->ReleaseIntArrayElements(keyCodes, codes, 0);
1895 return result;
1896}
1897
1898static void throwInputChannelNotInitialized(JNIEnv* env) {
1899 jniThrowException(env, "java/lang/IllegalStateException",
1900 "inputChannel is not initialized");
1901}
1902
1903static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
1904 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
1905 LOGW("Input channel object '%s' was disposed without first being unregistered with "
1906 "the input manager!", inputChannel->getName().string());
1907
Jeff Brown9c3cda02010-06-15 01:31:58 -07001908 if (gNativeInputManager != NULL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07001909 gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001910 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001911}
1912
1913static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
1914 jobject inputChannelObj) {
1915 if (checkInputManagerUnitialized(env)) {
1916 return;
1917 }
1918
1919 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1920 inputChannelObj);
1921 if (inputChannel == NULL) {
1922 throwInputChannelNotInitialized(env);
1923 return;
1924 }
1925
Jeff Brown7fbdc842010-06-17 20:52:56 -07001926
1927 status_t status = gNativeInputManager->registerInputChannel(
1928 env, inputChannel, inputChannelObj);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001929 if (status) {
1930 jniThrowRuntimeException(env, "Failed to register input channel. "
1931 "Check logs for details.");
1932 return;
1933 }
1934
1935 android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
1936 android_server_InputManager_handleInputChannelDisposed, NULL);
1937}
1938
1939static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
1940 jobject inputChannelObj) {
1941 if (checkInputManagerUnitialized(env)) {
1942 return;
1943 }
1944
1945 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1946 inputChannelObj);
1947 if (inputChannel == NULL) {
1948 throwInputChannelNotInitialized(env);
1949 return;
1950 }
1951
1952 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
1953
Jeff Brown7fbdc842010-06-17 20:52:56 -07001954 status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001955 if (status) {
1956 jniThrowRuntimeException(env, "Failed to unregister input channel. "
1957 "Check logs for details.");
1958 }
1959}
1960
Jeff Brown7fbdc842010-06-17 20:52:56 -07001961static jint android_server_InputManager_nativeInjectKeyEvent(JNIEnv* env, jclass clazz,
1962 jobject keyEventObj, jint nature, jint injectorPid, jint injectorUid,
1963 jboolean sync, jint timeoutMillis) {
1964 if (checkInputManagerUnitialized(env)) {
1965 return INPUT_EVENT_INJECTION_FAILED;
1966 }
1967
1968 KeyEvent keyEvent;
1969 android_view_KeyEvent_toNative(env, keyEventObj, nature, & keyEvent);
1970
1971 return gNativeInputManager->getInputManager()->injectInputEvent(& keyEvent,
1972 injectorPid, injectorUid, sync, timeoutMillis);
1973}
1974
1975static jint android_server_InputManager_nativeInjectMotionEvent(JNIEnv* env, jclass clazz,
1976 jobject motionEventObj, jint nature, jint injectorPid, jint injectorUid,
1977 jboolean sync, jint timeoutMillis) {
1978 if (checkInputManagerUnitialized(env)) {
1979 return INPUT_EVENT_INJECTION_FAILED;
1980 }
1981
1982 MotionEvent motionEvent;
1983 android_view_MotionEvent_toNative(env, motionEventObj, nature, & motionEvent);
1984
1985 return gNativeInputManager->getInputManager()->injectInputEvent(& motionEvent,
1986 injectorPid, injectorUid, sync, timeoutMillis);
1987}
1988
Jeff Brown349703e2010-06-22 01:27:15 -07001989static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
1990 jobjectArray windowObjArray) {
1991 if (checkInputManagerUnitialized(env)) {
1992 return;
1993 }
1994
1995 gNativeInputManager->setInputWindows(env, windowObjArray);
1996}
1997
1998static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
1999 jobject applicationObj) {
2000 if (checkInputManagerUnitialized(env)) {
2001 return;
2002 }
2003
2004 gNativeInputManager->setFocusedApplication(env, applicationObj);
2005}
2006
2007static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
2008 jclass clazz, jboolean enabled, jboolean frozen) {
2009 if (checkInputManagerUnitialized(env)) {
2010 return;
2011 }
2012
2013 gNativeInputManager->setInputDispatchMode(enabled, frozen);
2014}
2015
2016static void android_server_InputManager_nativePreemptInputDispatch(JNIEnv* env,
2017 jclass clazz) {
2018 if (checkInputManagerUnitialized(env)) {
2019 return;
2020 }
2021
2022 gNativeInputManager->preemptInputDispatch();
2023}
2024
Jeff Brown9c3cda02010-06-15 01:31:58 -07002025// ----------------------------------------------------------------------------
2026
Jeff Brown46b9ac02010-04-22 18:58:52 -07002027static JNINativeMethod gInputManagerMethods[] = {
2028 /* name, signature, funcPtr */
2029 { "nativeInit", "(Lcom/android/server/InputManager$Callbacks;)V",
2030 (void*) android_server_InputManager_nativeInit },
2031 { "nativeStart", "()V",
2032 (void*) android_server_InputManager_nativeStart },
2033 { "nativeSetDisplaySize", "(III)V",
2034 (void*) android_server_InputManager_nativeSetDisplaySize },
2035 { "nativeSetDisplayOrientation", "(II)V",
2036 (void*) android_server_InputManager_nativeSetDisplayOrientation },
2037 { "nativeGetScanCodeState", "(III)I",
2038 (void*) android_server_InputManager_nativeGetScanCodeState },
2039 { "nativeGetKeyCodeState", "(III)I",
2040 (void*) android_server_InputManager_nativeGetKeyCodeState },
2041 { "nativeGetSwitchState", "(III)I",
2042 (void*) android_server_InputManager_nativeGetSwitchState },
2043 { "nativeHasKeys", "([I[Z)Z",
2044 (void*) android_server_InputManager_nativeHasKeys },
2045 { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;)V",
2046 (void*) android_server_InputManager_nativeRegisterInputChannel },
2047 { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002048 (void*) android_server_InputManager_nativeUnregisterInputChannel },
2049 { "nativeInjectKeyEvent", "(Landroid/view/KeyEvent;IIIZI)I",
2050 (void*) android_server_InputManager_nativeInjectKeyEvent },
2051 { "nativeInjectMotionEvent", "(Landroid/view/MotionEvent;IIIZI)I",
Jeff Brown349703e2010-06-22 01:27:15 -07002052 (void*) android_server_InputManager_nativeInjectMotionEvent },
2053 { "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V",
2054 (void*) android_server_InputManager_nativeSetInputWindows },
2055 { "nativeSetFocusedApplication", "(Lcom/android/server/InputApplication;)V",
2056 (void*) android_server_InputManager_nativeSetFocusedApplication },
2057 { "nativeSetInputDispatchMode", "(ZZ)V",
2058 (void*) android_server_InputManager_nativeSetInputDispatchMode },
2059 { "nativePreemptInputDispatch", "()V",
2060 (void*) android_server_InputManager_nativePreemptInputDispatch }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002061};
2062
2063#define FIND_CLASS(var, className) \
2064 var = env->FindClass(className); \
2065 LOG_FATAL_IF(! var, "Unable to find class " className); \
2066 var = jclass(env->NewGlobalRef(var));
2067
2068#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2069 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2070 LOG_FATAL_IF(! var, "Unable to find method " methodName);
2071
2072#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
2073 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
2074 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
2075
2076int register_android_server_InputManager(JNIEnv* env) {
2077 int res = jniRegisterNativeMethods(env, "com/android/server/InputManager",
2078 gInputManagerMethods, NELEM(gInputManagerMethods));
2079 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2080
Jeff Brown9c3cda02010-06-15 01:31:58 -07002081 // Callbacks
Jeff Brown46b9ac02010-04-22 18:58:52 -07002082
2083 FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
2084
2085 GET_METHOD_ID(gCallbacksClassInfo.isScreenOn, gCallbacksClassInfo.clazz,
2086 "isScreenOn", "()Z");
2087
2088 GET_METHOD_ID(gCallbacksClassInfo.isScreenBright, gCallbacksClassInfo.clazz,
2089 "isScreenBright", "()Z");
2090
2091 GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
2092 "notifyConfigurationChanged", "(JIII)V");
2093
2094 GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
2095 "notifyLidSwitchChanged", "(JZ)V");
2096
Jeff Brown7fbdc842010-06-17 20:52:56 -07002097 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
2098 "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
2099
2100 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelANR, gCallbacksClassInfo.clazz,
2101 "notifyInputChannelANR", "(Landroid/view/InputChannel;)J");
2102
2103 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelRecoveredFromANR, gCallbacksClassInfo.clazz,
2104 "notifyInputChannelRecoveredFromANR", "(Landroid/view/InputChannel;)V");
2105
Jeff Brown349703e2010-06-22 01:27:15 -07002106 GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
2107 "notifyANR", "(Ljava/lang/Object;)J");
2108
Jeff Brown46b9ac02010-04-22 18:58:52 -07002109 GET_METHOD_ID(gCallbacksClassInfo.virtualKeyFeedback, gCallbacksClassInfo.clazz,
2110 "virtualKeyFeedback", "(JIIIIIIJ)V");
2111
Jeff Brown349703e2010-06-22 01:27:15 -07002112 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
2113 "interceptKeyBeforeQueueing", "(IIIIIIJZ)I");
2114
2115 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
2116 "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIZII)Z");
2117
2118 GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
2119 "checkInjectEventsPermission", "(II)Z");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002120
2121 GET_METHOD_ID(gCallbacksClassInfo.goToSleep, gCallbacksClassInfo.clazz,
2122 "goToSleep", "(J)V");
2123
Jeff Brown349703e2010-06-22 01:27:15 -07002124 GET_METHOD_ID(gCallbacksClassInfo.pokeUserActivity, gCallbacksClassInfo.clazz,
2125 "pokeUserActivity", "(JI)V");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002126
2127 GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz,
2128 "notifyAppSwitchComing", "()V");
2129
2130 GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz,
2131 "filterTouchEvents", "()Z");
2132
2133 GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
2134 "filterJumpyTouchEvents", "()Z");
2135
2136 GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz,
2137 "getVirtualKeyDefinitions",
2138 "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
2139
2140 GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
2141 "getExcludedDeviceNames", "()[Ljava/lang/String;");
2142
Jeff Brown46b9ac02010-04-22 18:58:52 -07002143 // VirtualKeyDefinition
2144
2145 FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
2146 "com/android/server/InputManager$VirtualKeyDefinition");
2147
2148 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz,
2149 "scanCode", "I");
2150
2151 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz,
2152 "centerX", "I");
2153
2154 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz,
2155 "centerY", "I");
2156
2157 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz,
2158 "width", "I");
2159
2160 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
2161 "height", "I");
2162
Jeff Brown349703e2010-06-22 01:27:15 -07002163 // InputWindow
Jeff Brown7fbdc842010-06-17 20:52:56 -07002164
Jeff Brown349703e2010-06-22 01:27:15 -07002165 FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002166
Jeff Brown349703e2010-06-22 01:27:15 -07002167 GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
2168 "inputChannel", "Landroid/view/InputChannel;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002169
Jeff Brown349703e2010-06-22 01:27:15 -07002170 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
2171 "layoutParamsFlags", "I");
2172
2173 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
2174 "layoutParamsType", "I");
2175
2176 GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
2177 "dispatchingTimeoutNanos", "J");
2178
2179 GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
2180 "frameLeft", "I");
2181
2182 GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
2183 "frameTop", "I");
2184
2185 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
2186 "touchableAreaLeft", "I");
2187
2188 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
2189 "touchableAreaTop", "I");
2190
2191 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
2192 "touchableAreaRight", "I");
2193
2194 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
2195 "touchableAreaBottom", "I");
2196
2197 GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
2198 "visible", "Z");
2199
2200 GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
2201 "hasFocus", "Z");
2202
2203 GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
2204 "hasWallpaper", "Z");
2205
2206 GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
2207 "paused", "Z");
2208
2209 GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
2210 "ownerPid", "I");
2211
2212 GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
2213 "ownerUid", "I");
2214
2215 // InputApplication
2216
2217 FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
2218
2219 GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
2220 "name", "Ljava/lang/String;");
2221
2222 GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
2223 gInputApplicationClassInfo.clazz,
2224 "dispatchingTimeoutNanos", "J");
2225
2226 GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
2227 "token", "Ljava/lang/Object;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002228
Jeff Brown46b9ac02010-04-22 18:58:52 -07002229 return 0;
2230}
2231
Jeff Brown46b9ac02010-04-22 18:58:52 -07002232} /* namespace android */