blob: a332376766e6885fd048912d37e971560d57903a [file] [log] [blame]
Jeff Brown46b9ac0a2010-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 Brown46b9ac0a2010-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 Brown46b9ac0a2010-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 Brown46b9ac0a2010-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 Brown46b9ac0a2010-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 Brown46b9ac0a2010-04-22 18:58:52 -0700123
124static struct {
125 jclass clazz;
126
Jeff Brown46b9ac0a2010-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 Brown46b9ac0a2010-04-22 18:58:52 -0700137 jmethodID notifyAppSwitchComing;
138 jmethodID filterTouchEvents;
139 jmethodID filterJumpyTouchEvents;
140 jmethodID getVirtualKeyDefinitions;
141 jmethodID getExcludedDeviceNames;
Jeff Brown46b9ac0a2010-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
183// ----------------------------------------------------------------------------
184
185static inline nsecs_t now() {
186 return systemTime(SYSTEM_TIME_MONOTONIC);
187}
Jeff Brown7fbdc842010-06-17 20:52:56 -0700188
Jeff Brown9c3cda02010-06-15 01:31:58 -0700189// ----------------------------------------------------------------------------
190
191class NativeInputManager : public virtual RefBase,
192 public virtual InputReaderPolicyInterface,
193 public virtual InputDispatcherPolicyInterface {
194protected:
195 virtual ~NativeInputManager();
196
197public:
198 NativeInputManager(jobject callbacksObj);
199
200 inline sp<InputManager> getInputManager() const { return mInputManager; }
201
Jeff Browne33348b2010-07-15 23:54:05 -0700202 String8 dump();
203
Jeff Brown9c3cda02010-06-15 01:31:58 -0700204 void setDisplaySize(int32_t displayId, int32_t width, int32_t height);
205 void setDisplayOrientation(int32_t displayId, int32_t orientation);
206
Jeff Brown7fbdc842010-06-17 20:52:56 -0700207 status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
208 jweak inputChannelObjWeak);
209 status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
210
Jeff Brown349703e2010-06-22 01:27:15 -0700211 void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
212 void setFocusedApplication(JNIEnv* env, jobject applicationObj);
213 void setInputDispatchMode(bool enabled, bool frozen);
214 void preemptInputDispatch();
215
Jeff Brown9c3cda02010-06-15 01:31:58 -0700216 /* --- InputReaderPolicyInterface implementation --- */
217
218 virtual bool getDisplayInfo(int32_t displayId,
219 int32_t* width, int32_t* height, int32_t* orientation);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700220 virtual void virtualKeyDownFeedback();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700221 virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700222 bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags);
223 virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
224 uint32_t& policyFlags);
225 virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700226 virtual bool filterTouchEvents();
227 virtual bool filterJumpyTouchEvents();
228 virtual void getVirtualKeyDefinitions(const String8& deviceName,
229 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions);
230 virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
231
232 /* --- InputDispatcherPolicyInterface implementation --- */
233
234 virtual void notifyConfigurationChanged(nsecs_t when);
235 virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700236 virtual bool notifyInputChannelANR(const sp<InputChannel>& inputChannel,
237 nsecs_t& outNewTimeout);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700238 virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel);
239 virtual nsecs_t getKeyRepeatTimeout();
Jeff Brown349703e2010-06-22 01:27:15 -0700240 virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700241 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown349703e2010-06-22 01:27:15 -0700242 virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown7fbdc842010-06-17 20:52:56 -0700243 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700244
245private:
Jeff Brown349703e2010-06-22 01:27:15 -0700246 struct InputWindow {
247 sp<InputChannel> inputChannel;
248 int32_t layoutParamsFlags;
249 int32_t layoutParamsType;
250 nsecs_t dispatchingTimeout;
251 int32_t frameLeft;
252 int32_t frameTop;
253 int32_t touchableAreaLeft;
254 int32_t touchableAreaTop;
255 int32_t touchableAreaRight;
256 int32_t touchableAreaBottom;
257 bool visible;
258 bool hasFocus;
259 bool hasWallpaper;
260 bool paused;
261 int32_t ownerPid;
262 int32_t ownerUid;
263
264 inline bool touchableAreaContainsPoint(int32_t x, int32_t y) {
265 return x >= touchableAreaLeft && x <= touchableAreaRight
266 && y >= touchableAreaTop && y <= touchableAreaBottom;
267 }
268 };
269
270 struct InputApplication {
271 String8 name;
272 nsecs_t dispatchingTimeout;
273 jweak tokenObjWeak;
274 };
275
276 class ANRTimer {
277 enum Budget {
278 SYSTEM = 0,
279 APPLICATION = 1
280 };
281
282 Budget mBudget;
283 nsecs_t mStartTime;
284 bool mFrozen;
285 InputWindow* mPausedWindow;
286
287 public:
288 ANRTimer();
289
290 void dispatchFrozenBySystem();
291 void dispatchPausedByApplication(InputWindow* pausedWindow);
292 bool waitForDispatchStateChangeLd(NativeInputManager* inputManager);
293
294 nsecs_t getTimeSpentWaitingForApplication() const;
295 };
296
Jeff Brown9c3cda02010-06-15 01:31:58 -0700297 sp<InputManager> mInputManager;
298
299 jobject mCallbacksObj;
300
301 // Cached filtering policies.
302 int32_t mFilterTouchEvents;
303 int32_t mFilterJumpyTouchEvents;
304
305 // Cached display state. (lock mDisplayLock)
306 Mutex mDisplayLock;
307 int32_t mDisplayWidth, mDisplayHeight;
308 int32_t mDisplayOrientation;
309
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700310 // Power manager interactions.
Jeff Brown9c3cda02010-06-15 01:31:58 -0700311 bool isScreenOn();
312 bool isScreenBright();
313
Jeff Brown7fbdc842010-06-17 20:52:56 -0700314 // Weak references to all currently registered input channels by receive fd.
315 Mutex mInputChannelRegistryLock;
316 KeyedVector<int, jweak> mInputChannelObjWeakByReceiveFd;
317
318 jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
319
Jeff Brown349703e2010-06-22 01:27:15 -0700320 // Input target and focus tracking. (lock mDispatchLock)
321 Mutex mDispatchLock;
322 Condition mDispatchStateChanged;
323
324 bool mDispatchEnabled;
325 bool mDispatchFrozen;
326 bool mWindowsReady;
327 Vector<InputWindow> mWindows;
328 Vector<InputWindow*> mWallpaperWindows;
329
330 // Focus tracking for keys, trackball, etc.
331 InputWindow* mFocusedWindow;
332
333 // Focus tracking for touch.
334 bool mTouchDown;
335 InputWindow* mTouchedWindow; // primary target for current down
336 Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
337
338 Vector<InputWindow*> mTempTouchedOutsideWindows; // temporary outside touch targets
339 Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
340
341 // Focused application.
342 InputApplication* mFocusedApplication;
343 InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
344
Jeff Brown6d0fec22010-07-23 21:28:06 -0700345 void dumpDeviceInfo(String8& dump);
Jeff Browne33348b2010-07-15 23:54:05 -0700346 void dumpDispatchStateLd(String8& dump);
347 void logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -0700348
349 bool notifyANR(jobject tokenObj, nsecs_t& outNewTimeout);
350 void releaseFocusedApplicationLd(JNIEnv* env);
351
352 int32_t waitForFocusedWindowLd(uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
353 Vector<InputTarget>& outTargets, InputWindow*& outFocusedWindow);
354 int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
355 int32_t injectorPid, int32_t injectorUid,
356 Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
357
358 void releaseTouchedWindowLd();
359
Jeff Brownc5ed5912010-07-14 18:48:53 -0700360 int32_t waitForNonTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700361 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700362 int32_t waitForTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700363 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
364
Jeff Brownd0097872010-06-30 14:41:59 -0700365 bool interceptKeyBeforeDispatching(const InputTarget& target,
366 const KeyEvent* keyEvent, uint32_t policyFlags);
367
Jeff Brown349703e2010-06-22 01:27:15 -0700368 void pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType);
369 void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
370 bool checkInjectionPermission(const InputWindow* window,
371 int32_t injectorPid, int32_t injectorUid);
372
373 static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
374 static void addTarget(const InputWindow* window, int32_t targetFlags,
375 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets);
376
Jeff Brown9c3cda02010-06-15 01:31:58 -0700377 static inline JNIEnv* jniEnv() {
378 return AndroidRuntime::getJNIEnv();
379 }
380
381 static bool isAppSwitchKey(int32_t keyCode);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700382 static bool isPolicyKey(int32_t keyCode, bool isScreenOn);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700383 static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700384};
385
386// ----------------------------------------------------------------------------
387
388NativeInputManager::NativeInputManager(jobject callbacksObj) :
389 mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
Jeff Brown0b72e822010-06-29 16:52:21 -0700390 mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0),
Jeff Brown349703e2010-06-22 01:27:15 -0700391 mDispatchEnabled(true), mDispatchFrozen(false), mWindowsReady(true),
392 mFocusedWindow(NULL), mTouchDown(false), mTouchedWindow(NULL),
393 mFocusedApplication(NULL) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700394 JNIEnv* env = jniEnv();
395
396 mCallbacksObj = env->NewGlobalRef(callbacksObj);
397
398 sp<EventHub> eventHub = new EventHub();
399 mInputManager = new InputManager(eventHub, this, this);
400}
401
402NativeInputManager::~NativeInputManager() {
403 JNIEnv* env = jniEnv();
404
405 env->DeleteGlobalRef(mCallbacksObj);
Jeff Brown349703e2010-06-22 01:27:15 -0700406
407 releaseFocusedApplicationLd(env);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700408}
409
Jeff Browne33348b2010-07-15 23:54:05 -0700410String8 NativeInputManager::dump() {
411 String8 dump;
Jeff Brown00ba8842010-07-16 15:01:56 -0700412 { // acquire lock
413 AutoMutex _l(mDisplayLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700414 dump.append("Native Input Dispatcher State:\n");
Jeff Brown00ba8842010-07-16 15:01:56 -0700415 dumpDispatchStateLd(dump);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700416 dump.append("\n");
Jeff Brown00ba8842010-07-16 15:01:56 -0700417 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -0700418
419 dump.append("Input Devices:\n");
420 dumpDeviceInfo(dump);
421
Jeff Browne33348b2010-07-15 23:54:05 -0700422 return dump;
423}
424
Jeff Brown9c3cda02010-06-15 01:31:58 -0700425bool NativeInputManager::isAppSwitchKey(int32_t keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700426 return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700427}
428
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700429bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) {
430 // Special keys that the WindowManagerPolicy might care about.
431 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700432 case AKEYCODE_VOLUME_UP:
433 case AKEYCODE_VOLUME_DOWN:
434 case AKEYCODE_ENDCALL:
435 case AKEYCODE_POWER:
436 case AKEYCODE_CALL:
437 case AKEYCODE_HOME:
438 case AKEYCODE_MENU:
439 case AKEYCODE_SEARCH:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700440 // media keys
Jeff Brownfd035822010-06-30 16:10:35 -0700441 case AKEYCODE_HEADSETHOOK:
442 case AKEYCODE_MEDIA_PLAY_PAUSE:
443 case AKEYCODE_MEDIA_STOP:
444 case AKEYCODE_MEDIA_NEXT:
445 case AKEYCODE_MEDIA_PREVIOUS:
446 case AKEYCODE_MEDIA_REWIND:
447 case AKEYCODE_MEDIA_FAST_FORWARD:
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700448 return true;
449 default:
450 // We need to pass all keys to the policy in the following cases:
451 // - screen is off
452 // - keyguard is visible
453 // - policy is performing key chording
454 //return ! isScreenOn || keyguardVisible || chording;
455 return true; // XXX stubbed out for now
456 }
457}
458
Jeff Brown7fbdc842010-06-17 20:52:56 -0700459bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700460 if (env->ExceptionCheck()) {
461 LOGE("An exception was thrown by callback '%s'.", methodName);
462 LOGE_EX(env);
463 env->ExceptionClear();
464 return true;
465 }
466 return false;
467}
468
469void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
470 if (displayId == 0) {
471 AutoMutex _l(mDisplayLock);
472
473 mDisplayWidth = width;
474 mDisplayHeight = height;
475 }
476}
477
478void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
479 if (displayId == 0) {
480 AutoMutex _l(mDisplayLock);
481
482 mDisplayOrientation = orientation;
483 }
484}
485
Jeff Brown7fbdc842010-06-17 20:52:56 -0700486status_t NativeInputManager::registerInputChannel(JNIEnv* env,
487 const sp<InputChannel>& inputChannel, jobject inputChannelObj) {
488 jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
489 if (! inputChannelObjWeak) {
490 LOGE("Could not create weak reference for input channel.");
491 LOGE_EX(env);
492 return NO_MEMORY;
493 }
494
495 status_t status;
496 {
497 AutoMutex _l(mInputChannelRegistryLock);
498
499 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
500 inputChannel->getReceivePipeFd());
501 if (index >= 0) {
502 LOGE("Input channel object '%s' has already been registered",
503 inputChannel->getName().string());
504 status = INVALID_OPERATION;
505 goto DeleteWeakRef;
506 }
507
508 mInputChannelObjWeakByReceiveFd.add(inputChannel->getReceivePipeFd(),
509 inputChannelObjWeak);
510 }
511
512 status = mInputManager->registerInputChannel(inputChannel);
513 if (! status) {
514 return OK;
515 }
516
517 {
518 AutoMutex _l(mInputChannelRegistryLock);
519 mInputChannelObjWeakByReceiveFd.removeItem(inputChannel->getReceivePipeFd());
520 }
521
522DeleteWeakRef:
523 env->DeleteWeakGlobalRef(inputChannelObjWeak);
524 return status;
525}
526
527status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
528 const sp<InputChannel>& inputChannel) {
529 jweak inputChannelObjWeak;
530 {
531 AutoMutex _l(mInputChannelRegistryLock);
532
533 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
534 inputChannel->getReceivePipeFd());
535 if (index < 0) {
536 LOGE("Input channel object '%s' is not currently registered",
537 inputChannel->getName().string());
538 return INVALID_OPERATION;
539 }
540
541 inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
542 mInputChannelObjWeakByReceiveFd.removeItemsAt(index);
543 }
544
545 env->DeleteWeakGlobalRef(inputChannelObjWeak);
546
547 return mInputManager->unregisterInputChannel(inputChannel);
548}
549
550jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
551 const sp<InputChannel>& inputChannel) {
552 {
553 AutoMutex _l(mInputChannelRegistryLock);
554
555 ssize_t index = mInputChannelObjWeakByReceiveFd.indexOfKey(
556 inputChannel->getReceivePipeFd());
557 if (index < 0) {
558 return NULL;
559 }
560
561 jweak inputChannelObjWeak = mInputChannelObjWeakByReceiveFd.valueAt(index);
562 return env->NewLocalRef(inputChannelObjWeak);
563 }
564}
565
Jeff Brown9c3cda02010-06-15 01:31:58 -0700566bool NativeInputManager::getDisplayInfo(int32_t displayId,
567 int32_t* width, int32_t* height, int32_t* orientation) {
568 bool result = false;
569 if (displayId == 0) {
570 AutoMutex _l(mDisplayLock);
571
572 if (mDisplayWidth > 0) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700573 if (width) {
574 *width = mDisplayWidth;
575 }
576 if (height) {
577 *height = mDisplayHeight;
578 }
579 if (orientation) {
580 *orientation = mDisplayOrientation;
581 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700582 result = true;
583 }
584 }
585 return result;
586}
587
588bool NativeInputManager::isScreenOn() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700589 return android_server_PowerManagerService_isScreenOn();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700590}
591
592bool NativeInputManager::isScreenBright() {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700593 return android_server_PowerManagerService_isScreenBright();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700594}
595
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700596void NativeInputManager::virtualKeyDownFeedback() {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700597#if DEBUG_INPUT_READER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700598 LOGD("virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700599#endif
600
601 JNIEnv* env = jniEnv();
602
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700603 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback);
604 checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700605}
606
607int32_t NativeInputManager::interceptKey(nsecs_t when,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700608 int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700609#if DEBUG_INPUT_READER_POLICY
610 LOGD("interceptKey - when=%lld, deviceId=%d, down=%d, keyCode=%d, scanCode=%d, "
Jeff Brown349703e2010-06-22 01:27:15 -0700611 "policyFlags=0x%x",
Jeff Brown9c3cda02010-06-15 01:31:58 -0700612 when, deviceId, down, keyCode, scanCode, policyFlags);
613#endif
614
615 const int32_t WM_ACTION_PASS_TO_USER = 1;
616 const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
617 const int32_t WM_ACTION_GO_TO_SLEEP = 4;
618
Jeff Brown9c3cda02010-06-15 01:31:58 -0700619 bool isScreenOn = this->isScreenOn();
620 bool isScreenBright = this->isScreenBright();
621
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700622 jint wmActions = 0;
623 if (isPolicyKey(keyCode, isScreenOn)) {
624 JNIEnv* env = jniEnv();
625
626 wmActions = env->CallIntMethod(mCallbacksObj,
627 gCallbacksClassInfo.interceptKeyBeforeQueueing,
628 when, keyCode, down, policyFlags, isScreenOn);
629 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
630 wmActions = 0;
631 }
632 } else {
633 wmActions = WM_ACTION_PASS_TO_USER;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700634 }
635
636 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
637 if (! isScreenOn) {
638 // Key presses and releases wake the device.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700639 policyFlags |= POLICY_FLAG_WOKE_HERE;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700640 }
641
642 if (! isScreenBright) {
643 // Key presses and releases brighten the screen if dimmed.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700644 policyFlags |= POLICY_FLAG_BRIGHT_HERE;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700645 }
646
647 if (wmActions & WM_ACTION_GO_TO_SLEEP) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700648 android_server_PowerManagerService_goToSleep(when);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700649 }
650
651 if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
Jeff Brown349703e2010-06-22 01:27:15 -0700652 pokeUserActivity(when, POWER_MANAGER_BUTTON_EVENT);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700653 }
654
655 if (wmActions & WM_ACTION_PASS_TO_USER) {
656 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700657
Jeff Brown9c3cda02010-06-15 01:31:58 -0700658 if (down && isAppSwitchKey(keyCode)) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700659 JNIEnv* env = jniEnv();
660
Jeff Brown9c3cda02010-06-15 01:31:58 -0700661 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700662 checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700663
664 actions |= InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING;
665 }
666 }
Jeff Brown349703e2010-06-22 01:27:15 -0700667
Jeff Brown9c3cda02010-06-15 01:31:58 -0700668 return actions;
669}
670
Jeff Brown6d0fec22010-07-23 21:28:06 -0700671int32_t NativeInputManager::interceptGeneric(nsecs_t when, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700672#if DEBUG_INPUT_READER_POLICY
Jeff Brown6d0fec22010-07-23 21:28:06 -0700673 LOGD("interceptGeneric - when=%lld, policyFlags=0x%x", when, policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700674#endif
675
Jeff Brown5c225b12010-06-16 01:53:36 -0700676 int32_t actions = InputReaderPolicyInterface::ACTION_NONE;
677 if (isScreenOn()) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700678 // Only dispatch events when the device is awake.
Jeff Brown349703e2010-06-22 01:27:15 -0700679 // Do not wake the device.
Jeff Brown5c225b12010-06-16 01:53:36 -0700680 actions |= InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700681
Jeff Brown349703e2010-06-22 01:27:15 -0700682 if (! isScreenBright()) {
683 // Brighten the screen if dimmed.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700684 policyFlags |= POLICY_FLAG_BRIGHT_HERE;
Jeff Brown349703e2010-06-22 01:27:15 -0700685 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700686 }
687
688 return actions;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700689}
690
691int32_t NativeInputManager::interceptSwitch(nsecs_t when, int32_t switchCode,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700692 int32_t switchValue, uint32_t& policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700693#if DEBUG_INPUT_READER_POLICY
Jeff Brown6d0fec22010-07-23 21:28:06 -0700694 LOGD("interceptSwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x",
695 when, switchCode, switchValue, policyFlags);
Jeff Brown9c3cda02010-06-15 01:31:58 -0700696#endif
697
698 JNIEnv* env = jniEnv();
699
700 switch (switchCode) {
701 case SW_LID:
702 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
703 when, switchValue == 0);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700704 checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700705 break;
706 }
707
708 return InputReaderPolicyInterface::ACTION_NONE;
709}
710
711bool NativeInputManager::filterTouchEvents() {
712 if (mFilterTouchEvents < 0) {
713 JNIEnv* env = jniEnv();
714
715 jboolean result = env->CallBooleanMethod(mCallbacksObj,
716 gCallbacksClassInfo.filterTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700717 if (checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700718 result = false;
719 }
720
721 mFilterTouchEvents = result ? 1 : 0;
722 }
723 return mFilterTouchEvents;
724}
725
726bool NativeInputManager::filterJumpyTouchEvents() {
727 if (mFilterJumpyTouchEvents < 0) {
728 JNIEnv* env = jniEnv();
729
730 jboolean result = env->CallBooleanMethod(mCallbacksObj,
731 gCallbacksClassInfo.filterJumpyTouchEvents);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700732 if (checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700733 result = false;
734 }
735
736 mFilterJumpyTouchEvents = result ? 1 : 0;
737 }
738 return mFilterJumpyTouchEvents;
739}
740
741void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
742 Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions) {
743 JNIEnv* env = jniEnv();
744
745 jstring deviceNameStr = env->NewStringUTF(deviceName.string());
Jeff Brown7fbdc842010-06-17 20:52:56 -0700746 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700747 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
748 gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700749 if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700750 jsize length = env->GetArrayLength(result);
751 for (jsize i = 0; i < length; i++) {
752 jobject item = env->GetObjectArrayElement(result, i);
753
754 outVirtualKeyDefinitions.add();
755 outVirtualKeyDefinitions.editTop().scanCode =
756 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode));
757 outVirtualKeyDefinitions.editTop().centerX =
758 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX));
759 outVirtualKeyDefinitions.editTop().centerY =
760 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY));
761 outVirtualKeyDefinitions.editTop().width =
762 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width));
763 outVirtualKeyDefinitions.editTop().height =
764 int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height));
765
766 env->DeleteLocalRef(item);
767 }
768 env->DeleteLocalRef(result);
769 }
770 env->DeleteLocalRef(deviceNameStr);
771 }
772}
773
774void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
775 JNIEnv* env = jniEnv();
776
777 jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
778 gCallbacksClassInfo.getExcludedDeviceNames));
Jeff Brown7fbdc842010-06-17 20:52:56 -0700779 if (! checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && result) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700780 jsize length = env->GetArrayLength(result);
781 for (jsize i = 0; i < length; i++) {
782 jstring item = jstring(env->GetObjectArrayElement(result, i));
783
784 const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
785 outExcludedDeviceNames.add(String8(deviceNameChars));
786 env->ReleaseStringUTFChars(item, deviceNameChars);
787
788 env->DeleteLocalRef(item);
789 }
790 env->DeleteLocalRef(result);
791 }
792}
793
794void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
795#if DEBUG_INPUT_DISPATCHER_POLICY
796 LOGD("notifyConfigurationChanged - when=%lld", when);
797#endif
798
799 JNIEnv* env = jniEnv();
800
801 InputConfiguration config;
802 mInputManager->getInputConfiguration(& config);
803
804 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
805 when, config.touchScreen, config.keyboard, config.navigation);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700806 checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
Jeff Brown9c3cda02010-06-15 01:31:58 -0700807}
808
809void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
810#if DEBUG_INPUT_DISPATCHER_POLICY
811 LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
812#endif
813
Jeff Brown7fbdc842010-06-17 20:52:56 -0700814 JNIEnv* env = jniEnv();
815
816 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
817 if (inputChannelObjLocal) {
818 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
819 inputChannelObjLocal);
820 checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
821
822 env->DeleteLocalRef(inputChannelObjLocal);
823 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700824}
825
Jeff Brown7fbdc842010-06-17 20:52:56 -0700826bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel,
827 nsecs_t& outNewTimeout) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700828#if DEBUG_INPUT_DISPATCHER_POLICY
829 LOGD("notifyInputChannelANR - inputChannel='%s'",
830 inputChannel->getName().string());
831#endif
832
Jeff Brown7fbdc842010-06-17 20:52:56 -0700833 JNIEnv* env = jniEnv();
834
835 jlong newTimeout;
836 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
837 if (inputChannelObjLocal) {
838 newTimeout = env->CallLongMethod(mCallbacksObj,
839 gCallbacksClassInfo.notifyInputChannelANR, inputChannelObjLocal);
840 if (checkAndClearExceptionFromCallback(env, "notifyInputChannelANR")) {
841 newTimeout = -2;
842 }
843
844 env->DeleteLocalRef(inputChannelObjLocal);
845 } else {
846 newTimeout = -2;
847 }
848
849 if (newTimeout == -2) {
850 return false; // abort
851 }
852
853 outNewTimeout = newTimeout;
854 return true; // resume
Jeff Brown9c3cda02010-06-15 01:31:58 -0700855}
856
857void NativeInputManager::notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) {
858#if DEBUG_INPUT_DISPATCHER_POLICY
859 LOGD("notifyInputChannelRecoveredFromANR - inputChannel='%s'",
860 inputChannel->getName().string());
861#endif
862
Jeff Brown7fbdc842010-06-17 20:52:56 -0700863 JNIEnv* env = jniEnv();
864
865 jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
866 if (inputChannelObjLocal) {
867 env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelRecoveredFromANR,
868 inputChannelObjLocal);
869 checkAndClearExceptionFromCallback(env, "notifyInputChannelRecoveredFromANR");
870
871 env->DeleteLocalRef(inputChannelObjLocal);
872 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700873}
874
Jeff Brown349703e2010-06-22 01:27:15 -0700875bool NativeInputManager::notifyANR(jobject tokenObj, nsecs_t& outNewTimeout) {
876#if DEBUG_INPUT_DISPATCHER_POLICY
877 LOGD("notifyANR");
878#endif
879
880 JNIEnv* env = jniEnv();
881
882 jlong newTimeout = env->CallLongMethod(mCallbacksObj,
883 gCallbacksClassInfo.notifyANR, tokenObj);
884 if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
885 newTimeout = -2;
886 }
887
888 if (newTimeout == -2) {
889 return false; // abort
890 }
891
892 outNewTimeout = newTimeout;
893 return true; // resume
894}
895
Jeff Brown9c3cda02010-06-15 01:31:58 -0700896nsecs_t NativeInputManager::getKeyRepeatTimeout() {
897 if (! isScreenOn()) {
898 // Disable key repeat when the screen is off.
899 return -1;
900 } else {
901 // TODO use ViewConfiguration.getLongPressTimeout()
902 return milliseconds_to_nanoseconds(500);
903 }
904}
905
Jeff Brown349703e2010-06-22 01:27:15 -0700906void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
907#if DEBUG_FOCUS
908 LOGD("setInputWindows");
909#endif
910 { // acquire lock
911 AutoMutex _l(mDispatchLock);
912
913 sp<InputChannel> touchedWindowChannel;
914 if (mTouchedWindow) {
915 touchedWindowChannel = mTouchedWindow->inputChannel;
916 mTouchedWindow = NULL;
917 }
918 size_t numTouchedWallpapers = mTouchedWallpaperWindows.size();
919 if (numTouchedWallpapers != 0) {
920 for (size_t i = 0; i < numTouchedWallpapers; i++) {
921 mTempTouchedWallpaperChannels.push(mTouchedWallpaperWindows[i]->inputChannel);
922 }
923 mTouchedWallpaperWindows.clear();
924 }
925
Jeff Browne33348b2010-07-15 23:54:05 -0700926 bool hadFocusedWindow = mFocusedWindow != NULL;
927
Jeff Brown349703e2010-06-22 01:27:15 -0700928 mWindows.clear();
929 mFocusedWindow = NULL;
930 mWallpaperWindows.clear();
931
932 if (windowObjArray) {
933 mWindowsReady = true;
934
935 jsize length = env->GetArrayLength(windowObjArray);
936 for (jsize i = 0; i < length; i++) {
937 jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
938 if (! inputTargetObj) {
939 break; // found null element indicating end of used portion of the array
940 }
941
942 mWindows.push();
943 InputWindow& window = mWindows.editTop();
944 bool valid = populateWindow(env, inputTargetObj, window);
945 if (! valid) {
946 mWindows.pop();
947 }
948
949 env->DeleteLocalRef(inputTargetObj);
950 }
951
952 size_t numWindows = mWindows.size();
953 for (size_t i = 0; i < numWindows; i++) {
954 InputWindow* window = & mWindows.editItemAt(i);
955 if (window->hasFocus) {
956 mFocusedWindow = window;
957 }
958
959 if (window->layoutParamsType == TYPE_WALLPAPER) {
960 mWallpaperWindows.push(window);
961
962 for (size_t j = 0; j < numTouchedWallpapers; j++) {
963 if (window->inputChannel == mTempTouchedWallpaperChannels[i]) {
964 mTouchedWallpaperWindows.push(window);
965 }
966 }
967 }
968
969 if (window->inputChannel == touchedWindowChannel) {
970 mTouchedWindow = window;
971 }
972 }
973 } else {
974 mWindowsReady = false;
975 }
976
977 mTempTouchedWallpaperChannels.clear();
978
Jeff Brown00ba8842010-07-16 15:01:56 -0700979 if ((hadFocusedWindow && ! mFocusedWindow)
980 || (mFocusedWindow && ! mFocusedWindow->visible)) {
Jeff Browne33348b2010-07-15 23:54:05 -0700981 preemptInputDispatch();
982 }
983
Jeff Brown349703e2010-06-22 01:27:15 -0700984 mDispatchStateChanged.broadcast();
985
986#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -0700987 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -0700988#endif
989 } // release lock
990}
991
992bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
993 InputWindow& outWindow) {
994 bool valid = false;
995
996 jobject inputChannelObj = env->GetObjectField(windowObj,
997 gInputWindowClassInfo.inputChannel);
998 if (inputChannelObj) {
999 sp<InputChannel> inputChannel =
1000 android_view_InputChannel_getInputChannel(env, inputChannelObj);
1001 if (inputChannel != NULL) {
1002 jint layoutParamsFlags = env->GetIntField(windowObj,
1003 gInputWindowClassInfo.layoutParamsFlags);
1004 jint layoutParamsType = env->GetIntField(windowObj,
1005 gInputWindowClassInfo.layoutParamsType);
1006 jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
1007 gInputWindowClassInfo.dispatchingTimeoutNanos);
1008 jint frameLeft = env->GetIntField(windowObj,
1009 gInputWindowClassInfo.frameLeft);
1010 jint frameTop = env->GetIntField(windowObj,
1011 gInputWindowClassInfo.frameTop);
1012 jint touchableAreaLeft = env->GetIntField(windowObj,
1013 gInputWindowClassInfo.touchableAreaLeft);
1014 jint touchableAreaTop = env->GetIntField(windowObj,
1015 gInputWindowClassInfo.touchableAreaTop);
1016 jint touchableAreaRight = env->GetIntField(windowObj,
1017 gInputWindowClassInfo.touchableAreaRight);
1018 jint touchableAreaBottom = env->GetIntField(windowObj,
1019 gInputWindowClassInfo.touchableAreaBottom);
1020 jboolean visible = env->GetBooleanField(windowObj,
1021 gInputWindowClassInfo.visible);
1022 jboolean hasFocus = env->GetBooleanField(windowObj,
1023 gInputWindowClassInfo.hasFocus);
1024 jboolean hasWallpaper = env->GetBooleanField(windowObj,
1025 gInputWindowClassInfo.hasWallpaper);
1026 jboolean paused = env->GetBooleanField(windowObj,
1027 gInputWindowClassInfo.paused);
1028 jint ownerPid = env->GetIntField(windowObj,
1029 gInputWindowClassInfo.ownerPid);
1030 jint ownerUid = env->GetIntField(windowObj,
1031 gInputWindowClassInfo.ownerUid);
1032
1033 outWindow.inputChannel = inputChannel;
1034 outWindow.layoutParamsFlags = layoutParamsFlags;
1035 outWindow.layoutParamsType = layoutParamsType;
1036 outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
1037 outWindow.frameLeft = frameLeft;
1038 outWindow.frameTop = frameTop;
1039 outWindow.touchableAreaLeft = touchableAreaLeft;
1040 outWindow.touchableAreaTop = touchableAreaTop;
1041 outWindow.touchableAreaRight = touchableAreaRight;
1042 outWindow.touchableAreaBottom = touchableAreaBottom;
1043 outWindow.visible = visible;
1044 outWindow.hasFocus = hasFocus;
1045 outWindow.hasWallpaper = hasWallpaper;
1046 outWindow.paused = paused;
1047 outWindow.ownerPid = ownerPid;
1048 outWindow.ownerUid = ownerUid;
1049 valid = true;
1050 } else {
1051 LOGW("Dropping input target because its input channel is not initialized.");
1052 }
1053
1054 env->DeleteLocalRef(inputChannelObj);
1055 } else {
1056 LOGW("Dropping input target because the input channel object was null.");
1057 }
1058 return valid;
1059}
1060
1061void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
1062#if DEBUG_FOCUS
1063 LOGD("setFocusedApplication");
1064#endif
1065 { // acquire lock
1066 AutoMutex _l(mDispatchLock);
1067
1068 releaseFocusedApplicationLd(env);
1069
1070 if (applicationObj) {
1071 jstring nameObj = jstring(env->GetObjectField(applicationObj,
1072 gInputApplicationClassInfo.name));
1073 jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
1074 gInputApplicationClassInfo.dispatchingTimeoutNanos);
1075 jobject tokenObj = env->GetObjectField(applicationObj,
1076 gInputApplicationClassInfo.token);
1077 jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
1078 if (! tokenObjWeak) {
1079 LOGE("Could not create weak reference for application token.");
1080 LOGE_EX(env);
1081 env->ExceptionClear();
1082 }
1083 env->DeleteLocalRef(tokenObj);
1084
1085 mFocusedApplication = & mFocusedApplicationStorage;
1086
1087 if (nameObj) {
1088 const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
1089 mFocusedApplication->name.setTo(nameStr);
1090 env->ReleaseStringUTFChars(nameObj, nameStr);
1091 env->DeleteLocalRef(nameObj);
1092 } else {
1093 LOGE("InputApplication.name should not be null.");
1094 mFocusedApplication->name.setTo("unknown");
1095 }
1096
1097 mFocusedApplication->dispatchingTimeout = dispatchingTimeoutNanos;
1098 mFocusedApplication->tokenObjWeak = tokenObjWeak;
1099 }
1100
1101 mDispatchStateChanged.broadcast();
1102
1103#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001104 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001105#endif
1106 } // release lock
1107}
1108
1109void NativeInputManager::releaseFocusedApplicationLd(JNIEnv* env) {
1110 if (mFocusedApplication) {
1111 env->DeleteWeakGlobalRef(mFocusedApplication->tokenObjWeak);
1112 mFocusedApplication = NULL;
1113 }
1114}
1115
1116void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
1117#if DEBUG_FOCUS
1118 LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001119#endif
1120
Jeff Brown349703e2010-06-22 01:27:15 -07001121 { // acquire lock
1122 AutoMutex _l(mDispatchLock);
Jeff Brown9c3cda02010-06-15 01:31:58 -07001123
Jeff Brown349703e2010-06-22 01:27:15 -07001124 if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
1125 mDispatchEnabled = enabled;
1126 mDispatchFrozen = frozen;
1127
1128 mDispatchStateChanged.broadcast();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001129 }
Jeff Brown349703e2010-06-22 01:27:15 -07001130
1131#if DEBUG_FOCUS
Jeff Browne33348b2010-07-15 23:54:05 -07001132 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001133#endif
1134 } // release lock
1135}
1136
1137void NativeInputManager::preemptInputDispatch() {
1138#if DEBUG_FOCUS
1139 LOGD("preemptInputDispatch");
1140#endif
1141
1142 mInputManager->preemptInputDispatch();
1143}
1144
1145int32_t NativeInputManager::waitForFocusedWindowLd(uint32_t policyFlags,
1146 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1147 InputWindow*& outFocusedWindow) {
1148
1149 int32_t injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1150 bool firstIteration = true;
1151 ANRTimer anrTimer;
1152 for (;;) {
1153 if (firstIteration) {
1154 firstIteration = false;
1155 } else {
1156 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1157 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1158 "the window that should receive it.");
1159 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
1160 break;
1161 }
1162 }
1163
1164 // If dispatch is not enabled then fail.
1165 if (! mDispatchEnabled) {
1166 LOGI("Dropping event because input dispatch is disabled.");
1167 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1168 break;
1169 }
1170
1171 // If dispatch is frozen or we don't have valid window data yet then wait.
1172 if (mDispatchFrozen || ! mWindowsReady) {
1173#if DEBUG_FOCUS
1174 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1175#endif
1176 anrTimer.dispatchFrozenBySystem();
1177 continue;
1178 }
1179
1180 // If there is no currently focused window and no focused application
1181 // then drop the event.
1182 if (! mFocusedWindow) {
1183 if (mFocusedApplication) {
1184#if DEBUG_FOCUS
1185 LOGD("Waiting because there is no focused window but there is a "
1186 "focused application that may yet introduce a new target: '%s'.",
1187 mFocusedApplication->name.string());
1188#endif
1189 continue;
1190 }
1191
1192 LOGI("Dropping event because there is no focused window or focused application.");
1193 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1194 break;
1195 }
1196
1197 // Check permissions.
1198 if (! checkInjectionPermission(mFocusedWindow, injectorPid, injectorUid)) {
1199 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1200 break;
1201 }
1202
1203 // If the currently focused window is paused then keep waiting.
1204 if (mFocusedWindow->paused) {
1205#if DEBUG_FOCUS
1206 LOGD("Waiting because focused window is paused.");
1207#endif
1208 anrTimer.dispatchPausedByApplication(mFocusedWindow);
1209 continue;
1210 }
1211
1212 // Success!
1213 break; // done waiting, exit loop
Jeff Brown9c3cda02010-06-15 01:31:58 -07001214 }
Jeff Brown349703e2010-06-22 01:27:15 -07001215
1216 // Output targets.
1217 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
1218 addTarget(mFocusedWindow, InputTarget::FLAG_SYNC,
1219 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1220
1221 outFocusedWindow = mFocusedWindow;
1222 } else {
1223 outFocusedWindow = NULL;
1224 }
1225
1226#if DEBUG_FOCUS
1227 LOGD("waitForFocusedWindow finished: injectionResult=%d",
1228 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001229 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001230#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001231 return injectionResult;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001232}
1233
Jeff Brownc5ed5912010-07-14 18:48:53 -07001234enum InjectionPermission {
1235 INJECTION_PERMISSION_UNKNOWN,
1236 INJECTION_PERMISSION_GRANTED,
1237 INJECTION_PERMISSION_DENIED
1238};
1239
Jeff Brown349703e2010-06-22 01:27:15 -07001240int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
1241 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets,
1242 InputWindow*& outTouchedWindow) {
1243 nsecs_t startTime = now();
Jeff Brown9c3cda02010-06-15 01:31:58 -07001244
Jeff Brown349703e2010-06-22 01:27:15 -07001245 // For security reasons, we defer updating the touch state until we are sure that
1246 // event injection will be allowed.
1247 //
1248 // FIXME In the original code, screenWasOff could never be set to true.
1249 // The reason is that the POLICY_FLAG_WOKE_HERE
1250 // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
1251 // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
1252 // actually enqueued using the policyFlags that appeared in the final EV_SYN
1253 // events upon which no preprocessing took place. So policyFlags was always 0.
1254 // In the new native input dispatcher we're a bit more careful about event
1255 // preprocessing so the touches we receive can actually have non-zero policyFlags.
1256 // Unfortunately we obtain undesirable behavior.
1257 //
1258 // Here's what happens:
1259 //
1260 // When the device dims in anticipation of going to sleep, touches
1261 // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
1262 // the device to brighten and reset the user activity timer.
1263 // Touches on other windows (such as the launcher window)
1264 // are dropped. Then after a moment, the device goes to sleep. Oops.
1265 //
1266 // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
1267 // instead of POLICY_FLAG_WOKE_HERE...
1268 //
1269 bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001270
1271 int32_t action = motionEvent->getAction();
1272
Jeff Brown349703e2010-06-22 01:27:15 -07001273 bool firstIteration = true;
1274 ANRTimer anrTimer;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001275 int32_t injectionResult;
1276 InjectionPermission injectionPermission;
Jeff Brown349703e2010-06-22 01:27:15 -07001277 for (;;) {
1278 if (firstIteration) {
1279 firstIteration = false;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001280 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001281 if (! anrTimer.waitForDispatchStateChangeLd(this)) {
1282 LOGW("Dropping event because the dispatcher timed out waiting to identify "
1283 "the window that should receive it.");
1284 injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001285 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
1286 break; // timed out, exit wait loop
Jeff Brown349703e2010-06-22 01:27:15 -07001287 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001288 }
Jeff Brown349703e2010-06-22 01:27:15 -07001289
1290 // If dispatch is not enabled then fail.
1291 if (! mDispatchEnabled) {
1292 LOGI("Dropping event because input dispatch is disabled.");
1293 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001294 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001295 break; // failed, exit wait loop
1296 }
1297
1298 // If dispatch is frozen or we don't have valid window data yet then wait.
1299 if (mDispatchFrozen || ! mWindowsReady) {
1300#if DEBUG_INPUT_DISPATCHER_POLICY
1301 LOGD("Waiting because dispatch is frozen or windows are not ready.");
1302#endif
1303 anrTimer.dispatchFrozenBySystem();
1304 continue;
1305 }
1306
1307 // Update the touch state as needed based on the properties of the touch event.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001308 if (action == AMOTION_EVENT_ACTION_DOWN) {
1309 /* Case 1: ACTION_DOWN */
1310
Jeff Brown349703e2010-06-22 01:27:15 -07001311 InputWindow* newTouchedWindow = NULL;
1312 mTempTouchedOutsideWindows.clear();
1313
1314 int32_t x = int32_t(motionEvent->getX(0));
1315 int32_t y = int32_t(motionEvent->getY(0));
1316 InputWindow* topErrorWindow = NULL;
1317
1318 // Traverse windows from front to back to find touched window and outside targets.
1319 size_t numWindows = mWindows.size();
1320 for (size_t i = 0; i < numWindows; i++) {
1321 InputWindow* window = & mWindows.editItemAt(i);
1322 int32_t flags = window->layoutParamsFlags;
1323
1324 if (flags & FLAG_SYSTEM_ERROR) {
1325 if (! topErrorWindow) {
1326 topErrorWindow = window;
1327 }
1328 }
1329
1330 if (window->visible) {
1331 if (! (flags & FLAG_NOT_TOUCHABLE)) {
1332 bool isTouchModal = (flags &
1333 (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL)) == 0;
1334 if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
1335 if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
1336 newTouchedWindow = window;
1337 }
1338 break; // found touched window, exit window loop
1339 }
1340 }
1341
1342 if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
1343 mTempTouchedOutsideWindows.push(window);
1344 }
1345 }
1346 }
1347
1348 // If there is an error window but it is not taking focus (typically because
1349 // it is invisible) then wait for it. Any other focused window may in
1350 // fact be in ANR state.
1351 if (topErrorWindow && newTouchedWindow != topErrorWindow) {
1352#if DEBUG_INPUT_DISPATCHER_POLICY
1353 LOGD("Waiting because system error window is pending.");
1354#endif
1355 anrTimer.dispatchFrozenBySystem();
1356 continue; // wait some more
1357 }
1358
1359 // If we did not find a touched window then fail.
1360 if (! newTouchedWindow) {
1361 if (mFocusedApplication) {
1362#if DEBUG_FOCUS
1363 LOGD("Waiting because there is no focused window but there is a "
1364 "focused application that may yet introduce a new target: '%s'.",
1365 mFocusedApplication->name.string());
1366#endif
1367 continue;
1368 }
1369
1370 LOGI("Dropping event because there is no touched window or focused application.");
1371 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001372 injectionPermission = INJECTION_PERMISSION_UNKNOWN;
Jeff Brown349703e2010-06-22 01:27:15 -07001373 break; // failed, exit wait loop
1374 }
1375
1376 // Check permissions.
1377 if (! checkInjectionPermission(newTouchedWindow, injectorPid, injectorUid)) {
1378 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001379 injectionPermission = INJECTION_PERMISSION_DENIED;
Jeff Brown349703e2010-06-22 01:27:15 -07001380 break; // failed, exit wait loop
1381 }
1382
1383 // If the touched window is paused then keep waiting.
1384 if (newTouchedWindow->paused) {
1385#if DEBUG_INPUT_DISPATCHER_POLICY
1386 LOGD("Waiting because touched window is paused.");
1387#endif
1388 anrTimer.dispatchPausedByApplication(newTouchedWindow);
1389 continue; // wait some more
1390 }
1391
1392 // Success! Update the touch dispatch state for real.
1393 releaseTouchedWindowLd();
1394
1395 mTouchedWindow = newTouchedWindow;
1396
1397 if (newTouchedWindow->hasWallpaper) {
1398 mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
1399 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001400
1401 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1402 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001403 break; // done
1404 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001405 /* Case 2: Everything but ACTION_DOWN */
1406
Jeff Brown349703e2010-06-22 01:27:15 -07001407 // Check permissions.
1408 if (! checkInjectionPermission(mTouchedWindow, injectorPid, injectorUid)) {
1409 injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001410 injectionPermission = INJECTION_PERMISSION_DENIED;
1411 break; // failed, exit wait loop
1412 }
1413
1414 // If the pointer is not currently down, then ignore the event.
1415 if (! mTouchDown) {
1416 LOGI("Dropping event because the pointer is not down.");
1417 injectionResult = INPUT_EVENT_INJECTION_FAILED;
1418 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001419 break; // failed, exit wait loop
1420 }
1421
1422 // If there is no currently touched window then fail.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001423 if (! mTouchedWindow) {
1424 LOGW("Dropping event because there is no touched window to receive it.");
Jeff Brown349703e2010-06-22 01:27:15 -07001425 injectionResult = INPUT_EVENT_INJECTION_FAILED;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001426 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001427 break; // failed, exit wait loop
1428 }
1429
1430 // If the touched window is paused then keep waiting.
1431 if (mTouchedWindow->paused) {
1432#if DEBUG_INPUT_DISPATCHER_POLICY
1433 LOGD("Waiting because touched window is paused.");
1434#endif
1435 anrTimer.dispatchPausedByApplication(mTouchedWindow);
1436 continue; // wait some more
1437 }
1438
1439 // Success!
Jeff Brownc5ed5912010-07-14 18:48:53 -07001440 injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
1441 injectionPermission = INJECTION_PERMISSION_GRANTED;
Jeff Brown349703e2010-06-22 01:27:15 -07001442 break; // done
1443 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001444 }
Jeff Brown349703e2010-06-22 01:27:15 -07001445
1446 // Output targets.
Jeff Brown349703e2010-06-22 01:27:15 -07001447 if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
Jeff Brown349703e2010-06-22 01:27:15 -07001448 size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
1449 for (size_t i = 0; i < numWallpaperWindows; i++) {
1450 addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
1451 }
1452
1453 size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
1454 for (size_t i = 0; i < numOutsideWindows; i++) {
1455 addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
1456 }
1457
1458 addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
1459 anrTimer.getTimeSpentWaitingForApplication(), outTargets);
1460 outTouchedWindow = mTouchedWindow;
1461 } else {
Jeff Brown349703e2010-06-22 01:27:15 -07001462 outTouchedWindow = NULL;
1463 }
1464 mTempTouchedOutsideWindows.clear();
1465
Jeff Brownc5ed5912010-07-14 18:48:53 -07001466 // Check injection permission once and for all.
1467 if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
1468 if (checkInjectionPermission(action == AMOTION_EVENT_ACTION_DOWN ? NULL : mTouchedWindow,
1469 injectorPid, injectorUid)) {
1470 injectionPermission = INJECTION_PERMISSION_GRANTED;
1471 } else {
1472 injectionPermission = INJECTION_PERMISSION_DENIED;
1473 }
1474 }
1475
1476 // Update final pieces of touch state if the injector had permission.
1477 if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
1478 if (action == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brown349703e2010-06-22 01:27:15 -07001479 if (mTouchDown) {
1480 // This is weird. We got a down but we thought it was already down!
1481 LOGW("Pointer down received while already down.");
1482 } else {
1483 mTouchDown = true;
1484 }
1485
1486 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1487 // Since we failed to identify a target for this touch down, we may still
1488 // be holding on to an earlier target from a previous touch down. Release it.
1489 releaseTouchedWindowLd();
1490 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001491 } else if (action == AMOTION_EVENT_ACTION_UP) {
Jeff Brown349703e2010-06-22 01:27:15 -07001492 mTouchDown = false;
1493 releaseTouchedWindowLd();
1494 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001495 } else {
1496 LOGW("Not updating touch focus because injection was denied.");
Jeff Brown349703e2010-06-22 01:27:15 -07001497 }
1498
1499#if DEBUG_FOCUS
1500 LOGD("waitForTouchedWindow finished: injectionResult=%d",
1501 injectionResult);
Jeff Browne33348b2010-07-15 23:54:05 -07001502 logDispatchStateLd();
Jeff Brown349703e2010-06-22 01:27:15 -07001503#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001504 return injectionResult;
1505}
1506
Jeff Brown349703e2010-06-22 01:27:15 -07001507void NativeInputManager::releaseTouchedWindowLd() {
1508 mTouchedWindow = NULL;
1509 mTouchedWallpaperWindows.clear();
1510}
1511
1512void NativeInputManager::addTarget(const InputWindow* window, int32_t targetFlags,
1513 nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets) {
1514 nsecs_t timeout = window->dispatchingTimeout - timeSpentWaitingForApplication;
1515 if (timeout < MIN_INPUT_DISPATCHING_TIMEOUT) {
1516 timeout = MIN_INPUT_DISPATCHING_TIMEOUT;
1517 }
1518
1519 outTargets.push();
1520
1521 InputTarget& target = outTargets.editTop();
1522 target.inputChannel = window->inputChannel;
1523 target.flags = targetFlags;
1524 target.timeout = timeout;
1525 target.xOffset = - window->frameLeft;
1526 target.yOffset = - window->frameTop;
1527}
1528
1529bool NativeInputManager::checkInjectionPermission(const InputWindow* window,
1530 int32_t injectorPid, int32_t injectorUid) {
1531 if (injectorUid > 0 && (window == NULL || window->ownerUid != injectorUid)) {
1532 JNIEnv* env = jniEnv();
1533 jboolean result = env->CallBooleanMethod(mCallbacksObj,
1534 gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
1535 checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission");
1536
1537 if (! result) {
1538 if (window) {
1539 LOGW("Permission denied: injecting event from pid %d uid %d to window "
1540 "with input channel %s owned by uid %d",
1541 injectorPid, injectorUid, window->inputChannel->getName().string(),
1542 window->ownerUid);
1543 } else {
1544 LOGW("Permission denied: injecting event from pid %d uid %d",
1545 injectorPid, injectorUid);
1546 }
1547 return false;
1548 }
1549 }
1550
1551 return true;
1552}
1553
1554int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
1555 int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
1556#if DEBUG_INPUT_DISPATCHER_POLICY
1557 LOGD("waitForKeyEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1558 policyFlags, injectorPid, injectorUid);
1559#endif
1560
1561 int32_t windowType;
1562 { // acquire lock
1563 AutoMutex _l(mDispatchLock);
1564
1565 InputWindow* focusedWindow;
1566 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1567 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1568 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1569 return injectionResult;
1570 }
1571
1572 windowType = focusedWindow->layoutParamsType;
1573 } // release lock
1574
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001575 if (isPolicyKey(keyEvent->getKeyCode(), isScreenOn())) {
1576 const InputTarget& target = outTargets.top();
1577 bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags);
1578 if (consumed) {
1579 outTargets.clear();
1580 return INPUT_EVENT_INJECTION_SUCCEEDED;
1581 }
Jeff Brown349703e2010-06-22 01:27:15 -07001582 }
1583
1584 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1585 return INPUT_EVENT_INJECTION_SUCCEEDED;
1586}
1587
1588int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent,
1589 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07001590 Vector<InputTarget>& outTargets) {
Jeff Brown349703e2010-06-22 01:27:15 -07001591#if DEBUG_INPUT_DISPATCHER_POLICY
1592 LOGD("waitForMotionEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
1593 policyFlags, injectorPid, injectorUid);
1594#endif
Jeff Brown7fbdc842010-06-17 20:52:56 -07001595
Jeff Brownc5ed5912010-07-14 18:48:53 -07001596 int32_t source = motionEvent->getSource();
1597 if (source & AINPUT_SOURCE_CLASS_POINTER) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001598 return waitForTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
Jeff Brown349703e2010-06-22 01:27:15 -07001599 outTargets);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001600 } else {
1601 return waitForNonTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid,
1602 outTargets);
Jeff Brown7fbdc842010-06-17 20:52:56 -07001603 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001604}
1605
Jeff Brownc5ed5912010-07-14 18:48:53 -07001606int32_t NativeInputManager::waitForNonTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001607 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1608 Vector<InputTarget>& outTargets) {
1609#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brownc5ed5912010-07-14 18:48:53 -07001610 LOGD("waitForNonTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001611 policyFlags, injectorPid, injectorUid);
1612#endif
1613
1614 int32_t windowType;
1615 { // acquire lock
1616 AutoMutex _l(mDispatchLock);
1617
1618 InputWindow* focusedWindow;
1619 int32_t injectionResult = waitForFocusedWindowLd(policyFlags,
1620 injectorPid, injectorUid, outTargets, /*out*/ focusedWindow);
1621 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1622 return injectionResult;
1623 }
1624
1625 windowType = focusedWindow->layoutParamsType;
1626 } // release lock
1627
1628 pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
1629 return INPUT_EVENT_INJECTION_SUCCEEDED;
1630}
1631
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001632int32_t NativeInputManager::waitForTouchEventTargets(MotionEvent* motionEvent,
Jeff Brown349703e2010-06-22 01:27:15 -07001633 uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid,
1634 Vector<InputTarget>& outTargets) {
1635#if DEBUG_INPUT_DISPATCHER_POLICY
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001636 LOGD("waitForTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d",
Jeff Brown349703e2010-06-22 01:27:15 -07001637 policyFlags, injectorPid, injectorUid);
1638#endif
1639
1640 int32_t windowType;
1641 { // acquire lock
1642 AutoMutex _l(mDispatchLock);
1643
1644 InputWindow* touchedWindow;
1645 int32_t injectionResult = waitForTouchedWindowLd(motionEvent, policyFlags,
1646 injectorPid, injectorUid, outTargets, /*out*/ touchedWindow);
1647 if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1648 return injectionResult;
1649 }
1650
1651 windowType = touchedWindow->layoutParamsType;
1652 } // release lock
1653
1654 int32_t eventType;
1655 switch (motionEvent->getAction()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001656 case AMOTION_EVENT_ACTION_DOWN:
Jeff Brown349703e2010-06-22 01:27:15 -07001657 eventType = POWER_MANAGER_TOUCH_EVENT;
1658 break;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001659 case AMOTION_EVENT_ACTION_UP:
Jeff Brown349703e2010-06-22 01:27:15 -07001660 eventType = POWER_MANAGER_TOUCH_UP_EVENT;
1661 break;
1662 default:
1663 if (motionEvent->getEventTime() - motionEvent->getDownTime()
1664 >= EVENT_IGNORE_DURATION) {
1665 eventType = POWER_MANAGER_TOUCH_EVENT;
1666 } else {
1667 eventType = POWER_MANAGER_LONG_TOUCH_EVENT;
1668 }
1669 break;
1670 }
1671 pokeUserActivityIfNeeded(windowType, eventType);
1672 return INPUT_EVENT_INJECTION_SUCCEEDED;
1673}
1674
Jeff Brownd0097872010-06-30 14:41:59 -07001675bool NativeInputManager::interceptKeyBeforeDispatching(const InputTarget& target,
1676 const KeyEvent* keyEvent, uint32_t policyFlags) {
1677 JNIEnv* env = jniEnv();
1678
1679 jobject inputChannelObj = getInputChannelObjLocal(env, target.inputChannel);
1680 if (inputChannelObj) {
1681 jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
1682 gCallbacksClassInfo.interceptKeyBeforeDispatching,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001683 inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
1684 keyEvent->getKeyCode(), keyEvent->getMetaState(),
Jeff Brownd0097872010-06-30 14:41:59 -07001685 keyEvent->getRepeatCount(), policyFlags);
1686 bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
1687
1688 env->DeleteLocalRef(inputChannelObj);
1689
1690 return consumed && ! error;
1691 } else {
1692 LOGW("Could not apply key dispatch policy because input channel '%s' is "
1693 "no longer valid.", target.inputChannel->getName().string());
1694 return false;
1695 }
1696}
1697
Jeff Brown349703e2010-06-22 01:27:15 -07001698void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t eventType) {
1699 if (windowType != TYPE_KEYGUARD) {
1700 nsecs_t eventTime = now();
1701 pokeUserActivity(eventTime, eventType);
1702 }
1703}
1704
1705void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001706 android_server_PowerManagerService_userActivity(eventTime, eventType);
Jeff Brown349703e2010-06-22 01:27:15 -07001707}
1708
Jeff Brown6d0fec22010-07-23 21:28:06 -07001709static void dumpMotionRange(String8& dump,
1710 const char* name, const InputDeviceInfo::MotionRange* range) {
1711 if (range) {
1712 dump.appendFormat(" %s = { min: %0.3f, max: %0.3f, flat: %0.3f, fuzz: %0.3f }\n",
1713 name, range->min, range->max, range->flat, range->fuzz);
1714 }
1715}
1716
1717#define DUMP_MOTION_RANGE(range) \
1718 dumpMotionRange(dump, #range, deviceInfo.getMotionRange(AINPUT_MOTION_RANGE_##range));
1719
1720void NativeInputManager::dumpDeviceInfo(String8& dump) {
1721 Vector<int32_t> deviceIds;
1722 mInputManager->getInputDeviceIds(deviceIds);
1723
1724 InputDeviceInfo deviceInfo;
1725 for (size_t i = 0; i < deviceIds.size(); i++) {
1726 int32_t deviceId = deviceIds[i];
1727
1728 status_t result = mInputManager->getInputDeviceInfo(deviceId, & deviceInfo);
1729 if (result == NAME_NOT_FOUND) {
1730 continue;
1731 } else if (result != OK) {
1732 dump.appendFormat(" ** Unexpected error %d getting information about input devices.\n",
1733 result);
1734 continue;
1735 }
1736
1737 dump.appendFormat(" Device %d: '%s'\n",
1738 deviceInfo.getId(), deviceInfo.getName().string());
1739 dump.appendFormat(" sources = 0x%08x\n",
1740 deviceInfo.getSources());
1741 dump.appendFormat(" keyboardType = %d\n",
1742 deviceInfo.getKeyboardType());
1743
1744 dump.append(" motion ranges:\n");
1745 DUMP_MOTION_RANGE(X);
1746 DUMP_MOTION_RANGE(Y);
1747 DUMP_MOTION_RANGE(PRESSURE);
1748 DUMP_MOTION_RANGE(SIZE);
1749 DUMP_MOTION_RANGE(TOUCH_MAJOR);
1750 DUMP_MOTION_RANGE(TOUCH_MINOR);
1751 DUMP_MOTION_RANGE(TOOL_MAJOR);
1752 DUMP_MOTION_RANGE(TOOL_MINOR);
1753 DUMP_MOTION_RANGE(ORIENTATION);
1754 }
1755}
1756
1757#undef DUMP_MOTION_RANGE
1758
Jeff Browne33348b2010-07-15 23:54:05 -07001759void NativeInputManager::logDispatchStateLd() {
1760 String8 dump;
1761 dumpDispatchStateLd(dump);
1762 LOGD("%s", dump.string());
1763}
1764
1765void NativeInputManager::dumpDispatchStateLd(String8& dump) {
1766 dump.appendFormat(" dispatchEnabled: %d\n", mDispatchEnabled);
1767 dump.appendFormat(" dispatchFrozen: %d\n", mDispatchFrozen);
1768 dump.appendFormat(" windowsReady: %d\n", mWindowsReady);
1769
Jeff Brown349703e2010-06-22 01:27:15 -07001770 if (mFocusedApplication) {
Jeff Browne33348b2010-07-15 23:54:05 -07001771 dump.appendFormat(" focusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001772 mFocusedApplication->name.string(),
1773 mFocusedApplication->dispatchingTimeout / 1000000.0);
1774 } else {
Jeff Browne33348b2010-07-15 23:54:05 -07001775 dump.append(" focusedApplication: <null>\n");
Jeff Brown349703e2010-06-22 01:27:15 -07001776 }
Jeff Browne33348b2010-07-15 23:54:05 -07001777 dump.appendFormat(" focusedWindow: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001778 mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
Jeff Browne33348b2010-07-15 23:54:05 -07001779 dump.appendFormat(" touchedWindow: '%s', touchDown=%d\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001780 mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
1781 mTouchDown);
1782 for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001783 dump.appendFormat(" touchedWallpaperWindows[%d]: '%s'\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001784 i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
1785 }
1786 for (size_t i = 0; i < mWindows.size(); i++) {
Jeff Browne33348b2010-07-15 23:54:05 -07001787 dump.appendFormat(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, "
1788 "visible=%d, flags=0x%08x, type=0x%08x, "
Jeff Brown349703e2010-06-22 01:27:15 -07001789 "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
Jeff Browne33348b2010-07-15 23:54:05 -07001790 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
Jeff Brown349703e2010-06-22 01:27:15 -07001791 i, mWindows[i].inputChannel->getName().string(),
1792 mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
1793 mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
1794 mWindows[i].frameLeft, mWindows[i].frameTop,
1795 mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
1796 mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
1797 mWindows[i].ownerPid, mWindows[i].ownerUid,
1798 mWindows[i].dispatchingTimeout / 1000000.0);
1799 }
Jeff Brown349703e2010-06-22 01:27:15 -07001800}
1801
1802// ----------------------------------------------------------------------------
1803
1804NativeInputManager::ANRTimer::ANRTimer() :
1805 mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
1806}
1807
1808void NativeInputManager::ANRTimer::dispatchFrozenBySystem() {
1809 mFrozen = true;
1810}
1811
1812void NativeInputManager::ANRTimer::dispatchPausedByApplication(InputWindow* pausedWindow) {
1813 mPausedWindow = pausedWindow;
1814}
1815
1816bool NativeInputManager::ANRTimer::waitForDispatchStateChangeLd(NativeInputManager* inputManager) {
1817 nsecs_t currentTime = now();
1818
1819 Budget newBudget;
1820 nsecs_t dispatchingTimeout;
1821 sp<InputChannel> pausedChannel = NULL;
1822 jobject tokenObj = NULL;
1823 if (mFrozen) {
1824 newBudget = SYSTEM;
1825 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1826 mFrozen = false;
1827 } else if (mPausedWindow) {
1828 newBudget = APPLICATION;
1829 dispatchingTimeout = mPausedWindow->dispatchingTimeout;
1830 pausedChannel = mPausedWindow->inputChannel;
1831 mPausedWindow = NULL;
1832 } else if (inputManager->mFocusedApplication) {
1833 newBudget = APPLICATION;
1834 dispatchingTimeout = inputManager->mFocusedApplication->dispatchingTimeout;
1835 tokenObj = jniEnv()->NewLocalRef(inputManager->mFocusedApplication->tokenObjWeak);
1836 } else {
1837 newBudget = APPLICATION;
1838 dispatchingTimeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1839 }
1840
1841 if (mBudget != newBudget) {
1842 mBudget = newBudget;
1843 mStartTime = currentTime;
1844 }
1845
1846 bool result = false;
1847 nsecs_t timeoutRemaining = mStartTime + dispatchingTimeout - currentTime;
1848 if (timeoutRemaining > 0
1849 && inputManager->mDispatchStateChanged.waitRelative(inputManager->mDispatchLock,
1850 timeoutRemaining) == OK) {
1851 result = true;
1852 } else {
1853 if (pausedChannel != NULL || tokenObj != NULL) {
1854 bool resumed;
1855 nsecs_t newTimeout = 0;
1856
1857 inputManager->mDispatchLock.unlock(); // release lock
1858 if (pausedChannel != NULL) {
1859 resumed = inputManager->notifyInputChannelANR(pausedChannel, /*out*/ newTimeout);
1860 } else {
1861 resumed = inputManager->notifyANR(tokenObj, /*out*/ newTimeout);
1862 }
1863 inputManager->mDispatchLock.lock(); // re-acquire lock
1864
1865 if (resumed) {
1866 mStartTime = now() - dispatchingTimeout + newTimeout;
1867 result = true;
1868 }
1869 }
1870 }
1871
1872 if (tokenObj) {
1873 jniEnv()->DeleteLocalRef(tokenObj);
1874 }
1875
1876 return result;
1877}
1878
1879nsecs_t NativeInputManager::ANRTimer::getTimeSpentWaitingForApplication() const {
1880 return mBudget == APPLICATION ? now() - mStartTime : 0;
1881}
Jeff Brown9c3cda02010-06-15 01:31:58 -07001882
1883// ----------------------------------------------------------------------------
1884
1885static sp<NativeInputManager> gNativeInputManager;
1886
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001887static bool checkInputManagerUnitialized(JNIEnv* env) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001888 if (gNativeInputManager == NULL) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001889 LOGE("Input manager not initialized.");
1890 jniThrowRuntimeException(env, "Input manager not initialized.");
1891 return true;
1892 }
1893 return false;
1894}
1895
1896static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
1897 jobject callbacks) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001898 if (gNativeInputManager == NULL) {
1899 gNativeInputManager = new NativeInputManager(callbacks);
1900 } else {
1901 LOGE("Input manager already initialized.");
1902 jniThrowRuntimeException(env, "Input manager already initialized.");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001903 }
1904}
1905
1906static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
1907 if (checkInputManagerUnitialized(env)) {
1908 return;
1909 }
1910
Jeff Brown9c3cda02010-06-15 01:31:58 -07001911 status_t result = gNativeInputManager->getInputManager()->start();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001912 if (result) {
1913 jniThrowRuntimeException(env, "Input manager could not be started.");
1914 }
1915}
1916
1917static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
1918 jint displayId, jint width, jint height) {
1919 if (checkInputManagerUnitialized(env)) {
1920 return;
1921 }
1922
1923 // XXX we could get this from the SurfaceFlinger directly instead of requiring it
1924 // to be passed in like this, not sure which is better but leaving it like this
1925 // keeps the window manager in direct control of when display transitions propagate down
1926 // to the input dispatcher
Jeff Brown9c3cda02010-06-15 01:31:58 -07001927 gNativeInputManager->setDisplaySize(displayId, width, height);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001928}
1929
1930static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
1931 jint displayId, jint orientation) {
1932 if (checkInputManagerUnitialized(env)) {
1933 return;
1934 }
1935
Jeff Brown9c3cda02010-06-15 01:31:58 -07001936 gNativeInputManager->setDisplayOrientation(displayId, orientation);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001937}
1938
1939static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07001940 jint deviceId, jint sourceMask, jint scanCode) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001941 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001942 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001943 }
1944
Jeff Brown9c3cda02010-06-15 01:31:58 -07001945 return gNativeInputManager->getInputManager()->getScanCodeState(
Jeff Brown6d0fec22010-07-23 21:28:06 -07001946 deviceId, uint32_t(sourceMask), scanCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001947}
1948
1949static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07001950 jint deviceId, jint sourceMask, jint keyCode) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001951 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001952 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001953 }
1954
Jeff Brown9c3cda02010-06-15 01:31:58 -07001955 return gNativeInputManager->getInputManager()->getKeyCodeState(
Jeff Brown6d0fec22010-07-23 21:28:06 -07001956 deviceId, uint32_t(sourceMask), keyCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001957}
1958
1959static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07001960 jint deviceId, jint sourceMask, jint sw) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001961 if (checkInputManagerUnitialized(env)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001962 return AKEY_STATE_UNKNOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001963 }
1964
Jeff Brown6d0fec22010-07-23 21:28:06 -07001965 return gNativeInputManager->getInputManager()->getSwitchState(
1966 deviceId, uint32_t(sourceMask), sw);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001967}
1968
1969static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
Jeff Brown6d0fec22010-07-23 21:28:06 -07001970 jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001971 if (checkInputManagerUnitialized(env)) {
1972 return JNI_FALSE;
1973 }
1974
1975 int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
1976 uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
1977 jsize numCodes = env->GetArrayLength(keyCodes);
1978 jboolean result;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001979 if (numCodes == env->GetArrayLength(keyCodes)) {
1980 result = gNativeInputManager->getInputManager()->hasKeys(
1981 deviceId, uint32_t(sourceMask), numCodes, codes, flags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001982 } else {
1983 result = JNI_FALSE;
1984 }
1985
1986 env->ReleaseBooleanArrayElements(outFlags, flags, 0);
1987 env->ReleaseIntArrayElements(keyCodes, codes, 0);
1988 return result;
1989}
1990
1991static void throwInputChannelNotInitialized(JNIEnv* env) {
1992 jniThrowException(env, "java/lang/IllegalStateException",
1993 "inputChannel is not initialized");
1994}
1995
1996static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
1997 jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
1998 LOGW("Input channel object '%s' was disposed without first being unregistered with "
1999 "the input manager!", inputChannel->getName().string());
2000
Jeff Brown9c3cda02010-06-15 01:31:58 -07002001 if (gNativeInputManager != NULL) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07002002 gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002003 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002004}
2005
2006static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
2007 jobject inputChannelObj) {
2008 if (checkInputManagerUnitialized(env)) {
2009 return;
2010 }
2011
2012 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
2013 inputChannelObj);
2014 if (inputChannel == NULL) {
2015 throwInputChannelNotInitialized(env);
2016 return;
2017 }
2018
Jeff Brown7fbdc842010-06-17 20:52:56 -07002019
2020 status_t status = gNativeInputManager->registerInputChannel(
2021 env, inputChannel, inputChannelObj);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002022 if (status) {
2023 jniThrowRuntimeException(env, "Failed to register input channel. "
2024 "Check logs for details.");
2025 return;
2026 }
2027
2028 android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
2029 android_server_InputManager_handleInputChannelDisposed, NULL);
2030}
2031
2032static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
2033 jobject inputChannelObj) {
2034 if (checkInputManagerUnitialized(env)) {
2035 return;
2036 }
2037
2038 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
2039 inputChannelObj);
2040 if (inputChannel == NULL) {
2041 throwInputChannelNotInitialized(env);
2042 return;
2043 }
2044
2045 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
2046
Jeff Brown7fbdc842010-06-17 20:52:56 -07002047 status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002048 if (status) {
2049 jniThrowRuntimeException(env, "Failed to unregister input channel. "
2050 "Check logs for details.");
2051 }
2052}
2053
Jeff Brown7fbdc842010-06-17 20:52:56 -07002054static jint android_server_InputManager_nativeInjectKeyEvent(JNIEnv* env, jclass clazz,
Jeff Brownc5ed5912010-07-14 18:48:53 -07002055 jobject keyEventObj, jint injectorPid, jint injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002056 jboolean sync, jint timeoutMillis) {
2057 if (checkInputManagerUnitialized(env)) {
2058 return INPUT_EVENT_INJECTION_FAILED;
2059 }
2060
2061 KeyEvent keyEvent;
Jeff Brownc5ed5912010-07-14 18:48:53 -07002062 android_view_KeyEvent_toNative(env, keyEventObj, & keyEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002063
2064 return gNativeInputManager->getInputManager()->injectInputEvent(& keyEvent,
2065 injectorPid, injectorUid, sync, timeoutMillis);
2066}
2067
2068static jint android_server_InputManager_nativeInjectMotionEvent(JNIEnv* env, jclass clazz,
Jeff Brownc5ed5912010-07-14 18:48:53 -07002069 jobject motionEventObj, jint injectorPid, jint injectorUid,
Jeff Brown7fbdc842010-06-17 20:52:56 -07002070 jboolean sync, jint timeoutMillis) {
2071 if (checkInputManagerUnitialized(env)) {
2072 return INPUT_EVENT_INJECTION_FAILED;
2073 }
2074
2075 MotionEvent motionEvent;
Jeff Brownc5ed5912010-07-14 18:48:53 -07002076 android_view_MotionEvent_toNative(env, motionEventObj, & motionEvent);
Jeff Brown7fbdc842010-06-17 20:52:56 -07002077
2078 return gNativeInputManager->getInputManager()->injectInputEvent(& motionEvent,
2079 injectorPid, injectorUid, sync, timeoutMillis);
2080}
2081
Jeff Brown349703e2010-06-22 01:27:15 -07002082static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
2083 jobjectArray windowObjArray) {
2084 if (checkInputManagerUnitialized(env)) {
2085 return;
2086 }
2087
2088 gNativeInputManager->setInputWindows(env, windowObjArray);
2089}
2090
2091static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
2092 jobject applicationObj) {
2093 if (checkInputManagerUnitialized(env)) {
2094 return;
2095 }
2096
2097 gNativeInputManager->setFocusedApplication(env, applicationObj);
2098}
2099
2100static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
2101 jclass clazz, jboolean enabled, jboolean frozen) {
2102 if (checkInputManagerUnitialized(env)) {
2103 return;
2104 }
2105
2106 gNativeInputManager->setInputDispatchMode(enabled, frozen);
2107}
2108
2109static void android_server_InputManager_nativePreemptInputDispatch(JNIEnv* env,
2110 jclass clazz) {
2111 if (checkInputManagerUnitialized(env)) {
2112 return;
2113 }
2114
2115 gNativeInputManager->preemptInputDispatch();
2116}
2117
Jeff Browne33348b2010-07-15 23:54:05 -07002118static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
2119 if (checkInputManagerUnitialized(env)) {
2120 return NULL;
2121 }
2122
2123 String8 dump(gNativeInputManager->dump());
2124 return env->NewStringUTF(dump.string());
2125}
2126
Jeff Brown9c3cda02010-06-15 01:31:58 -07002127// ----------------------------------------------------------------------------
2128
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002129static JNINativeMethod gInputManagerMethods[] = {
2130 /* name, signature, funcPtr */
2131 { "nativeInit", "(Lcom/android/server/InputManager$Callbacks;)V",
2132 (void*) android_server_InputManager_nativeInit },
2133 { "nativeStart", "()V",
2134 (void*) android_server_InputManager_nativeStart },
2135 { "nativeSetDisplaySize", "(III)V",
2136 (void*) android_server_InputManager_nativeSetDisplaySize },
2137 { "nativeSetDisplayOrientation", "(II)V",
2138 (void*) android_server_InputManager_nativeSetDisplayOrientation },
2139 { "nativeGetScanCodeState", "(III)I",
2140 (void*) android_server_InputManager_nativeGetScanCodeState },
2141 { "nativeGetKeyCodeState", "(III)I",
2142 (void*) android_server_InputManager_nativeGetKeyCodeState },
2143 { "nativeGetSwitchState", "(III)I",
2144 (void*) android_server_InputManager_nativeGetSwitchState },
Jeff Brown6d0fec22010-07-23 21:28:06 -07002145 { "nativeHasKeys", "(II[I[Z)Z",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002146 (void*) android_server_InputManager_nativeHasKeys },
2147 { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;)V",
2148 (void*) android_server_InputManager_nativeRegisterInputChannel },
2149 { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002150 (void*) android_server_InputManager_nativeUnregisterInputChannel },
Jeff Brownc5ed5912010-07-14 18:48:53 -07002151 { "nativeInjectKeyEvent", "(Landroid/view/KeyEvent;IIZI)I",
Jeff Brown7fbdc842010-06-17 20:52:56 -07002152 (void*) android_server_InputManager_nativeInjectKeyEvent },
Jeff Brownc5ed5912010-07-14 18:48:53 -07002153 { "nativeInjectMotionEvent", "(Landroid/view/MotionEvent;IIZI)I",
Jeff Brown349703e2010-06-22 01:27:15 -07002154 (void*) android_server_InputManager_nativeInjectMotionEvent },
2155 { "nativeSetInputWindows", "([Lcom/android/server/InputWindow;)V",
2156 (void*) android_server_InputManager_nativeSetInputWindows },
2157 { "nativeSetFocusedApplication", "(Lcom/android/server/InputApplication;)V",
2158 (void*) android_server_InputManager_nativeSetFocusedApplication },
2159 { "nativeSetInputDispatchMode", "(ZZ)V",
2160 (void*) android_server_InputManager_nativeSetInputDispatchMode },
2161 { "nativePreemptInputDispatch", "()V",
Jeff Browne33348b2010-07-15 23:54:05 -07002162 (void*) android_server_InputManager_nativePreemptInputDispatch },
2163 { "nativeDump", "()Ljava/lang/String;",
2164 (void*) android_server_InputManager_nativeDump },
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002165};
2166
2167#define FIND_CLASS(var, className) \
2168 var = env->FindClass(className); \
2169 LOG_FATAL_IF(! var, "Unable to find class " className); \
2170 var = jclass(env->NewGlobalRef(var));
2171
2172#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2173 var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2174 LOG_FATAL_IF(! var, "Unable to find method " methodName);
2175
2176#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
2177 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
2178 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
2179
2180int register_android_server_InputManager(JNIEnv* env) {
2181 int res = jniRegisterNativeMethods(env, "com/android/server/InputManager",
2182 gInputManagerMethods, NELEM(gInputManagerMethods));
2183 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2184
Jeff Brown9c3cda02010-06-15 01:31:58 -07002185 // Callbacks
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002186
2187 FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
2188
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002189 GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
2190 "notifyConfigurationChanged", "(JIII)V");
2191
2192 GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
2193 "notifyLidSwitchChanged", "(JZ)V");
2194
Jeff Brown7fbdc842010-06-17 20:52:56 -07002195 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
2196 "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
2197
2198 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelANR, gCallbacksClassInfo.clazz,
2199 "notifyInputChannelANR", "(Landroid/view/InputChannel;)J");
2200
2201 GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelRecoveredFromANR, gCallbacksClassInfo.clazz,
2202 "notifyInputChannelRecoveredFromANR", "(Landroid/view/InputChannel;)V");
2203
Jeff Brown349703e2010-06-22 01:27:15 -07002204 GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
2205 "notifyANR", "(Ljava/lang/Object;)J");
2206
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002207 GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz,
2208 "virtualKeyDownFeedback", "()V");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002209
Jeff Brown349703e2010-06-22 01:27:15 -07002210 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002211 "interceptKeyBeforeQueueing", "(JIZIZ)I");
Jeff Brown349703e2010-06-22 01:27:15 -07002212
2213 GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002214 "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z");
Jeff Brown349703e2010-06-22 01:27:15 -07002215
2216 GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
2217 "checkInjectEventsPermission", "(II)Z");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002218
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002219 GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz,
2220 "notifyAppSwitchComing", "()V");
2221
2222 GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, gCallbacksClassInfo.clazz,
2223 "filterTouchEvents", "()Z");
2224
2225 GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
2226 "filterJumpyTouchEvents", "()Z");
2227
2228 GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz,
2229 "getVirtualKeyDefinitions",
2230 "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
2231
2232 GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
2233 "getExcludedDeviceNames", "()[Ljava/lang/String;");
2234
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002235 // VirtualKeyDefinition
2236
2237 FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
2238 "com/android/server/InputManager$VirtualKeyDefinition");
2239
2240 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz,
2241 "scanCode", "I");
2242
2243 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz,
2244 "centerX", "I");
2245
2246 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz,
2247 "centerY", "I");
2248
2249 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz,
2250 "width", "I");
2251
2252 GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
2253 "height", "I");
2254
Jeff Brown349703e2010-06-22 01:27:15 -07002255 // InputWindow
Jeff Brown7fbdc842010-06-17 20:52:56 -07002256
Jeff Brown349703e2010-06-22 01:27:15 -07002257 FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002258
Jeff Brown349703e2010-06-22 01:27:15 -07002259 GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
2260 "inputChannel", "Landroid/view/InputChannel;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002261
Jeff Brown349703e2010-06-22 01:27:15 -07002262 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
2263 "layoutParamsFlags", "I");
2264
2265 GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
2266 "layoutParamsType", "I");
2267
2268 GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
2269 "dispatchingTimeoutNanos", "J");
2270
2271 GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
2272 "frameLeft", "I");
2273
2274 GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
2275 "frameTop", "I");
2276
2277 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
2278 "touchableAreaLeft", "I");
2279
2280 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
2281 "touchableAreaTop", "I");
2282
2283 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
2284 "touchableAreaRight", "I");
2285
2286 GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
2287 "touchableAreaBottom", "I");
2288
2289 GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
2290 "visible", "Z");
2291
2292 GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
2293 "hasFocus", "Z");
2294
2295 GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
2296 "hasWallpaper", "Z");
2297
2298 GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
2299 "paused", "Z");
2300
2301 GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
2302 "ownerPid", "I");
2303
2304 GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
2305 "ownerUid", "I");
2306
2307 // InputApplication
2308
2309 FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
2310
2311 GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
2312 "name", "Ljava/lang/String;");
2313
2314 GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
2315 gInputApplicationClassInfo.clazz,
2316 "dispatchingTimeoutNanos", "J");
2317
2318 GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
2319 "token", "Ljava/lang/Object;");
Jeff Brown7fbdc842010-06-17 20:52:56 -07002320
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002321 return 0;
2322}
2323
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002324} /* namespace android */