blob: 0982b32719a47cc2fb17f37695080d650be1a3c3 [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 Brown00fa7bd2010-07-02 15:37:36 -070043#include "com_android_server_PowerManagerService.h"
Jeff Brown46b9ac02010-04-22 18:58:52 -070044
45namespace android {
46
Jeff Brown349703e2010-06-22 01:27:15 -070047// Window flags from WindowManager.LayoutParams
48enum {
49 FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
50 FLAG_DIM_BEHIND = 0x00000002,
51 FLAG_BLUR_BEHIND = 0x00000004,
52 FLAG_NOT_FOCUSABLE = 0x00000008,
53 FLAG_NOT_TOUCHABLE = 0x00000010,
54 FLAG_NOT_TOUCH_MODAL = 0x00000020,
55 FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
56 FLAG_KEEP_SCREEN_ON = 0x00000080,
57 FLAG_LAYOUT_IN_SCREEN = 0x00000100,
58 FLAG_LAYOUT_NO_LIMITS = 0x00000200,
59 FLAG_FULLSCREEN = 0x00000400,
60 FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
61 FLAG_DITHER = 0x00001000,
62 FLAG_SECURE = 0x00002000,
63 FLAG_SCALED = 0x00004000,
64 FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
65 FLAG_LAYOUT_INSET_DECOR = 0x00010000,
66 FLAG_ALT_FOCUSABLE_IM = 0x00020000,
67 FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
68 FLAG_SHOW_WHEN_LOCKED = 0x00080000,
69 FLAG_SHOW_WALLPAPER = 0x00100000,
70 FLAG_TURN_SCREEN_ON = 0x00200000,
71 FLAG_DISMISS_KEYGUARD = 0x00400000,
72 FLAG_IMMERSIVE = 0x00800000,
73 FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
74 FLAG_COMPATIBLE_WINDOW = 0x20000000,
75 FLAG_SYSTEM_ERROR = 0x40000000,
76};
77
78// Window types from WindowManager.LayoutParams
79enum {
80 FIRST_APPLICATION_WINDOW = 1,
81 TYPE_BASE_APPLICATION = 1,
82 TYPE_APPLICATION = 2,
83 TYPE_APPLICATION_STARTING = 3,
84 LAST_APPLICATION_WINDOW = 99,
85 FIRST_SUB_WINDOW = 1000,
86 TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
87 TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
88 TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
89 TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
90 TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
91 LAST_SUB_WINDOW = 1999,
92 FIRST_SYSTEM_WINDOW = 2000,
93 TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
94 TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
95 TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
96 TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
97 TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
98 TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
99 TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
100 TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
101 TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
102 TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
103 TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
104 TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
105 TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
106 TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
107 TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14,
108 LAST_SYSTEM_WINDOW = 2999,
109};
110
Jeff Brown349703e2010-06-22 01:27:15 -0700111// Delay between reporting long touch events to the power manager.
112const nsecs_t EVENT_IGNORE_DURATION = 300 * 1000000LL; // 300 ms
113
114// Default input dispatching timeout if there is no focused application or paused window
115// from which to determine an appropriate dispatching timeout.
116const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
117
118// Minimum amount of time to provide to the input dispatcher for delivery of an event
119// regardless of how long the application window was paused.
120const nsecs_t MIN_INPUT_DISPATCHING_TIMEOUT = 1000 * 1000000LL; // 1 sec
121
Jeff Brown9c3cda02010-06-15 01:31:58 -0700122// ----------------------------------------------------------------------------
Jeff Brown46b9ac02010-04-22 18:58:52 -0700123
124static struct {
125 jclass clazz;
126
Jeff Brown46b9ac02010-04-22 18:58:52 -0700127 jmethodID notifyConfigurationChanged;
128 jmethodID notifyLidSwitchChanged;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700129 jmethodID notifyInputChannelBroken;
130 jmethodID notifyInputChannelANR;
131 jmethodID notifyInputChannelRecoveredFromANR;
Jeff Brown349703e2010-06-22 01:27:15 -0700132 jmethodID notifyANR;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700133 jmethodID virtualKeyDownFeedback;
Jeff Brown349703e2010-06-22 01:27:15 -0700134 jmethodID interceptKeyBeforeQueueing;
135 jmethodID interceptKeyBeforeDispatching;
136 jmethodID checkInjectEventsPermission;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700137 jmethodID notifyAppSwitchComing;
138 jmethodID filterTouchEvents;
139 jmethodID filterJumpyTouchEvents;
140 jmethodID getVirtualKeyDefinitions;
141 jmethodID getExcludedDeviceNames;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700142} gCallbacksClassInfo;
143
144static struct {
145 jclass clazz;
146
147 jfieldID scanCode;
148 jfieldID centerX;
149 jfieldID centerY;
150 jfieldID width;
151 jfieldID height;
152} gVirtualKeyDefinitionClassInfo;
153
Jeff Brown7fbdc842010-06-17 20:52:56 -0700154static struct {
155 jclass clazz;
156
Jeff Brown349703e2010-06-22 01:27:15 -0700157 jfieldID inputChannel;
158 jfieldID layoutParamsFlags;
159 jfieldID layoutParamsType;
160 jfieldID dispatchingTimeoutNanos;
161 jfieldID frameLeft;
162 jfieldID frameTop;
163 jfieldID touchableAreaLeft;
164 jfieldID touchableAreaTop;
165 jfieldID touchableAreaRight;
166 jfieldID touchableAreaBottom;
167 jfieldID visible;
168 jfieldID hasFocus;
169 jfieldID hasWallpaper;
170 jfieldID paused;
171 jfieldID ownerPid;
172 jfieldID ownerUid;
173} gInputWindowClassInfo;
174
175static struct {
176 jclass clazz;
177
178 jfieldID name;
179 jfieldID dispatchingTimeoutNanos;
180 jfieldID token;
181} gInputApplicationClassInfo;
182
Jeff Brown6ec402b2010-07-28 15:48:59 -0700183static struct {
184 jclass clazz;
185} gKeyEventClassInfo;
186
187static struct {
188 jclass clazz;
189} gMotionEventClassInfo;
190
Jeff Brown349703e2010-06-22 01:27:15 -0700191// ----------------------------------------------------------------------------
192
193static inline nsecs_t now() {
194 return systemTime(SYSTEM_TIME_MONOTONIC);
195}
Jeff Brown7fbdc842010-06-17 20:52:56 -0700196
Jeff Brown9c3cda02010-06-15 01:31:58 -0700197// ----------------------------------------------------------------------------
198
199class NativeInputManager : public virtual RefBase,
200 public virtual InputReaderPolicyInterface,
201 public virtual InputDispatcherPolicyInterface {
202protected:
203 virtual ~NativeInputManager();
204
205public:
206 NativeInputManager(jobject callbacksObj);
207
208 inline sp<InputManager> getInputManager() const { return mInputManager; }
209
Jeff Browne33348b2010-07-15 23:54:05 -0700210 String8 dump();
211
Jeff Brown9c3cda02010-06-15 01:31:58 -0700212 void setDisplaySize(int32_t displayId, int32_t width, int32_t height);
213 void setDisplayOrientation(int32_t displayId, int32_t orientation);
214
Jeff Brown7fbdc842010-06-17 20:52:56 -0700215 status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
216 jweak inputChannelObjWeak);
217 status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
218
Jeff Brown349703e2010-06-22 01:27:15 -0700219 void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
220 void setFocusedApplication(JNIEnv* env, jobject applicationObj);
221 void setInputDispatchMode(bool enabled, bool frozen);
222 void preemptInputDispatch();
223
Jeff Brown9c3cda02010-06-15 01:31:58 -0700224 /* --- InputReaderPolicyInterface implementation --- */
225
226 virtual bool getDisplayInfo(int32_t displayId,
227 int32_t* width, int32_t* height, int32_t* orientation);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700228 virtual void virtualKeyDownFeedback();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700229 virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700230 bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags);
231 virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
232 uint32_t& policyFlags);
233 virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700234 virtual bool filterTouchEvents();
235 virtual bool filterJumpyTouchEvents();
236 virtual void getVirtualKeyDefinitions(const String8& deviceName,
237 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions);
238 virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
239
240 /* --- InputDispatcherPolicyInterface implementation --- */
241
242 virtual void notifyConfigurationChanged(nsecs_t when);
243 virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700244 virtual bool notifyInputChannelANR(const sp<InputChannel>& inputChannel,
245 nsecs_t& outNewTimeout);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700246 virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel);
247 virtual nsecs_t getKeyRepeatTimeout();
Jeff Brown349703e2010-06-22 01:27:15 -0700248 virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700249 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -0700250 virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700251 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700252
253private:
Jeff Brown349703e2010-06-22 01:27:15 -0700254 struct InputWindow {
255 sp<InputChannel> inputChannel;
256 int32_t layoutParamsFlags;
257 int32_t layoutParamsType;
258 nsecs_t dispatchingTimeout;
259 int32_t frameLeft;
260 int32_t frameTop;
261 int32_t touchableAreaLeft;
262 int32_t touchableAreaTop;
263 int32_t touchableAreaRight;
264 int32_t touchableAreaBottom;
265 bool visible;
266 bool hasFocus;
267 bool hasWallpaper;
268 bool paused;
269 int32_t ownerPid;
270 int32_t ownerUid;
271
272 inline bool touchableAreaContainsPoint(int32_t x, int32_t y) {
273 return x >= touchableAreaLeft && x <= touchableAreaRight
274 && y >= touchableAreaTop && y <= touchableAreaBottom;
275 }
276 };
277
278 struct InputApplication {
279 String8 name;
280 nsecs_t dispatchingTimeout;
281 jweak tokenObjWeak;
282 };
283
284 class ANRTimer {
285 enum Budget {
286 SYSTEM = 0,
287 APPLICATION = 1
288 };
289
290 Budget mBudget;
291 nsecs_t mStartTime;
292 bool mFrozen;
293 InputWindow* mPausedWindow;
294
295 public:
296 ANRTimer();
297
298 void dispatchFrozenBySystem();
299 void dispatchPausedByApplication(InputWindow* pausedWindow);
300 bool waitForDispatchStateChangeLd(NativeInputManager* inputManager);
301
302 nsecs_t getTimeSpentWaitingForApplication() const;
303 };
304
Jeff Brown9c3cda02010-06-15 01:31:58 -0700305 sp<InputManager> mInputManager;
306
307 jobject mCallbacksObj;
308
309 // Cached filtering policies.
310 int32_t mFilterTouchEvents;
311 int32_t mFilterJumpyTouchEvents;
312
313 // Cached display state. (lock mDisplayLock)
314 Mutex mDisplayLock;
315 int32_t mDisplayWidth, mDisplayHeight;
316 int32_t mDisplayOrientation;
317
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700318 // Power manager interactions.
Jeff Brown9c3cda02010-06-15 01:31:58 -0700319 bool isScreenOn();
320 bool isScreenBright();
321
Jeff Brown7fbdc842010-06-17 20:52:56 -0700322 // Weak references to all currently registered input channels by receive fd.
323 Mutex mInputChannelRegistryLock;
324 KeyedVector<int, jweak> mInputChannelObjWeakByReceiveFd;
325
326 jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
327
Jeff Brown349703e2010-06-22 01:27:15 -0700328 // Input target and focus tracking. (lock mDispatchLock)
329 Mutex mDispatchLock;
330 Condition mDispatchStateChanged;
331
332 bool mDispatchEnabled;
333 bool mDispatchFrozen;
334 bool mWindowsReady;
335 Vector<InputWindow> mWindows;
336 Vector<InputWindow*> mWallpaperWindows;
337
338 // Focus tracking for keys, trackball, etc.
339 InputWindow* mFocusedWindow;
340
341 // Focus tracking for touch.
342 bool mTouchDown;
343 InputWindow* mTouchedWindow; // primary target for current down
344 Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
345
346 Vector<InputWindow*> mTempTouchedOutsideWindows; // temporary outside touch targets
347 Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
348
349 // Focused application.
350 InputApplication* mFocusedApplication;
351 InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
352
Jeff Brown6d0fec22010-07-23 21:28:06 -0700353 void dumpDeviceInfo(String8& dump);
Jeff Browne33348b2010-07-15 23:54:05 -0700354 void dumpDispatchStateLd(String8& dump);
355 void logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -0700356
357 bool notifyANR(jobject tokenObj, nsecs_t& outNewTimeout);
358 void releaseFocusedApplicationLd(JNIEnv* env);
359
360 int32_t waitForFocusedWindowLd(uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
361 Vector<InputTarget>& outTargets, InputWindow*& outFocusedWindow);
362 int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
363 int32_t injectorPid, int32_t injectorUid,
364 Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
365
366 void releaseTouchedWindowLd();
367
Jeff Brownc5ed5912010-07-14 18:48:53 -0700368 int32_t waitForNonTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700369 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700370 int32_t waitForTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700371 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
372
Jeff Brownd0097872010-06-30 14:41:59 -0700373 bool interceptKeyBeforeDispatching(const InputTarget& target,
374 const KeyEvent* keyEvent, uint32_t policyFlags);
375
Jeff Brown349703e2010-06-22 01:27:15 -0700376 void pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType);
377 void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
378 bool checkInjectionPermission(const InputWindow* window,
379 int32_t injectorPid, int32_t injectorUid);
380
381 static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
382 static void addTarget(const InputWindow* window, int32_t targetFlags,
383 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets);
384
Jeff Brown9c3cda02010-06-15 01:31:58 -0700385 static inline JNIEnv* jniEnv() {
386 return AndroidRuntime::getJNIEnv();
387 }
388
389 static bool isAppSwitchKey(int32_t keyCode);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700390 static bool isPolicyKey(int32_t keyCode, bool isScreenOn);
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 Brown0b72e822010-06-29 16:52:21 -0700398 mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0),
Jeff Brown349703e2010-06-22 01:27:15 -0700399 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
Jeff Browne33348b2010-07-15 23:54:05 -0700418String8 NativeInputManager::dump() {
419 String8 dump;
Jeff Brown00ba8842010-07-16 15:01:56 -0700420 { // acquire lock
421 AutoMutex _l(mDisplayLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700422 dump.append("Native Input Dispatcher State:\n");
Jeff Brown00ba8842010-07-16 15:01:56 -0700423 dumpDispatchStateLd(dump);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700424 dump.append("\n");
Jeff Brown00ba8842010-07-16 15:01:56 -0700425 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -0700426
427 dump.append("Input Devices:\n");
428 dumpDeviceInfo(dump);
429
Jeff Browne33348b2010-07-15 23:54:05 -0700430 return dump;
431}
432
Jeff Brown9c3cda02010-06-15 01:31:58 -0700433bool NativeInputManager::isAppSwitchKey(int32_t keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700434 return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700435}
436
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700437bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) {
438 // Special keys that the WindowManagerPolicy might care about.
439 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700440 case AKEYCODE_VOLUME_UP:
441 case AKEYCODE_VOLUME_DOWN:
442 case AKEYCODE_ENDCALL:
443 case AKEYCODE_POWER:
444 case AKEYCODE_CALL:
445 case AKEYCODE_HOME:
446 case AKEYCODE_MENU:
447 case AKEYCODE_SEARCH:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700448 // media keys
Jeff Brownfd035822010-06-30 16:10:35 -0700449 case AKEYCODE_HEADSETHOOK:
450 case AKEYCODE_MEDIA_PLAY_PAUSE:
451 case AKEYCODE_MEDIA_STOP:
452 case AKEYCODE_MEDIA_NEXT:
453 case AKEYCODE_MEDIA_PREVIOUS:
454 case AKEYCODE_MEDIA_REWIND:
455 case AKEYCODE_MEDIA_FAST_FORWARD:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700456 return true;
457 default:
458 // We need to pass all keys to the policy in the following cases:
459 // - screen is off
460 // - keyguard is visible
461 // - policy is performing key chording
462 //return ! isScreenOn || keyguardVisible || chording;
463 return true; // XXX stubbed out for now
464 }
465}
466
Jeff Brown7fbdc842010-06-17 20:52:56 -0700467bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700468 if (env->ExceptionCheck()) {
469 LOGE("An exception was thrown by callback '%s'.", methodName);
470 LOGE_EX(env);
471 env->ExceptionClear();
472 return true;
473 }
474 return false;
475}
476
477void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
478 if (displayId == 0) {
479 AutoMutex _l(mDisplayLock);
480
481 mDisplayWidth = width;
482 mDisplayHeight = height;
483 }
484}
485
486void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
487 if (displayId == 0) {
488 AutoMutex _l(mDisplayLock);
489
490 mDisplayOrientation = orientation;
491 }
492}
493
Jeff Brown7fbdc842010-06-17 20:52:56 -0700494status_t NativeInputManager::registerInputChannel(JNIEnv* env,
495 const sp<InputChannel>& inputChannel, jobject inputChannelObj) {
496 jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
497 if (! inputChannelObjWeak) {
498 LOGE("Could not create weak reference for input channel.");
499 LOGE_EX(env);
500 return NO_MEMORY;
501 }
502
503 status_t status;
504 {
505 AutoMutex _l(mInputChannelRegistryLock);
506
507 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
508 inputChannel->getReceivePipeFd());
509 if (index >= 0) {
510 LOGE("Input channel object '%s' has already been registered",
511 inputChannel->getName().string());
512 status = INVALID_OPERATION;
513 goto DeleteWeakRef;
514 }
515
516 mInputChannelObjWeakByReceiveFd.add(inputChannel->getReceivePipeFd(),
517 inputChannelObjWeak);
518 }
519
520 status = mInputManager->registerInputChannel(inputChannel);
521 if (! status) {
522 return OK;
523 }
524
525 {
526 AutoMutex _l(mInputChannelRegistryLock);
527 mInputChannelObjWeakByReceiveFd.removeItem(inputChannel->getReceivePipeFd());
528 }
529
530DeleteWeakRef:
531 env->DeleteWeakGlobalRef(inputChannelObjWeak);
532 return status;
533}
534
535status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
536 const sp<InputChannel>& inputChannel) {
537 jweak inputChannelObjWeak;
538 {
539 AutoMutex _l(mInputChannelRegistryLock);
540
541 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
542 inputChannel->getReceivePipeFd());
543 if (index < 0) {
544 LOGE("Input channel object '%s' is not currently registered",
545 inputChannel->getName().string());
546 return INVALID_OPERATION;
547 }
548
549 inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
550 mInputChannelObjWeakByReceiveFd.removeItemsAt(index);
551 }
552
553 env->DeleteWeakGlobalRef(inputChannelObjWeak);
554
555 return mInputManager->unregisterInputChannel(inputChannel);
556}
557
558jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
559 const sp<InputChannel>& inputChannel) {
560 {
561 AutoMutex _l(mInputChannelRegistryLock);
562
563 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
564 inputChannel->getReceivePipeFd());
565 if (index < 0) {
566 return NULL;
567 }
568
569 jweak inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
570 return env->NewLocalRef(inputChannelObjWeak);
571 }
572}
573
Jeff Brown9c3cda02010-06-15 01:31:58 -0700574bool NativeInputManager::getDisplayInfo(int32_t displayId,
575 int32_t* width, int32_t* height, int32_t* orientation) {
576 bool result = false;
577 if (displayId == 0) {
578 AutoMutex _l(mDisplayLock);
579
580 if (mDisplayWidth > 0) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700581 if (width) {
582 *width = mDisplayWidth;
583 }
584 if (height) {
585 *height = mDisplayHeight;
586 }
587 if (orientation) {
588 *orientation = mDisplayOrientation;
589 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700590 result = true;
591 }
592 }
593 return result;
594}
595
596bool NativeInputManager::isScreenOn() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700597 return android_server_PowerManagerService_isScreenOn();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700598}
599
600bool NativeInputManager::isScreenBright() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700601 return android_server_PowerManagerService_isScreenBright();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700602}
603
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700604void NativeInputManager::virtualKeyDownFeedback() {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700605#if DEBUG_INPUT_READER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700606 LOGD("virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700607#endif
608
609 JNIEnv* env = jniEnv();
610
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700611 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback);
612 checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700613}
614
615int32_t NativeInputManager::interceptKey(nsecs_t when,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700616 int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700617#if DEBUG_INPUT_READER_POLICY
618 LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
Jeff Brown349703e2010-06-22 01:27:15 -0700619 "policyFlags=0x%x",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700620 when, deviceId, down, keyCode, scanCode, policyFlags);
621#endif
622
623 const int32_t WM_ACTION_PASS_TO_USER = 1;
624 const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
625 const int32_t WM_ACTION_GO_TO_SLEEP = 4;
626
Jeff Brown9c3cda02010-06-15 01:31:58 -0700627 bool isScreenOn = this->isScreenOn();
628 bool isScreenBright = this->isScreenBright();
629
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700630 jint wmActions = 0;
631 if (isPolicyKey(keyCode, isScreenOn)) {
632 JNIEnv* env = jniEnv();
633
634 wmActions = env->CallIntMethod(mCallbacksObj,
635 gCallbacksClassInfo.interceptKeyBeforeQueueing,
636 when, keyCode, down, policyFlags, isScreenOn);
637 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
638 wmActions = 0;
639 }
640 } else {
641 wmActions = WM_ACTION_PASS_TO_USER;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700642 }
643
644 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
645 if (! isScreenOn) {
646 // Key presses and releases wake the device.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700647 policyFlags |= POLICY_FLAG_WOKE_HERE;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700648 }
649
650 if (! isScreenBright) {
651 // Key presses and releases brighten the screen if dimmed.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700652 policyFlags |= POLICY_FLAG_BRIGHT_HERE;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700653 }
654
655 if (wmActions & WM_ACTION_GO_TO_SLEEP) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700656 android_server_PowerManagerService_goToSleep(when);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700657 }
658
659 if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
Jeff Brown349703e2010-06-22 01:27:15 -0700660 pokeUserActivity(when, POWER_MANAGER_BUTTON_EVENT);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700661 }
662
663 if (wmActions & WM_ACTION_PASS_TO_USER) {
664 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700665
Jeff Brown9c3cda02010-06-15 01:31:58 -0700666 if (down && isAppSwitchKey(keyCode)) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700667 JNIEnv* env = jniEnv();
668
Jeff Brown9c3cda02010-06-15 01:31:58 -0700669 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700670 checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700671
672 actions |= InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING;
673 }
674 }
Jeff Brown349703e2010-06-22 01:27:15 -0700675
Jeff Brown9c3cda02010-06-15 01:31:58 -0700676 return actions;
677}
678
Jeff Brown6d0fec22010-07-23 21:28:06 -0700679int32_t NativeInputManager::interceptGeneric(nsecs_t when, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700680#if DEBUG_INPUT_READER_POLICY
Jeff Brown6d0fec22010-07-23 21:28:06 -0700681 LOGD("interceptGeneric - when=%lld, policyFlags=0x%x", when, policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700682#endif
683
Jeff Brown5c225b12010-06-16 01:53:36 -0700684 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
685 if (isScreenOn()) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700686 // Only dispatch events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700687 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700688 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700689
Jeff Brown349703e2010-06-22 01:27:15 -0700690 if (! isScreenBright()) {
691 // Brighten the screen if dimmed.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700692 policyFlags |= POLICY_FLAG_BRIGHT_HERE;
Jeff Brown349703e2010-06-22 01:27:15 -0700693 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700694 }
695
696 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700697}
698
699int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700700 int32_t switchValue, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700701#if DEBUG_INPUT_READER_POLICY
Jeff Brown6d0fec22010-07-23 21:28:06 -0700702 LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x",
703 when, switchCode, switchValue, policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700704#endif
705
706 JNIEnv* env = jniEnv();
707
708 switch (switchCode) {
709 case SW_LID:
710 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
711 when, switchValue == 0);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700712 checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700713 break;
714 }
715
716 return InputReaderPolicyInterface::ACTION_NONE;
717}
718
719bool NativeInputManager::filterTouchEvents() {
720 if (mFilterTouchEvents < 0) {
721 JNIEnv* env = jniEnv();
722
723 jboolean result = env->CallBooleanMethod(mCallbacksObj,
724 gCallbacksClassInfo.filterTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700725 if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700726 result = false;
727 }
728
729 mFilterTouchEvents = result ? 1 : 0;
730 }
731 return mFilterTouchEvents;
732}
733
734bool NativeInputManager::filterJumpyTouchEvents() {
735 if (mFilterJumpyTouchEvents < 0) {
736 JNIEnv* env = jniEnv();
737
738 jboolean result = env->CallBooleanMethod(mCallbacksObj,
739 gCallbacksClassInfo.filterJumpyTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700740 if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700741 result = false;
742 }
743
744 mFilterJumpyTouchEvents = result ? 1 : 0;
745 }
746 return mFilterJumpyTouchEvents;
747}
748
749void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
750 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions) {
751 JNIEnv* env = jniEnv();
752
753 jstring deviceNameStr = env->NewStringUTF(deviceName.string());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700754 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700755 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
756 gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700757 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700758 jsize length = env->GetArrayLength(result);
759 for (jsize i = 0; i < length; i++) {
760 jobject item = env->GetObjectArrayElement(result, i);
761
762 outVirtualKeyDefinitions.add();
763 outVirtualKeyDefinitions.editTop().scanCode =
764 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode));
765 outVirtualKeyDefinitions.editTop().centerX =
766 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX));
767 outVirtualKeyDefinitions.editTop().centerY =
768 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY));
769 outVirtualKeyDefinitions.editTop().width =
770 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width));
771 outVirtualKeyDefinitions.editTop().height =
772 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height));
773
774 env->DeleteLocalRef(item);
775 }
776 env->DeleteLocalRef(result);
777 }
778 env->DeleteLocalRef(deviceNameStr);
779 }
780}
781
782void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
783 JNIEnv* env = jniEnv();
784
785 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
786 gCallbacksClassInfo.getExcludedDeviceNames));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700787 if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700788 jsize length = env->GetArrayLength(result);
789 for (jsize i = 0; i < length; i++) {
790 jstring item = jstring(env->GetObjectArrayElement(result, i));
791
792 const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
793 outExcludedDeviceNames.add(String8(deviceNameChars));
794 env->ReleaseStringUTFChars(item, deviceNameChars);
795
796 env->DeleteLocalRef(item);
797 }
798 env->DeleteLocalRef(result);
799 }
800}
801
802void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
803#if DEBUG_INPUT_DISPATCHER_POLICY
804 LOGD("notifyConfigurationChanged - when=%lld", when);
805#endif
806
807 JNIEnv* env = jniEnv();
808
809 InputConfiguration config;
810 mInputManager->getInputConfiguration(& config);
811
812 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
813 when, config.touchScreen, config.keyboard, config.navigation);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700814 checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700815}
816
817void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
818#if DEBUG_INPUT_DISPATCHER_POLICY
819 LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
820#endif
821
Jeff Brown7fbdc842010-06-17 20:52:56 -0700822 JNIEnv* env = jniEnv();
823
824 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
825 if (inputChannelObjLocal) {
826 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
827 inputChannelObjLocal);
828 checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
829
830 env->DeleteLocalRef(inputChannelObjLocal);
831 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700832}
833
Jeff Brown7fbdc842010-06-17 20:52:56 -0700834bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel,
835 nsecs_t& outNewTimeout) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700836#if DEBUG_INPUT_DISPATCHER_POLICY
837 LOGD("notifyInputChannelANR - inputChannel='%s'",
838 inputChannel->getName().string());
839#endif
840
Jeff Brown7fbdc842010-06-17 20:52:56 -0700841 JNIEnv* env = jniEnv();
842
843 jlong newTimeout;
844 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
845 if (inputChannelObjLocal) {
846 newTimeout = env->CallLongMethod(mCallbacksObj,
847 gCallbacksClassInfo.notifyInputChannelANR, inputChannelObjLocal);
848 if (checkAndClearExceptionFromCallback(env, "notifyInputChannelANR")) {
849 newTimeout = -2;
850 }
851
852 env->DeleteLocalRef(inputChannelObjLocal);
853 } else {
854 newTimeout = -2;
855 }
856
857 if (newTimeout == -2) {
858 return false; // abort
859 }
860
861 outNewTimeout = newTimeout;
862 return true; // resume
Jeff Brown9c3cda02010-06-15 01:31:58 -0700863}
864
865void NativeInputManager::notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) {
866#if DEBUG_INPUT_DISPATCHER_POLICY
867 LOGD("notifyInputChannelRecoveredFromANR - inputChannel='%s'",
868 inputChannel->getName().string());
869#endif
870
Jeff Brown7fbdc842010-06-17 20:52:56 -0700871 JNIEnv* env = jniEnv();
872
873 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
874 if (inputChannelObjLocal) {
875 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelRecoveredFromANR,
876 inputChannelObjLocal);
877 checkAndClearExceptionFromCallback(env, "notifyInputChannelRecoveredFromANR");
878
879 env->DeleteLocalRef(inputChannelObjLocal);
880 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700881}
882
Jeff Brown349703e2010-06-22 01:27:15 -0700883bool NativeInputManager::notifyANR(jobject tokenObj, nsecs_t& outNewTimeout) {
884#if DEBUG_INPUT_DISPATCHER_POLICY
885 LOGD("notifyANR");
886#endif
887
888 JNIEnv* env = jniEnv();
889
890 jlong newTimeout = env->CallLongMethod(mCallbacksObj,
891 gCallbacksClassInfo.notifyANR, tokenObj);
892 if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
893 newTimeout = -2;
894 }
895
896 if (newTimeout == -2) {
897 return false; // abort
898 }
899
900 outNewTimeout = newTimeout;
901 return true; // resume
902}
903
Jeff Brown9c3cda02010-06-15 01:31:58 -0700904nsecs_t NativeInputManager::getKeyRepeatTimeout() {
905 if (! isScreenOn()) {
906 // Disable key repeat when the screen is off.
907 return -1;
908 } else {
909 // TODO use ViewConfiguration.getLongPressTimeout()
910 return milliseconds_to_nanoseconds(500);
911 }
912}
913
Jeff Brown349703e2010-06-22 01:27:15 -0700914void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
915#if DEBUG_FOCUS
916 LOGD("setInputWindows");
917#endif
918 { // acquire lock
919 AutoMutex _l(mDispatchLock);
920
921 sp<InputChannel> touchedWindowChannel;
922 if (mTouchedWindow) {
923 touchedWindowChannel = mTouchedWindow->inputChannel;
924 mTouchedWindow = NULL;
925 }
926 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
927 if (numTouchedWallpapers != 0) {
928 for (size_t i = 0; i < numTouchedWallpapers; i++) {
929 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
930 }
931 mTouchedWallpaperWindows.clear();
932 }
933
Jeff Browne33348b2010-07-15 23:54:05 -0700934 bool hadFocusedWindow = mFocusedWindow != NULL;
935
Jeff Brown349703e2010-06-22 01:27:15 -0700936 mWindows.clear();
937 mFocusedWindow = NULL;
938 mWallpaperWindows.clear();
939
940 if (windowObjArray) {
941 mWindowsReady = true;
942
943 jsize length = env->GetArrayLength(windowObjArray);
944 for (jsize i = 0; i < length; i++) {
945 jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
946 if (! inputTargetObj) {
947 break; // found null element indicating end of used portion of the array
948 }
949
950 mWindows.push();
951 InputWindow& window = mWindows.editTop();
952 bool valid = populateWindow(env, inputTargetObj, window);
953 if (! valid) {
954 mWindows.pop();
955 }
956
957 env->DeleteLocalRef(inputTargetObj);
958 }
959
960 size_t numWindows = mWindows.size();
961 for (size_t i = 0; i < numWindows; i++) {
962 InputWindow* window = & mWindows.editItemAt(i);
963 if (window->hasFocus) {
964 mFocusedWindow = window;
965 }
966
967 if (window->layoutParamsType == TYPE_WALLPAPER) {
968 mWallpaperWindows.push(window);
969
970 for (size_t j = 0; j < numTouchedWallpapers; j++) {
971 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
972 mTouchedWallpaperWindows.push(window);
973 }
974 }
975 }
976
977 if (window->inputChannel == touchedWindowChannel) {
978 mTouchedWindow = window;
979 }
980 }
981 } else {
982 mWindowsReady = false;
983 }
984
985 mTempTouchedWallpaperChannels.clear();
986
Jeff Brown00ba8842010-07-16 15:01:56 -0700987 if ((hadFocusedWindow && ! mFocusedWindow)
988 || (mFocusedWindow && ! mFocusedWindow->visible)) {
Jeff Browne33348b2010-07-15 23:54:05 -0700989 preemptInputDispatch();
990 }
991
Jeff Brown349703e2010-06-22 01:27:15 -0700992 mDispatchStateChanged.broadcast();
993
994#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -0700995 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -0700996#endif
997 } // release lock
998}
999
1000bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
1001 InputWindow& outWindow) {
1002 bool valid = false;
1003
1004 jobject inputChannelObj = env->GetObjectField(windowObj,
1005 gInputWindowClassInfo.inputChannel);
1006 if (inputChannelObj) {
1007 sp<InputChannel> inputChannel =
1008 android_view_InputChannel_getInputChannel(env, inputChannelObj);
1009 if (inputChannel != NULL) {
1010 jint layoutParamsFlags = env->GetIntField(windowObj,
1011 gInputWindowClassInfo.layoutParamsFlags);
1012 jint layoutParamsType = env->GetIntField(windowObj,
1013 gInputWindowClassInfo.layoutParamsType);
1014 jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
1015 gInputWindowClassInfo.dispatchingTimeoutNanos);
1016 jint frameLeft = env->GetIntField(windowObj,
1017 gInputWindowClassInfo.frameLeft);
1018 jint frameTop = env->GetIntField(windowObj,
1019 gInputWindowClassInfo.frameTop);
1020 jint touchableAreaLeft = env->GetIntField(windowObj,
1021 gInputWindowClassInfo.touchableAreaLeft);
1022 jint touchableAreaTop = env->GetIntField(windowObj,
1023 gInputWindowClassInfo.touchableAreaTop);
1024 jint touchableAreaRight = env->GetIntField(windowObj,
1025 gInputWindowClassInfo.touchableAreaRight);
1026 jint touchableAreaBottom = env->GetIntField(windowObj,
1027 gInputWindowClassInfo.touchableAreaBottom);
1028 jboolean visible = env->GetBooleanField(windowObj,
1029 gInputWindowClassInfo.visible);
1030 jboolean hasFocus = env->GetBooleanField(windowObj,
1031 gInputWindowClassInfo.hasFocus);
1032 jboolean hasWallpaper = env->GetBooleanField(windowObj,
1033 gInputWindowClassInfo.hasWallpaper);
1034 jboolean paused = env->GetBooleanField(windowObj,
1035 gInputWindowClassInfo.paused);
1036 jint ownerPid = env->GetIntField(windowObj,
1037 gInputWindowClassInfo.ownerPid);
1038 jint ownerUid = env->GetIntField(windowObj,
1039 gInputWindowClassInfo.ownerUid);
1040
1041 outWindow.inputChannel = inputChannel;
1042 outWindow.layoutParamsFlags = layoutParamsFlags;
1043 outWindow.layoutParamsType = layoutParamsType;
1044 outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
1045 outWindow.frameLeft = frameLeft;
1046 outWindow.frameTop = frameTop;
1047 outWindow.touchableAreaLeft = touchableAreaLeft;
1048 outWindow.touchableAreaTop = touchableAreaTop;
1049 outWindow.touchableAreaRight = touchableAreaRight;
1050 outWindow.touchableAreaBottom = touchableAreaBottom;
1051 outWindow.visible = visible;
1052 outWindow.hasFocus = hasFocus;
1053 outWindow.hasWallpaper = hasWallpaper;
1054 outWindow.paused = paused;
1055 outWindow.ownerPid = ownerPid;
1056 outWindow.ownerUid = ownerUid;
1057 valid = true;
1058 } else {
1059 LOGW("Dropping input target because its input channel is not initialized.");
1060 }
1061
1062 env->DeleteLocalRef(inputChannelObj);
1063 } else {
1064 LOGW("Dropping input target because the input channel object was null.");
1065 }
1066 return valid;
1067}
1068
1069void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
1070#if DEBUG_FOCUS
1071 LOGD("setFocusedApplication");
1072#endif
1073 { // acquire lock
1074 AutoMutex _l(mDispatchLock);
1075
1076 releaseFocusedApplicationLd(env);
1077
1078 if (applicationObj) {
1079 jstring nameObj = jstring(env->GetObjectField(applicationObj,
1080 gInputApplicationClassInfo.name));
1081 jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
1082 gInputApplicationClassInfo.dispatchingTimeoutNanos);
1083 jobject tokenObj = env->GetObjectField(applicationObj,
1084 gInputApplicationClassInfo.token);
1085 jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
1086 if (! tokenObjWeak) {
1087 LOGE("Could not create weak reference for application token.");
1088 LOGE_EX(env);
1089 env->ExceptionClear();
1090 }
1091 env->DeleteLocalRef(tokenObj);
1092
1093 mFocusedApplication = & mFocusedApplicationStorage;
1094
1095 if (nameObj) {
1096 const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
1097 mFocusedApplication->name.setTo(nameStr);
1098 env->ReleaseStringUTFChars(nameObj, nameStr);
1099 env->DeleteLocalRef(nameObj);
1100 } else {
1101 LOGE("InputApplication.name should not be null.");
1102 mFocusedApplication->name.setTo("unknown");
1103 }
1104
1105 mFocusedApplication->dispatchingTimeout = dispatchingTimeoutNanos;
1106 mFocusedApplication->tokenObjWeak = tokenObjWeak;
1107 }
1108
1109 mDispatchStateChanged.broadcast();
1110
1111#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001112 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001113#endif
1114 } // release lock
1115}
1116
1117void NativeInputManager::releaseFocusedApplicationLd(JNIEnv* env) {
1118 if (mFocusedApplication) {
1119 env->DeleteWeakGlobalRef(mFocusedApplication->tokenObjWeak);
1120 mFocusedApplication = NULL;
1121 }
1122}
1123
1124void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
1125#if DEBUG_FOCUS
1126 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001127#endif
1128
Jeff Brown349703e2010-06-22 01:27:15 -07001129 { // acquire lock
1130 AutoMutex _l(mDispatchLock);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001131
Jeff Brown349703e2010-06-22 01:27:15 -07001132 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
1133 mDispatchEnabled = enabled;
1134 mDispatchFrozen = frozen;
1135
1136 mDispatchStateChanged.broadcast();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001137 }
Jeff Brown349703e2010-06-22 01:27:15 -07001138
1139#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001140 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001141#endif
1142 } // release lock
1143}
1144
1145void NativeInputManager::preemptInputDispatch() {
1146#if DEBUG_FOCUS
1147 LOGD("preemptInputDispatch");
1148#endif
1149
1150 mInputManager->preemptInputDispatch();
1151}
1152
1153int32_t NativeInputManager::waitForFocusedWindowLd(uint32_t policyFlags,
1154 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1155 InputWindow*& outFocusedWindow) {
1156
1157 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1158 bool firstIteration = true;
1159 ANRTimer anrTimer;
1160 for (;;) {
1161 if (firstIteration) {
1162 firstIteration = false;
1163 } else {
1164 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1165 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1166 "the window that should receive it.");
1167 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1168 break;
1169 }
1170 }
1171
1172 // If dispatch is not enabled then fail.
1173 if (! mDispatchEnabled) {
1174 LOGI("Dropping event because input dispatch is disabled.");
1175 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1176 break;
1177 }
1178
1179 // If dispatch is frozen or we don't have valid window data yet then wait.
1180 if (mDispatchFrozen || ! mWindowsReady) {
1181#if DEBUG_FOCUS
1182 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1183#endif
1184 anrTimer.dispatchFrozenBySystem();
1185 continue;
1186 }
1187
1188 // If there is no currently focused window and no focused application
1189 // then drop the event.
1190 if (! mFocusedWindow) {
1191 if (mFocusedApplication) {
1192#if DEBUG_FOCUS
1193 LOGD("Waiting because there is no focused window but there is a "
1194 "focused application that may yet introduce a new target: '%s'.",
1195 mFocusedApplication->name.string());
1196#endif
1197 continue;
1198 }
1199
1200 LOGI("Dropping event because there is no focused window or focused application.");
1201 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1202 break;
1203 }
1204
1205 // Check permissions.
1206 if (! checkInjectionPermission(mFocusedWindow, injectorPid, injectorUid)) {
1207 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1208 break;
1209 }
1210
1211 // If the currently focused window is paused then keep waiting.
1212 if (mFocusedWindow->paused) {
1213#if DEBUG_FOCUS
1214 LOGD("Waiting because focused window is paused.");
1215#endif
1216 anrTimer.dispatchPausedByApplication(mFocusedWindow);
1217 continue;
1218 }
1219
1220 // Success!
1221 break; // done waiting, exit loop
Jeff Brown9c3cda02010-06-15 01:31:58 -07001222 }
Jeff Brown349703e2010-06-22 01:27:15 -07001223
1224 // Output targets.
1225 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1226 addTarget(mFocusedWindow, InputTarget::FLAG_SYNC,
1227 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1228
1229 outFocusedWindow = mFocusedWindow;
1230 } else {
1231 outFocusedWindow = NULL;
1232 }
1233
1234#if DEBUG_FOCUS
1235 LOGD("waitForFocusedWindow finished: injectionResult=%d",
1236 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001237 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001238#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001239 return injectionResult;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001240}
1241
Jeff Brownc5ed5912010-07-14 18:48:53 -07001242enum InjectionPermission {
1243 INJECTION_PERMISSION_UNKNOWN,
1244 INJECTION_PERMISSION_GRANTED,
1245 INJECTION_PERMISSION_DENIED
1246};
1247
Jeff Brown349703e2010-06-22 01:27:15 -07001248int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
1249 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1250 InputWindow*& outTouchedWindow) {
1251 nsecs_t startTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001252
Jeff Brown349703e2010-06-22 01:27:15 -07001253 // For security reasons, we defer updating the touch state until we are sure that
1254 // event injection will be allowed.
1255 //
1256 // FIXME In the original code, screenWasOff could never be set to true.
1257 // The reason is that the POLICY_FLAG_WOKE_HERE
1258 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
1259 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
1260 // actually enqueued using the policyFlags that appeared in the final EV_SYN
1261 // events upon which no preprocessing took place. So policyFlags was always 0.
1262 // In the new native input dispatcher we're a bit more careful about event
1263 // preprocessing so the touches we receive can actually have non-zero policyFlags.
1264 // Unfortunately we obtain undesirable behavior.
1265 //
1266 // Here's what happens:
1267 //
1268 // When the device dims in anticipation of going to sleep, touches
1269 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
1270 // the device to brighten and reset the user activity timer.
1271 // Touches on other windows (such as the launcher window)
1272 // are dropped. Then after a moment, the device goes to sleep. Oops.
1273 //
1274 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
1275 // instead of POLICY_FLAG_WOKE_HERE...
1276 //
1277 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001278
1279 int32_t action = motionEvent->getAction();
1280
Jeff Brown349703e2010-06-22 01:27:15 -07001281 bool firstIteration = true;
1282 ANRTimer anrTimer;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001283 int32_t injectionResult;
1284 InjectionPermission injectionPermission;
Jeff Brown349703e2010-06-22 01:27:15 -07001285 for (;;) {
1286 if (firstIteration) {
1287 firstIteration = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001288 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001289 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1290 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1291 "the window that should receive it.");
1292 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001293 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1294 break; // timed out, exit wait loop
Jeff Brown349703e2010-06-22 01:27:15 -07001295 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001296 }
Jeff Brown349703e2010-06-22 01:27:15 -07001297
1298 // If dispatch is not enabled then fail.
1299 if (! mDispatchEnabled) {
1300 LOGI("Dropping event because input dispatch is disabled.");
1301 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001302 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001303 break; // failed, exit wait loop
1304 }
1305
1306 // If dispatch is frozen or we don't have valid window data yet then wait.
1307 if (mDispatchFrozen || ! mWindowsReady) {
1308#if DEBUG_INPUT_DISPATCHER_POLICY
1309 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1310#endif
1311 anrTimer.dispatchFrozenBySystem();
1312 continue;
1313 }
1314
1315 // Update the touch state as needed based on the properties of the touch event.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001316 if (action == AMOTION_EVENT_ACTION_DOWN) {
1317 /* Case 1: ACTION_DOWN */
1318
Jeff Brown349703e2010-06-22 01:27:15 -07001319 InputWindow* newTouchedWindow = NULL;
1320 mTempTouchedOutsideWindows.clear();
1321
1322 int32_t x = int32_t(motionEvent->getX(0));
1323 int32_t y = int32_t(motionEvent->getY(0));
1324 InputWindow* topErrorWindow = NULL;
1325
1326 // Traverse windows from front to back to find touched window and outside targets.
1327 size_t numWindows = mWindows.size();
1328 for (size_t i = 0; i < numWindows; i++) {
1329 InputWindow* window = & mWindows.editItemAt(i);
1330 int32_t flags = window->layoutParamsFlags;
1331
1332 if (flags & FLAG_SYSTEM_ERROR) {
1333 if (! topErrorWindow) {
1334 topErrorWindow = window;
1335 }
1336 }
1337
1338 if (window->visible) {
1339 if (! (flags & FLAG_NOT_TOUCHABLE)) {
1340 bool isTouchModal = (flags &
1341 (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL)) == 0;
1342 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
1343 if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
1344 newTouchedWindow = window;
1345 }
1346 break; // found touched window, exit window loop
1347 }
1348 }
1349
1350 if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
1351 mTempTouchedOutsideWindows.push(window);
1352 }
1353 }
1354 }
1355
1356 // If there is an error window but it is not taking focus (typically because
1357 // it is invisible) then wait for it. Any other focused window may in
1358 // fact be in ANR state.
1359 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1360#if DEBUG_INPUT_DISPATCHER_POLICY
1361 LOGD("Waiting because system error window is pending.");
1362#endif
1363 anrTimer.dispatchFrozenBySystem();
1364 continue; // wait some more
1365 }
1366
1367 // If we did not find a touched window then fail.
1368 if (! newTouchedWindow) {
1369 if (mFocusedApplication) {
1370#if DEBUG_FOCUS
1371 LOGD("Waiting because there is no focused window but there is a "
1372 "focused application that may yet introduce a new target: '%s'.",
1373 mFocusedApplication->name.string());
1374#endif
1375 continue;
1376 }
1377
1378 LOGI("Dropping event because there is no touched window or focused application.");
1379 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001380 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001381 break; // failed, exit wait loop
1382 }
1383
1384 // Check permissions.
1385 if (! checkInjectionPermission(newTouchedWindow, injectorPid, injectorUid)) {
1386 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001387 injectionPermission = INJECTION_PERMISSION_DENIED;
Jeff Brown349703e2010-06-22 01:27:15 -07001388 break; // failed, exit wait loop
1389 }
1390
1391 // If the touched window is paused then keep waiting.
1392 if (newTouchedWindow->paused) {
1393#if DEBUG_INPUT_DISPATCHER_POLICY
1394 LOGD("Waiting because touched window is paused.");
1395#endif
1396 anrTimer.dispatchPausedByApplication(newTouchedWindow);
1397 continue; // wait some more
1398 }
1399
1400 // Success! Update the touch dispatch state for real.
1401 releaseTouchedWindowLd();
1402
1403 mTouchedWindow = newTouchedWindow;
1404
1405 if (newTouchedWindow->hasWallpaper) {
1406 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1407 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001408
1409 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1410 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001411 break; // done
1412 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001413 /* Case 2: Everything but ACTION_DOWN */
1414
Jeff Brown349703e2010-06-22 01:27:15 -07001415 // Check permissions.
1416 if (! checkInjectionPermission(mTouchedWindow, injectorPid, injectorUid)) {
1417 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001418 injectionPermission = INJECTION_PERMISSION_DENIED;
1419 break; // failed, exit wait loop
1420 }
1421
1422 // If the pointer is not currently down, then ignore the event.
1423 if (! mTouchDown) {
1424 LOGI("Dropping event because the pointer is not down.");
1425 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1426 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001427 break; // failed, exit wait loop
1428 }
1429
1430 // If there is no currently touched window then fail.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001431 if (! mTouchedWindow) {
1432 LOGW("Dropping event because there is no touched window to receive it.");
Jeff Brown349703e2010-06-22 01:27:15 -07001433 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001434 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001435 break; // failed, exit wait loop
1436 }
1437
1438 // If the touched window is paused then keep waiting.
1439 if (mTouchedWindow->paused) {
1440#if DEBUG_INPUT_DISPATCHER_POLICY
1441 LOGD("Waiting because touched window is paused.");
1442#endif
1443 anrTimer.dispatchPausedByApplication(mTouchedWindow);
1444 continue; // wait some more
1445 }
1446
1447 // Success!
Jeff Brownc5ed5912010-07-14 18:48:53 -07001448 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1449 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001450 break; // done
1451 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001452 }
Jeff Brown349703e2010-06-22 01:27:15 -07001453
1454 // Output targets.
Jeff Brown349703e2010-06-22 01:27:15 -07001455 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
Jeff Brown349703e2010-06-22 01:27:15 -07001456 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1457 for (size_t i = 0; i < numWallpaperWindows; i++) {
1458 addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
1459 }
1460
1461 size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
1462 for (size_t i = 0; i < numOutsideWindows; i++) {
1463 addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
1464 }
1465
1466 addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
1467 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1468 outTouchedWindow = mTouchedWindow;
1469 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001470 outTouchedWindow = NULL;
1471 }
1472 mTempTouchedOutsideWindows.clear();
1473
Jeff Brownc5ed5912010-07-14 18:48:53 -07001474 // Check injection permission once and for all.
1475 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
1476 if (checkInjectionPermission(action == AMOTION_EVENT_ACTION_DOWN ? NULL : mTouchedWindow,
1477 injectorPid, injectorUid)) {
1478 injectionPermission = INJECTION_PERMISSION_GRANTED;
1479 } else {
1480 injectionPermission = INJECTION_PERMISSION_DENIED;
1481 }
1482 }
1483
1484 // Update final pieces of touch state if the injector had permission.
1485 if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
1486 if (action == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brown349703e2010-06-22 01:27:15 -07001487 if (mTouchDown) {
1488 // This is weird. We got a down but we thought it was already down!
1489 LOGW("Pointer down received while already down.");
1490 } else {
1491 mTouchDown = true;
1492 }
1493
1494 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1495 // Since we failed to identify a target for this touch down, we may still
1496 // be holding on to an earlier target from a previous touch down. Release it.
1497 releaseTouchedWindowLd();
1498 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001499 } else if (action == AMOTION_EVENT_ACTION_UP) {
Jeff Brown349703e2010-06-22 01:27:15 -07001500 mTouchDown = false;
1501 releaseTouchedWindowLd();
1502 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001503 } else {
1504 LOGW("Not updating touch focus because injection was denied.");
Jeff Brown349703e2010-06-22 01:27:15 -07001505 }
1506
1507#if DEBUG_FOCUS
1508 LOGD("waitForTouchedWindow finished: injectionResult=%d",
1509 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001510 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001511#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001512 return injectionResult;
1513}
1514
Jeff Brown349703e2010-06-22 01:27:15 -07001515void NativeInputManager::releaseTouchedWindowLd() {
1516 mTouchedWindow = NULL;
1517 mTouchedWallpaperWindows.clear();
1518}
1519
1520void NativeInputManager::addTarget(const InputWindow* window, int32_t targetFlags,
1521 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets) {
1522 nsecs_t timeout = window->dispatchingTimeout - timeSpentWaitingForApplication;
1523 if (timeout < MIN_INPUT_DISPATCHING_TIMEOUT) {
1524 timeout = MIN_INPUT_DISPATCHING_TIMEOUT;
1525 }
1526
1527 outTargets.push();
1528
1529 InputTarget& target = outTargets.editTop();
1530 target.inputChannel = window->inputChannel;
1531 target.flags = targetFlags;
1532 target.timeout = timeout;
1533 target.xOffset = - window->frameLeft;
1534 target.yOffset = - window->frameTop;
1535}
1536
1537bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
1538 int32_t injectorPid, int32_t injectorUid) {
1539 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1540 JNIEnv* env = jniEnv();
1541 jboolean result = env->CallBooleanMethod(mCallbacksObj,
1542 gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
1543 checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission");
1544
1545 if (! result) {
1546 if (window) {
1547 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1548 "with input channel %s owned by uid %d",
1549 injectorPid, injectorUid, window->inputChannel->getName().string(),
1550 window->ownerUid);
1551 } else {
1552 LOGW("Permission denied: injecting event from pid %d uid %d",
1553 injectorPid, injectorUid);
1554 }
1555 return false;
1556 }
1557 }
1558
1559 return true;
1560}
1561
1562int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
1563 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
1564#if DEBUG_INPUT_DISPATCHER_POLICY
1565 LOGD("waitForKeyEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1566 policyFlags, injectorPid, injectorUid);
1567#endif
1568
1569 int32_t windowType;
1570 { // acquire lock
1571 AutoMutex _l(mDispatchLock);
1572
1573 InputWindow* focusedWindow;
1574 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1575 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1576 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1577 return injectionResult;
1578 }
1579
1580 windowType = focusedWindow->layoutParamsType;
1581 } // release lock
1582
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001583 if (isPolicyKey(keyEvent->getKeyCode(), isScreenOn())) {
1584 const InputTarget& target = outTargets.top();
1585 bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags);
1586 if (consumed) {
1587 outTargets.clear();
1588 return INPUT_EVENT_INJECTION_SUCCEEDED;
1589 }
Jeff Brown349703e2010-06-22 01:27:15 -07001590 }
1591
1592 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1593 return INPUT_EVENT_INJECTION_SUCCEEDED;
1594}
1595
1596int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
1597 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001598 Vector<InputTarget>& outTargets) {
Jeff Brown349703e2010-06-22 01:27:15 -07001599#if DEBUG_INPUT_DISPATCHER_POLICY
1600 LOGD("waitForMotionEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1601 policyFlags, injectorPid, injectorUid);
1602#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001603
Jeff Brownc5ed5912010-07-14 18:48:53 -07001604 int32_t source = motionEvent->getSource();
1605 if (source & AINPUT_SOURCE_CLASS_POINTER) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001606 return waitForTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
Jeff Brown349703e2010-06-22 01:27:15 -07001607 outTargets);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001608 } else {
1609 return waitForNonTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
1610 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001611 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001612}
1613
Jeff Brownc5ed5912010-07-14 18:48:53 -07001614int32_t NativeInputManager::waitForNonTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001615 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1616 Vector<InputTarget>& outTargets) {
1617#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brownc5ed5912010-07-14 18:48:53 -07001618 LOGD("waitForNonTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001619 policyFlags, injectorPid, injectorUid);
1620#endif
1621
1622 int32_t windowType;
1623 { // acquire lock
1624 AutoMutex _l(mDispatchLock);
1625
1626 InputWindow* focusedWindow;
1627 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1628 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1629 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1630 return injectionResult;
1631 }
1632
1633 windowType = focusedWindow->layoutParamsType;
1634 } // release lock
1635
1636 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1637 return INPUT_EVENT_INJECTION_SUCCEEDED;
1638}
1639
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001640int32_t NativeInputManager::waitForTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001641 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1642 Vector<InputTarget>& outTargets) {
1643#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001644 LOGD("waitForTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001645 policyFlags, injectorPid, injectorUid);
1646#endif
1647
1648 int32_t windowType;
1649 { // acquire lock
1650 AutoMutex _l(mDispatchLock);
1651
1652 InputWindow* touchedWindow;
1653 int32_t injectionResult = waitForTouchedWindowLd(motionEvent, policyFlags,
1654 injectorPid, injectorUid, outTargets, /*out*/ touchedWindow);
1655 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1656 return injectionResult;
1657 }
1658
1659 windowType = touchedWindow->layoutParamsType;
1660 } // release lock
1661
1662 int32_t eventType;
1663 switch (motionEvent->getAction()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001664 case AMOTION_EVENT_ACTION_DOWN:
Jeff Brown349703e2010-06-22 01:27:15 -07001665 eventType = POWER_MANAGER_TOUCH_EVENT;
1666 break;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001667 case AMOTION_EVENT_ACTION_UP:
Jeff Brown349703e2010-06-22 01:27:15 -07001668 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
1669 break;
1670 default:
1671 if (motionEvent->getEventTime() - motionEvent->getDownTime()
1672 >= EVENT_IGNORE_DURATION) {
1673 eventType = POWER_MANAGER_TOUCH_EVENT;
1674 } else {
1675 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
1676 }
1677 break;
1678 }
1679 pokeUserActivityIfNeeded(windowType, eventType);
1680 return INPUT_EVENT_INJECTION_SUCCEEDED;
1681}
1682
Jeff Brownd0097872010-06-30 14:41:59 -07001683bool NativeInputManager::interceptKeyBeforeDispatching(const InputTarget& target,
1684 const KeyEvent* keyEvent, uint32_t policyFlags) {
1685 JNIEnv* env = jniEnv();
1686
1687 jobject inputChannelObj = getInputChannelObjLocal(env, target.inputChannel);
1688 if (inputChannelObj) {
1689 jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
1690 gCallbacksClassInfo.interceptKeyBeforeDispatching,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001691 inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
1692 keyEvent->getKeyCode(), keyEvent->getMetaState(),
Jeff Brownd0097872010-06-30 14:41:59 -07001693 keyEvent->getRepeatCount(), policyFlags);
1694 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
1695
1696 env->DeleteLocalRef(inputChannelObj);
1697
1698 return consumed && ! error;
1699 } else {
1700 LOGW("Could not apply key dispatch policy because input channel '%s' is "
1701 "no longer valid.", target.inputChannel->getName().string());
1702 return false;
1703 }
1704}
1705
Jeff Brown349703e2010-06-22 01:27:15 -07001706void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType) {
1707 if (windowType != TYPE_KEYGUARD) {
1708 nsecs_t eventTime = now();
1709 pokeUserActivity(eventTime, eventType);
1710 }
1711}
1712
1713void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001714 android_server_PowerManagerService_userActivity(eventTime, eventType);
Jeff Brown349703e2010-06-22 01:27:15 -07001715}
1716
Jeff Brown6d0fec22010-07-23 21:28:06 -07001717static void dumpMotionRange(String8& dump,
1718 const char* name, const InputDeviceInfo::MotionRange* range) {
1719 if (range) {
1720 dump.appendFormat(" %s = { min: %0.3f, max: %0.3f, flat: %0.3f, fuzz: %0.3f }\n",
1721 name, range->min, range->max, range->flat, range->fuzz);
1722 }
1723}
1724
1725#define DUMP_MOTION_RANGE(range) \
1726 dumpMotionRange(dump, #range, deviceInfo.getMotionRange(AINPUT_MOTION_RANGE_##range));
1727
1728void NativeInputManager::dumpDeviceInfo(String8& dump) {
1729 Vector<int32_t> deviceIds;
1730 mInputManager->getInputDeviceIds(deviceIds);
1731
1732 InputDeviceInfo deviceInfo;
1733 for (size_t i = 0; i < deviceIds.size(); i++) {
1734 int32_t deviceId = deviceIds[i];
1735
1736 status_t result = mInputManager->getInputDeviceInfo(deviceId, & deviceInfo);
1737 if (result == NAME_NOT_FOUND) {
1738 continue;
1739 } else if (result != OK) {
1740 dump.appendFormat(" ** Unexpected error %d getting information about input devices.\n",
1741 result);
1742 continue;
1743 }
1744
1745 dump.appendFormat(" Device %d: '%s'\n",
1746 deviceInfo.getId(), deviceInfo.getName().string());
1747 dump.appendFormat(" sources = 0x%08x\n",
1748 deviceInfo.getSources());
1749 dump.appendFormat(" keyboardType = %d\n",
1750 deviceInfo.getKeyboardType());
1751
1752 dump.append(" motion ranges:\n");
1753 DUMP_MOTION_RANGE(X);
1754 DUMP_MOTION_RANGE(Y);
1755 DUMP_MOTION_RANGE(PRESSURE);
1756 DUMP_MOTION_RANGE(SIZE);
1757 DUMP_MOTION_RANGE(TOUCH_MAJOR);
1758 DUMP_MOTION_RANGE(TOUCH_MINOR);
1759 DUMP_MOTION_RANGE(TOOL_MAJOR);
1760 DUMP_MOTION_RANGE(TOOL_MINOR);
1761 DUMP_MOTION_RANGE(ORIENTATION);
1762 }
1763}
1764
1765#undef DUMP_MOTION_RANGE
1766
Jeff Browne33348b2010-07-15 23:54:05 -07001767void NativeInputManager::logDispatchStateLd() {
1768 String8 dump;
1769 dumpDispatchStateLd(dump);
1770 LOGD("%s", dump.string());
1771}
1772
1773void NativeInputManager::dumpDispatchStateLd(String8& dump) {
1774 dump.appendFormat(" dispatchEnabled: %d\n", mDispatchEnabled);
1775 dump.appendFormat(" dispatchFrozen: %d\n", mDispatchFrozen);
1776 dump.appendFormat(" windowsReady: %d\n", mWindowsReady);
1777
Jeff Brown349703e2010-06-22 01:27:15 -07001778 if (mFocusedApplication) {
Jeff Browne33348b2010-07-15 23:54:05 -07001779 dump.appendFormat(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001780 mFocusedApplication->name.string(),
1781 mFocusedApplication->dispatchingTimeout / 1000000.0);
1782 } else {
Jeff Browne33348b2010-07-15 23:54:05 -07001783 dump.append(" focusedApplication: <null>\n");
Jeff Brown349703e2010-06-22 01:27:15 -07001784 }
Jeff Browne33348b2010-07-15 23:54:05 -07001785 dump.appendFormat(" focusedWindow: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001786 mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
Jeff Browne33348b2010-07-15 23:54:05 -07001787 dump.appendFormat(" touchedWindow: '%s', touchDown=%d\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001788 mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
1789 mTouchDown);
1790 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001791 dump.appendFormat(" touchedWallpaperWindows[%d]: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001792 i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
1793 }
1794 for (size_t i = 0; i < mWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001795 dump.appendFormat(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, "
1796 "visible=%d, flags=0x%08x, type=0x%08x, "
Jeff Brown349703e2010-06-22 01:27:15 -07001797 "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
Jeff Browne33348b2010-07-15 23:54:05 -07001798 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001799 i, mWindows[i].inputChannel->getName().string(),
1800 mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
1801 mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
1802 mWindows[i].frameLeft, mWindows[i].frameTop,
1803 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
1804 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
1805 mWindows[i].ownerPid, mWindows[i].ownerUid,
1806 mWindows[i].dispatchingTimeout / 1000000.0);
1807 }
Jeff Brown349703e2010-06-22 01:27:15 -07001808}
1809
1810// ----------------------------------------------------------------------------
1811
1812NativeInputManager::ANRTimer::ANRTimer() :
1813 mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
1814}
1815
1816void NativeInputManager::ANRTimer::dispatchFrozenBySystem() {
1817 mFrozen = true;
1818}
1819
1820void NativeInputManager::ANRTimer::dispatchPausedByApplication(InputWindow* pausedWindow) {
1821 mPausedWindow = pausedWindow;
1822}
1823
1824bool NativeInputManager::ANRTimer::waitForDispatchStateChangeLd(NativeInputManager* inputManager) {
1825 nsecs_t currentTime = now();
1826
1827 Budget newBudget;
1828 nsecs_t dispatchingTimeout;
1829 sp<InputChannel> pausedChannel = NULL;
1830 jobject tokenObj = NULL;
1831 if (mFrozen) {
1832 newBudget = SYSTEM;
1833 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1834 mFrozen = false;
1835 } else if (mPausedWindow) {
1836 newBudget = APPLICATION;
1837 dispatchingTimeout = mPausedWindow->dispatchingTimeout;
1838 pausedChannel = mPausedWindow->inputChannel;
1839 mPausedWindow = NULL;
1840 } else if (inputManager->mFocusedApplication) {
1841 newBudget = APPLICATION;
1842 dispatchingTimeout = inputManager->mFocusedApplication->dispatchingTimeout;
1843 tokenObj = jniEnv()->NewLocalRef(inputManager->mFocusedApplication->tokenObjWeak);
1844 } else {
1845 newBudget = APPLICATION;
1846 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1847 }
1848
1849 if (mBudget != newBudget) {
1850 mBudget = newBudget;
1851 mStartTime = currentTime;
1852 }
1853
1854 bool result = false;
1855 nsecs_t timeoutRemaining = mStartTime + dispatchingTimeout - currentTime;
1856 if (timeoutRemaining > 0
1857 && inputManager->mDispatchStateChanged.waitRelative(inputManager->mDispatchLock,
1858 timeoutRemaining) == OK) {
1859 result = true;
1860 } else {
1861 if (pausedChannel != NULL || tokenObj != NULL) {
1862 bool resumed;
1863 nsecs_t newTimeout = 0;
1864
1865 inputManager->mDispatchLock.unlock(); // release lock
1866 if (pausedChannel != NULL) {
1867 resumed = inputManager->notifyInputChannelANR(pausedChannel, /*out*/ newTimeout);
1868 } else {
1869 resumed = inputManager->notifyANR(tokenObj, /*out*/ newTimeout);
1870 }
1871 inputManager->mDispatchLock.lock(); // re-acquire lock
1872
1873 if (resumed) {
1874 mStartTime = now() - dispatchingTimeout + newTimeout;
1875 result = true;
1876 }
1877 }
1878 }
1879
1880 if (tokenObj) {
1881 jniEnv()->DeleteLocalRef(tokenObj);
1882 }
1883
1884 return result;
1885}
1886
1887nsecs_t NativeInputManager::ANRTimer::getTimeSpentWaitingForApplication() const {
1888 return mBudget == APPLICATION ? now() - mStartTime : 0;
1889}
Jeff Brown9c3cda02010-06-15 01:31:58 -07001890
1891// ----------------------------------------------------------------------------
1892
1893static sp<NativeInputManager> gNativeInputManager;
1894
Jeff Brown46b9ac02010-04-22 18:58:52 -07001895static bool checkInputManagerUnitialized(JNIEnv* env) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001896 if (gNativeInputManager == NULL) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001897 LOGE("Input manager not initialized.");
1898 jniThrowRuntimeException(env, "Input manager not initialized.");
1899 return true;
1900 }
1901 return false;
1902}
1903
1904static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
1905 jobject callbacks) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001906 if (gNativeInputManager == NULL) {
1907 gNativeInputManager = new NativeInputManager(callbacks);
1908 } else {
1909 LOGE("Input manager already initialized.");
1910 jniThrowRuntimeException(env, "Input manager already initialized.");
Jeff Brown46b9ac02010-04-22 18:58:52 -07001911 }
1912}
1913
1914static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
1915 if (checkInputManagerUnitialized(env)) {
1916 return;
1917 }
1918
Jeff Brown9c3cda02010-06-15 01:31:58 -07001919 status_t result = gNativeInputManager->getInputManager()->start();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001920 if (result) {
1921 jniThrowRuntimeException(env, "Input manager could not be started.");
1922 }
1923}
1924
1925static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
1926 jint displayId, jint width, jint height) {
1927 if (checkInputManagerUnitialized(env)) {
1928 return;
1929 }
1930
1931 // XXX we could get this from the SurfaceFlinger directly instead of requiring it
1932 // to be passed in like this, not sure which is better but leaving it like this
1933 // keeps the window manager in direct control of when display transitions propagate down
1934 // to the input dispatcher
Jeff Brown9c3cda02010-06-15 01:31:58 -07001935 gNativeInputManager->setDisplaySize(displayId, width, height);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001936}
1937
1938static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
1939 jint displayId, jint orientation) {
1940 if (checkInputManagerUnitialized(env)) {
1941 return;
1942 }
1943
Jeff Brown9c3cda02010-06-15 01:31:58 -07001944 gNativeInputManager->setDisplayOrientation(displayId, orientation);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001945}
1946
1947static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07001948 jint deviceId, jint sourceMask, jint scanCode) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001949 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001950 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001951 }
1952
Jeff Brown9c3cda02010-06-15 01:31:58 -07001953 return gNativeInputManager->getInputManager()->getScanCodeState(
Jeff Brown6d0fec22010-07-23 21:28:06 -07001954 deviceId, uint32_t(sourceMask), scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001955}
1956
1957static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07001958 jint deviceId, jint sourceMask, jint keyCode) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001959 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001960 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001961 }
1962
Jeff Brown9c3cda02010-06-15 01:31:58 -07001963 return gNativeInputManager->getInputManager()->getKeyCodeState(
Jeff Brown6d0fec22010-07-23 21:28:06 -07001964 deviceId, uint32_t(sourceMask), keyCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001965}
1966
1967static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07001968 jint deviceId, jint sourceMask, jint sw) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001969 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001970 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001971 }
1972
Jeff Brown6d0fec22010-07-23 21:28:06 -07001973 return gNativeInputManager->getInputManager()->getSwitchState(
1974 deviceId, uint32_t(sourceMask), sw);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001975}
1976
1977static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07001978 jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001979 if (checkInputManagerUnitialized(env)) {
1980 return JNI_FALSE;
1981 }
1982
1983 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
1984 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
1985 jsize numCodes = env->GetArrayLength(keyCodes);
1986 jboolean result;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001987 if (numCodes == env->GetArrayLength(keyCodes)) {
1988 result = gNativeInputManager->getInputManager()->hasKeys(
1989 deviceId, uint32_t(sourceMask), numCodes, codes, flags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001990 } else {
1991 result = JNI_FALSE;
1992 }
1993
1994 env->ReleaseBooleanArrayElements(outFlags, flags, 0);
1995 env->ReleaseIntArrayElements(keyCodes, codes, 0);
1996 return result;
1997}
1998
1999static void throwInputChannelNotInitialized(JNIEnv* env) {
2000 jniThrowException(env, "java/lang/IllegalStateException",
2001 "inputChannel is not initialized");
2002}
2003
2004static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
2005 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
2006 LOGW("Input channel object '%s' was disposed without first being unregistered with "
2007 "the input manager!", inputChannel->getName().string());
2008
Jeff Brown9c3cda02010-06-15 01:31:58 -07002009 if (gNativeInputManager != NULL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002010 gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002011 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002012}
2013
2014static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
2015 jobject inputChannelObj) {
2016 if (checkInputManagerUnitialized(env)) {
2017 return;
2018 }
2019
2020 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
2021 inputChannelObj);
2022 if (inputChannel == NULL) {
2023 throwInputChannelNotInitialized(env);
2024 return;
2025 }
2026
Jeff Brown7fbdc842010-06-17 20:52:56 -07002027
2028 status_t status = gNativeInputManager->registerInputChannel(
2029 env, inputChannel, inputChannelObj);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002030 if (status) {
2031 jniThrowRuntimeException(env, "Failed to register input channel. "
2032 "Check logs for details.");
2033 return;
2034 }
2035
2036 android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
2037 android_server_InputManager_handleInputChannelDisposed, NULL);
2038}
2039
2040static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
2041 jobject inputChannelObj) {
2042 if (checkInputManagerUnitialized(env)) {
2043 return;
2044 }
2045
2046 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
2047 inputChannelObj);
2048 if (inputChannel == NULL) {
2049 throwInputChannelNotInitialized(env);
2050 return;
2051 }
2052
2053 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
2054
Jeff Brown7fbdc842010-06-17 20:52:56 -07002055 status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002056 if (status) {
2057 jniThrowRuntimeException(env, "Failed to unregister input channel. "
2058 "Check logs for details.");
2059 }
2060}
2061
Jeff Brown6ec402b2010-07-28 15:48:59 -07002062static jint android_server_InputManager_nativeInjectInputEvent(JNIEnv* env, jclass clazz,
2063 jobject inputEventObj, jint injectorPid, jint injectorUid,
2064 jint syncMode, jint timeoutMillis) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002065 if (checkInputManagerUnitialized(env)) {
2066 return INPUT_EVENT_INJECTION_FAILED;
2067 }
2068
Jeff Brown6ec402b2010-07-28 15:48:59 -07002069 if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
2070 KeyEvent keyEvent;
2071 android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002072
Jeff Brown6ec402b2010-07-28 15:48:59 -07002073 return gNativeInputManager->getInputManager()->injectInputEvent(& keyEvent,
2074 injectorPid, injectorUid, syncMode, timeoutMillis);
2075 } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
2076 MotionEvent motionEvent;
2077 android_view_MotionEvent_toNative(env, inputEventObj, & motionEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002078
Jeff Brown6ec402b2010-07-28 15:48:59 -07002079 return gNativeInputManager->getInputManager()->injectInputEvent(& motionEvent,
2080 injectorPid, injectorUid, syncMode, timeoutMillis);
2081 } else {
2082 jniThrowRuntimeException(env, "Invalid input event type.");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002083 return INPUT_EVENT_INJECTION_FAILED;
2084 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07002085}
2086
Jeff Brown349703e2010-06-22 01:27:15 -07002087static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
2088 jobjectArray windowObjArray) {
2089 if (checkInputManagerUnitialized(env)) {
2090 return;
2091 }
2092
2093 gNativeInputManager->setInputWindows(env, windowObjArray);
2094}
2095
2096static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
2097 jobject applicationObj) {
2098 if (checkInputManagerUnitialized(env)) {
2099 return;
2100 }
2101
2102 gNativeInputManager->setFocusedApplication(env, applicationObj);
2103}
2104
2105static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
2106 jclass clazz, jboolean enabled, jboolean frozen) {
2107 if (checkInputManagerUnitialized(env)) {
2108 return;
2109 }
2110
2111 gNativeInputManager->setInputDispatchMode(enabled, frozen);
2112}
2113
2114static void android_server_InputManager_nativePreemptInputDispatch(JNIEnv* env,
2115 jclass clazz) {
2116 if (checkInputManagerUnitialized(env)) {
2117 return;
2118 }
2119
2120 gNativeInputManager->preemptInputDispatch();
2121}
2122
Jeff Browne33348b2010-07-15 23:54:05 -07002123static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
2124 if (checkInputManagerUnitialized(env)) {
2125 return NULL;
2126 }
2127
2128 String8 dump(gNativeInputManager->dump());
2129 return env->NewStringUTF(dump.string());
2130}
2131
Jeff Brown9c3cda02010-06-15 01:31:58 -07002132// ----------------------------------------------------------------------------
2133
Jeff Brown46b9ac02010-04-22 18:58:52 -07002134static JNINativeMethod gInputManagerMethods[] = {
2135 /* name, signature, funcPtr */
2136 { "nativeInit", "(Lcom/android/server/InputManager$Callbacks;)V",
2137 (void*) android_server_InputManager_nativeInit },
2138 { "nativeStart", "()V",
2139 (void*) android_server_InputManager_nativeStart },
2140 { "nativeSetDisplaySize", "(III)V",
2141 (void*) android_server_InputManager_nativeSetDisplaySize },
2142 { "nativeSetDisplayOrientation", "(II)V",
2143 (void*) android_server_InputManager_nativeSetDisplayOrientation },
2144 { "nativeGetScanCodeState", "(III)I",
2145 (void*) android_server_InputManager_nativeGetScanCodeState },
2146 { "nativeGetKeyCodeState", "(III)I",
2147 (void*) android_server_InputManager_nativeGetKeyCodeState },
2148 { "nativeGetSwitchState", "(III)I",
2149 (void*) android_server_InputManager_nativeGetSwitchState },
Jeff Brown6d0fec22010-07-23 21:28:06 -07002150 { "nativeHasKeys", "(II[I[Z)Z",
Jeff Brown46b9ac02010-04-22 18:58:52 -07002151 (void*) android_server_InputManager_nativeHasKeys },
2152 { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;)V",
2153 (void*) android_server_InputManager_nativeRegisterInputChannel },
2154 { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002155 (void*) android_server_InputManager_nativeUnregisterInputChannel },
Jeff Brown6ec402b2010-07-28 15:48:59 -07002156 { "nativeInjectInputEvent", "(Landroid/view/InputEvent;IIII)I",
2157 (void*) android_server_InputManager_nativeInjectInputEvent },
Jeff Brown349703e2010-06-22 01:27:15 -07002158 { "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V",
2159 (void*) android_server_InputManager_nativeSetInputWindows },
2160 { "nativeSetFocusedApplication", "(Lcom/android/server/InputApplication;)V",
2161 (void*) android_server_InputManager_nativeSetFocusedApplication },
2162 { "nativeSetInputDispatchMode", "(ZZ)V",
2163 (void*) android_server_InputManager_nativeSetInputDispatchMode },
2164 { "nativePreemptInputDispatch", "()V",
Jeff Browne33348b2010-07-15 23:54:05 -07002165 (void*) android_server_InputManager_nativePreemptInputDispatch },
2166 { "nativeDump", "()Ljava/lang/String;",
2167 (void*) android_server_InputManager_nativeDump },
Jeff Brown46b9ac02010-04-22 18:58:52 -07002168};
2169
2170#define FIND_CLASS(var, className) \
2171 var = env->FindClass(className); \
2172 LOG_FATAL_IF(! var, "Unable to find class " className); \
2173 var = jclass(env->NewGlobalRef(var));
2174
2175#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2176 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2177 LOG_FATAL_IF(! var, "Unable to find method " methodName);
2178
2179#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
2180 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
2181 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
2182
2183int register_android_server_InputManager(JNIEnv* env) {
2184 int res = jniRegisterNativeMethods(env, "com/android/server/InputManager",
2185 gInputManagerMethods, NELEM(gInputManagerMethods));
2186 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2187
Jeff Brown9c3cda02010-06-15 01:31:58 -07002188 // Callbacks
Jeff Brown46b9ac02010-04-22 18:58:52 -07002189
2190 FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
2191
Jeff Brown46b9ac02010-04-22 18:58:52 -07002192 GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
2193 "notifyConfigurationChanged", "(JIII)V");
2194
2195 GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
2196 "notifyLidSwitchChanged", "(JZ)V");
2197
Jeff Brown7fbdc842010-06-17 20:52:56 -07002198 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
2199 "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
2200
2201 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelANR, gCallbacksClassInfo.clazz,
2202 "notifyInputChannelANR", "(Landroid/view/InputChannel;)J");
2203
2204 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelRecoveredFromANR, gCallbacksClassInfo.clazz,
2205 "notifyInputChannelRecoveredFromANR", "(Landroid/view/InputChannel;)V");
2206
Jeff Brown349703e2010-06-22 01:27:15 -07002207 GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
2208 "notifyANR", "(Ljava/lang/Object;)J");
2209
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002210 GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
2211 "virtualKeyDownFeedback", "()V");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002212
Jeff Brown349703e2010-06-22 01:27:15 -07002213 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002214 "interceptKeyBeforeQueueing", "(JIZIZ)I");
Jeff Brown349703e2010-06-22 01:27:15 -07002215
2216 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002217 "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z");
Jeff Brown349703e2010-06-22 01:27:15 -07002218
2219 GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
2220 "checkInjectEventsPermission", "(II)Z");
Jeff Brown46b9ac02010-04-22 18:58:52 -07002221
Jeff Brown46b9ac02010-04-22 18:58:52 -07002222 GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz,
2223 "notifyAppSwitchComing", "()V");
2224
2225 GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz,
2226 "filterTouchEvents", "()Z");
2227
2228 GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
2229 "filterJumpyTouchEvents", "()Z");
2230
2231 GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz,
2232 "getVirtualKeyDefinitions",
2233 "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
2234
2235 GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
2236 "getExcludedDeviceNames", "()[Ljava/lang/String;");
2237
Jeff Brown46b9ac02010-04-22 18:58:52 -07002238 // VirtualKeyDefinition
2239
2240 FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
2241 "com/android/server/InputManager$VirtualKeyDefinition");
2242
2243 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz,
2244 "scanCode", "I");
2245
2246 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz,
2247 "centerX", "I");
2248
2249 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz,
2250 "centerY", "I");
2251
2252 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz,
2253 "width", "I");
2254
2255 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
2256 "height", "I");
2257
Jeff Brown349703e2010-06-22 01:27:15 -07002258 // InputWindow
Jeff Brown7fbdc842010-06-17 20:52:56 -07002259
Jeff Brown349703e2010-06-22 01:27:15 -07002260 FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002261
Jeff Brown349703e2010-06-22 01:27:15 -07002262 GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
2263 "inputChannel", "Landroid/view/InputChannel;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002264
Jeff Brown349703e2010-06-22 01:27:15 -07002265 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
2266 "layoutParamsFlags", "I");
2267
2268 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
2269 "layoutParamsType", "I");
2270
2271 GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
2272 "dispatchingTimeoutNanos", "J");
2273
2274 GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
2275 "frameLeft", "I");
2276
2277 GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
2278 "frameTop", "I");
2279
2280 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
2281 "touchableAreaLeft", "I");
2282
2283 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
2284 "touchableAreaTop", "I");
2285
2286 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
2287 "touchableAreaRight", "I");
2288
2289 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
2290 "touchableAreaBottom", "I");
2291
2292 GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
2293 "visible", "Z");
2294
2295 GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
2296 "hasFocus", "Z");
2297
2298 GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
2299 "hasWallpaper", "Z");
2300
2301 GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
2302 "paused", "Z");
2303
2304 GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
2305 "ownerPid", "I");
2306
2307 GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
2308 "ownerUid", "I");
2309
2310 // InputApplication
2311
2312 FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
2313
2314 GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
2315 "name", "Ljava/lang/String;");
2316
2317 GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
2318 gInputApplicationClassInfo.clazz,
2319 "dispatchingTimeoutNanos", "J");
2320
2321 GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
2322 "token", "Ljava/lang/Object;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002323
Jeff Brown6ec402b2010-07-28 15:48:59 -07002324 // KeyEvent
2325
2326 FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
2327
2328 // MotionEVent
2329
2330 FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
2331
Jeff Brown46b9ac02010-04-22 18:58:52 -07002332 return 0;
2333}
2334
Jeff Brown46b9ac02010-04-22 18:58:52 -07002335} /* namespace android */